mirror of
https://github.com/oxen-io/session-android.git
synced 2024-11-25 02:55:23 +00:00
fix: database update not deleting in certain circumstances, storage persisting and removing the volatile convo info for thread deletion / creation, NTS hidden getter values in shared library
This commit is contained in:
parent
f111513211
commit
38454bedfc
@ -205,7 +205,7 @@ object FullBackupImporter {
|
||||
db.query(ThreadDatabase.TABLE_NAME, arrayOf(ThreadDatabase.ID),
|
||||
ThreadDatabase.EXPIRES_IN + " > 0", null, null, null, null).use { cursor ->
|
||||
while (cursor != null && cursor.moveToNext()) {
|
||||
DatabaseComponent.get(context).threadDatabase().update(cursor.getLong(0), false)
|
||||
DatabaseComponent.get(context).threadDatabase().update(cursor.getLong(0), false, true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -238,6 +238,10 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
|
||||
}
|
||||
val recipient = Recipient.from(this, address, false)
|
||||
threadId = storage.getOrCreateThreadIdFor(recipient.address)
|
||||
// assume created thread
|
||||
if (recipient.isContactRecipient && !recipient.isLocalNumber) {
|
||||
storage.setRecipientApproved(recipient, true) // assume approved when we CREATE the thread, not send first message
|
||||
}
|
||||
}
|
||||
} ?: finish()
|
||||
}
|
||||
@ -706,7 +710,7 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
|
||||
// region Animation & Updating
|
||||
override fun onModified(recipient: Recipient) {
|
||||
runOnUiThread {
|
||||
val threadRecipient = viewModel.recipient ?: return@runOnUiThread
|
||||
val threadRecipient = viewModel.recipient ?: return@runOnUiThread Log.d("Loki-DBG", "Recipient no longer here, go back?")
|
||||
if (threadRecipient.isContactRecipient) {
|
||||
binding?.blockedBanner?.isVisible = threadRecipient.isBlocked
|
||||
}
|
||||
|
@ -186,7 +186,7 @@ class MmsDatabase(context: Context, databaseHelper: SQLCipherOpenHelper) : Messa
|
||||
)
|
||||
get(context).groupReceiptDatabase()
|
||||
.update(ourAddress, id, status, timestamp)
|
||||
get(context).threadDatabase().update(threadId, false)
|
||||
get(context).threadDatabase().update(threadId, false, true)
|
||||
notifyConversationListeners(threadId)
|
||||
}
|
||||
}
|
||||
@ -264,7 +264,7 @@ class MmsDatabase(context: Context, databaseHelper: SQLCipherOpenHelper) : Messa
|
||||
" WHERE " + ID + " = ?", arrayOf(id.toString() + "")
|
||||
)
|
||||
if (threadId.isPresent) {
|
||||
get(context).threadDatabase().update(threadId.get(), false)
|
||||
get(context).threadDatabase().update(threadId.get(), false, true)
|
||||
}
|
||||
}
|
||||
|
||||
@ -651,7 +651,7 @@ class MmsDatabase(context: Context, databaseHelper: SQLCipherOpenHelper) : Messa
|
||||
)
|
||||
if (!MmsSmsColumns.Types.isExpirationTimerUpdate(mailbox)) {
|
||||
if (runThreadUpdate) {
|
||||
get(context).threadDatabase().update(threadId, true)
|
||||
get(context).threadDatabase().update(threadId, true, true)
|
||||
}
|
||||
}
|
||||
notifyConversationListeners(threadId)
|
||||
@ -790,7 +790,7 @@ class MmsDatabase(context: Context, databaseHelper: SQLCipherOpenHelper) : Messa
|
||||
setLastSeen(threadId)
|
||||
setHasSent(threadId, true)
|
||||
if (runThreadUpdate) {
|
||||
update(threadId, true)
|
||||
update(threadId, true, true)
|
||||
}
|
||||
}
|
||||
return messageId
|
||||
@ -925,7 +925,7 @@ class MmsDatabase(context: Context, databaseHelper: SQLCipherOpenHelper) : Messa
|
||||
groupReceiptDatabase.deleteRowsForMessage(messageId)
|
||||
val database = databaseHelper.writableDatabase
|
||||
database!!.delete(TABLE_NAME, ID_WHERE, arrayOf(messageId.toString()))
|
||||
val threadDeleted = get(context).threadDatabase().update(threadId, false)
|
||||
val threadDeleted = get(context).threadDatabase().update(threadId, false, true)
|
||||
notifyConversationListeners(threadId)
|
||||
notifyStickerListeners()
|
||||
notifyStickerPackListeners()
|
||||
@ -942,7 +942,7 @@ class MmsDatabase(context: Context, databaseHelper: SQLCipherOpenHelper) : Messa
|
||||
val database = databaseHelper.writableDatabase
|
||||
database!!.delete(TABLE_NAME, ID_IN, arrayOf(messageIds.joinToString(",")))
|
||||
|
||||
val threadDeleted = get(context).threadDatabase().update(threadId, false)
|
||||
val threadDeleted = get(context).threadDatabase().update(threadId, false, true)
|
||||
notifyConversationListeners(threadId)
|
||||
notifyStickerListeners()
|
||||
notifyStickerPackListeners()
|
||||
@ -1140,7 +1140,7 @@ class MmsDatabase(context: Context, databaseHelper: SQLCipherOpenHelper) : Messa
|
||||
}
|
||||
val threadDb = get(context).threadDatabase()
|
||||
for (threadId in threadIds) {
|
||||
val threadDeleted = threadDb.update(threadId, false)
|
||||
val threadDeleted = threadDb.update(threadId, false, true)
|
||||
notifyConversationListeners(threadId)
|
||||
}
|
||||
notifyStickerListeners()
|
||||
|
@ -147,7 +147,7 @@ public class SmsDatabase extends MessagingDatabase {
|
||||
|
||||
long threadId = getThreadIdForMessage(id);
|
||||
|
||||
DatabaseComponent.get(context).threadDatabase().update(threadId, false);
|
||||
DatabaseComponent.get(context).threadDatabase().update(threadId, false, true);
|
||||
notifyConversationListeners(threadId);
|
||||
}
|
||||
|
||||
@ -236,7 +236,7 @@ public class SmsDatabase extends MessagingDatabase {
|
||||
|
||||
long threadId = getThreadIdForMessage(id);
|
||||
|
||||
DatabaseComponent.get(context).threadDatabase().update(threadId, false);
|
||||
DatabaseComponent.get(context).threadDatabase().update(threadId, false, true);
|
||||
notifyConversationListeners(threadId);
|
||||
}
|
||||
|
||||
@ -299,7 +299,7 @@ public class SmsDatabase extends MessagingDatabase {
|
||||
ID + " = ?",
|
||||
new String[] {String.valueOf(cursor.getLong(cursor.getColumnIndexOrThrow(ID)))});
|
||||
|
||||
DatabaseComponent.get(context).threadDatabase().update(threadId, false);
|
||||
DatabaseComponent.get(context).threadDatabase().update(threadId, false, true);
|
||||
notifyConversationListeners(threadId);
|
||||
foundMessage = true;
|
||||
}
|
||||
@ -383,7 +383,7 @@ public class SmsDatabase extends MessagingDatabase {
|
||||
|
||||
long threadId = getThreadIdForMessage(messageId);
|
||||
|
||||
DatabaseComponent.get(context).threadDatabase().update(threadId, true);
|
||||
DatabaseComponent.get(context).threadDatabase().update(threadId, true, true);
|
||||
notifyConversationListeners(threadId);
|
||||
notifyConversationListListeners();
|
||||
|
||||
@ -470,7 +470,7 @@ public class SmsDatabase extends MessagingDatabase {
|
||||
long messageId = db.insert(TABLE_NAME, null, values);
|
||||
|
||||
if (runThreadUpdate) {
|
||||
DatabaseComponent.get(context).threadDatabase().update(threadId, true);
|
||||
DatabaseComponent.get(context).threadDatabase().update(threadId, true, true);
|
||||
}
|
||||
|
||||
if (message.getSubscriptionId() != -1) {
|
||||
@ -546,7 +546,7 @@ public class SmsDatabase extends MessagingDatabase {
|
||||
}
|
||||
|
||||
if (runThreadUpdate) {
|
||||
DatabaseComponent.get(context).threadDatabase().update(threadId, true);
|
||||
DatabaseComponent.get(context).threadDatabase().update(threadId, true, true);
|
||||
}
|
||||
DatabaseComponent.get(context).threadDatabase().setLastSeen(threadId);
|
||||
|
||||
@ -595,7 +595,7 @@ public class SmsDatabase extends MessagingDatabase {
|
||||
SQLiteDatabase db = databaseHelper.getWritableDatabase();
|
||||
long threadId = getThreadIdForMessage(messageId);
|
||||
db.delete(TABLE_NAME, ID_WHERE, new String[] {messageId+""});
|
||||
boolean threadDeleted = DatabaseComponent.get(context).threadDatabase().update(threadId, false);
|
||||
boolean threadDeleted = DatabaseComponent.get(context).threadDatabase().update(threadId, false, true);
|
||||
notifyConversationListeners(threadId);
|
||||
return threadDeleted;
|
||||
}
|
||||
@ -619,7 +619,7 @@ public class SmsDatabase extends MessagingDatabase {
|
||||
ID + " IN (" + StringUtils.join(argsArray, ',') + ")",
|
||||
argValues
|
||||
);
|
||||
boolean threadDeleted = DatabaseComponent.get(context).threadDatabase().update(threadId, false);
|
||||
boolean threadDeleted = DatabaseComponent.get(context).threadDatabase().update(threadId, false, true);
|
||||
notifyConversationListeners(threadId);
|
||||
return threadDeleted;
|
||||
}
|
||||
|
@ -89,8 +89,73 @@ import org.thoughtcrime.securesms.util.SessionMetaProtocol
|
||||
import java.security.MessageDigest
|
||||
import network.loki.messenger.libsession_util.util.Contact as LibSessionContact
|
||||
|
||||
class Storage(context: Context, helper: SQLCipherOpenHelper, private val configFactory: ConfigFactory) : Database(context, helper), StorageProtocol {
|
||||
|
||||
class Storage(context: Context, helper: SQLCipherOpenHelper, private val configFactory: ConfigFactory) : Database(context, helper), StorageProtocol,
|
||||
ThreadDatabase.ConversationThreadUpdateListener {
|
||||
|
||||
init {
|
||||
DatabaseComponent.get(context).threadDatabase().setUpdateListener(this)
|
||||
}
|
||||
|
||||
// TODO: maybe add time here from formation / creation message
|
||||
override fun threadCreated(address: Address, threadId: Long) {
|
||||
val volatile = configFactory.convoVolatile ?: return
|
||||
if (address.isGroup) {
|
||||
val groups = configFactory.userGroups ?: return
|
||||
if (address.isClosedGroup) {
|
||||
val sessionId = GroupUtil.doubleDecodeGroupId(address.serialize())
|
||||
val legacyGroup = groups.getOrConstructLegacyGroupInfo(sessionId)
|
||||
groups.set(legacyGroup)
|
||||
val newVolatileParams = volatile.getOrConstructLegacyGroup(sessionId).copy(
|
||||
lastRead = SnodeAPI.nowWithOffset,
|
||||
)
|
||||
volatile.set(newVolatileParams)
|
||||
} else if (address.isOpenGroup) {
|
||||
// these should be added on the group join / group info fetch
|
||||
Log.w("Loki", "Thread created called for open group address, not adding any extra information")
|
||||
}
|
||||
} else if (address.isContact) {
|
||||
// don't update our own address into the contacts DB
|
||||
if (getUserPublicKey() != address.serialize()) {
|
||||
val contacts = configFactory.contacts ?: return
|
||||
contacts.upsertContact(address.serialize())
|
||||
} else {
|
||||
val userProfile = configFactory.user ?: return
|
||||
userProfile.setNtsHidden(false)
|
||||
}
|
||||
val newVolatileParams = volatile.getOrConstructOneToOne(address.serialize()).copy(
|
||||
lastRead = SnodeAPI.nowWithOffset
|
||||
)
|
||||
volatile.set(newVolatileParams)
|
||||
}
|
||||
}
|
||||
|
||||
override fun threadDeleted(address: Address, threadId: Long) {
|
||||
val volatile = configFactory.convoVolatile ?: return
|
||||
if (address.isGroup) {
|
||||
val groups = configFactory.userGroups ?: return
|
||||
if (address.isClosedGroup) {
|
||||
val sessionId = GroupUtil.doubleDecodeGroupId(address.serialize())
|
||||
volatile.eraseLegacyClosedGroup(sessionId)
|
||||
groups.eraseLegacyGroup(sessionId)
|
||||
} else if (address.isOpenGroup) {
|
||||
// these should be removed in the group leave / handling new configs
|
||||
Log.w("Loki", "Thread delete called for open group address, expecting to be handled elsewhere")
|
||||
}
|
||||
} else {
|
||||
volatile.eraseOneToOne(address.serialize())
|
||||
if (getUserPublicKey() != address.serialize()) {
|
||||
val contacts = configFactory.contacts ?: return
|
||||
contacts.upsertContact(address.serialize()) {
|
||||
// hidden = true TODO: maybe this?
|
||||
}
|
||||
} else {
|
||||
val userProfile = configFactory.user ?: return
|
||||
userProfile.setNtsHidden(true)
|
||||
}
|
||||
}
|
||||
ConfigurationMessageUtilities.forceSyncConfigurationNowIfNeeded(context)
|
||||
}
|
||||
|
||||
override fun getUserPublicKey(): String? {
|
||||
return TextSecurePreferences.getLocalNumber(context)
|
||||
}
|
||||
@ -167,7 +232,7 @@ class Storage(context: Context, helper: SQLCipherOpenHelper, private val configF
|
||||
|
||||
override fun updateThread(threadId: Long, unarchive: Boolean) {
|
||||
val threadDb = DatabaseComponent.get(context).threadDatabase()
|
||||
threadDb.update(threadId, unarchive)
|
||||
threadDb.update(threadId, unarchive, false)
|
||||
}
|
||||
|
||||
override fun persist(message: VisibleMessage,
|
||||
@ -349,6 +414,16 @@ class Storage(context: Context, helper: SQLCipherOpenHelper, private val configF
|
||||
profileManager.setProfileKey(context, recipient, userPic.key)
|
||||
setUserProfilePictureURL(userPic.url)
|
||||
}
|
||||
if (userProfile.getNtsHidden()) {
|
||||
// delete nts thread if needed
|
||||
val ourThread = getThreadId(recipient) ?: return
|
||||
deleteConversation(ourThread)
|
||||
} else {
|
||||
// create note to self thread if needed (?)
|
||||
val ourThread = getOrCreateThreadIdFor(recipient.address)
|
||||
setPinned(ourThread, userProfile.getNtsPriority() > 0)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun updateContacts(contacts: Contacts) {
|
||||
@ -378,15 +453,9 @@ class Storage(context: Context, helper: SQLCipherOpenHelper, private val configF
|
||||
val extracted = convos.all()
|
||||
for (conversation in extracted) {
|
||||
val threadId = when (conversation) {
|
||||
is Conversation.OneToOne -> conversation.sessionId.let {
|
||||
getOrCreateThreadIdFor(fromSerialized(it))
|
||||
}
|
||||
is Conversation.LegacyGroup -> conversation.groupId.let {
|
||||
getOrCreateThreadIdFor("", it,null)
|
||||
}
|
||||
is Conversation.Community -> conversation.baseCommunityInfo.baseUrl.let {
|
||||
getOrCreateThreadIdFor("",null, it)
|
||||
}
|
||||
is Conversation.OneToOne -> getOrCreateThreadIdFor(fromSerialized(conversation.sessionId))
|
||||
is Conversation.LegacyGroup -> getOrCreateThreadIdFor("", conversation.groupId,null)
|
||||
is Conversation.Community -> getOrCreateThreadIdFor("",null, "${conversation.baseCommunityInfo.baseUrl}.${conversation.baseCommunityInfo.room}")
|
||||
}
|
||||
if (threadId >= 0) {
|
||||
markConversationAsRead(threadId, conversation.lastRead)
|
||||
@ -408,8 +477,8 @@ class Storage(context: Context, helper: SQLCipherOpenHelper, private val configF
|
||||
|
||||
val existingCommunities: Map<Long, OpenGroup> = allOpenGroups.filterKeys { it !in toDeleteCommunities.keys }
|
||||
val toAddCommunities = communities.filter { it.community.fullUrl() !in existingCommunities.map { it.value.joinURL } }
|
||||
|
||||
val existingJoinUrls = existingCommunities.values.map { it.joinURL }
|
||||
|
||||
val existingClosedGroups = getAllGroups().filter { it.isClosedGroup }
|
||||
val lgcIds = lgc.map { it.sessionId }
|
||||
val toDeleteClosedGroups = existingClosedGroups.filter { group ->
|
||||
@ -837,7 +906,7 @@ class Storage(context: Context, helper: SQLCipherOpenHelper, private val configF
|
||||
override fun setExpirationTimer(address: String, duration: Int) {
|
||||
val recipient = Recipient.from(context, fromSerialized(address), false)
|
||||
DatabaseComponent.get(context).recipientDatabase().setExpireMessages(recipient, duration)
|
||||
if (recipient.isContactRecipient) {
|
||||
if (recipient.isContactRecipient && !recipient.isLocalNumber) {
|
||||
configFactory.contacts?.upsertContact(address) {
|
||||
this.expiryMode = if (duration != 0) {
|
||||
ExpiryMode.AfterRead(duration.toLong())
|
||||
@ -1074,6 +1143,33 @@ class Storage(context: Context, helper: SQLCipherOpenHelper, private val configF
|
||||
override fun setPinned(threadID: Long, isPinned: Boolean) {
|
||||
val threadDB = DatabaseComponent.get(context).threadDatabase()
|
||||
threadDB.setPinned(threadID, isPinned)
|
||||
val threadRecipient = getRecipientForThread(threadID) ?: return
|
||||
if (threadRecipient.isLocalNumber) {
|
||||
val user = configFactory.user ?: return
|
||||
user.setNtsPriority(if (isPinned) 1 else 0)
|
||||
} else if (threadRecipient.isContactRecipient) {
|
||||
val contacts = configFactory.contacts ?: return
|
||||
contacts.upsertContact(threadRecipient.address.serialize()) {
|
||||
priority = if (isPinned) 1 else 0
|
||||
}
|
||||
} else if (threadRecipient.isGroupRecipient) {
|
||||
val groups = configFactory.userGroups ?: return
|
||||
if (threadRecipient.isClosedGroupRecipient) {
|
||||
val sessionId = GroupUtil.doubleDecodeGroupId(threadRecipient.address.serialize())
|
||||
val newGroupInfo = groups.getOrConstructLegacyGroupInfo(sessionId).copy (
|
||||
priority = if (isPinned) 1 else 0
|
||||
)
|
||||
groups.set(newGroupInfo)
|
||||
} else if (threadRecipient.isOpenGroupRecipient) {
|
||||
val openGroup = getOpenGroup(threadID) ?: return
|
||||
val (baseUrl, room, pubKeyHex) = BaseCommunityInfo.parseFullUrl(openGroup.joinURL) ?: return
|
||||
val newGroupInfo = groups.getOrConstructCommunityInfo(baseUrl, room, Hex.toStringCondensed(pubKeyHex)).copy (
|
||||
priority = if (isPinned) 1 else 0
|
||||
)
|
||||
groups.set(newGroupInfo)
|
||||
}
|
||||
}
|
||||
ConfigurationMessageUtilities.forceSyncConfigurationNowIfNeeded(context)
|
||||
}
|
||||
|
||||
override fun isPinned(threadID: Long): Boolean {
|
||||
@ -1234,6 +1330,7 @@ class Storage(context: Context, helper: SQLCipherOpenHelper, private val configF
|
||||
|
||||
override fun setRecipientApproved(recipient: Recipient, approved: Boolean) {
|
||||
DatabaseComponent.get(context).recipientDatabase().setApproved(recipient, approved)
|
||||
if (recipient.isLocalNumber || !recipient.isContactRecipient) return
|
||||
configFactory.contacts?.upsertContact(recipient.address.serialize()) {
|
||||
this.approved = approved
|
||||
}
|
||||
@ -1241,6 +1338,7 @@ class Storage(context: Context, helper: SQLCipherOpenHelper, private val configF
|
||||
|
||||
override fun setRecipientApprovedMe(recipient: Recipient, approvedMe: Boolean) {
|
||||
DatabaseComponent.get(context).recipientDatabase().setApprovedMe(recipient, approvedMe)
|
||||
if (recipient.isLocalNumber || !recipient.isContactRecipient) return
|
||||
configFactory.contacts?.upsertContact(recipient.address.serialize()) {
|
||||
this.approvedMe = approvedMe
|
||||
}
|
||||
@ -1376,7 +1474,7 @@ class Storage(context: Context, helper: SQLCipherOpenHelper, private val configF
|
||||
override fun setBlocked(recipients: List<Recipient>, isBlocked: Boolean, fromConfigUpdate: Boolean) {
|
||||
val recipientDb = DatabaseComponent.get(context).recipientDatabase()
|
||||
recipientDb.setBlocked(recipients, isBlocked)
|
||||
recipients.filter { it.isContactRecipient }.forEach { recipient ->
|
||||
recipients.filter { it.isContactRecipient && !it.isLocalNumber }.forEach { recipient ->
|
||||
configFactory.contacts?.upsertContact(recipient.address.serialize()) {
|
||||
this.blocked = isBlocked
|
||||
}
|
||||
|
@ -72,6 +72,11 @@ import java.util.Set;
|
||||
|
||||
public class ThreadDatabase extends Database {
|
||||
|
||||
public interface ConversationThreadUpdateListener {
|
||||
public void threadCreated(@NonNull Address address, long threadId);
|
||||
public void threadDeleted(@NonNull Address address, long threadId);
|
||||
}
|
||||
|
||||
private static final String TAG = ThreadDatabase.class.getSimpleName();
|
||||
|
||||
private final Map<Long, Address> addressCache = new HashMap<>();
|
||||
@ -139,10 +144,16 @@ public class ThreadDatabase extends Database {
|
||||
"ADD COLUMN " + UNREAD_MENTION_COUNT + " INTEGER DEFAULT 0;";
|
||||
}
|
||||
|
||||
private ConversationThreadUpdateListener updateListener;
|
||||
|
||||
public ThreadDatabase(Context context, SQLCipherOpenHelper databaseHelper) {
|
||||
super(context, databaseHelper);
|
||||
}
|
||||
|
||||
public void setUpdateListener(ConversationThreadUpdateListener updateListener) {
|
||||
this.updateListener = updateListener;
|
||||
}
|
||||
|
||||
private long createThreadForRecipient(Address address, boolean group, int distributionType) {
|
||||
ContentValues contentValues = new ContentValues(4);
|
||||
long date = System.currentTimeMillis();
|
||||
@ -205,10 +216,14 @@ public class ThreadDatabase extends Database {
|
||||
}
|
||||
|
||||
private void deleteThread(long threadId) {
|
||||
Recipient recipient = getRecipientForThreadId(threadId);
|
||||
SQLiteDatabase db = databaseHelper.getWritableDatabase();
|
||||
db.delete(TABLE_NAME, ID_WHERE, new String[] {threadId + ""});
|
||||
int numberRemoved = db.delete(TABLE_NAME, ID_WHERE, new String[] {threadId + ""});
|
||||
addressCache.remove(threadId);
|
||||
notifyConversationListListeners();
|
||||
if (updateListener != null && numberRemoved > 0 && recipient != null) {
|
||||
updateListener.threadDeleted(recipient.getAddress(), threadId);
|
||||
}
|
||||
}
|
||||
|
||||
private void deleteThreads(Set<Long> threadIds) {
|
||||
@ -276,7 +291,7 @@ public class ThreadDatabase extends Database {
|
||||
DatabaseComponent.get(context).smsDatabase().deleteMessagesInThreadBeforeDate(threadId, lastTweetDate);
|
||||
DatabaseComponent.get(context).mmsDatabase().deleteMessagesInThreadBeforeDate(threadId, lastTweetDate);
|
||||
|
||||
update(threadId, false);
|
||||
update(threadId, false, true);
|
||||
notifyConversationListeners(threadId);
|
||||
}
|
||||
} finally {
|
||||
@ -289,7 +304,7 @@ public class ThreadDatabase extends Database {
|
||||
Log.i("ThreadDatabase", "Trimming thread: " + threadId + " before :"+timestamp);
|
||||
DatabaseComponent.get(context).smsDatabase().deleteMessagesInThreadBeforeDate(threadId, timestamp);
|
||||
DatabaseComponent.get(context).mmsDatabase().deleteMessagesInThreadBeforeDate(threadId, timestamp);
|
||||
update(threadId, false);
|
||||
update(threadId, false, true);
|
||||
notifyConversationListeners(threadId);
|
||||
}
|
||||
|
||||
@ -475,7 +490,7 @@ public class ThreadDatabase extends Database {
|
||||
}
|
||||
|
||||
public Cursor getApprovedConversationList() {
|
||||
String where = "((" + MESSAGE_COUNT + " != 0 AND (" + HAS_SENT + " = 1 OR " + RecipientDatabase.APPROVED + " = 1 OR "+ GroupDatabase.TABLE_NAME +"."+GROUP_ID+" LIKE '"+CLOSED_GROUP_PREFIX+"%')) OR " + GroupDatabase.TABLE_NAME + "." + GROUP_ID + " LIKE '" + OPEN_GROUP_PREFIX + "%') " +
|
||||
String where = "((" + HAS_SENT + " = 1 OR " + RecipientDatabase.APPROVED + " = 1 OR "+ GroupDatabase.TABLE_NAME +"."+GROUP_ID+" LIKE '"+CLOSED_GROUP_PREFIX+"%') OR " + GroupDatabase.TABLE_NAME + "." + GROUP_ID + " LIKE '" + OPEN_GROUP_PREFIX + "%') " +
|
||||
"AND " + ARCHIVED + " = 0 ";
|
||||
return getConversationList(where);
|
||||
}
|
||||
@ -640,13 +655,19 @@ public class ThreadDatabase extends Database {
|
||||
|
||||
try {
|
||||
cursor = db.query(TABLE_NAME, new String[]{ID}, where, recipientsArg, null, null, null);
|
||||
|
||||
long threadId;
|
||||
boolean created = false;
|
||||
if (cursor != null && cursor.moveToFirst()) {
|
||||
return cursor.getLong(cursor.getColumnIndexOrThrow(ID));
|
||||
threadId = cursor.getLong(cursor.getColumnIndexOrThrow(ID));
|
||||
} else {
|
||||
DatabaseComponent.get(context).recipientDatabase().setProfileSharing(recipient, true);
|
||||
return createThreadForRecipient(recipient.getAddress(), recipient.isGroupRecipient(), distributionType);
|
||||
threadId = createThreadForRecipient(recipient.getAddress(), recipient.isGroupRecipient(), distributionType);
|
||||
created = true;
|
||||
}
|
||||
if (created && updateListener != null) {
|
||||
updateListener.threadCreated(recipient.getAddress(), threadId);
|
||||
}
|
||||
return threadId;
|
||||
} finally {
|
||||
if (cursor != null)
|
||||
cursor.close();
|
||||
@ -687,11 +708,11 @@ public class ThreadDatabase extends Database {
|
||||
notifyConversationListeners(threadId);
|
||||
}
|
||||
|
||||
public boolean update(long threadId, boolean unarchive) {
|
||||
public boolean update(long threadId, boolean unarchive, boolean shouldDeleteOnEmpty) {
|
||||
MmsSmsDatabase mmsSmsDatabase = DatabaseComponent.get(context).mmsSmsDatabase();
|
||||
long count = mmsSmsDatabase.getConversationCount(threadId);
|
||||
|
||||
boolean shouldDeleteEmptyThread = deleteThreadOnEmpty(threadId);
|
||||
boolean shouldDeleteEmptyThread = !shouldDeleteOnEmpty ? false : deleteThreadOnEmpty(threadId);
|
||||
|
||||
if (count == 0 && shouldDeleteEmptyThread) {
|
||||
deleteThread(threadId);
|
||||
|
@ -573,7 +573,7 @@ class HomeActivity : PassphraseRequiredActionBarActivity(),
|
||||
|
||||
private fun setConversationPinned(threadId: Long, pinned: Boolean) {
|
||||
lifecycleScope.launch(Dispatchers.IO) {
|
||||
threadDb.setPinned(threadId, pinned)
|
||||
storage.setPinned(threadId, pinned)
|
||||
homeViewModel.tryUpdateChannel()
|
||||
}
|
||||
}
|
||||
|
@ -22,28 +22,40 @@ import org.session.libsession.messaging.utilities.SessionId
|
||||
import org.session.libsession.utilities.Address
|
||||
import org.session.libsession.utilities.GroupUtil
|
||||
import org.session.libsession.utilities.TextSecurePreferences
|
||||
import org.session.libsession.utilities.WindowDebouncer
|
||||
import org.session.libsignal.utilities.Hex
|
||||
import org.session.libsignal.utilities.Log
|
||||
import org.session.libsignal.utilities.toHexString
|
||||
import org.thoughtcrime.securesms.dependencies.DatabaseComponent
|
||||
import java.util.*
|
||||
|
||||
object ConfigurationMessageUtilities {
|
||||
|
||||
val debouncer = WindowDebouncer(3000, Timer())
|
||||
|
||||
private fun scheduleConfigSync(userPublicKey: String) {
|
||||
debouncer.publish {
|
||||
// don't schedule job if we already have one
|
||||
val storage = MessagingModuleConfiguration.shared.storage
|
||||
val ourDestination = Destination.Contact(userPublicKey)
|
||||
val currentStorageJob = storage.getConfigSyncJob(ourDestination)
|
||||
if (currentStorageJob != null) {
|
||||
(currentStorageJob as ConfigurationSyncJob).shouldRunAgain.set(true)
|
||||
Log.d("Loki-DBG", "Not scheduling another one")
|
||||
return@publish
|
||||
}
|
||||
val newConfigSync = ConfigurationSyncJob(ourDestination)
|
||||
Log.d("Loki", "Scheduling new ConfigurationSyncJob")
|
||||
JobQueue.shared.add(newConfigSync)
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun syncConfigurationIfNeeded(context: Context) {
|
||||
// add if check here to schedule new config job process and return early
|
||||
val userPublicKey = TextSecurePreferences.getLocalNumber(context) ?: return
|
||||
val storage = MessagingModuleConfiguration.shared.storage
|
||||
if (ConfigBase.isNewConfigEnabled) {
|
||||
// don't schedule job if we already have one
|
||||
val ourDestination = Destination.Contact(userPublicKey)
|
||||
if (storage.getConfigSyncJob(ourDestination) != null) {
|
||||
Log.d("Loki", "ConfigSyncJob is already running for our destination")
|
||||
return
|
||||
}
|
||||
val newConfigSync = ConfigurationSyncJob(ourDestination)
|
||||
Log.d("Loki", "Scheduling new ConfigurationSyncJob")
|
||||
JobQueue.shared.add(newConfigSync)
|
||||
scheduleConfigSync(userPublicKey)
|
||||
return
|
||||
}
|
||||
val lastSyncTime = TextSecurePreferences.getLastConfigurationSyncTime(context)
|
||||
@ -70,22 +82,11 @@ object ConfigurationMessageUtilities {
|
||||
fun forceSyncConfigurationNowIfNeeded(context: Context): Promise<Unit, Exception> {
|
||||
// add if check here to schedule new config job process and return early
|
||||
val userPublicKey = TextSecurePreferences.getLocalNumber(context) ?: return Promise.ofFail(NullPointerException("User Public Key is null"))
|
||||
val storage = MessagingModuleConfiguration.shared.storage
|
||||
if (ConfigBase.isNewConfigEnabled) {
|
||||
// schedule job if none exist
|
||||
// don't schedule job if we already have one
|
||||
Log.d("Loki-DBG", "Forcing config sync")
|
||||
val ourDestination = Destination.Contact(userPublicKey)
|
||||
val currentStorageJob = storage.getConfigSyncJob(ourDestination)
|
||||
if (currentStorageJob != null) {
|
||||
(currentStorageJob as ConfigurationSyncJob).shouldRunAgain.set(true)
|
||||
Log.d("Loki-DBG", "Not scheduling another one")
|
||||
return Promise.ofFail(NullPointerException("A job is already pending or in progress, don't schedule another job"))
|
||||
}
|
||||
val newConfigSync = ConfigurationSyncJob(ourDestination)
|
||||
Log.d("Loki", "Scheduling new ConfigurationSyncJob")
|
||||
JobQueue.shared.add(newConfigSync)
|
||||
// treat this promise as succeeding now (so app continues running and doesn't block UI)
|
||||
scheduleConfigSync(userPublicKey)
|
||||
return Promise.ofSuccess(Unit)
|
||||
}
|
||||
val contacts = ContactUtilities.getAllContacts(context).filter { recipient ->
|
||||
|
@ -89,4 +89,16 @@ Java_network_loki_messenger_libsession_1util_UserProfile_setNtsHidden(JNIEnv *en
|
||||
jboolean is_hidden) {
|
||||
auto profile = ptrToProfile(env, thiz);
|
||||
profile->set_nts_hidden(is_hidden);
|
||||
}
|
||||
extern "C"
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_UserProfile_getNtsPriority(JNIEnv *env, jobject thiz) {
|
||||
auto profile = ptrToProfile(env, thiz);
|
||||
return profile->get_nts_priority();
|
||||
}
|
||||
extern "C"
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_UserProfile_getNtsHidden(JNIEnv *env, jobject thiz) {
|
||||
auto profile = ptrToProfile(env, thiz);
|
||||
return profile->get_nts_hidden();
|
||||
}
|
@ -64,7 +64,7 @@ class Contacts(pointer: Long) : ConfigBase(pointer) {
|
||||
/**
|
||||
* Similar to [updateIfExists], but will create the underlying contact if it doesn't exist before passing to [updateFunction]
|
||||
*/
|
||||
fun upsertContact(sessionId: String, updateFunction: Contact.()->Unit) {
|
||||
fun upsertContact(sessionId: String, updateFunction: Contact.()->Unit = {}) {
|
||||
val contact = getOrConstruct(sessionId)
|
||||
updateFunction(contact)
|
||||
set(contact)
|
||||
@ -95,7 +95,9 @@ class UserProfile(pointer: Long) : ConfigBase(pointer) {
|
||||
external fun getPic(): UserPic
|
||||
external fun setPic(userPic: UserPic)
|
||||
external fun setNtsPriority(priority: Int)
|
||||
external fun getNtsPriority(): Int
|
||||
external fun setNtsHidden(isHidden: Boolean)
|
||||
external fun getNtsHidden(): Boolean
|
||||
}
|
||||
|
||||
class ConversationVolatileConfig(pointer: Long): ConfigBase(pointer) {
|
||||
|
@ -86,7 +86,9 @@ class OpenGroupPoller(private val server: String, private val executorService: S
|
||||
isCaughtUp = true
|
||||
}
|
||||
}
|
||||
executorService?.schedule(this@OpenGroupPoller::poll, pollInterval, TimeUnit.MILLISECONDS)
|
||||
if (hasStarted) {
|
||||
executorService?.schedule(this@OpenGroupPoller::poll, pollInterval, TimeUnit.MILLISECONDS)
|
||||
}
|
||||
}.fail {
|
||||
updateCapabilitiesIfNeeded(isPostCapabilitiesRetry, it)
|
||||
}.map { }
|
||||
@ -115,6 +117,7 @@ class OpenGroupPoller(private val server: String, private val executorService: S
|
||||
roomToken: String,
|
||||
pollInfo: OpenGroupApi.RoomPollInfo
|
||||
) {
|
||||
if (!hasStarted) return
|
||||
val storage = MessagingModuleConfiguration.shared.storage
|
||||
val groupId = "$server.$roomToken"
|
||||
val dbGroupId = GroupUtil.getEncodedOpenGroupID(groupId.toByteArray())
|
||||
|
Loading…
Reference in New Issue
Block a user