mirror of
https://github.com/oxen-io/session-android.git
synced 2025-12-09 08:21:48 +00:00
Merge pull request #675 from hjubb/notification_control
Fine-Grained Notification controls
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -24,7 +24,6 @@ import android.widget.Toast
|
||||
import androidx.annotation.DimenRes
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.core.view.children
|
||||
import androidx.core.view.get
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.lifecycle.Observer
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
@@ -53,17 +52,13 @@ import org.session.libsession.messaging.mentions.MentionsManager
|
||||
import org.session.libsession.messaging.messages.control.DataExtractionNotification
|
||||
import org.session.libsession.messaging.messages.signal.OutgoingMediaMessage
|
||||
import org.session.libsession.messaging.messages.signal.OutgoingTextMessage
|
||||
import org.session.libsession.messaging.messages.visible.LinkPreview.Companion.from
|
||||
import org.session.libsession.messaging.messages.visible.OpenGroupInvitation
|
||||
import org.session.libsession.messaging.messages.visible.Quote.Companion.from
|
||||
import org.session.libsession.messaging.messages.visible.VisibleMessage
|
||||
import org.session.libsession.messaging.open_groups.OpenGroupAPIV2
|
||||
import org.session.libsession.messaging.sending_receiving.MessageSender
|
||||
import org.session.libsession.messaging.sending_receiving.attachments.Attachment
|
||||
import org.session.libsession.messaging.sending_receiving.link_preview.LinkPreview
|
||||
import org.session.libsession.messaging.sending_receiving.quotes.QuoteModel
|
||||
import org.session.libsession.messaging.utilities.UpdateMessageData
|
||||
import org.session.libsession.messaging.utilities.UpdateMessageData.Companion.fromJSON
|
||||
import org.session.libsession.utilities.Address
|
||||
import org.session.libsession.utilities.Address.Companion.fromSerialized
|
||||
import org.session.libsession.utilities.MediaTypes
|
||||
@@ -116,6 +111,9 @@ import org.thoughtcrime.securesms.permissions.Permissions
|
||||
import org.thoughtcrime.securesms.util.*
|
||||
import java.util.*
|
||||
import java.util.concurrent.ExecutionException
|
||||
import kotlin.collections.component1
|
||||
import kotlin.collections.component2
|
||||
import kotlin.collections.set
|
||||
import kotlin.math.*
|
||||
|
||||
// Some things that seemingly belong to the input bar (e.g. the voice message recording UI) are actually
|
||||
@@ -502,7 +500,7 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
|
||||
} else {
|
||||
MarkReadReceiver.process(this, messages)
|
||||
}
|
||||
ApplicationContext.getInstance(this).messageNotifier.updateNotification(this)
|
||||
ApplicationContext.getInstance(this).messageNotifier.updateNotification(this, threadID)
|
||||
}
|
||||
|
||||
override fun inputBarHeightChanged(newValue: Int) {
|
||||
@@ -720,7 +718,11 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
|
||||
muteIconImageView.isVisible = thread.isMuted
|
||||
conversationSubtitleView.isVisible = true
|
||||
if (thread.isMuted) {
|
||||
conversationSubtitleView.text = getString(R.string.ConversationActivity_muted_until_date, DateUtils.getFormattedDateTime(thread.mutedUntil, "EEE, MMM d, yyyy HH:mm", Locale.getDefault()))
|
||||
if (thread.mutedUntil != Long.MAX_VALUE) {
|
||||
conversationSubtitleView.text = getString(R.string.ConversationActivity_muted_until_date, DateUtils.getFormattedDateTime(thread.mutedUntil, "EEE, MMM d, yyyy HH:mm", Locale.getDefault()))
|
||||
} else {
|
||||
conversationSubtitleView.text = getString(R.string.ConversationActivity_muted_forever)
|
||||
}
|
||||
} else if (thread.isGroupRecipient) {
|
||||
val openGroup = DatabaseFactory.getLokiThreadDatabase(this).getOpenGroupChat(threadID)
|
||||
if (openGroup != null) {
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
@@ -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<String> 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);
|
||||
|
||||
|
||||
@@ -30,18 +30,18 @@ import com.annimon.stream.Stream;
|
||||
|
||||
import net.sqlcipher.database.SQLiteDatabase;
|
||||
|
||||
import org.session.libsession.utilities.DistributionTypes;
|
||||
import org.session.libsession.utilities.Contact;
|
||||
import org.session.libsession.utilities.Address;
|
||||
import org.session.libsession.utilities.GroupRecord;
|
||||
import org.session.libsession.utilities.recipients.Recipient;
|
||||
import org.session.libsession.utilities.recipients.Recipient.RecipientSettings;
|
||||
import org.session.libsession.utilities.Contact;
|
||||
import org.session.libsession.utilities.DelimiterUtil;
|
||||
import org.session.libsession.utilities.DistributionTypes;
|
||||
import org.session.libsession.utilities.GroupRecord;
|
||||
import org.session.libsession.utilities.TextSecurePreferences;
|
||||
import org.session.libsession.utilities.Util;
|
||||
import org.session.libsession.utilities.recipients.Recipient;
|
||||
import org.session.libsession.utilities.recipients.Recipient.RecipientSettings;
|
||||
import org.session.libsignal.utilities.Log;
|
||||
import org.session.libsignal.utilities.Pair;
|
||||
import org.session.libsignal.utilities.guava.Optional;
|
||||
import org.session.libsignal.utilities.Log;
|
||||
import org.thoughtcrime.securesms.contactshare.ContactUtil;
|
||||
import org.thoughtcrime.securesms.database.MessagingDatabase.MarkedMessageInfo;
|
||||
import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper;
|
||||
@@ -49,9 +49,9 @@ 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.database.model.ThreadRecord;
|
||||
import org.thoughtcrime.securesms.util.SessionMetaProtocol;
|
||||
import org.thoughtcrime.securesms.mms.Slide;
|
||||
import org.thoughtcrime.securesms.mms.SlideDeck;
|
||||
import org.thoughtcrime.securesms.util.SessionMetaProtocol;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.util.HashMap;
|
||||
@@ -651,7 +651,7 @@ public class ThreadDatabase extends Database {
|
||||
groupRecord = Optional.absent();
|
||||
}
|
||||
|
||||
Recipient recipient = Recipient.from(context, address, settings, groupRecord, true);
|
||||
Recipient recipient = Recipient.from(context, address, settings, groupRecord, false);
|
||||
String body = cursor.getString(cursor.getColumnIndexOrThrow(ThreadDatabase.SNIPPET));
|
||||
long date = cursor.getLong(cursor.getColumnIndexOrThrow(ThreadDatabase.DATE));
|
||||
long count = cursor.getLong(cursor.getColumnIndexOrThrow(ThreadDatabase.MESSAGE_COUNT));
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -14,9 +14,10 @@ import androidx.recyclerview.widget.RecyclerView
|
||||
import kotlinx.android.synthetic.main.view_conversation.view.*
|
||||
import network.loki.messenger.R
|
||||
import org.session.libsession.utilities.recipients.Recipient
|
||||
import org.thoughtcrime.securesms.database.model.ThreadRecord
|
||||
import org.thoughtcrime.securesms.conversation.v2.utilities.MentionManagerUtilities.populateUserPublicKeyCacheIfNeeded
|
||||
import org.thoughtcrime.securesms.conversation.v2.utilities.MentionUtilities.highlightMentions
|
||||
import org.thoughtcrime.securesms.database.RecipientDatabase
|
||||
import org.thoughtcrime.securesms.database.model.ThreadRecord
|
||||
import org.thoughtcrime.securesms.mms.GlideRequests
|
||||
import org.thoughtcrime.securesms.util.DateUtils
|
||||
import java.util.*
|
||||
@@ -59,7 +60,14 @@ class ConversationView : LinearLayout {
|
||||
val senderDisplayName = getUserDisplayName(thread.recipient) ?: thread.recipient.address.toString()
|
||||
conversationViewDisplayNameTextView.text = senderDisplayName
|
||||
timestampTextView.text = DateUtils.getDisplayFormattedTimeSpanString(context, Locale.getDefault(), thread.date)
|
||||
muteIndicatorImageView.visibility = if (thread.recipient.isMuted) VISIBLE else GONE
|
||||
val recipient = thread.recipient
|
||||
muteIndicatorImageView.isVisible = recipient.isMuted || recipient.notifyType != RecipientDatabase.NOTIFY_TYPE_ALL
|
||||
val drawableRes = if (recipient.isMuted || recipient.notifyType == RecipientDatabase.NOTIFY_TYPE_NONE) {
|
||||
R.drawable.ic_outline_notifications_off_24
|
||||
} else {
|
||||
R.drawable.ic_notifications_mentions
|
||||
}
|
||||
muteIndicatorImageView.setImageResource(drawableRes)
|
||||
val rawSnippet = thread.getDisplayBody(context)
|
||||
val snippet = highlightMentions(rawSnippet, thread.threadId, context)
|
||||
snippetTextView.text = snippet
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -4,18 +4,21 @@ import android.app.Notification;
|
||||
import android.content.Context;
|
||||
import android.graphics.Color;
|
||||
import android.net.Uri;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.app.NotificationCompat;
|
||||
import android.os.Bundle;
|
||||
import android.text.SpannableStringBuilder;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import network.loki.messenger.R;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.app.NotificationCompat;
|
||||
|
||||
import org.session.libsession.utilities.NotificationPrivacyPreference;
|
||||
import org.session.libsession.utilities.recipients.Recipient;
|
||||
import org.session.libsession.utilities.recipients.Recipient.*;
|
||||
import org.session.libsession.utilities.TextSecurePreferences;
|
||||
import org.session.libsession.utilities.Util;
|
||||
import org.session.libsession.utilities.recipients.Recipient;
|
||||
import org.session.libsession.utilities.recipients.Recipient.VibrateState;
|
||||
|
||||
import network.loki.messenger.R;
|
||||
|
||||
public abstract class AbstractNotificationBuilder extends NotificationCompat.Builder {
|
||||
|
||||
@@ -26,10 +29,11 @@ public abstract class AbstractNotificationBuilder extends NotificationCompat.Bui
|
||||
|
||||
protected Context context;
|
||||
protected NotificationPrivacyPreference privacy;
|
||||
protected final Bundle extras;
|
||||
|
||||
public AbstractNotificationBuilder(Context context, NotificationPrivacyPreference privacy) {
|
||||
super(context);
|
||||
|
||||
extras = new Bundle();
|
||||
this.context = context;
|
||||
this.privacy = privacy;
|
||||
|
||||
@@ -97,4 +101,10 @@ public abstract class AbstractNotificationBuilder extends NotificationCompat.Bui
|
||||
return text.length() <= MAX_DISPLAY_LENGTH ? text
|
||||
: text.subSequence(0, MAX_DISPLAY_LENGTH);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Notification build() {
|
||||
addExtras(extras);
|
||||
return super.build();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
@@ -87,6 +87,7 @@ public class DefaultMessageNotifier implements MessageNotifier {
|
||||
private static final String TAG = DefaultMessageNotifier.class.getSimpleName();
|
||||
|
||||
public static final String EXTRA_REMOTE_REPLY = "extra_remote_reply";
|
||||
public static final String LATEST_MESSAGE_ID_TAG = "extra_latest_message_id";
|
||||
|
||||
private static final int FOREGROUND_ID = 313399;
|
||||
private static final int SUMMARY_NOTIFICATION_ID = 1338;
|
||||
@@ -272,16 +273,9 @@ public class DefaultMessageNotifier implements MessageNotifier {
|
||||
lastAudibleNotification = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
if (notificationState.hasMultipleThreads()) {
|
||||
if (Build.VERSION.SDK_INT >= 23) {
|
||||
for (long threadId : notificationState.getThreads()) {
|
||||
sendSingleThreadNotification(context, new NotificationState(notificationState.getNotificationsForThread(threadId)), false, true);
|
||||
}
|
||||
}
|
||||
|
||||
sendMultipleThreadNotification(context, notificationState, signal);
|
||||
} else {
|
||||
sendSingleThreadNotification(context, notificationState, signal, false);
|
||||
boolean hasMultipleThreads = notificationState.hasMultipleThreads();
|
||||
for (long threadId : notificationState.getThreads()) {
|
||||
sendSingleThreadNotification(context, new NotificationState(notificationState.getNotificationsForThread(threadId)), signal, hasMultipleThreads);
|
||||
}
|
||||
|
||||
cancelOrphanedNotifications(context, notificationState);
|
||||
@@ -312,7 +306,20 @@ public class DefaultMessageNotifier implements MessageNotifier {
|
||||
List<NotificationItem> notifications = notificationState.getNotifications();
|
||||
Recipient recipient = notifications.get(0).getRecipient();
|
||||
int notificationId = (int) (SUMMARY_NOTIFICATION_ID + (bundled ? notifications.get(0).getThreadId() : 0));
|
||||
String messageIdTag = String.valueOf(notifications.get(0).getId());
|
||||
|
||||
NotificationManager notificationManager = ServiceUtil.getNotificationManager(context);
|
||||
for (StatusBarNotification notification: notificationManager.getActiveNotifications()) {
|
||||
|
||||
if (messageIdTag.equals(notification.getNotification().extras.getString(LATEST_MESSAGE_ID_TAG))) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
long timestamp = notifications.get(0).getTimestamp();
|
||||
if (timestamp != 0) builder.setWhen(timestamp);
|
||||
|
||||
builder.putStringExtra(LATEST_MESSAGE_ID_TAG, messageIdTag);
|
||||
|
||||
builder.setThread(notifications.get(0).getRecipient());
|
||||
builder.setMessageCount(notificationState.getMessageCount());
|
||||
@@ -325,11 +332,6 @@ public class DefaultMessageNotifier implements MessageNotifier {
|
||||
builder.setGroupAlertBehavior(NotificationCompat.GROUP_ALERT_SUMMARY);
|
||||
builder.setAutoCancel(true);
|
||||
|
||||
long timestamp = notifications.get(0).getTimestamp();
|
||||
if (timestamp != 0) builder.setWhen(timestamp);
|
||||
|
||||
long threadID = notifications.get(0).getThreadId();
|
||||
|
||||
ReplyMethod replyMethod = ReplyMethod.forRecipient(context, recipient);
|
||||
|
||||
boolean canReply = SessionMetaProtocol.canUserReplyToNotification(recipient);
|
||||
@@ -493,7 +495,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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,33 +15,38 @@ import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.text.SpannableStringBuilder;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.core.app.NotificationCompat;
|
||||
import androidx.core.app.NotificationCompat.Action;
|
||||
import androidx.core.app.RemoteInput;
|
||||
|
||||
import com.bumptech.glide.load.engine.DiskCacheStrategy;
|
||||
|
||||
import org.session.libsession.avatars.ContactColors;
|
||||
import org.session.libsession.avatars.ContactPhoto;
|
||||
import org.session.libsession.avatars.GeneratedContactPhoto;
|
||||
import org.session.libsession.messaging.contacts.Contact;
|
||||
import org.session.libsession.utilities.NotificationPrivacyPreference;
|
||||
import org.session.libsession.utilities.TextSecurePreferences;
|
||||
import org.session.libsession.utilities.Util;
|
||||
import org.session.libsession.utilities.recipients.Recipient;
|
||||
import org.session.libsignal.utilities.Log;
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.database.SessionContactDatabase;
|
||||
import org.thoughtcrime.securesms.util.AvatarPlaceholderGenerator;
|
||||
import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader;
|
||||
import org.thoughtcrime.securesms.mms.GlideApp;
|
||||
import org.thoughtcrime.securesms.mms.Slide;
|
||||
import org.thoughtcrime.securesms.mms.SlideDeck;
|
||||
import org.session.libsession.utilities.NotificationPrivacyPreference;
|
||||
import org.session.libsession.utilities.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.util.AvatarPlaceholderGenerator;
|
||||
import org.thoughtcrime.securesms.util.BitmapUtil;
|
||||
import org.session.libsession.utilities.TextSecurePreferences;
|
||||
import org.session.libsession.utilities.Util;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
import network.loki.messenger.R;
|
||||
|
||||
public class SingleRecipientNotificationBuilder extends AbstractNotificationBuilder {
|
||||
@@ -58,6 +63,7 @@ public class SingleRecipientNotificationBuilder extends AbstractNotificationBuil
|
||||
{
|
||||
super(context, privacy);
|
||||
|
||||
|
||||
setSmallIcon(R.drawable.ic_notification);
|
||||
setColor(context.getResources().getColor(R.color.textsecure_primary));
|
||||
setCategory(NotificationCompat.CATEGORY_MESSAGE);
|
||||
@@ -198,6 +204,10 @@ public class SingleRecipientNotificationBuilder extends AbstractNotificationBuil
|
||||
return R.string.MessageNotifier_reply;
|
||||
}
|
||||
|
||||
public void putStringExtra(String key, String value) {
|
||||
extras.putString(key,value);
|
||||
}
|
||||
|
||||
public void addMessageBody(@NonNull Recipient threadRecipient,
|
||||
@NonNull Recipient individualRecipient,
|
||||
@Nullable CharSequence messageBody)
|
||||
|
||||
Reference in New Issue
Block a user