mirror of
https://github.com/oxen-io/session-android.git
synced 2024-12-01 05:55:18 +00:00
feat: add contacts expiry serialization/deserialization, more LGC, timestamps to add closed group encryption info (for latest tracking)
This commit is contained in:
parent
0b4cff71e3
commit
3318b53a1f
@ -458,9 +458,8 @@ class LokiAPIDatabase(context: Context, helper: SQLCipherOpenHelper) : Database(
|
||||
return ECKeyPair(DjbECPublicKey(keyPair.publicKey.serialize().removingIdPrefixIfNeeded()), DjbECPrivateKey(keyPair.privateKey.serialize()))
|
||||
}
|
||||
|
||||
fun addClosedGroupEncryptionKeyPair(encryptionKeyPair: ECKeyPair, groupPublicKey: String) {
|
||||
fun addClosedGroupEncryptionKeyPair(encryptionKeyPair: ECKeyPair, groupPublicKey: String, timestamp: Long) {
|
||||
val database = databaseHelper.writableDatabase
|
||||
val timestamp = Date().time.toString()
|
||||
val index = "$groupPublicKey-$timestamp"
|
||||
val encryptionKeyPairPublicKey = encryptionKeyPair.publicKey.serialize().toHexString().removingIdPrefixIfNeeded()
|
||||
val encryptionKeyPairPrivateKey = encryptionKeyPair.privateKey.serialize().toHexString()
|
||||
|
@ -3,6 +3,7 @@ package org.thoughtcrime.securesms.database
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import network.loki.messenger.libsession_util.*
|
||||
import network.loki.messenger.libsession_util.util.BaseCommunityInfo
|
||||
import network.loki.messenger.libsession_util.util.Conversation
|
||||
import network.loki.messenger.libsession_util.util.UserPic
|
||||
import org.session.libsession.avatars.AvatarHelper
|
||||
@ -27,14 +28,19 @@ import org.session.libsession.messaging.sending_receiving.attachments.Attachment
|
||||
import org.session.libsession.messaging.sending_receiving.attachments.DatabaseAttachment
|
||||
import org.session.libsession.messaging.sending_receiving.data_extraction.DataExtractionNotificationInfoMessage
|
||||
import org.session.libsession.messaging.sending_receiving.link_preview.LinkPreview
|
||||
import org.session.libsession.messaging.sending_receiving.notifications.PushNotificationAPI
|
||||
import org.session.libsession.messaging.sending_receiving.pollers.ClosedGroupPollerV2
|
||||
import org.session.libsession.messaging.sending_receiving.quotes.QuoteModel
|
||||
import org.session.libsession.messaging.utilities.SessionId
|
||||
import org.session.libsession.messaging.utilities.SodiumUtilities
|
||||
import org.session.libsession.messaging.utilities.UpdateMessageData
|
||||
import org.session.libsession.snode.OnionRequestAPI
|
||||
import org.session.libsession.snode.SnodeAPI
|
||||
import org.session.libsession.utilities.*
|
||||
import org.session.libsession.utilities.Address.Companion.fromSerialized
|
||||
import org.session.libsession.utilities.recipients.Recipient
|
||||
import org.session.libsignal.crypto.ecc.DjbECPrivateKey
|
||||
import org.session.libsignal.crypto.ecc.DjbECPublicKey
|
||||
import org.session.libsignal.crypto.ecc.ECKeyPair
|
||||
import org.session.libsignal.messages.SignalServiceAttachmentPointer
|
||||
import org.session.libsignal.messages.SignalServiceGroup
|
||||
@ -49,7 +55,7 @@ import org.thoughtcrime.securesms.database.model.MessageId
|
||||
import org.thoughtcrime.securesms.database.model.ReactionRecord
|
||||
import org.thoughtcrime.securesms.dependencies.ConfigFactory
|
||||
import org.thoughtcrime.securesms.dependencies.DatabaseComponent
|
||||
import org.thoughtcrime.securesms.groups.GroupManager
|
||||
import org.thoughtcrime.securesms.groups.ClosedGroupManager
|
||||
import org.thoughtcrime.securesms.groups.OpenGroupManager
|
||||
import org.thoughtcrime.securesms.jobs.RetrieveProfileAvatarJob
|
||||
import org.thoughtcrime.securesms.mms.PartAuthority
|
||||
@ -119,7 +125,7 @@ class Storage(context: Context, helper: SQLCipherOpenHelper, private val configF
|
||||
// recipient is open group
|
||||
recipient.isOpenGroupRecipient -> {
|
||||
val openGroupJoinUrl = getOpenGroup(threadId)?.joinURL ?: return
|
||||
Conversation.Community.parseFullUrl(openGroupJoinUrl)?.let { (base, room, pubKey) ->
|
||||
BaseCommunityInfo.parseFullUrl(openGroupJoinUrl)?.let { (base, room, pubKey) ->
|
||||
config.getOrConstructCommunity(base, room, pubKey)
|
||||
} ?: return
|
||||
}
|
||||
@ -269,6 +275,11 @@ class Storage(context: Context, helper: SQLCipherOpenHelper, private val configF
|
||||
return DatabaseComponent.get(context).sessionJobDatabase().isJobCanceled(job)
|
||||
}
|
||||
|
||||
override fun cancelPendingMessageSendJobs(threadID: Long) {
|
||||
val jobDb = DatabaseComponent.get(context).sessionJobDatabase()
|
||||
jobDb.cancelPendingMessageSendJobs(threadID)
|
||||
}
|
||||
|
||||
override fun getAuthToken(room: String, server: String): String? {
|
||||
val id = "$server.$room"
|
||||
return DatabaseComponent.get(context).lokiAPIDatabase().getAuthToken(id)
|
||||
@ -361,6 +372,10 @@ class Storage(context: Context, helper: SQLCipherOpenHelper, private val configF
|
||||
|
||||
private fun updateUserGroups(userGroups: UserGroupsConfig) {
|
||||
val threadDb = DatabaseComponent.get(context).threadDatabase()
|
||||
val localUserPublicKey = getUserPublicKey() ?: return Log.w(
|
||||
"Loki-DBG",
|
||||
"No user public key when trying to update user groups from config"
|
||||
)
|
||||
val communities = userGroups.allCommunityInfo()
|
||||
val lgc = userGroups.allLegacyGroupInfo()
|
||||
val allOpenGroups = getAllOpenGroups()
|
||||
@ -378,7 +393,14 @@ class Storage(context: Context, helper: SQLCipherOpenHelper, private val configF
|
||||
OpenGroupManager.delete(openGroup.server, openGroup.room, context)
|
||||
}
|
||||
|
||||
// GroupManager.deleteGroup()
|
||||
toDeleteClosedGroups.forEach { deleteGroup ->
|
||||
val threadId = getThreadId(deleteGroup.encodedId)
|
||||
if (threadId == null) {
|
||||
Log.w("Loki-DBG", "Existing group had no thread to delete")
|
||||
} else {
|
||||
ClosedGroupManager.silentlyRemoveGroup(context,threadId,GroupUtil.doubleDecodeGroupId(deleteGroup.encodedId), deleteGroup.encodedId, localUserPublicKey, delete = true)
|
||||
}
|
||||
}
|
||||
|
||||
for (groupInfo in communities) {
|
||||
val groupBaseCommunity = groupInfo.community
|
||||
@ -407,8 +429,24 @@ class Storage(context: Context, helper: SQLCipherOpenHelper, private val configF
|
||||
val admins = group.members.filter { it.value /*admin = true*/ }.keys.map { Address.fromSerialized(it) }
|
||||
val groupId = GroupUtil.doubleEncodeGroupID(group.sessionId)
|
||||
val title = group.name
|
||||
val formationTimestamp = 0L
|
||||
val formationTimestamp = SnodeAPI.nowWithOffset // TODO: formation timestamp for legacy ? current time?
|
||||
createGroup(groupId, title, members, null, null, admins, formationTimestamp)
|
||||
setProfileSharing(Address.fromSerialized(groupId), true)
|
||||
// Add the group to the user's set of public keys to poll for
|
||||
addClosedGroupPublicKey(group.sessionId)
|
||||
// Store the encryption key pair
|
||||
val keyPair = ECKeyPair(DjbECPublicKey(group.encPubKey), DjbECPrivateKey(group.encSecKey))
|
||||
addClosedGroupEncryptionKeyPair(keyPair, group.sessionId, SnodeAPI.nowWithOffset)
|
||||
// Set expiration timer
|
||||
val expireTimer = group.expiration
|
||||
setExpirationTimer(groupId, expireTimer)
|
||||
// Notify the PN server
|
||||
PushNotificationAPI.performOperation(PushNotificationAPI.ClosedGroupOperation.Subscribe, group.sessionId, localUserPublicKey)
|
||||
// Notify the user
|
||||
val threadID = getOrCreateThreadIdFor(Address.fromSerialized(groupId))
|
||||
insertOutgoingInfoMessage(context, groupId, SignalServiceGroup.Type.CREATION, title, members.map { it.serialize() }, admins.map { it.serialize() }, threadID, formationTimestamp)
|
||||
// Start polling
|
||||
ClosedGroupPollerV2.shared.startPolling(group.sessionId)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -696,8 +734,8 @@ class Storage(context: Context, helper: SQLCipherOpenHelper, private val configF
|
||||
DatabaseComponent.get(context).lokiAPIDatabase().removeClosedGroupPublicKey(groupPublicKey)
|
||||
}
|
||||
|
||||
override fun addClosedGroupEncryptionKeyPair(encryptionKeyPair: ECKeyPair, groupPublicKey: String) {
|
||||
DatabaseComponent.get(context).lokiAPIDatabase().addClosedGroupEncryptionKeyPair(encryptionKeyPair, groupPublicKey)
|
||||
override fun addClosedGroupEncryptionKeyPair(encryptionKeyPair: ECKeyPair, groupPublicKey: String, timestamp: Long) {
|
||||
DatabaseComponent.get(context).lokiAPIDatabase().addClosedGroupEncryptionKeyPair(encryptionKeyPair, groupPublicKey, timestamp)
|
||||
}
|
||||
|
||||
override fun removeAllClosedGroupEncryptionKeyPairs(groupPublicKey: String) {
|
||||
@ -716,7 +754,7 @@ class Storage(context: Context, helper: SQLCipherOpenHelper, private val configF
|
||||
|
||||
override fun setExpirationTimer(groupID: String, duration: Int) {
|
||||
val recipient = Recipient.from(context, fromSerialized(groupID), false)
|
||||
DatabaseComponent.get(context).recipientDatabase().setExpireMessages(recipient, duration);
|
||||
DatabaseComponent.get(context).recipientDatabase().setExpireMessages(recipient, duration)
|
||||
}
|
||||
|
||||
override fun setServerCapabilities(server: String, capabilities: List<String>) {
|
||||
@ -917,6 +955,11 @@ class Storage(context: Context, helper: SQLCipherOpenHelper, private val configF
|
||||
return threadDB.isPinned(threadID)
|
||||
}
|
||||
|
||||
override fun deleteConversation(threadID: Long) {
|
||||
val threadDB = DatabaseComponent.get(context).threadDatabase()
|
||||
threadDB.deleteConversation(threadID)
|
||||
}
|
||||
|
||||
override fun getAttachmentDataUri(attachmentId: AttachmentId): Uri {
|
||||
return PartAuthority.getAttachmentDataUri(attachmentId)
|
||||
}
|
||||
|
@ -514,7 +514,7 @@ public class ThreadDatabase extends Database {
|
||||
public void setLastSeen(long threadId, long timestamp) {
|
||||
SQLiteDatabase db = databaseHelper.getWritableDatabase();
|
||||
ContentValues contentValues = new ContentValues(1);
|
||||
long lastSeenTime = timestamp == -1 ? SnodeAPI.INSTANCE.getNowWithOffset() : timestamp;
|
||||
long lastSeenTime = timestamp == -1 ? SnodeAPI.getNowWithOffset() : timestamp;
|
||||
contentValues.put(LAST_SEEN, lastSeenTime);
|
||||
db.beginTransaction();
|
||||
db.update(TABLE_NAME, contentValues, ID_WHERE, new String[] {String.valueOf(threadId)});
|
||||
|
@ -0,0 +1,31 @@
|
||||
package org.thoughtcrime.securesms.groups
|
||||
|
||||
import android.content.Context
|
||||
import org.session.libsession.messaging.MessagingModuleConfiguration
|
||||
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.thoughtcrime.securesms.ApplicationContext
|
||||
|
||||
object ClosedGroupManager {
|
||||
|
||||
fun silentlyRemoveGroup(context: Context, threadId: Long, groupPublicKey: String, groupID: String, userPublicKey: String, delete: Boolean = true) {
|
||||
val storage = MessagingModuleConfiguration.shared.storage
|
||||
storage.removeClosedGroupPublicKey(groupPublicKey)
|
||||
// Remove the key pairs
|
||||
storage.removeAllClosedGroupEncryptionKeyPairs(groupPublicKey)
|
||||
// Mark the group as inactive
|
||||
storage.setActive(groupID, false)
|
||||
storage.removeMember(groupID, Address.fromSerialized(userPublicKey))
|
||||
// Notify the PN server
|
||||
PushNotificationAPI.performOperation(PushNotificationAPI.ClosedGroupOperation.Unsubscribe, groupPublicKey, userPublicKey)
|
||||
// Stop polling
|
||||
ClosedGroupPollerV2.shared.stopPolling(groupPublicKey)
|
||||
storage.cancelPendingMessageSendJobs(threadId)
|
||||
ApplicationContext.getInstance(context).messageNotifier.updateNotification(context)
|
||||
if (delete) {
|
||||
storage.deleteConversation(threadId)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -13,8 +13,7 @@ inline session::config::Contacts *ptrToContacts(JNIEnv *env, jobject obj) {
|
||||
|
||||
inline jobject serialize_contact(JNIEnv *env, session::config::contact_info info) {
|
||||
jclass contactClass = env->FindClass("network/loki/messenger/libsession_util/util/Contact");
|
||||
jmethodID constructor = env->GetMethodID(contactClass, "<init>",
|
||||
"(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZZZLnetwork/loki/messenger/libsession_util/util/UserPic;I)V");
|
||||
jmethodID constructor = env->GetMethodID(contactClass, "<init>", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZZZLnetwork/loki/messenger/libsession_util/util/UserPic;ILnetwork/loki/messenger/libsession_util/util/ExpiryMode;)V");
|
||||
jstring id = env->NewStringUTF(info.session_id.data());
|
||||
jstring name = env->NewStringUTF(info.name.data());
|
||||
jstring nickname = env->NewStringUTF(info.nickname.data());
|
||||
@ -23,22 +22,27 @@ inline jobject serialize_contact(JNIEnv *env, session::config::contact_info info
|
||||
approvedMe = info.approved_me;
|
||||
blocked = info.blocked;
|
||||
jobject profilePic = util::serialize_user_pic(env, info.profile_picture);
|
||||
jobject returnObj = env->NewObject(contactClass, constructor, id, name, nickname, approved, approvedMe, blocked, profilePic, info.priority);
|
||||
jobject returnObj = env->NewObject(contactClass, constructor, id, name, nickname, approved,
|
||||
approvedMe, blocked, profilePic, info.priority,
|
||||
util::serialize_expiry(env, info.exp_mode, info.exp_timer));
|
||||
return returnObj;
|
||||
}
|
||||
|
||||
inline session::config::contact_info deserialize_contact(JNIEnv *env, jobject info, session::config::Contacts *conf) {
|
||||
inline session::config::contact_info
|
||||
deserialize_contact(JNIEnv *env, jobject info, session::config::Contacts *conf) {
|
||||
jclass contactClass = env->FindClass("network/loki/messenger/libsession_util/util/Contact");
|
||||
|
||||
jfieldID getId, getName, getNick, getApproved, getApprovedMe, getBlocked, getUserPic, getPriority;
|
||||
jfieldID getId, getName, getNick, getApproved, getApprovedMe, getBlocked, getUserPic, getPriority, getExpiry;
|
||||
getId = env->GetFieldID(contactClass, "id", "Ljava/lang/String;");
|
||||
getName = env->GetFieldID(contactClass, "name", "Ljava/lang/String;");
|
||||
getNick = env->GetFieldID(contactClass, "nickname", "Ljava/lang/String;");
|
||||
getApproved = env->GetFieldID(contactClass, "approved", "Z");
|
||||
getApprovedMe = env->GetFieldID(contactClass, "approvedMe", "Z");
|
||||
getBlocked = env->GetFieldID(contactClass, "blocked", "Z");
|
||||
getUserPic = env->GetFieldID(contactClass, "profilePicture", "Lnetwork/loki/messenger/libsession_util/util/UserPic;");
|
||||
getUserPic = env->GetFieldID(contactClass, "profilePicture",
|
||||
"Lnetwork/loki/messenger/libsession_util/util/UserPic;");
|
||||
getPriority = env->GetFieldID(contactClass, "priority", "I");
|
||||
getExpiry = env->GetFieldID(contactClass, "expiryMode", "Lnetwork/loki/messenger/libsession_util/util/ExpiryMode;");
|
||||
jstring name, nickname, session_id;
|
||||
session_id = static_cast<jstring>(env->GetObjectField(info, getId));
|
||||
name = static_cast<jstring>(env->GetObjectField(info, getName));
|
||||
@ -49,6 +53,9 @@ inline session::config::contact_info deserialize_contact(JNIEnv *env, jobject in
|
||||
approvedMe = env->GetBooleanField(info, getApprovedMe);
|
||||
blocked = env->GetBooleanField(info, getBlocked);
|
||||
jobject user_pic = env->GetObjectField(info, getUserPic);
|
||||
jobject expiry_mode = env->GetObjectField(info, getExpiry);
|
||||
|
||||
auto expiry_pair = util::deserialize_expiry(env, expiry_mode);
|
||||
|
||||
std::string url;
|
||||
session::ustring key;
|
||||
@ -91,6 +98,8 @@ inline session::config::contact_info deserialize_contact(JNIEnv *env, jobject in
|
||||
}
|
||||
|
||||
contact_info.priority = priority;
|
||||
contact_info.exp_mode = expiry_pair.first;
|
||||
contact_info.exp_timer = std::chrono::seconds(expiry_pair.second);
|
||||
|
||||
return contact_info;
|
||||
}
|
||||
|
@ -51,6 +51,7 @@ inline session::config::legacy_group_info deserialize_legacy_group_info(JNIEnv *
|
||||
auto enc_pub_key_field = env->GetFieldID(clazz, "encPubKey", "[B");
|
||||
auto enc_sec_key_field = env->GetFieldID(clazz, "encSecKey", "[B");
|
||||
auto priority_field = env->GetFieldID(clazz, "priority", "I");
|
||||
auto disappearing_timer_field = env->GetFieldID(clazz, "disappearingTimer", "J");
|
||||
jstring id = static_cast<jstring>(env->GetObjectField(info, id_field));
|
||||
jstring name = static_cast<jstring>(env->GetObjectField(info, name_field));
|
||||
jobject members_map = env->GetObjectField(info, members_field);
|
||||
@ -72,8 +73,7 @@ inline session::config::legacy_group_info deserialize_legacy_group_info(JNIEnv *
|
||||
info_deserialized.hidden = hidden;
|
||||
info_deserialized.enc_pubkey = enc_pub_key_bytes;
|
||||
info_deserialized.enc_seckey = enc_sec_key_bytes;
|
||||
// TODO: this
|
||||
// info_deserialized.disappearing_timer
|
||||
info_deserialized.disappearing_timer = std::chrono::seconds(env->GetLongField(info, disappearing_timer_field));
|
||||
env->ReleaseStringUTFChars(id, id_bytes);
|
||||
env->ReleaseStringUTFChars(name, name_bytes);
|
||||
return info_deserialized;
|
||||
@ -119,8 +119,8 @@ inline jobject serialize_legacy_group_info(JNIEnv *env, session::config::legacy_
|
||||
bool hidden = info.hidden;
|
||||
|
||||
jclass legacy_group_class = env->FindClass("network/loki/messenger/libsession_util/util/GroupInfo$LegacyGroupInfo");
|
||||
jmethodID constructor = env->GetMethodID(legacy_group_class, "<init>", "(Ljava/lang/String;Ljava/lang/String;Ljava/util/Map;Z[B[BI)V");
|
||||
jobject serialized = env->NewObject(legacy_group_class, constructor, session_id, name, members, hidden, enc_pubkey, enc_seckey, priority);
|
||||
jmethodID constructor = env->GetMethodID(legacy_group_class, "<init>", "(Ljava/lang/String;Ljava/lang/String;Ljava/util/Map;Z[B[BIJ)V");
|
||||
jobject serialized = env->NewObject(legacy_group_class, constructor, session_id, name, members, hidden, enc_pubkey, enc_seckey, priority, (jlong) info.disappearing_timer.count());
|
||||
return serialized;
|
||||
}
|
||||
|
||||
|
@ -67,6 +67,40 @@ namespace util {
|
||||
return community;
|
||||
}
|
||||
|
||||
jobject serialize_expiry(JNIEnv *env, const session::config::expiration_mode& mode, const std::chrono::seconds& time_seconds) {
|
||||
jclass none = env->FindClass("network/loki/messenger/libsession_util/util/ExpiryMode$NONE");
|
||||
jfieldID none_instance = env->GetStaticFieldID(none, "INSTANCE", "Lnetwork/loki/messenger/libsession_util/util/ExpiryMode$NONE;");
|
||||
jclass after_send = env->FindClass("network/loki/messenger/libsession_util/util/ExpiryMode$AfterSend");
|
||||
jmethodID send_init = env->GetMethodID(after_send, "<init>", "(J)V");
|
||||
jclass after_read = env->FindClass("network/loki/messenger/libsession_util/util/ExpiryMode$AfterRead");
|
||||
jmethodID read_init = env->GetMethodID(after_read, "<init>", "(J)V");
|
||||
|
||||
if (mode == session::config::expiration_mode::none) {
|
||||
return env->GetStaticObjectField(none, none_instance);
|
||||
} else if (mode == session::config::expiration_mode::after_send) {
|
||||
return env->NewObject(after_send, send_init, time_seconds.count());
|
||||
} else if (mode == session::config::expiration_mode::after_read) {
|
||||
return env->NewObject(after_read, read_init, time_seconds.count());
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::pair<session::config::expiration_mode, long> deserialize_expiry(JNIEnv *env, jobject expiry_mode) {
|
||||
jclass parent = env->FindClass("network/loki/messenger/libsession_util/util/ExpiryMode");
|
||||
jclass after_read = env->FindClass("network/loki/messenger/libsession_util/util/ExpiryMode$AfterRead");
|
||||
jclass after_send = env->FindClass("network/loki/messenger/libsession_util/util/ExpiryMode$AfterSend");
|
||||
jfieldID duration_seconds = env->GetFieldID(parent, "expirySeconds", "J");
|
||||
|
||||
jclass object_class = env->GetObjectClass(expiry_mode);
|
||||
|
||||
if (object_class == after_read) {
|
||||
return std::pair(session::config::expiration_mode::after_read, env->GetLongField(expiry_mode, duration_seconds));
|
||||
} else if (object_class == after_send) {
|
||||
return std::pair(session::config::expiration_mode::after_send, env->GetLongField(expiry_mode, duration_seconds));
|
||||
}
|
||||
return std::pair(session::config::expiration_mode::none, 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extern "C"
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include "session/types.hpp"
|
||||
#include "session/config/profile_pic.hpp"
|
||||
#include "session/config/user_groups.hpp"
|
||||
#include "session/config/expiring.hpp"
|
||||
|
||||
namespace util {
|
||||
jbyteArray bytes_from_ustring(JNIEnv* env, session::ustring_view from_str);
|
||||
@ -15,6 +16,8 @@ namespace util {
|
||||
std::pair<jstring, jbyteArray> deserialize_user_pic(JNIEnv *env, jobject user_pic);
|
||||
jobject serialize_base_community(JNIEnv *env, const session::config::community& base_community);
|
||||
session::config::community deserialize_base_community(JNIEnv *env, jobject base_community);
|
||||
jobject serialize_expiry(JNIEnv *env, const session::config::expiration_mode& mode, const std::chrono::seconds& time_seconds);
|
||||
std::pair<session::config::expiration_mode, long> deserialize_expiry(JNIEnv *env, jobject expiry_mode);
|
||||
}
|
||||
|
||||
#endif
|
@ -2,11 +2,12 @@ package network.loki.messenger.libsession_util.util
|
||||
|
||||
data class Contact(
|
||||
val id: String,
|
||||
var name: String = "",
|
||||
var nickname: String = "",
|
||||
var approved: Boolean = false,
|
||||
var approvedMe: Boolean = false,
|
||||
var blocked: Boolean = false,
|
||||
var profilePicture: UserPic = UserPic.DEFAULT,
|
||||
var priority: Int = 0
|
||||
val name: String = "",
|
||||
val nickname: String = "",
|
||||
val approved: Boolean = false,
|
||||
val approvedMe: Boolean = false,
|
||||
val blocked: Boolean = false,
|
||||
val profilePicture: UserPic = UserPic.DEFAULT,
|
||||
val priority: Int = 0,
|
||||
val expiryMode: ExpiryMode
|
||||
)
|
@ -1,7 +1,7 @@
|
||||
package network.loki.messenger.libsession_util.util
|
||||
|
||||
sealed class ExpiryMode(val expiryMinutes: Long) {
|
||||
sealed class ExpiryMode(val expirySeconds: Long) {
|
||||
object NONE: ExpiryMode(0)
|
||||
class AfterSend(minutes: Long): ExpiryMode(minutes)
|
||||
class AfterRead(minutes: Long): ExpiryMode(minutes)
|
||||
class AfterSend(seconds: Long): ExpiryMode(seconds)
|
||||
class AfterRead(seconds: Long): ExpiryMode(seconds)
|
||||
}
|
@ -11,7 +11,8 @@ sealed class GroupInfo {
|
||||
val hidden: Boolean,
|
||||
val encPubKey: ByteArray,
|
||||
val encSecKey: ByteArray,
|
||||
val priority: Int = 0
|
||||
val priority: Int = 0,
|
||||
val disappearingTimer: Long
|
||||
): GroupInfo() {
|
||||
companion object {
|
||||
@Suppress("FunctionName")
|
||||
|
@ -56,6 +56,7 @@ interface StorageProtocol {
|
||||
fun getConfigSyncJob(destination: Destination): Job?
|
||||
fun resumeMessageSendJobIfNeeded(messageSendJobID: String)
|
||||
fun isJobCanceled(job: Job): Boolean
|
||||
fun cancelPendingMessageSendJobs(threadID: Long)
|
||||
|
||||
// Authorization
|
||||
fun getAuthToken(room: String, server: String): String?
|
||||
@ -130,7 +131,7 @@ interface StorageProtocol {
|
||||
fun getAllActiveClosedGroupPublicKeys(): Set<String>
|
||||
fun addClosedGroupPublicKey(groupPublicKey: String)
|
||||
fun removeClosedGroupPublicKey(groupPublicKey: String)
|
||||
fun addClosedGroupEncryptionKeyPair(encryptionKeyPair: ECKeyPair, groupPublicKey: String)
|
||||
fun addClosedGroupEncryptionKeyPair(encryptionKeyPair: ECKeyPair, groupPublicKey: String, timestamp: Long)
|
||||
fun removeAllClosedGroupEncryptionKeyPairs(groupPublicKey: String)
|
||||
fun insertIncomingInfoMessage(context: Context, senderPublicKey: String, groupID: String, type: SignalServiceGroup.Type,
|
||||
name: String, members: Collection<String>, admins: Collection<String>, sentTimestamp: Long)
|
||||
@ -163,6 +164,7 @@ interface StorageProtocol {
|
||||
fun getMessageCount(threadID: Long): Long
|
||||
fun setPinned(threadID: Long, isPinned: Boolean)
|
||||
fun isPinned(threadID: Long): Boolean
|
||||
fun deleteConversation(threadID: Long)
|
||||
|
||||
// Contacts
|
||||
fun getContactWithSessionID(sessionID: String): Contact?
|
||||
|
@ -748,7 +748,7 @@ private fun MessageReceiver.handleClosedGroupMemberLeft(message: ClosedGroupCont
|
||||
}
|
||||
}
|
||||
|
||||
private fun isValidGroupUpdate(group: GroupRecord, sentTimestamp: Long, senderPublicKey: String): Boolean {
|
||||
private fun isValidGroupUpdate(group: GroupRecord, sentTimestamp: Long, senderPublicKey: String): Boolean {
|
||||
val oldMembers = group.members.map { it.serialize() }
|
||||
// Check that the message isn't from before the group was created
|
||||
if (group.formationTimestamp > sentTimestamp) {
|
||||
|
Loading…
Reference in New Issue
Block a user