mirror of
https://github.com/oxen-io/session-android.git
synced 2024-11-25 02:55:23 +00:00
feat: add broken unreads everywhere
This commit is contained in:
parent
2f2ebe9451
commit
66fb6b30e9
@ -3,18 +3,31 @@ package org.thoughtcrime.securesms.conversation.v2
|
||||
import android.Manifest
|
||||
import android.animation.FloatEvaluator
|
||||
import android.animation.ValueAnimator
|
||||
import android.content.*
|
||||
import android.content.ClipData
|
||||
import android.content.ClipboardManager
|
||||
import android.content.Context
|
||||
import android.content.DialogInterface
|
||||
import android.content.Intent
|
||||
import android.content.res.Resources
|
||||
import android.database.Cursor
|
||||
import android.graphics.Rect
|
||||
import android.graphics.Typeface
|
||||
import android.net.Uri
|
||||
import android.os.*
|
||||
import android.os.AsyncTask
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.provider.MediaStore
|
||||
import android.text.TextUtils
|
||||
import android.util.Pair
|
||||
import android.util.TypedValue
|
||||
import android.view.*
|
||||
import android.view.ActionMode
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import android.view.MotionEvent
|
||||
import android.view.View
|
||||
import android.view.WindowManager
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.RelativeLayout
|
||||
import android.widget.Toast
|
||||
@ -57,8 +70,12 @@ 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.SessionId
|
||||
import org.session.libsession.utilities.*
|
||||
import org.session.libsession.utilities.Address
|
||||
import org.session.libsession.utilities.Address.Companion.fromSerialized
|
||||
import org.session.libsession.utilities.GroupUtil
|
||||
import org.session.libsession.utilities.MediaTypes
|
||||
import org.session.libsession.utilities.Stub
|
||||
import org.session.libsession.utilities.TextSecurePreferences
|
||||
import org.session.libsession.utilities.concurrent.SimpleTask
|
||||
import org.session.libsession.utilities.recipients.Recipient
|
||||
import org.session.libsession.utilities.recipients.RecipientModifiedListener
|
||||
@ -91,10 +108,25 @@ import org.thoughtcrime.securesms.conversation.v2.messages.VisibleMessageView
|
||||
import org.thoughtcrime.securesms.conversation.v2.messages.VisibleMessageViewDelegate
|
||||
import org.thoughtcrime.securesms.conversation.v2.search.SearchBottomBar
|
||||
import org.thoughtcrime.securesms.conversation.v2.search.SearchViewModel
|
||||
import org.thoughtcrime.securesms.conversation.v2.utilities.*
|
||||
import org.thoughtcrime.securesms.conversation.v2.utilities.AttachmentManager
|
||||
import org.thoughtcrime.securesms.conversation.v2.utilities.BaseDialog
|
||||
import org.thoughtcrime.securesms.conversation.v2.utilities.MentionManagerUtilities
|
||||
import org.thoughtcrime.securesms.conversation.v2.utilities.MentionUtilities
|
||||
import org.thoughtcrime.securesms.conversation.v2.utilities.ResendMessageUtilities
|
||||
import org.thoughtcrime.securesms.crypto.IdentityKeyUtil
|
||||
import org.thoughtcrime.securesms.crypto.MnemonicUtilities
|
||||
import org.thoughtcrime.securesms.database.*
|
||||
import org.thoughtcrime.securesms.database.GroupDatabase
|
||||
import org.thoughtcrime.securesms.database.LokiAPIDatabase
|
||||
import org.thoughtcrime.securesms.database.LokiMessageDatabase
|
||||
import org.thoughtcrime.securesms.database.LokiThreadDatabase
|
||||
import org.thoughtcrime.securesms.database.MmsDatabase
|
||||
import org.thoughtcrime.securesms.database.MmsSmsDatabase
|
||||
import org.thoughtcrime.securesms.database.ReactionDatabase
|
||||
import org.thoughtcrime.securesms.database.RecipientDatabase
|
||||
import org.thoughtcrime.securesms.database.SessionContactDatabase
|
||||
import org.thoughtcrime.securesms.database.SmsDatabase
|
||||
import org.thoughtcrime.securesms.database.Storage
|
||||
import org.thoughtcrime.securesms.database.ThreadDatabase
|
||||
import org.thoughtcrime.securesms.database.model.MessageId
|
||||
import org.thoughtcrime.securesms.database.model.MessageRecord
|
||||
import org.thoughtcrime.securesms.database.model.MmsMessageRecord
|
||||
@ -107,12 +139,25 @@ import org.thoughtcrime.securesms.linkpreview.LinkPreviewViewModel
|
||||
import org.thoughtcrime.securesms.linkpreview.LinkPreviewViewModel.LinkPreviewState
|
||||
import org.thoughtcrime.securesms.mediasend.Media
|
||||
import org.thoughtcrime.securesms.mediasend.MediaSendActivity
|
||||
import org.thoughtcrime.securesms.mms.*
|
||||
import org.thoughtcrime.securesms.mms.AudioSlide
|
||||
import org.thoughtcrime.securesms.mms.GifSlide
|
||||
import org.thoughtcrime.securesms.mms.GlideApp
|
||||
import org.thoughtcrime.securesms.mms.ImageSlide
|
||||
import org.thoughtcrime.securesms.mms.MediaConstraints
|
||||
import org.thoughtcrime.securesms.mms.Slide
|
||||
import org.thoughtcrime.securesms.mms.SlideDeck
|
||||
import org.thoughtcrime.securesms.mms.VideoSlide
|
||||
import org.thoughtcrime.securesms.permissions.Permissions
|
||||
import org.thoughtcrime.securesms.reactions.ReactionsDialogFragment
|
||||
import org.thoughtcrime.securesms.reactions.any.ReactWithAnyEmojiDialogFragment
|
||||
import org.thoughtcrime.securesms.util.*
|
||||
import java.util.*
|
||||
import org.thoughtcrime.securesms.util.ActivityDispatcher
|
||||
import org.thoughtcrime.securesms.util.ConfigurationMessageUtilities
|
||||
import org.thoughtcrime.securesms.util.DateUtils
|
||||
import org.thoughtcrime.securesms.util.MediaUtil
|
||||
import org.thoughtcrime.securesms.util.SaveAttachmentTask
|
||||
import org.thoughtcrime.securesms.util.push
|
||||
import org.thoughtcrime.securesms.util.toPx
|
||||
import java.util.Locale
|
||||
import java.util.concurrent.ExecutionException
|
||||
import java.util.concurrent.atomic.AtomicLong
|
||||
import java.util.concurrent.atomic.AtomicReference
|
||||
@ -363,10 +408,9 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
ApplicationContext.getInstance(this).messageNotifier.setVisibleThread(viewModel.threadId)
|
||||
val recipient = viewModel.recipient ?: return
|
||||
|
||||
lifecycleScope.launch(Dispatchers.IO) {
|
||||
threadDb.markAllAsRead(viewModel.threadId, recipient.isOpenGroupRecipient)
|
||||
storage.markConversationAsRead(viewModel.threadId, System.currentTimeMillis())
|
||||
}
|
||||
|
||||
contentResolver.registerContentObserver(
|
||||
|
@ -35,7 +35,7 @@ class ConfigDatabase(context: Context, helper: SQLCipherOpenHelper): Database(co
|
||||
|
||||
fun retrieveConfigAndHashes(variant: String, publicKey: String): Pair<ByteArray,List<String>>? {
|
||||
val db = readableDatabase
|
||||
val query = db.query(TABLE_NAME, arrayOf(DATA), VARIANT_AND_PUBKEY_WHERE, arrayOf(variant, publicKey),null, null, null)
|
||||
val query = db.query(TABLE_NAME, arrayOf(DATA, COMBINED_MESSAGE_HASHES), VARIANT_AND_PUBKEY_WHERE, arrayOf(variant, publicKey),null, null, null)
|
||||
return query?.use { cursor ->
|
||||
if (!cursor.moveToFirst()) return@use null
|
||||
val bytes = cursor.getBlobOrNull(cursor.getColumnIndex(DATA)) ?: return@use null
|
||||
|
@ -366,10 +366,7 @@ class MmsDatabase(context: Context, databaseHelper: SQLCipherOpenHelper) : Messa
|
||||
val attachmentDatabase = get(context).attachmentDatabase()
|
||||
queue(Runnable { attachmentDatabase.deleteAttachmentsForMessage(messageId) })
|
||||
val threadId = getThreadIdForMessage(messageId)
|
||||
if (!read) {
|
||||
val mentionChange = if (hasMention) { 1 } else { 0 }
|
||||
get(context).threadDatabase().decrementUnread(threadId, 1, mentionChange)
|
||||
}
|
||||
|
||||
updateMailboxBitmask(
|
||||
messageId,
|
||||
MmsSmsColumns.Types.BASE_TYPE_MASK,
|
||||
@ -634,7 +631,6 @@ class MmsDatabase(context: Context, databaseHelper: SQLCipherOpenHelper) : Messa
|
||||
contentLocation: String,
|
||||
threadId: Long, mailbox: Long,
|
||||
serverTimestamp: Long,
|
||||
runIncrement: Boolean,
|
||||
runThreadUpdate: Boolean
|
||||
): Optional<InsertResult> {
|
||||
var threadId = threadId
|
||||
@ -699,10 +695,6 @@ class MmsDatabase(context: Context, databaseHelper: SQLCipherOpenHelper) : Messa
|
||||
null,
|
||||
)
|
||||
if (!MmsSmsColumns.Types.isExpirationTimerUpdate(mailbox)) {
|
||||
if (runIncrement) {
|
||||
val mentionAmount = if (retrieved.hasMention()) { 1 } else { 0 }
|
||||
get(context).threadDatabase().incrementUnread(threadId, 1, mentionAmount)
|
||||
}
|
||||
if (runThreadUpdate) {
|
||||
get(context).threadDatabase().update(threadId, true)
|
||||
}
|
||||
@ -753,7 +745,6 @@ class MmsDatabase(context: Context, databaseHelper: SQLCipherOpenHelper) : Messa
|
||||
retrieved: IncomingMediaMessage,
|
||||
threadId: Long,
|
||||
serverTimestamp: Long = 0,
|
||||
runIncrement: Boolean,
|
||||
runThreadUpdate: Boolean
|
||||
): Optional<InsertResult> {
|
||||
var type = MmsSmsColumns.Types.BASE_INBOX_TYPE or MmsSmsColumns.Types.SECURE_MESSAGE_BIT
|
||||
@ -772,7 +763,7 @@ class MmsDatabase(context: Context, databaseHelper: SQLCipherOpenHelper) : Messa
|
||||
if (retrieved.isMessageRequestResponse) {
|
||||
type = type or MmsSmsColumns.Types.MESSAGE_REQUEST_RESPONSE_BIT
|
||||
}
|
||||
return insertMessageInbox(retrieved, "", threadId, type, serverTimestamp, runIncrement, runThreadUpdate)
|
||||
return insertMessageInbox(retrieved, "", threadId, type, serverTimestamp, runThreadUpdate)
|
||||
}
|
||||
|
||||
@JvmOverloads
|
||||
|
@ -218,10 +218,6 @@ public class SmsDatabase extends MessagingDatabase {
|
||||
contentValues.put(BODY, "");
|
||||
contentValues.put(HAS_MENTION, 0);
|
||||
database.update(TABLE_NAME, contentValues, ID_WHERE, new String[] {String.valueOf(messageId)});
|
||||
long threadId = getThreadIdForMessage(messageId);
|
||||
if (!read) {
|
||||
DatabaseComponent.get(context).threadDatabase().decrementUnread(threadId, 1, (hasMention ? 1 : 0));
|
||||
}
|
||||
updateTypeBitmask(messageId, Types.BASE_TYPE_MASK, Types.BASE_DELETED_TYPE);
|
||||
}
|
||||
|
||||
@ -394,7 +390,7 @@ public class SmsDatabase extends MessagingDatabase {
|
||||
return new Pair<>(messageId, threadId);
|
||||
}
|
||||
|
||||
protected Optional<InsertResult> insertMessageInbox(IncomingTextMessage message, long type, long serverTimestamp, boolean runIncrement, boolean runThreadUpdate) {
|
||||
protected Optional<InsertResult> insertMessageInbox(IncomingTextMessage message, long type, long serverTimestamp, boolean runThreadUpdate) {
|
||||
if (message.isSecureMessage()) {
|
||||
type |= Types.SECURE_MESSAGE_BIT;
|
||||
} else if (message.isGroup()) {
|
||||
@ -473,10 +469,6 @@ public class SmsDatabase extends MessagingDatabase {
|
||||
SQLiteDatabase db = databaseHelper.getWritableDatabase();
|
||||
long messageId = db.insert(TABLE_NAME, null, values);
|
||||
|
||||
if (unread && runIncrement) {
|
||||
DatabaseComponent.get(context).threadDatabase().incrementUnread(threadId, 1, (message.hasMention() ? 1 : 0));
|
||||
}
|
||||
|
||||
if (runThreadUpdate) {
|
||||
DatabaseComponent.get(context).threadDatabase().update(threadId, true);
|
||||
}
|
||||
@ -491,16 +483,16 @@ public class SmsDatabase extends MessagingDatabase {
|
||||
}
|
||||
}
|
||||
|
||||
public Optional<InsertResult> insertMessageInbox(IncomingTextMessage message, boolean runIncrement, boolean runThreadUpdate) {
|
||||
return insertMessageInbox(message, Types.BASE_INBOX_TYPE, 0, runIncrement, runThreadUpdate);
|
||||
public Optional<InsertResult> insertMessageInbox(IncomingTextMessage message, boolean runThreadUpdate) {
|
||||
return insertMessageInbox(message, Types.BASE_INBOX_TYPE, 0, runThreadUpdate);
|
||||
}
|
||||
|
||||
public Optional<InsertResult> insertCallMessage(IncomingTextMessage message) {
|
||||
return insertMessageInbox(message, 0, 0, true, true);
|
||||
return insertMessageInbox(message, 0, 0, true);
|
||||
}
|
||||
|
||||
public Optional<InsertResult> insertMessageInbox(IncomingTextMessage message, long serverTimestamp, boolean runIncrement, boolean runThreadUpdate) {
|
||||
return insertMessageInbox(message, Types.BASE_INBOX_TYPE, serverTimestamp, runIncrement, runThreadUpdate);
|
||||
public Optional<InsertResult> insertMessageInbox(IncomingTextMessage message, long serverTimestamp, boolean runThreadUpdate) {
|
||||
return insertMessageInbox(message, Types.BASE_INBOX_TYPE, serverTimestamp, runThreadUpdate);
|
||||
}
|
||||
|
||||
public Optional<InsertResult> insertMessageOutbox(long threadId, OutgoingTextMessage message, long serverTimestamp, boolean runThreadUpdate) {
|
||||
|
@ -121,14 +121,16 @@ class Storage(context: Context, helper: SQLCipherOpenHelper, private val configF
|
||||
return database.getAttachmentsForMessage(messageID)
|
||||
}
|
||||
|
||||
override fun markConversationAsRead(threadId: Long, updateLastSeen: Boolean) {
|
||||
override fun getLastSeen(threadId: Long): Long {
|
||||
val threadDb = DatabaseComponent.get(context).threadDatabase()
|
||||
threadDb.setRead(threadId, updateLastSeen)
|
||||
return threadDb.getLastSeenAndHasSent(threadId)?.first() ?: 0L
|
||||
}
|
||||
|
||||
override fun incrementUnread(threadId: Long, amount: Int, unreadMentionAmount: Int) {
|
||||
override fun markConversationAsRead(threadId: Long, lastSeenTime: Long) {
|
||||
val threadDb = DatabaseComponent.get(context).threadDatabase()
|
||||
threadDb.incrementUnread(threadId, amount, unreadMentionAmount)
|
||||
getRecipientForThread(threadId)?.let {
|
||||
threadDb.markAllAsRead(threadId, it.isGroupRecipient, lastSeenTime)
|
||||
}
|
||||
}
|
||||
|
||||
override fun updateThread(threadId: Long, unarchive: Boolean) {
|
||||
@ -142,7 +144,6 @@ class Storage(context: Context, helper: SQLCipherOpenHelper, private val configF
|
||||
groupPublicKey: String?,
|
||||
openGroupID: String?,
|
||||
attachments: List<Attachment>,
|
||||
runIncrement: Boolean,
|
||||
runThreadUpdate: Boolean): Long? {
|
||||
var messageID: Long? = null
|
||||
val senderAddress = fromSerialized(message.sender!!)
|
||||
@ -189,7 +190,7 @@ class Storage(context: Context, helper: SQLCipherOpenHelper, private val configF
|
||||
it.toSignalPointer()
|
||||
}
|
||||
val mediaMessage = IncomingMediaMessage.from(message, senderAddress, targetRecipient.expireMessages * 1000L, group, signalServiceAttachments, quote, linkPreviews)
|
||||
mmsDatabase.insertSecureDecryptedMessageInbox(mediaMessage, message.threadID ?: -1, message.receivedTimestamp ?: 0, runIncrement, runThreadUpdate)
|
||||
mmsDatabase.insertSecureDecryptedMessageInbox(mediaMessage, message.threadID ?: -1, message.receivedTimestamp ?: 0, runThreadUpdate)
|
||||
}
|
||||
if (insertResult.isPresent) {
|
||||
messageID = insertResult.get().messageId
|
||||
@ -206,7 +207,7 @@ class Storage(context: Context, helper: SQLCipherOpenHelper, private val configF
|
||||
val textMessage = if (isOpenGroupInvitation) IncomingTextMessage.fromOpenGroupInvitation(message.openGroupInvitation, senderAddress, message.sentTimestamp)
|
||||
else IncomingTextMessage.from(message, senderAddress, group, targetRecipient.expireMessages * 1000L)
|
||||
val encrypted = IncomingEncryptedMessage(textMessage, textMessage.messageBody)
|
||||
smsDatabase.insertMessageInbox(encrypted, message.receivedTimestamp ?: 0, runIncrement, runThreadUpdate)
|
||||
smsDatabase.insertMessageInbox(encrypted, message.receivedTimestamp ?: 0, runThreadUpdate)
|
||||
}
|
||||
insertResult.orNull()?.let { result ->
|
||||
messageID = result.messageId
|
||||
@ -344,6 +345,10 @@ class Storage(context: Context, helper: SQLCipherOpenHelper, private val configF
|
||||
}
|
||||
}
|
||||
Log.d("Loki-DBG", "Should update thread $threadId")
|
||||
if (threadId >= 0) {
|
||||
DatabaseComponent.get(context).threadDatabase()
|
||||
.setLastSeen(threadId, conversation.lastRead)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -578,7 +583,7 @@ class Storage(context: Context, helper: SQLCipherOpenHelper, private val configF
|
||||
val updateData = UpdateMessageData.buildGroupUpdate(type, name, members)?.toJSON()
|
||||
val infoMessage = IncomingGroupMessage(m, groupID, updateData, true)
|
||||
val smsDB = DatabaseComponent.get(context).smsDatabase()
|
||||
smsDB.insertMessageInbox(infoMessage, true, true)
|
||||
smsDB.insertMessageInbox(infoMessage, true)
|
||||
}
|
||||
|
||||
override fun insertOutgoingInfoMessage(context: Context, groupID: String, type: SignalServiceGroup.Type, name: String, members: Collection<String>, admins: Collection<String>, threadID: Long, sentTimestamp: Long) {
|
||||
@ -866,7 +871,7 @@ class Storage(context: Context, helper: SQLCipherOpenHelper, private val configF
|
||||
Optional.of(message)
|
||||
)
|
||||
|
||||
database.insertSecureDecryptedMessageInbox(mediaMessage, -1, runIncrement = true, runThreadUpdate = true)
|
||||
database.insertSecureDecryptedMessageInbox(mediaMessage, -1, runThreadUpdate = true)
|
||||
}
|
||||
|
||||
override fun insertMessageRequestResponse(response: MessageRequestResponse) {
|
||||
@ -959,7 +964,7 @@ class Storage(context: Context, helper: SQLCipherOpenHelper, private val configF
|
||||
Optional.absent(),
|
||||
Optional.absent()
|
||||
)
|
||||
mmsDb.insertSecureDecryptedMessageInbox(message, threadId, runIncrement = true, runThreadUpdate = true)
|
||||
mmsDb.insertSecureDecryptedMessageInbox(message, threadId, runThreadUpdate = true)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -35,6 +35,7 @@ import com.annimon.stream.Stream;
|
||||
import net.zetetic.database.sqlcipher.SQLiteDatabase;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.session.libsession.snode.SnodeAPI;
|
||||
import org.session.libsession.utilities.Address;
|
||||
import org.session.libsession.utilities.Contact;
|
||||
import org.session.libsession.utilities.DelimiterUtil;
|
||||
@ -101,6 +102,8 @@ public class ThreadDatabase extends Database {
|
||||
public static final String HAS_SENT = "has_sent";
|
||||
public static final String IS_PINNED = "is_pinned";
|
||||
|
||||
public static final String LAST_SEEN_TRIGGER = "thread_last_seen_trigger";
|
||||
|
||||
public static final String CREATE_TABLE = "CREATE TABLE " + TABLE_NAME + " (" +
|
||||
ID + " INTEGER PRIMARY KEY, " + DATE + " INTEGER DEFAULT 0, " +
|
||||
MESSAGE_COUNT + " INTEGER DEFAULT 0, " + ADDRESS + " TEXT, " + SNIPPET + " TEXT, " +
|
||||
@ -296,18 +299,17 @@ public class ThreadDatabase extends Database {
|
||||
}
|
||||
|
||||
public List<MarkedMessageInfo> setRead(long threadId, long lastReadTime) {
|
||||
|
||||
final List<MarkedMessageInfo> smsRecords = DatabaseComponent.get(context).smsDatabase().setMessagesRead(threadId, lastReadTime);
|
||||
final List<MarkedMessageInfo> mmsRecords = DatabaseComponent.get(context).mmsDatabase().setMessagesRead(threadId, lastReadTime);
|
||||
|
||||
ContentValues contentValues = new ContentValues(1);
|
||||
contentValues.put(READ, 1);
|
||||
contentValues.put(UNREAD_COUNT, 0);
|
||||
contentValues.put(UNREAD_MENTION_COUNT, 0);
|
||||
contentValues.put(LAST_SEEN, lastReadTime);
|
||||
|
||||
SQLiteDatabase db = databaseHelper.getWritableDatabase();
|
||||
db.update(TABLE_NAME, contentValues, ID_WHERE, new String[] {threadId+""});
|
||||
|
||||
final List<MarkedMessageInfo> smsRecords = DatabaseComponent.get(context).smsDatabase().setMessagesRead(threadId, lastReadTime);
|
||||
final List<MarkedMessageInfo> mmsRecords = DatabaseComponent.get(context).mmsDatabase().setMessagesRead(threadId, lastReadTime);
|
||||
|
||||
notifyConversationListListeners();
|
||||
|
||||
return new LinkedList<MarkedMessageInfo>() {{
|
||||
@ -340,30 +342,6 @@ public class ThreadDatabase extends Database {
|
||||
}};
|
||||
}
|
||||
|
||||
public void incrementUnread(long threadId, int amount, int unreadMentionAmount) {
|
||||
SQLiteDatabase db = databaseHelper.getWritableDatabase();
|
||||
db.execSQL("UPDATE " + TABLE_NAME + " SET " + READ + " = 0, " +
|
||||
UNREAD_COUNT + " = " + UNREAD_COUNT + " + ?, " +
|
||||
UNREAD_MENTION_COUNT + " = " + UNREAD_MENTION_COUNT + " + ? WHERE " + ID + " = ?",
|
||||
new String[] {
|
||||
String.valueOf(amount),
|
||||
String.valueOf(unreadMentionAmount),
|
||||
String.valueOf(threadId)
|
||||
});
|
||||
}
|
||||
|
||||
public void decrementUnread(long threadId, int amount, int unreadMentionAmount) {
|
||||
SQLiteDatabase db = databaseHelper.getWritableDatabase();
|
||||
db.execSQL("UPDATE " + TABLE_NAME + " SET " + READ + " = 0, " +
|
||||
UNREAD_COUNT + " = " + UNREAD_COUNT + " - ?, " +
|
||||
UNREAD_MENTION_COUNT + " = " + UNREAD_MENTION_COUNT + " - ? WHERE " + ID + " = ? AND " + UNREAD_COUNT + " > 0",
|
||||
new String[] {
|
||||
String.valueOf(amount),
|
||||
String.valueOf(unreadMentionAmount),
|
||||
String.valueOf(threadId)
|
||||
});
|
||||
}
|
||||
|
||||
public void setDistributionType(long threadId, int distributionType) {
|
||||
ContentValues contentValues = new ContentValues(1);
|
||||
contentValues.put(TYPE, distributionType);
|
||||
@ -541,13 +519,15 @@ public class ThreadDatabase extends Database {
|
||||
public void setLastSeen(long threadId, long timestamp) {
|
||||
SQLiteDatabase db = databaseHelper.getWritableDatabase();
|
||||
ContentValues contentValues = new ContentValues(1);
|
||||
if (timestamp == -1) {
|
||||
contentValues.put(LAST_SEEN, System.currentTimeMillis());
|
||||
} else {
|
||||
contentValues.put(LAST_SEEN, timestamp);
|
||||
}
|
||||
|
||||
long lastSeenTime = timestamp == -1 ? SnodeAPI.INSTANCE.getNowWithOffset() : timestamp;
|
||||
contentValues.put(LAST_SEEN, lastSeenTime);
|
||||
db.beginTransaction();
|
||||
db.update(TABLE_NAME, contentValues, ID_WHERE, new String[] {String.valueOf(threadId)});
|
||||
String countSubQuery = "SELECT COUNT(*) FROM "+SmsDatabase.TABLE_NAME+" AS s INNER JOIN "+TABLE_NAME+" AS t ON s.thread_id = t._id WHERE t._id = ? AND s."+SmsDatabase.DATE_SENT+" > t."+LAST_SEEN+"";
|
||||
String reflectUpdates = "UPDATE "+TABLE_NAME+" AS t SET "+UNREAD_COUNT+" = ("+countSubQuery+") WHERE t."+ID+" = ?";
|
||||
db.query(reflectUpdates, new String[]{threadId+"", threadId+""});
|
||||
db.setTransactionSuccessful();
|
||||
db.endTransaction();
|
||||
notifyConversationListListeners();
|
||||
}
|
||||
|
||||
@ -755,8 +735,8 @@ public class ThreadDatabase extends Database {
|
||||
notifyConversationListeners(threadId);
|
||||
}
|
||||
|
||||
public void markAllAsRead(long threadId, boolean isGroupRecipient) {
|
||||
List<MarkedMessageInfo> messages = setRead(threadId, true);
|
||||
public void markAllAsRead(long threadId, boolean isGroupRecipient, long lastSeenTime) {
|
||||
List<MarkedMessageInfo> messages = setRead(threadId, lastSeenTime);
|
||||
if (isGroupRecipient) {
|
||||
for (MarkedMessageInfo message: messages) {
|
||||
MarkReadReceiver.scheduleDeletion(context, message.getExpirationInfo());
|
||||
@ -765,6 +745,7 @@ public class ThreadDatabase extends Database {
|
||||
MarkReadReceiver.process(context, messages);
|
||||
}
|
||||
ApplicationContext.getInstance(context).messageNotifier.updateNotification(context, false, 0);
|
||||
setLastSeen(threadId, lastSeenTime);
|
||||
}
|
||||
|
||||
private boolean deleteThreadOnEmpty(long threadId) {
|
||||
|
@ -88,9 +88,10 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper {
|
||||
private static final int lokiV39 = 60;
|
||||
private static final int lokiV40 = 61;
|
||||
private static final int lokiV41 = 62;
|
||||
private static final int lokiV42 = 63;
|
||||
|
||||
// Loki - onUpgrade(...) must be updated to use Loki version numbers if Signal makes any database changes
|
||||
private static final int DATABASE_VERSION = lokiV41;
|
||||
private static final int DATABASE_VERSION = lokiV42;
|
||||
private static final int MIN_DATABASE_VERSION = lokiV7;
|
||||
private static final String CIPHER3_DATABASE_NAME = "signal.db";
|
||||
public static final String DATABASE_NAME = "signal_v4.db";
|
||||
@ -324,6 +325,7 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper {
|
||||
executeStatements(db, ReactionDatabase.CREATE_INDEXS);
|
||||
|
||||
executeStatements(db, ReactionDatabase.CREATE_REACTION_TRIGGERS);
|
||||
// db.execSQL(ThreadDatabase.getCreateLastSeenTrigger());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -560,6 +562,10 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper {
|
||||
db.execSQL(ConfigDatabase.CREATE_CONFIG_TABLE_COMMAND);
|
||||
}
|
||||
|
||||
if (oldVersion < lokiV42) {
|
||||
// db.execSQL(ThreadDatabase.getCreateLastSeenTrigger());
|
||||
}
|
||||
|
||||
db.setTransactionSuccessful();
|
||||
} finally {
|
||||
db.endTransaction();
|
||||
|
@ -28,6 +28,7 @@ import network.loki.messenger.databinding.ViewMessageRequestBannerBinding
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import org.greenrobot.eventbus.Subscribe
|
||||
import org.greenrobot.eventbus.ThreadMode
|
||||
import org.session.libsession.messaging.MessagingModuleConfiguration
|
||||
import org.session.libsession.messaging.jobs.JobQueue
|
||||
import org.session.libsession.messaging.sending_receiving.MessageSender
|
||||
import org.session.libsession.utilities.Address
|
||||
@ -556,7 +557,7 @@ class HomeActivity : PassphraseRequiredActionBarActivity(),
|
||||
|
||||
private fun markAllAsRead(thread: ThreadRecord) {
|
||||
ThreadUtils.queue {
|
||||
threadDb.markAllAsRead(thread.threadId, thread.recipient.isOpenGroupRecipient)
|
||||
MessagingModuleConfiguration.shared.storage.markConversationAsRead(thread.threadId, System.currentTimeMillis())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -120,7 +120,7 @@ public class ExpiringMessageManager implements SSKEnvironment.MessageExpirationM
|
||||
Optional.absent(),
|
||||
Optional.absent());
|
||||
//insert the timer update message
|
||||
database.insertSecureDecryptedMessageInbox(mediaMessage, -1, true, true);
|
||||
database.insertSecureDecryptedMessageInbox(mediaMessage, -1, true);
|
||||
|
||||
//set the timer to the conversation
|
||||
DatabaseComponent.get(context).recipientDatabase().setExpireMessages(recipient, duration);
|
||||
|
@ -7,8 +7,6 @@ import org.session.libsession.messaging.messages.signal.IncomingTextMessage
|
||||
import org.session.libsession.messaging.messages.signal.OutgoingTextMessage
|
||||
import org.session.libsession.messaging.open_groups.OpenGroup
|
||||
import org.session.libsession.messaging.open_groups.OpenGroupApi
|
||||
import org.session.libsession.messaging.sending_receiving.notifications.PushNotificationAPI
|
||||
import org.session.libsession.messaging.sending_receiving.pollers.ClosedGroupPollerV2
|
||||
import org.session.libsession.utilities.Address
|
||||
import org.session.libsession.utilities.GroupUtil
|
||||
import org.session.libsession.utilities.recipients.Recipient
|
||||
@ -21,7 +19,6 @@ import org.thoughtcrime.securesms.crypto.KeyPairUtilities
|
||||
import org.thoughtcrime.securesms.dependencies.DatabaseComponent
|
||||
import org.thoughtcrime.securesms.groups.GroupManager
|
||||
import java.security.SecureRandom
|
||||
import java.util.*
|
||||
import kotlin.random.asKotlinRandom
|
||||
|
||||
object MockDataGenerator {
|
||||
@ -139,7 +136,6 @@ object MockDataGenerator {
|
||||
false
|
||||
),
|
||||
(timestampNow - (index * 5000)),
|
||||
false,
|
||||
false
|
||||
)
|
||||
}
|
||||
@ -269,7 +265,6 @@ object MockDataGenerator {
|
||||
false
|
||||
),
|
||||
(timestampNow - (index * 5000)),
|
||||
false,
|
||||
false
|
||||
)
|
||||
}
|
||||
@ -395,7 +390,6 @@ object MockDataGenerator {
|
||||
false
|
||||
),
|
||||
(timestampNow - (index * 5000)),
|
||||
false,
|
||||
false
|
||||
)
|
||||
} else {
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 3fd0e0977d156a2e748a14aaa0c94da0bb71560e
|
||||
Subproject commit bbdc35d2ec8204c1a36bbe45714625d093b82602
|
@ -177,9 +177,9 @@ interface StorageProtocol {
|
||||
/**
|
||||
* Returns the ID of the `TSIncomingMessage` that was constructed.
|
||||
*/
|
||||
fun persist(message: VisibleMessage, quotes: QuoteModel?, linkPreview: List<LinkPreview?>, groupPublicKey: String?, openGroupID: String?, attachments: List<Attachment>, runIncrement: Boolean, runThreadUpdate: Boolean): Long?
|
||||
fun markConversationAsRead(threadId: Long, updateLastSeen: Boolean)
|
||||
fun incrementUnread(threadId: Long, amount: Int, unreadMentionAmount: Int)
|
||||
fun persist(message: VisibleMessage, quotes: QuoteModel?, linkPreview: List<LinkPreview?>, groupPublicKey: String?, openGroupID: String?, attachments: List<Attachment>, runThreadUpdate: Boolean): Long?
|
||||
fun markConversationAsRead(threadId: Long, lastSeenTime: Long)
|
||||
fun getLastSeen(threadId: Long): Long
|
||||
fun updateThread(threadId: Long, unarchive: Boolean)
|
||||
fun insertDataExtractionNotificationMessage(senderPublicKey: String, message: DataExtractionNotificationInfoMessage, sentTimestamp: Long)
|
||||
fun insertMessageRequestResponse(response: MessageRequestResponse)
|
||||
|
@ -123,7 +123,7 @@ class BatchMessageReceiveJob(
|
||||
async {
|
||||
// The LinkedHashMap should preserve insertion order
|
||||
val messageIds = linkedMapOf<Long, Pair<Boolean, Boolean>>()
|
||||
|
||||
var myLastSeen = storage.getLastSeen(threadId)
|
||||
messages.forEach { (parameters, message, proto) ->
|
||||
try {
|
||||
when (message) {
|
||||
@ -137,6 +137,12 @@ class BatchMessageReceiveJob(
|
||||
if (messageId != null && message.reaction == null) {
|
||||
val isUserBlindedSender = message.sender == serverPublicKey?.let { SodiumUtilities.blindedKeyPair(it, MessagingModuleConfiguration.shared.getUserED25519KeyPair()!!) }?.let { SessionId(
|
||||
IdPrefix.BLINDED, it.publicKey.asBytes).hexString }
|
||||
if (message.sender == localUserPublicKey || isUserBlindedSender) {
|
||||
val sentTimestamp = message.sentTimestamp
|
||||
if (sentTimestamp != null && sentTimestamp > myLastSeen) {
|
||||
myLastSeen = sentTimestamp // use sent timestamp here since that is technically the last one we have
|
||||
}
|
||||
}
|
||||
messageIds[messageId] = Pair(
|
||||
(message.sender == localUserPublicKey || isUserBlindedSender),
|
||||
message.hasMention
|
||||
@ -169,21 +175,8 @@ class BatchMessageReceiveJob(
|
||||
}
|
||||
}
|
||||
// increment unreads, notify, and update thread
|
||||
val unreadFromMine = messageIds.map { it.value.first }.indexOfLast { it }
|
||||
var trueUnreadCount = messageIds.filter { !it.value.first }.size
|
||||
var trueUnreadMentionCount = messageIds.filter { !it.value.first && it.value.second }.size
|
||||
if (unreadFromMine >= 0) {
|
||||
storage.markConversationAsRead(threadId, false)
|
||||
|
||||
val trueUnreadIds = messageIds.keys.toList().subList(unreadFromMine + 1, messageIds.keys.count())
|
||||
trueUnreadCount = trueUnreadIds.size
|
||||
trueUnreadMentionCount = messageIds
|
||||
.filter { trueUnreadIds.contains(it.key) && !it.value.first && it.value.second }
|
||||
.size
|
||||
}
|
||||
if (trueUnreadCount > 0) {
|
||||
storage.incrementUnread(threadId, trueUnreadCount, trueUnreadMentionCount)
|
||||
}
|
||||
// last seen will be the current last seen if not changed (re-computes the read counts for thread record)
|
||||
storage.markConversationAsRead(threadId, 0)
|
||||
storage.updateThread(threadId, true)
|
||||
SSKEnvironment.shared.notificationManager.updateNotification(context, threadId)
|
||||
}
|
||||
|
@ -66,7 +66,8 @@ object MessageSender {
|
||||
return if (destination is Destination.LegacyOpenGroup || destination is Destination.OpenGroup || destination is Destination.OpenGroupInbox) {
|
||||
sendToOpenGroupDestination(destination, message)
|
||||
} else {
|
||||
sendToSnodeDestination(destination, message)
|
||||
val userPublicKey = MessagingModuleConfiguration.shared.storage.getUserPublicKey()
|
||||
sendToSnodeDestination(destination, message, destination is Destination.Contact && destination.publicKey == userPublicKey)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -343,7 +343,7 @@ fun MessageReceiver.handleVisibleMessage(message: VisibleMessage,
|
||||
message.threadID = threadID
|
||||
val messageID =
|
||||
storage.persist(message, quoteModel, linkPreviews, message.groupPublicKey, openGroupID,
|
||||
attachments, runIncrement, runThreadUpdate
|
||||
attachments, runThreadUpdate
|
||||
) ?: return null
|
||||
val openGroupServerID = message.openGroupServerMessageID
|
||||
if (openGroupServerID != null) {
|
||||
|
Loading…
Reference in New Issue
Block a user