diff --git a/app/src/main/java/org/thoughtcrime/securesms/MuteDialog.java b/app/src/main/java/org/thoughtcrime/securesms/MuteDialog.java index 33aace5123..acca9f8375 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/MuteDialog.java +++ b/app/src/main/java/org/thoughtcrime/securesms/MuteDialog.java @@ -2,6 +2,7 @@ package org.thoughtcrime.securesms; import android.content.Context; import android.content.DialogInterface; + import androidx.annotation.NonNull; import androidx.appcompat.app.AlertDialog; @@ -33,11 +34,10 @@ public class MuteDialog extends AlertDialog { final long muteUntil; switch (which) { - case 0: muteUntil = System.currentTimeMillis() + TimeUnit.HOURS.toMillis(1); break; case 1: muteUntil = System.currentTimeMillis() + TimeUnit.HOURS.toMillis(2); break; case 2: muteUntil = System.currentTimeMillis() + TimeUnit.DAYS.toMillis(1); break; case 3: muteUntil = System.currentTimeMillis() + TimeUnit.DAYS.toMillis(7); break; - case 4: muteUntil = System.currentTimeMillis() + TimeUnit.DAYS.toMillis(365); break; + case 4: muteUntil = Long.MAX_VALUE; break; default: muteUntil = System.currentTimeMillis() + TimeUnit.HOURS.toMillis(1); break; } diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/menus/ConversationMenuHelper.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/menus/ConversationMenuHelper.kt index 93278cb6a6..713add9277 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/menus/ConversationMenuHelper.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/menus/ConversationMenuHelper.kt @@ -36,13 +36,14 @@ import org.session.libsession.utilities.recipients.Recipient import org.session.libsignal.utilities.guava.Optional import org.session.libsignal.utilities.toHexString import org.thoughtcrime.securesms.* +import org.thoughtcrime.securesms.contacts.SelectContactsActivity import org.thoughtcrime.securesms.conversation.v2.ConversationActivityV2 +import org.thoughtcrime.securesms.conversation.v2.utilities.NotificationUtils import org.thoughtcrime.securesms.database.DatabaseFactory import org.thoughtcrime.securesms.groups.EditClosedGroupActivity import org.thoughtcrime.securesms.groups.EditClosedGroupActivity.Companion.groupIDKey -import org.thoughtcrime.securesms.contacts.SelectContactsActivity -import org.thoughtcrime.securesms.util.getColorWithID import org.thoughtcrime.securesms.util.BitmapUtil +import org.thoughtcrime.securesms.util.getColorWithID import java.io.IOException object ConversationMenuHelper { @@ -152,6 +153,7 @@ object ConversationMenuHelper { R.id.menu_invite_to_open_group -> { inviteContacts(context, thread) } R.id.menu_unmute_notifications -> { unmute(context, thread) } R.id.menu_mute_notifications -> { mute(context, thread) } + R.id.menu_notification_settings -> { setNotifyType(context, thread) } } return true } @@ -325,4 +327,11 @@ object ConversationMenuHelper { DatabaseFactory.getRecipientDatabase(context).setMuted(thread, until) } } + + private fun setNotifyType(context: Context, thread: Recipient) { + NotificationUtils.showNotifyDialog(context, thread) { notifyType -> + DatabaseFactory.getRecipientDatabase(context).setNotifyType(thread, notifyType) + } + } + } \ No newline at end of file diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/utilities/NotificationUtils.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/utilities/NotificationUtils.kt new file mode 100644 index 0000000000..dbbcfb51ef --- /dev/null +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/utilities/NotificationUtils.kt @@ -0,0 +1,21 @@ +package org.thoughtcrime.securesms.conversation.v2.utilities + +import android.content.Context +import androidx.appcompat.app.AlertDialog +import network.loki.messenger.R +import org.session.libsession.utilities.recipients.Recipient + +object NotificationUtils { + fun showNotifyDialog(context: Context, thread: Recipient, notifyTypeHandler: (Int)->Unit) { + val notifyTypes = context.resources.getStringArray(R.array.notify_types) + val currentSelected = thread.notifyType + + AlertDialog.Builder(context) + .setSingleChoiceItems(notifyTypes,currentSelected) { d, newSelection -> + notifyTypeHandler(newSelection) + d.dismiss() + } + .setTitle(R.string.RecipientPreferenceActivity_notification_settings) + .show() + } +} \ No newline at end of file diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/RecipientDatabase.java b/app/src/main/java/org/thoughtcrime/securesms/database/RecipientDatabase.java index 287a6d365c..8d7cedb61b 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/RecipientDatabase.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/RecipientDatabase.java @@ -10,17 +10,18 @@ import androidx.annotation.Nullable; import com.annimon.stream.Stream; import net.sqlcipher.database.SQLiteDatabase; -import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper; -import org.session.libsession.utilities.MaterialColor; import org.session.libsession.utilities.Address; -import org.session.libsession.utilities.recipients.Recipient; -import org.session.libsession.utilities.recipients.Recipient.*; -import org.session.libsignal.utilities.Base64; +import org.session.libsession.utilities.MaterialColor; import org.session.libsession.utilities.Util; - -import org.session.libsignal.utilities.guava.Optional; +import org.session.libsession.utilities.recipients.Recipient; +import org.session.libsession.utilities.recipients.Recipient.RecipientSettings; +import org.session.libsession.utilities.recipients.Recipient.RegisteredState; +import org.session.libsession.utilities.recipients.Recipient.UnidentifiedAccessMode; +import org.session.libsignal.utilities.Base64; import org.session.libsignal.utilities.Log; +import org.session.libsignal.utilities.guava.Optional; +import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper; import java.io.Closeable; import java.io.IOException; @@ -55,13 +56,14 @@ public class RecipientDatabase extends Database { private static final String NOTIFICATION_CHANNEL = "notification_channel"; private static final String UNIDENTIFIED_ACCESS_MODE = "unidentified_access_mode"; private static final String FORCE_SMS_SELECTION = "force_sms_selection"; + private static final String NOTIFY_TYPE = "notify_type"; // all, mentions only, none private static final String[] RECIPIENT_PROJECTION = new String[] { BLOCK, NOTIFICATION, CALL_RINGTONE, VIBRATE, CALL_VIBRATE, MUTE_UNTIL, COLOR, SEEN_INVITE_REMINDER, DEFAULT_SUBSCRIPTION_ID, EXPIRE_MESSAGES, REGISTERED, PROFILE_KEY, SYSTEM_DISPLAY_NAME, SYSTEM_PHOTO_URI, SYSTEM_PHONE_LABEL, SYSTEM_CONTACT_URI, SIGNAL_PROFILE_NAME, SIGNAL_PROFILE_AVATAR, PROFILE_SHARING, NOTIFICATION_CHANNEL, UNIDENTIFIED_ACCESS_MODE, - FORCE_SMS_SELECTION, + FORCE_SMS_SELECTION, NOTIFY_TYPE, }; static final List TYPED_RECIPIENT_PROJECTION = Stream.of(RECIPIENT_PROJECTION) @@ -95,6 +97,15 @@ public class RecipientDatabase extends Database { UNIDENTIFIED_ACCESS_MODE + " INTEGER DEFAULT 0, " + FORCE_SMS_SELECTION + " INTEGER DEFAULT 0);"; + public static String getCreateNotificationTypeCommand() { + return "ALTER TABLE "+ TABLE_NAME + " " + + "ADD COLUMN " + NOTIFY_TYPE + " INTEGER DEFAULT 0;"; + } + + public static final int NOTIFY_TYPE_ALL = 0; + public static final int NOTIFY_TYPE_MENTIONS = 1; + public static final int NOTIFY_TYPE_NONE = 2; + public RecipientDatabase(Context context, SQLCipherOpenHelper databaseHelper) { super(context, databaseHelper); } @@ -131,6 +142,7 @@ public class RecipientDatabase extends Database { int messageVibrateState = cursor.getInt(cursor.getColumnIndexOrThrow(VIBRATE)); int callVibrateState = cursor.getInt(cursor.getColumnIndexOrThrow(CALL_VIBRATE)); long muteUntil = cursor.getLong(cursor.getColumnIndexOrThrow(MUTE_UNTIL)); + int notifyType = cursor.getInt(cursor.getColumnIndexOrThrow(NOTIFY_TYPE)); String serializedColor = cursor.getString(cursor.getColumnIndexOrThrow(COLOR)); int defaultSubscriptionId = cursor.getInt(cursor.getColumnIndexOrThrow(DEFAULT_SUBSCRIPTION_ID)); int expireMessages = cursor.getInt(cursor.getColumnIndexOrThrow(EXPIRE_MESSAGES)); @@ -167,6 +179,7 @@ public class RecipientDatabase extends Database { } return Optional.of(new RecipientSettings(blocked, muteUntil, + notifyType, Recipient.VibrateState.fromId(messageVibrateState), Recipient.VibrateState.fromId(callVibrateState), Util.uri(messageRingtone), Util.uri(callRingtone), @@ -214,6 +227,18 @@ public class RecipientDatabase extends Database { recipient.resolve().setMuted(until); } + /** + * + * @param recipient to modify notifications for + * @param notifyType the new notification type {@link #NOTIFY_TYPE_ALL}, {@link #NOTIFY_TYPE_MENTIONS} or {@link #NOTIFY_TYPE_NONE} + */ + public void setNotifyType(@NonNull Recipient recipient, int notifyType) { + ContentValues values = new ContentValues(); + values.put(NOTIFY_TYPE, notifyType); + updateOrInsert(recipient.getAddress(), values); + recipient.resolve().setNotifyType(notifyType); + } + public void setExpireMessages(@NonNull Recipient recipient, int expiration) { recipient.setExpireMessages(expiration); diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/helpers/SQLCipherOpenHelper.java b/app/src/main/java/org/thoughtcrime/securesms/database/helpers/SQLCipherOpenHelper.java index 8c0763d233..efdf55c0b1 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/helpers/SQLCipherOpenHelper.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/helpers/SQLCipherOpenHelper.java @@ -10,26 +10,26 @@ import net.sqlcipher.database.SQLiteDatabase; import net.sqlcipher.database.SQLiteDatabaseHook; import net.sqlcipher.database.SQLiteOpenHelper; +import org.session.libsignal.utilities.Log; import org.thoughtcrime.securesms.crypto.DatabaseSecret; import org.thoughtcrime.securesms.database.AttachmentDatabase; import org.thoughtcrime.securesms.database.DraftDatabase; import org.thoughtcrime.securesms.database.GroupDatabase; import org.thoughtcrime.securesms.database.GroupReceiptDatabase; import org.thoughtcrime.securesms.database.JobDatabase; -import org.thoughtcrime.securesms.database.MmsDatabase; -import org.thoughtcrime.securesms.database.PushDatabase; -import org.thoughtcrime.securesms.database.RecipientDatabase; -import org.thoughtcrime.securesms.database.SearchDatabase; -import org.thoughtcrime.securesms.database.SmsDatabase; -import org.thoughtcrime.securesms.database.ThreadDatabase; -import org.session.libsignal.utilities.Log; import org.thoughtcrime.securesms.database.LokiAPIDatabase; import org.thoughtcrime.securesms.database.LokiBackupFilesDatabase; import org.thoughtcrime.securesms.database.LokiMessageDatabase; import org.thoughtcrime.securesms.database.LokiThreadDatabase; import org.thoughtcrime.securesms.database.LokiUserDatabase; +import org.thoughtcrime.securesms.database.MmsDatabase; +import org.thoughtcrime.securesms.database.PushDatabase; +import org.thoughtcrime.securesms.database.RecipientDatabase; +import org.thoughtcrime.securesms.database.SearchDatabase; import org.thoughtcrime.securesms.database.SessionContactDatabase; import org.thoughtcrime.securesms.database.SessionJobDatabase; +import org.thoughtcrime.securesms.database.SmsDatabase; +import org.thoughtcrime.securesms.database.ThreadDatabase; public class SQLCipherOpenHelper extends SQLiteOpenHelper { @@ -58,9 +58,10 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper { private static final int lokiV24 = 45; private static final int lokiV25 = 46; private static final int lokiV26 = 47; + private static final int lokiV27 = 48; // Loki - onUpgrade(...) must be updated to use Loki version numbers if Signal makes any database changes - private static final int DATABASE_VERSION = lokiV26; + private static final int DATABASE_VERSION = lokiV27; private static final String DATABASE_NAME = "signal.db"; private final Context context; @@ -296,6 +297,10 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper { db.execSQL(SessionContactDatabase.getCreateSessionContactTableCommand()); } + if (oldVersion < lokiV27) { + db.execSQL(RecipientDatabase.getCreateNotificationTypeCommand()); + } + db.setTransactionSuccessful(); } finally { db.endTransaction(); diff --git a/app/src/main/java/org/thoughtcrime/securesms/home/ConversationOptionsBottomSheet.kt b/app/src/main/java/org/thoughtcrime/securesms/home/ConversationOptionsBottomSheet.kt index 7b454d33c7..b82737932e 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/home/ConversationOptionsBottomSheet.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/home/ConversationOptionsBottomSheet.kt @@ -1,16 +1,17 @@ package org.thoughtcrime.securesms.home import android.os.Bundle -import com.google.android.material.bottomsheet.BottomSheetDialogFragment import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import androidx.core.view.isVisible +import com.google.android.material.bottomsheet.BottomSheetDialogFragment import kotlinx.android.synthetic.main.fragment_conversation_bottom_sheet.* import network.loki.messenger.R import org.session.libsession.utilities.recipients.Recipient import org.thoughtcrime.securesms.util.UiModeUtilities -public class ConversationOptionsBottomSheet : BottomSheetDialogFragment() { +public class ConversationOptionsBottomSheet : BottomSheetDialogFragment(), View.OnClickListener { //FIXME AC: Supplying a recipient directly into the field from an activity // is not the best idea. It doesn't survive configuration change. @@ -22,11 +23,25 @@ public class ConversationOptionsBottomSheet : BottomSheetDialogFragment() { var onBlockTapped: (() -> Unit)? = null var onUnblockTapped: (() -> Unit)? = null var onDeleteTapped: (() -> Unit)? = null + var onNotificationTapped: (() -> Unit)? = null + var onSetMuteTapped: ((Boolean) -> Unit)? = null override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { return inflater.inflate(R.layout.fragment_conversation_bottom_sheet, container, false) } + override fun onClick(v: View?) { + when (v) { + detailsTextView -> onViewDetailsTapped?.invoke() + blockTextView -> onBlockTapped?.invoke() + unblockTextView -> onUnblockTapped?.invoke() + deleteTextView -> onDeleteTapped?.invoke() + notificationsTextView -> onNotificationTapped?.invoke() + unMuteNotificationsTextView -> onSetMuteTapped?.invoke(false) + muteNotificationsTextView -> onSetMuteTapped?.invoke(true) + } + } + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) if (!this::recipient.isInitialized) { return dismiss() } @@ -34,13 +49,19 @@ public class ConversationOptionsBottomSheet : BottomSheetDialogFragment() { detailsTextView.visibility = View.VISIBLE unblockTextView.visibility = if (recipient.isBlocked) View.VISIBLE else View.GONE blockTextView.visibility = if (recipient.isBlocked) View.GONE else View.VISIBLE - detailsTextView.setOnClickListener { onViewDetailsTapped?.invoke() } - blockTextView.setOnClickListener { onBlockTapped?.invoke() } - unblockTextView.setOnClickListener { onUnblockTapped?.invoke() } + detailsTextView.setOnClickListener(this) + blockTextView.setOnClickListener(this) + unblockTextView.setOnClickListener(this) } else { detailsTextView.visibility = View.GONE } - deleteTextView.setOnClickListener { onDeleteTapped?.invoke() } + unMuteNotificationsTextView.isVisible = recipient.isMuted && !recipient.isLocalNumber + muteNotificationsTextView.isVisible = !recipient.isMuted && !recipient.isLocalNumber + unMuteNotificationsTextView.setOnClickListener(this) + muteNotificationsTextView.setOnClickListener(this) + notificationsTextView.isVisible = recipient.isGroupRecipient + notificationsTextView.setOnClickListener(this) + deleteTextView.setOnClickListener(this) } override fun onStart() { diff --git a/app/src/main/java/org/thoughtcrime/securesms/home/HomeActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/home/HomeActivity.kt index 6c6fd8e1ed..6d42d80de8 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/home/HomeActivity.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/home/HomeActivity.kt @@ -35,8 +35,10 @@ import org.session.libsession.utilities.Util import org.session.libsignal.utilities.ThreadUtils import org.session.libsignal.utilities.toHexString import org.thoughtcrime.securesms.ApplicationContext +import org.thoughtcrime.securesms.MuteDialog import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity import org.thoughtcrime.securesms.conversation.v2.ConversationActivityV2 +import org.thoughtcrime.securesms.conversation.v2.utilities.NotificationUtils import org.thoughtcrime.securesms.crypto.IdentityKeyUtil import org.thoughtcrime.securesms.database.DatabaseFactory import org.thoughtcrime.securesms.database.model.ThreadRecord @@ -44,14 +46,12 @@ import org.thoughtcrime.securesms.dms.CreatePrivateChatActivity import org.thoughtcrime.securesms.groups.CreateClosedGroupActivity import org.thoughtcrime.securesms.groups.JoinPublicChatActivity import org.thoughtcrime.securesms.groups.OpenGroupManager -import org.thoughtcrime.securesms.util.ConfigurationMessageUtilities -import org.thoughtcrime.securesms.util.* -import org.thoughtcrime.securesms.onboarding.SeedReminderViewDelegate import org.thoughtcrime.securesms.mms.GlideApp import org.thoughtcrime.securesms.mms.GlideRequests import org.thoughtcrime.securesms.onboarding.SeedActivity +import org.thoughtcrime.securesms.onboarding.SeedReminderViewDelegate import org.thoughtcrime.securesms.preferences.SettingsActivity -import org.thoughtcrime.securesms.util.IP2Country +import org.thoughtcrime.securesms.util.* import java.io.IOException import java.util.* @@ -257,6 +257,16 @@ class HomeActivity : PassphraseRequiredActionBarActivity(), ConversationClickLis bottomSheet.dismiss() deleteConversation(thread) } + bottomSheet.onSetMuteTapped = { muted -> + bottomSheet.dismiss() + setConversationMuted(thread, muted) + } + bottomSheet.onNotificationTapped = { + bottomSheet.dismiss() + NotificationUtils.showNotifyDialog(this, thread.recipient) { notifyType -> + setNotifyType(thread, notifyType) + } + } bottomSheet.show(supportFragmentManager, bottomSheet.tag) } @@ -292,6 +302,35 @@ class HomeActivity : PassphraseRequiredActionBarActivity(), ConversationClickLis }.show() } + private fun setConversationMuted(thread: ThreadRecord, isMuted: Boolean) { + if (!isMuted) { + ThreadUtils.queue { + DatabaseFactory.getRecipientDatabase(this).setMuted(thread.recipient, 0) + Util.runOnMain { + recyclerView.adapter!!.notifyDataSetChanged() + } + } + } else { + MuteDialog.show(this) { until: Long -> + ThreadUtils.queue { + DatabaseFactory.getRecipientDatabase(this).setMuted(thread.recipient, until) + Util.runOnMain { + recyclerView.adapter!!.notifyDataSetChanged() + } + } + } + } + } + + private fun setNotifyType(thread: ThreadRecord, newNotifyType: Int) { + ThreadUtils.queue { + DatabaseFactory.getRecipientDatabase(this).setNotifyType(thread.recipient, newNotifyType) + Util.runOnMain { + recyclerView.adapter!!.notifyDataSetChanged() + } + } + } + private fun deleteConversation(thread: ThreadRecord) { val threadID = thread.threadId val recipient = thread.recipient diff --git a/app/src/main/java/org/thoughtcrime/securesms/notifications/DefaultMessageNotifier.java b/app/src/main/java/org/thoughtcrime/securesms/notifications/DefaultMessageNotifier.java index 33f25c96b4..6e0fbbd183 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/notifications/DefaultMessageNotifier.java +++ b/app/src/main/java/org/thoughtcrime/securesms/notifications/DefaultMessageNotifier.java @@ -41,26 +41,26 @@ import androidx.core.app.NotificationManagerCompat; import org.session.libsession.messaging.sending_receiving.notifications.MessageNotifier; import org.session.libsession.utilities.Contact; -import org.session.libsession.utilities.recipients.Recipient; import org.session.libsession.utilities.ServiceUtil; import org.session.libsession.utilities.TextSecurePreferences; -import org.session.libsignal.utilities.Util; +import org.session.libsession.utilities.recipients.Recipient; import org.session.libsignal.utilities.Log; +import org.session.libsignal.utilities.Util; import org.thoughtcrime.securesms.ApplicationContext; import org.thoughtcrime.securesms.contactshare.ContactUtil; - import org.thoughtcrime.securesms.conversation.v2.ConversationActivityV2; +import org.thoughtcrime.securesms.conversation.v2.utilities.MentionUtilities; import org.thoughtcrime.securesms.database.DatabaseFactory; import org.thoughtcrime.securesms.database.MessagingDatabase.MarkedMessageInfo; import org.thoughtcrime.securesms.database.MmsSmsDatabase; +import org.thoughtcrime.securesms.database.RecipientDatabase; import org.thoughtcrime.securesms.database.ThreadDatabase; import org.thoughtcrime.securesms.database.model.MediaMmsMessageRecord; import org.thoughtcrime.securesms.database.model.MessageRecord; import org.thoughtcrime.securesms.database.model.MmsMessageRecord; -import org.thoughtcrime.securesms.util.SessionMetaProtocol; -import org.thoughtcrime.securesms.conversation.v2.utilities.MentionUtilities; import org.thoughtcrime.securesms.mms.SlideDeck; import org.thoughtcrime.securesms.service.KeyCachingService; +import org.thoughtcrime.securesms.util.SessionMetaProtocol; import org.thoughtcrime.securesms.util.SpanUtil; import java.util.HashSet; @@ -493,7 +493,16 @@ public class DefaultMessageNotifier implements MessageNotifier { } if (threadRecipients == null || !threadRecipients.isMuted()) { - notificationState.addNotification(new NotificationItem(id, mms, recipient, conversationRecipient, threadRecipients, threadId, body, timestamp, slideDeck)); + if (threadRecipients != null && threadRecipients.notifyType == RecipientDatabase.NOTIFY_TYPE_MENTIONS) { + // check if mentioned here + if (body.toString().contains("@"+TextSecurePreferences.getLocalNumber(context))) { + notificationState.addNotification(new NotificationItem(id, mms, recipient, conversationRecipient, threadRecipients, threadId, body, timestamp, slideDeck)); + } + } else if (threadRecipients != null && threadRecipients.notifyType == RecipientDatabase.NOTIFY_TYPE_NONE) { + // do nothing, no notifications + } else { + notificationState.addNotification(new NotificationItem(id, mms, recipient, conversationRecipient, threadRecipients, threadId, body, timestamp, slideDeck)); + } } } diff --git a/app/src/main/res/drawable/ic_outline_notification_important_24.xml b/app/src/main/res/drawable/ic_outline_notification_important_24.xml new file mode 100644 index 0000000000..5a4d7814d4 --- /dev/null +++ b/app/src/main/res/drawable/ic_outline_notification_important_24.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_outline_notifications_active_24.xml b/app/src/main/res/drawable/ic_outline_notifications_active_24.xml new file mode 100644 index 0000000000..0a327617e4 --- /dev/null +++ b/app/src/main/res/drawable/ic_outline_notifications_active_24.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/layout/fragment_conversation_bottom_sheet.xml b/app/src/main/res/layout/fragment_conversation_bottom_sheet.xml index 4cd4708573..ad1044a539 100644 --- a/app/src/main/res/layout/fragment_conversation_bottom_sheet.xml +++ b/app/src/main/res/layout/fragment_conversation_bottom_sheet.xml @@ -32,6 +32,33 @@ android:visibility="gone" tools:visibility="visible" /> + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/menu/menu_conversation_open_group.xml b/app/src/main/res/menu/menu_conversation_open_group.xml index 6ff025aadb..3a022a8384 100644 --- a/app/src/main/res/menu/menu_conversation_open_group.xml +++ b/app/src/main/res/menu/menu_conversation_open_group.xml @@ -6,4 +6,8 @@ android:title="@string/ConversationActivity_invite_to_open_group" android:id="@+id/menu_invite_to_open_group" /> + + \ No newline at end of file diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml index 172aefd74b..1ab8459684 100644 --- a/app/src/main/res/values/arrays.xml +++ b/app/src/main/res/values/arrays.xml @@ -187,7 +187,7 @@ @string/arrays__mute_for_two_hours @string/arrays__mute_for_one_day @string/arrays__mute_for_seven_days - @string/arrays__mute_for_one_year + @string/arrays__mute_forever @@ -244,5 +244,10 @@ 1 2 + + @string/notify_type_all + @string/notify_type_mentions + @string/notify_type_none + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index db2edb6196..ac6ad0b8f4 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -247,6 +247,7 @@ Unblock this contact? You will once again be able to receive messages and calls from this contact. Unblock + Notification Settings Image @@ -481,6 +482,7 @@ Mute for 1 day Mute for 7 days Mute for 1 year + Mute forever Settings default Enabled @@ -888,4 +890,7 @@ Warning This is your recovery phrase. If you send it to someone they\'ll have full access to your account. Send + All + Mentions + None diff --git a/libsession/src/main/java/org/session/libsession/utilities/recipients/Recipient.java b/libsession/src/main/java/org/session/libsession/utilities/recipients/Recipient.java index 3903908f3f..5b31ded3c5 100644 --- a/libsession/src/main/java/org/session/libsession/utilities/recipients/Recipient.java +++ b/libsession/src/main/java/org/session/libsession/utilities/recipients/Recipient.java @@ -26,29 +26,28 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import com.annimon.stream.function.Consumer; -import com.esotericsoftware.kryo.util.Null; import org.greenrobot.eventbus.EventBus; -import org.session.libsession.database.StorageProtocol; -import org.session.libsession.messaging.MessagingModuleConfiguration; -import org.session.libsession.avatars.TransparentContactPhoto; -import org.session.libsession.messaging.contacts.Contact; -import org.session.libsession.utilities.Address; -import org.session.libsession.utilities.GroupRecord; -import org.session.libsession.utilities.recipients.RecipientProvider.RecipientDetails; -import org.session.libsession.utilities.TextSecurePreferences; -import org.session.libsession.utilities.Util; -import org.session.libsession.utilities.MaterialColor; -import org.session.libsignal.utilities.Log; -import org.session.libsignal.utilities.guava.Optional; import org.session.libsession.avatars.ContactColors; import org.session.libsession.avatars.ContactPhoto; import org.session.libsession.avatars.GroupRecordContactPhoto; import org.session.libsession.avatars.ProfileContactPhoto; import org.session.libsession.avatars.SystemContactPhoto; -import org.session.libsession.utilities.ProfilePictureModifiedEvent; +import org.session.libsession.avatars.TransparentContactPhoto; +import org.session.libsession.database.StorageProtocol; +import org.session.libsession.messaging.MessagingModuleConfiguration; +import org.session.libsession.messaging.contacts.Contact; +import org.session.libsession.utilities.Address; import org.session.libsession.utilities.FutureTaskListener; +import org.session.libsession.utilities.GroupRecord; import org.session.libsession.utilities.ListenableFutureTask; +import org.session.libsession.utilities.MaterialColor; +import org.session.libsession.utilities.ProfilePictureModifiedEvent; +import org.session.libsession.utilities.TextSecurePreferences; +import org.session.libsession.utilities.Util; +import org.session.libsession.utilities.recipients.RecipientProvider.RecipientDetails; +import org.session.libsignal.utilities.Log; +import org.session.libsignal.utilities.guava.Optional; import java.util.Collections; import java.util.HashSet; @@ -80,6 +79,7 @@ public class Recipient implements RecipientModifiedListener { private @Nullable Uri messageRingtone = null; private @Nullable Uri callRingtone = null; public long mutedUntil = 0; + public int notifyType = 0; private boolean blocked = false; private VibrateState messageVibrate = VibrateState.DEFAULT; private VibrateState callVibrate = VibrateState.DEFAULT; @@ -249,6 +249,7 @@ public class Recipient implements RecipientModifiedListener { this.messageRingtone = details.messageRingtone; this.callRingtone = details.callRingtone; this.mutedUntil = details.mutedUntil; + this.notifyType = details.notifyType; this.blocked = details.blocked; this.messageVibrate = details.messageVibrateState; this.callVibrate = details.callVibrateState; @@ -547,6 +548,14 @@ public class Recipient implements RecipientModifiedListener { notifyListeners(); } + public void setNotifyType(int notifyType) { + synchronized (this) { + this.notifyType = notifyType; + } + + notifyListeners(); + } + public synchronized boolean isBlocked() { return blocked; } @@ -769,6 +778,7 @@ public class Recipient implements RecipientModifiedListener { public static class RecipientSettings { private final boolean blocked; private final long muteUntil; + private final int notifyType; private final VibrateState messageVibrateState; private final VibrateState callVibrateState; private final Uri messageRingtone; @@ -790,6 +800,7 @@ public class Recipient implements RecipientModifiedListener { private final boolean forceSmsSelection; public RecipientSettings(boolean blocked, long muteUntil, + int notifyType, @NonNull VibrateState messageVibrateState, @NonNull VibrateState callVibrateState, @Nullable Uri messageRingtone, @@ -812,6 +823,7 @@ public class Recipient implements RecipientModifiedListener { { this.blocked = blocked; this.muteUntil = muteUntil; + this.notifyType = notifyType; this.messageVibrateState = messageVibrateState; this.callVibrateState = callVibrateState; this.messageRingtone = messageRingtone; @@ -845,6 +857,10 @@ public class Recipient implements RecipientModifiedListener { return muteUntil; } + public int getNotifyType() { + return notifyType; + } + public @NonNull VibrateState getMessageVibrateState() { return messageVibrateState; } diff --git a/libsession/src/main/java/org/session/libsession/utilities/recipients/RecipientProvider.java b/libsession/src/main/java/org/session/libsession/utilities/recipients/RecipientProvider.java index 8bbabae97a..f87906e4f9 100644 --- a/libsession/src/main/java/org/session/libsession/utilities/recipients/RecipientProvider.java +++ b/libsession/src/main/java/org/session/libsession/utilities/recipients/RecipientProvider.java @@ -23,19 +23,20 @@ import android.text.TextUtils; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import org.session.libsession.R; import org.session.libsession.messaging.MessagingModuleConfiguration; -import org.session.libsignal.utilities.guava.Optional; -import org.session.libsession.utilities.MaterialColor; import org.session.libsession.utilities.Address; import org.session.libsession.utilities.GroupRecord; +import org.session.libsession.utilities.ListenableFutureTask; +import org.session.libsession.utilities.MaterialColor; +import org.session.libsession.utilities.SoftHashMap; +import org.session.libsession.utilities.TextSecurePreferences; +import org.session.libsession.utilities.Util; import org.session.libsession.utilities.recipients.Recipient.RecipientSettings; import org.session.libsession.utilities.recipients.Recipient.RegisteredState; import org.session.libsession.utilities.recipients.Recipient.UnidentifiedAccessMode; import org.session.libsession.utilities.recipients.Recipient.VibrateState; -import org.session.libsession.utilities.ListenableFutureTask; -import org.session.libsession.utilities.SoftHashMap; -import org.session.libsession.utilities.TextSecurePreferences; -import org.session.libsession.utilities.Util; +import org.session.libsignal.utilities.guava.Optional; import java.util.HashMap; import java.util.LinkedList; @@ -44,8 +45,6 @@ import java.util.Map; import java.util.concurrent.Callable; import java.util.concurrent.ExecutorService; -import org.session.libsession.R; - class RecipientProvider { @SuppressWarnings("unused") @@ -168,6 +167,7 @@ class RecipientProvider { @Nullable final Uri messageRingtone; @Nullable final Uri callRingtone; final long mutedUntil; + final int notifyType; @Nullable final VibrateState messageVibrateState; @Nullable final VibrateState callVibrateState; final boolean blocked; @@ -197,6 +197,7 @@ class RecipientProvider { this.messageRingtone = settings != null ? settings.getMessageRingtone() : null; this.callRingtone = settings != null ? settings.getCallRingtone() : null; this.mutedUntil = settings != null ? settings.getMuteUntil() : 0; + this.notifyType = settings != null ? settings.getNotifyType() : 0; this.messageVibrateState = settings != null ? settings.getMessageVibrateState() : null; this.callVibrateState = settings != null ? settings.getCallVibrateState() : null; this.blocked = settings != null && settings.isBlocked();