diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 1b7e96dca..97e6a2da8 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -101,6 +101,11 @@
+
+
dispatchingAndroidInjector;
private String accountId;
diff --git a/app/src/main/java/com/keylesspalace/tusky/BaseActivity.java b/app/src/main/java/com/keylesspalace/tusky/BaseActivity.java
index 0b691831d..f624a59cf 100644
--- a/app/src/main/java/com/keylesspalace/tusky/BaseActivity.java
+++ b/app/src/main/java/com/keylesspalace/tusky/BaseActivity.java
@@ -34,8 +34,13 @@ import com.keylesspalace.tusky.db.AccountEntity;
import com.keylesspalace.tusky.db.AccountManager;
import com.keylesspalace.tusky.util.ThemeUtils;
+import javax.inject.Inject;
+
public abstract class BaseActivity extends AppCompatActivity {
+ @Inject
+ public AccountManager accountManager;
+
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -48,6 +53,11 @@ public abstract class BaseActivity extends AppCompatActivity {
String theme = preferences.getString("appTheme", ThemeUtils.APP_THEME_DEFAULT);
ThemeUtils.setAppNightMode(theme, this);
+ long accountId = getIntent().getLongExtra("account", -1);
+ if (accountId != -1) {
+ accountManager.setActiveAccount(accountId);
+ }
+
int style;
switch (preferences.getString("statusTextSize", "medium")) {
case "large":
diff --git a/app/src/main/java/com/keylesspalace/tusky/ComposeActivity.java b/app/src/main/java/com/keylesspalace/tusky/ComposeActivity.java
index 1bfe8ea52..52d383af2 100644
--- a/app/src/main/java/com/keylesspalace/tusky/ComposeActivity.java
+++ b/app/src/main/java/com/keylesspalace/tusky/ComposeActivity.java
@@ -167,8 +167,6 @@ public final class ComposeActivity
@Inject
public MastodonApi mastodonApi;
- @Inject
- public AccountManager accountManager;
private TextView replyTextView;
private TextView replyContentTextView;
diff --git a/app/src/main/java/com/keylesspalace/tusky/MainActivity.java b/app/src/main/java/com/keylesspalace/tusky/MainActivity.java
index eee24f2d9..d41f23664 100644
--- a/app/src/main/java/com/keylesspalace/tusky/MainActivity.java
+++ b/app/src/main/java/com/keylesspalace/tusky/MainActivity.java
@@ -92,8 +92,6 @@ public class MainActivity extends BaseActivity implements ActionButtonActivity,
public MastodonApi mastodonApi;
@Inject
public DispatchingAndroidInjector fragmentInjector;
- @Inject
- public AccountManager accountManager;
private static int COMPOSE_RESULT = 1;
diff --git a/app/src/main/java/com/keylesspalace/tusky/di/ActivitiesModule.kt b/app/src/main/java/com/keylesspalace/tusky/di/ActivitiesModule.kt
index e36ff9ebb..dde3df4f0 100644
--- a/app/src/main/java/com/keylesspalace/tusky/di/ActivitiesModule.kt
+++ b/app/src/main/java/com/keylesspalace/tusky/di/ActivitiesModule.kt
@@ -25,6 +25,10 @@ import dagger.android.ContributesAndroidInjector
@Module
abstract class ActivitiesModule {
+
+ @ContributesAndroidInjector
+ abstract fun contributesBaseActivity(): BaseActivity
+
@ContributesAndroidInjector(modules = [FragmentBuildersModule::class])
abstract fun contributesMainActivity(): MainActivity
diff --git a/app/src/main/java/com/keylesspalace/tusky/di/BroadcastReceiverModule.kt b/app/src/main/java/com/keylesspalace/tusky/di/BroadcastReceiverModule.kt
index 335da5599..df4b09ff2 100644
--- a/app/src/main/java/com/keylesspalace/tusky/di/BroadcastReceiverModule.kt
+++ b/app/src/main/java/com/keylesspalace/tusky/di/BroadcastReceiverModule.kt
@@ -1,4 +1,5 @@
-/* Copyright 2018 Conny Duck
+/* Copyright 2018 Jeremiasz Nelz
+ * Copyright 2018 Conny Duck
*
* This file is a part of Tusky.
*
@@ -15,6 +16,7 @@
package com.keylesspalace.tusky.di
+import com.keylesspalace.tusky.receiver.SendStatusBroadcastReceiver
import com.keylesspalace.tusky.receiver.NotificationClearBroadcastReceiver
import dagger.Module
import dagger.android.ContributesAndroidInjector
@@ -22,5 +24,8 @@ import dagger.android.ContributesAndroidInjector
@Module
abstract class BroadcastReceiverModule {
@ContributesAndroidInjector
+
+ abstract fun contributeSendStatusBroadcastReceiver() : SendStatusBroadcastReceiver
+
abstract fun contributeNotificationClearBroadcastReceiver() : NotificationClearBroadcastReceiver
}
\ No newline at end of file
diff --git a/app/src/main/java/com/keylesspalace/tusky/receiver/SendStatusBroadcastReceiver.kt b/app/src/main/java/com/keylesspalace/tusky/receiver/SendStatusBroadcastReceiver.kt
new file mode 100644
index 000000000..8b2e535f9
--- /dev/null
+++ b/app/src/main/java/com/keylesspalace/tusky/receiver/SendStatusBroadcastReceiver.kt
@@ -0,0 +1,145 @@
+/* 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.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)
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/keylesspalace/tusky/util/NotificationHelper.java b/app/src/main/java/com/keylesspalace/tusky/util/NotificationHelper.java
index 858dc6e1b..bdbf1a713 100644
--- a/app/src/main/java/com/keylesspalace/tusky/util/NotificationHelper.java
+++ b/app/src/main/java/com/keylesspalace/tusky/util/NotificationHelper.java
@@ -1,4 +1,5 @@
-/* Copyright 2017 Andrew Dawson
+/* Copyright 2018 Jeremiasz Nelz
+ * Copyright 2017 Andrew Dawson
*
* This file is a part of Tusky.
*
@@ -27,6 +28,8 @@ import android.os.Build;
import android.provider.Settings;
import android.support.annotation.Nullable;
import android.support.v4.app.NotificationCompat;
+import android.support.v4.app.NotificationManagerCompat;
+import android.support.v4.app.RemoteInput;
import android.support.v4.app.TaskStackBuilder;
import android.support.v4.content.ContextCompat;
import android.util.Log;
@@ -34,10 +37,13 @@ import android.util.Log;
import com.keylesspalace.tusky.MainActivity;
import com.keylesspalace.tusky.R;
import com.keylesspalace.tusky.TuskyApplication;
+import com.keylesspalace.tusky.ViewThreadActivity;
import com.keylesspalace.tusky.db.AccountEntity;
import com.keylesspalace.tusky.db.AccountManager;
import com.keylesspalace.tusky.entity.Notification;
+import com.keylesspalace.tusky.entity.Status;
import com.keylesspalace.tusky.receiver.NotificationClearBroadcastReceiver;
+import com.keylesspalace.tusky.receiver.SendStatusBroadcastReceiver;
import com.keylesspalace.tusky.view.RoundedTransformation;
import com.squareup.picasso.Picasso;
@@ -46,10 +52,14 @@ import org.json.JSONException;
import java.io.IOException;
import java.util.ArrayList;
+import java.util.Collections;
+import java.util.LinkedHashSet;
import java.util.List;
public class NotificationHelper {
+ private static int notificationId = 0;
+
/**
* constants used in Intents
*/
@@ -57,13 +67,39 @@ public class NotificationHelper {
private static final String TAG = "NotificationHelper";
+ public static final String REPLY_ACTION = "REPLY_ACTION";
+
+ public static final String COMPOSE_ACTION = "COMPOSE_ACTION";
+
+ public static final String KEY_REPLY = "KEY_REPLY";
+
+ public static final String KEY_SENDER_ACCOUNT_ID = "KEY_SENDER_ACCOUNT_ID";
+
+ public static final String KEY_SENDER_ACCOUNT_IDENTIFIER = "KEY_SENDER_ACCOUNT_IDENTIFIER";
+
+ public static final String KEY_SENDER_ACCOUNT_FULL_NAME = "KEY_SENDER_ACCOUNT_FULL_NAME";
+
+ public static final String KEY_NOTIFICATION_ID = "KEY_NOTIFICATION_ID";
+
+ public static final String KEY_CITED_STATUS_ID = "KEY_CITED_STATUS_ID";
+
+ public static final String KEY_VISIBILITY = "KEY_VISIBILITY";
+
+ public static final String KEY_SPOILER = "KEY_SPOILER";
+
+ public static final String KEY_MENTIONS = "KEY_MENTIONS";
+
+ public static final String KEY_CITED_TEXT = "KEY_CITED_TEXT";
+
+ public static final String KEY_CITED_AUTHOR_LOCAL = "KEY_CITED_AUTHOR_LOCAL";
+
/**
* notification channels used on Android O+
**/
- private static final String CHANNEL_MENTION = "CHANNEL_MENTION";
- private static final String CHANNEL_FOLLOW = "CHANNEL_FOLLOW";
- private static final String CHANNEL_BOOST = "CHANNEL_BOOST";
- private static final String CHANNEL_FAVOURITE = " CHANNEL_FAVOURITE";
+ public static final String CHANNEL_MENTION = "CHANNEL_MENTION";
+ public static final String CHANNEL_FOLLOW = "CHANNEL_FOLLOW";
+ public static final String CHANNEL_BOOST = "CHANNEL_BOOST";
+ public static final String CHANNEL_FAVOURITE = "CHANNEL_FAVOURITE";
/**
* Takes a given Mastodon notification and either creates a new Android notification or updates
@@ -104,75 +140,172 @@ public class NotificationHelper {
account.setActiveNotifications(currentNotifications.toString());
- //no need to save account, this will be done in the calling function
+ // Notification group member
+ // =========================
+ final NotificationCompat.Builder builder = newNotification(context, body, account, false);
- Intent resultIntent = new Intent(context, MainActivity.class);
- resultIntent.putExtra(ACCOUNT_ID, account.getId());
- TaskStackBuilder stackBuilder = TaskStackBuilder.create(context);
- stackBuilder.addParentStack(MainActivity.class);
- stackBuilder.addNextIntent(resultIntent);
- PendingIntent resultPendingIntent = stackBuilder.getPendingIntent((int) account.getId(),
- PendingIntent.FLAG_UPDATE_CURRENT);
+ notificationId++;
- Intent deleteIntent = new Intent(context, NotificationClearBroadcastReceiver.class);
- deleteIntent.putExtra(ACCOUNT_ID, account.getId());
- PendingIntent deletePendingIntent = PendingIntent.getBroadcast(context, (int) account.getId(), deleteIntent,
- PendingIntent.FLAG_UPDATE_CURRENT);
+ builder.setContentTitle(titleForType(context, body))
+ .setContentText(bodyForType(body));
- final NotificationCompat.Builder builder = new NotificationCompat.Builder(context, getChannelId(account, body))
- .setSmallIcon(R.drawable.ic_notify)
- .setContentIntent(resultPendingIntent)
- .setDeleteIntent(deletePendingIntent)
- .setColor(ContextCompat.getColor(context, (R.color.primary)))
- .setDefaults(0); // So it doesn't ring twice, notify only in Target callback
+ if (body.getType() == Notification.Type.MENTION) {
+ builder.setStyle(new NotificationCompat.BigTextStyle()
+ .bigText(bodyForType(body)));
+ }
- setupPreferences(account, builder);
+ //load the avatar synchronously
+ Bitmap accountAvatar;
+ try {
+ accountAvatar = Picasso.with(context)
+ .load(body.getAccount().getAvatar())
+ .transform(new RoundedTransformation(20))
+ .get();
+ } catch (IOException e) {
+ Log.d(TAG, "error loading account avatar", e);
+ accountAvatar = BitmapFactory.decodeResource(context.getResources(), R.drawable.avatar_default);
+ }
- if (currentNotifications.length() == 1) {
- builder.setContentTitle(titleForType(context, body))
- .setContentText(bodyForType(body));
+ builder.setLargeIcon(accountAvatar);
- if (body.getType() == Notification.Type.MENTION) {
- builder.setStyle(new NotificationCompat.BigTextStyle()
- .bigText(bodyForType(body)));
- }
+ // Reply to mention action; RemoteInput is available from KitKat Watch, but buttons are available from Nougat
+ if (body.getType() == Notification.Type.MENTION
+ && android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
+ RemoteInput replyRemoteInput = new RemoteInput.Builder(KEY_REPLY)
+ .setLabel(context.getString(R.string.label_quick_reply))
+ .build();
- //load the avatar synchronously
- Bitmap accountAvatar;
- try {
- accountAvatar = Picasso.with(context)
- .load(body.getAccount().getAvatar())
- .transform(new RoundedTransformation(20))
- .get();
- } catch (IOException e) {
- Log.d(TAG, "error loading account avatar", e);
- accountAvatar = BitmapFactory.decodeResource(context.getResources(), R.drawable.avatar_default);
- }
+ PendingIntent quickReplyPendingIntent = getStatusReplyIntent(REPLY_ACTION, context, body, account);
- builder.setLargeIcon(accountAvatar);
+ NotificationCompat.Action quickReplyAction =
+ new NotificationCompat.Action.Builder(R.drawable.ic_reply_24dp,
+ context.getString(R.string.action_quick_reply), quickReplyPendingIntent)
+ .addRemoteInput(replyRemoteInput)
+ .build();
- } else {
+ builder.addAction(quickReplyAction);
+
+ PendingIntent composePendingIntent = getStatusReplyIntent(COMPOSE_ACTION, context, body, account);
+
+ NotificationCompat.Action composeAction =
+ new NotificationCompat.Action.Builder(R.drawable.ic_reply_24dp,
+ context.getString(R.string.action_compose_shortcut), composePendingIntent)
+ .build();
+
+ builder.addAction(composeAction);
+ }
+
+ builder.setSubText(account.getFullName());
+ builder.setVisibility(NotificationCompat.VISIBILITY_PRIVATE);
+ builder.setCategory(NotificationCompat.CATEGORY_SOCIAL);
+ builder.setOnlyAlertOnce(true);
+
+ // Summary
+ // =======
+ final NotificationCompat.Builder summaryBuilder = newNotification(context, body, account, true);
+
+ if (currentNotifications.length() != 1) {
try {
String title = context.getString(R.string.notification_title_summary, currentNotifications.length());
String text = joinNames(context, currentNotifications);
- builder.setContentTitle(title)
+ summaryBuilder.setContentTitle(title)
.setContentText(text);
} catch (JSONException e) {
Log.d(TAG, Log.getStackTraceString(e));
}
}
- builder.setSubText(account.getFullName());
+ summaryBuilder.setSubText(account.getFullName());
+ summaryBuilder.setVisibility(NotificationCompat.VISIBILITY_PRIVATE);
+ summaryBuilder.setCategory(NotificationCompat.CATEGORY_SOCIAL);
+ summaryBuilder.setOnlyAlertOnce(true);
+ summaryBuilder.setGroupSummary(true);
- builder.setVisibility(NotificationCompat.VISIBILITY_PRIVATE);
- builder.setCategory(NotificationCompat.CATEGORY_SOCIAL);
-
- builder.setOnlyAlertOnce(true);
-
- NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
+ NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);
//noinspection ConstantConditions
- notificationManager.notify((int) account.getId(), builder.build());
+ notificationManager.notify(notificationId, builder.build());
+ if (currentNotifications.length() == 1) {
+ notificationManager.notify((int) account.getId(), builder.setGroupSummary(true).build());
+ } else {
+ notificationManager.notify((int) account.getId(), summaryBuilder.build());
+ }
+ }
+
+ private static NotificationCompat.Builder newNotification(Context context, Notification body, AccountEntity account, boolean summary) {
+ Intent summaryResultIntent = new Intent(context, MainActivity.class);
+ summaryResultIntent.putExtra(ACCOUNT_ID, account.getId());
+ TaskStackBuilder summaryStackBuilder = TaskStackBuilder.create(context);
+ summaryStackBuilder.addParentStack(MainActivity.class);
+ summaryStackBuilder.addNextIntent(summaryResultIntent);
+
+ PendingIntent summaryResultPendingIntent = summaryStackBuilder.getPendingIntent(notificationId,
+ PendingIntent.FLAG_UPDATE_CURRENT);
+
+ // we have to switch account here
+ Intent eventResultIntent = new Intent(context, ViewThreadActivity.class);
+ eventResultIntent.putExtra("account", account.getId());
+ eventResultIntent.putExtra("id", body.getStatus().getId());
+ TaskStackBuilder eventStackBuilder = TaskStackBuilder.create(context);
+ eventStackBuilder.addParentStack(ViewThreadActivity.class);
+ eventStackBuilder.addNextIntent(eventResultIntent);
+
+ PendingIntent eventResultPendingIntent = eventStackBuilder.getPendingIntent((int) account.getId(),
+ PendingIntent.FLAG_UPDATE_CURRENT);
+
+ Intent deleteIntent = new Intent(context, NotificationClearBroadcastReceiver.class);
+ deleteIntent.putExtra(ACCOUNT_ID, account.getId());
+ PendingIntent deletePendingIntent = PendingIntent.getBroadcast(context, summary ? (int) account.getId() : notificationId, deleteIntent,
+ PendingIntent.FLAG_UPDATE_CURRENT);
+
+ NotificationCompat.Builder builder = new NotificationCompat.Builder(context, getChannelId(account, body))
+ .setSmallIcon(R.drawable.ic_notify)
+ .setContentIntent(summary ? summaryResultPendingIntent : eventResultPendingIntent)
+ .setDeleteIntent(deletePendingIntent)
+ .setColor(ContextCompat.getColor(context, (R.color.primary)))
+ .setGroup(account.getAccountId())
+ .setDefaults(0); // So it doesn't ring twice, notify only in Target callback
+
+ setupPreferences(account, builder);
+
+ return builder;
+ }
+
+ private static PendingIntent getStatusReplyIntent(String action, Context context, Notification body, AccountEntity account) {
+ Status status = body.getStatus();
+
+ String citedLocalAuthor = status.getAccount().getLocalUsername();
+ String citedText = status.getContent().toString();
+ String inReplyToId = status.getId();
+ Status actionableStatus = status.getActionableStatus();
+ Status.Visibility replyVisibility = actionableStatus.getVisibility();
+ String contentWarning = actionableStatus.getSpoilerText();
+ Status.Mention[] mentions = actionableStatus.getMentions();
+ List mentionedUsernames = new ArrayList<>();
+ mentionedUsernames.add(actionableStatus.getAccount().getUsername());
+ for (Status.Mention mention : mentions) {
+ mentionedUsernames.add(mention.getUsername());
+ }
+ mentionedUsernames.removeAll(Collections.singleton(account.getUsername()));
+ mentionedUsernames = new ArrayList<>(new LinkedHashSet<>(mentionedUsernames));
+
+ Intent replyIntent = new Intent(context, SendStatusBroadcastReceiver.class)
+ .setAction(action)
+ .putExtra(KEY_CITED_AUTHOR_LOCAL, citedLocalAuthor)
+ .putExtra(KEY_CITED_TEXT, citedText)
+ .putExtra(KEY_SENDER_ACCOUNT_ID, account.getId())
+ .putExtra(KEY_SENDER_ACCOUNT_IDENTIFIER, account.getIdentifier())
+ .putExtra(KEY_SENDER_ACCOUNT_FULL_NAME, account.getFullName())
+ .putExtra(KEY_NOTIFICATION_ID, notificationId)
+ .putExtra(KEY_CITED_STATUS_ID, inReplyToId)
+ .putExtra(KEY_VISIBILITY, replyVisibility)
+ .putExtra(KEY_SPOILER, contentWarning)
+ .putExtra(KEY_MENTIONS, mentionedUsernames.toArray(new String[0]));
+
+ return PendingIntent.getBroadcast(context.getApplicationContext(),
+ notificationId,
+ replyIntent,
+ PendingIntent.FLAG_UPDATE_CURRENT);
}
public static void createNotificationChannelsForAccount(AccountEntity account, Context context) {
diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml
index b39d1448f..ac195a1bc 100644
--- a/app/src/main/res/values-pl/strings.xml
+++ b/app/src/main/res/values-pl/strings.xml
@@ -63,11 +63,14 @@
Dodatkowe komentarze?
+ Odpowiedz…
+ Szybka odpowiedź
Odpowiedz
Podbij
Dodaj do ulubionych
Więcej
Napisz
+ Odpowiedz
Zaloguj się Kontem Mastodon
Wyloguj się
Czy na pewno chcesz wylogować się z konta %1$s?
@@ -318,5 +321,7 @@
Pobieranie %1$s…
Skopiuj odnośnik
+ Wysłano!
+ Pomyślnie wysłano odpowiedź.
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index e61d62335..c3bcb8b0f 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -18,6 +18,7 @@
The upload failed.
At least one status must be reported.
Invalid regular expression
+ Error sending toot.
Home
Advanced
@@ -56,6 +57,7 @@
Report @%s
Additional comments?
+ Quick Reply
Reply
Boost
Favourite
@@ -112,6 +114,9 @@
User unblocked
User unmuted
+ Sent!
+ Reply sent successfully.
+
Which instance?
What\'s happening?
Content warning
@@ -121,6 +126,7 @@
No results
+ Reply…
Avatar
Header
@@ -295,11 +301,12 @@
Lock account
Requires you to manually approve followers
Save draft?
- Sending Toot...
+ Sending Toot…
Error sending toot
Sending Toots
Sending cancelled
A copy of the toot has been saved to your drafts
+ Compose
Your instance %s does not have any custom emojis
Copied to clipboard