mirror of
https://github.com/oxen-io/session-android.git
synced 2025-02-17 11:58:25 +00:00
Clean
This commit is contained in:
parent
bc66c45bca
commit
676c307412
@ -30,7 +30,6 @@ interface MessageDataProvider {
|
||||
fun updateAttachmentAfterUploadSucceeded(attachmentId: Long, attachmentStream: SignalServiceAttachmentStream, attachmentKey: ByteArray, uploadResult: DotNetAPI.UploadResult)
|
||||
fun updateAttachmentAfterUploadFailed(attachmentId: Long)
|
||||
|
||||
// Quotes
|
||||
fun getMessageForQuote(timestamp: Long, author: Address): Pair<Long, Boolean>?
|
||||
fun getAttachmentsAndLinkPreviewFor(mmsId: Long): List<Attachment>
|
||||
fun getMessageBodyFor(timestamp: Long, author: String): String
|
||||
|
@ -1,6 +1,5 @@
|
||||
package org.session.libsession.messaging.avatars;
|
||||
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
@ -1,6 +1,5 @@
|
||||
package org.session.libsession.messaging.avatars;
|
||||
|
||||
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
|
||||
@ -19,5 +18,4 @@ public interface ContactPhoto extends Key {
|
||||
@Nullable Uri getUri(@NonNull Context context);
|
||||
|
||||
boolean isProfilePhoto();
|
||||
|
||||
}
|
||||
|
@ -7,5 +7,4 @@ public interface FallbackContactPhoto {
|
||||
|
||||
public Drawable asDrawable(Context context, int color);
|
||||
public Drawable asDrawable(Context context, int color, boolean inverted);
|
||||
|
||||
}
|
||||
|
@ -19,7 +19,6 @@ import org.session.libsession.utilities.ViewUtil;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
|
||||
public class GeneratedContactPhoto implements FallbackContactPhoto {
|
||||
|
||||
private static final Pattern PATTERN = Pattern.compile("[^\\p{L}\\p{Nd}\\p{S}]+");
|
||||
|
@ -1,6 +1,5 @@
|
||||
package org.session.libsession.messaging.avatars;
|
||||
|
||||
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
|
||||
|
@ -1,6 +1,5 @@
|
||||
package org.session.libsession.messaging.avatars;
|
||||
|
||||
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
|
||||
|
@ -1,6 +1,5 @@
|
||||
package org.session.libsession.messaging.avatars;
|
||||
|
||||
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
|
||||
|
@ -11,13 +11,10 @@ import java.io.File
|
||||
import java.io.FileInputStream
|
||||
|
||||
class AttachmentDownloadJob(val attachmentID: Long, val databaseMessageID: Long): Job {
|
||||
|
||||
override var delegate: JobDelegate? = null
|
||||
override var id: String? = null
|
||||
override var failureCount: Int = 0
|
||||
|
||||
private val MAX_ATTACHMENT_SIZE = 10 * 1024 * 1024
|
||||
|
||||
// Error
|
||||
internal sealed class Error(val description: String) : Exception(description) {
|
||||
object NoAttachment : Error("No such attachment.")
|
||||
@ -28,17 +25,17 @@ class AttachmentDownloadJob(val attachmentID: Long, val databaseMessageID: Long)
|
||||
companion object {
|
||||
val KEY: String = "AttachmentDownloadJob"
|
||||
|
||||
//keys used for database storage purpose
|
||||
// Keys used for database storage
|
||||
private val KEY_ATTACHMENT_ID = "attachment_id"
|
||||
private val KEY_TS_INCOMING_MESSAGE_ID = "tsIncoming_message_id"
|
||||
}
|
||||
|
||||
override fun execute() {
|
||||
val handleFailure: (java.lang.Exception) -> Unit = { exception ->
|
||||
if(exception is Error && exception == Error.NoAttachment) {
|
||||
if (exception == Error.NoAttachment) {
|
||||
MessagingConfiguration.shared.messageDataProvider.setAttachmentState(AttachmentState.FAILED, attachmentID, databaseMessageID)
|
||||
this.handlePermanentFailure(exception)
|
||||
} else if (exception is DotNetAPI.Error && exception == DotNetAPI.Error.ParsingFailed) {
|
||||
} else if (exception == DotNetAPI.Error.ParsingFailed) {
|
||||
// No need to retry if the response is invalid. Most likely this means we (incorrectly)
|
||||
// got a "Cannot GET ..." error from the file server.
|
||||
MessagingConfiguration.shared.messageDataProvider.setAttachmentState(AttachmentState.FAILED, attachmentID, databaseMessageID)
|
||||
@ -53,9 +50,7 @@ class AttachmentDownloadJob(val attachmentID: Long, val databaseMessageID: Long)
|
||||
messageDataProvider.setAttachmentState(AttachmentState.STARTED, attachmentID, this.databaseMessageID)
|
||||
val tempFile = createTempFile()
|
||||
|
||||
FileServerAPI.shared.downloadFile(tempFile, attachment.url, MAX_ATTACHMENT_SIZE, null)
|
||||
|
||||
// DECRYPTION
|
||||
FileServerAPI.shared.downloadFile(tempFile, attachment.url, null)
|
||||
|
||||
// Assume we're retrieving an attachment for an open group server if the digest is not set
|
||||
val stream = if (attachment.digest?.size ?: 0 == 0 || attachment.key.isNullOrEmpty()) FileInputStream(tempFile)
|
||||
@ -89,12 +84,10 @@ class AttachmentDownloadJob(val attachmentID: Long, val databaseMessageID: Long)
|
||||
return file
|
||||
}
|
||||
|
||||
//database functions
|
||||
|
||||
override fun serialize(): Data {
|
||||
return Data.Builder().putLong(KEY_ATTACHMENT_ID, attachmentID)
|
||||
.putLong(KEY_TS_INCOMING_MESSAGE_ID, databaseMessageID)
|
||||
.build();
|
||||
.putLong(KEY_TS_INCOMING_MESSAGE_ID, databaseMessageID)
|
||||
.build();
|
||||
}
|
||||
|
||||
override fun getFactoryKey(): String {
|
||||
@ -102,6 +95,7 @@ class AttachmentDownloadJob(val attachmentID: Long, val databaseMessageID: Long)
|
||||
}
|
||||
|
||||
class Factory: Job.Factory<AttachmentDownloadJob> {
|
||||
|
||||
override fun create(data: Data): AttachmentDownloadJob {
|
||||
return AttachmentDownloadJob(data.getLong(KEY_ATTACHMENT_ID), data.getLong(KEY_TS_INCOMING_MESSAGE_ID))
|
||||
}
|
||||
|
@ -18,7 +18,6 @@ import org.session.libsignal.service.loki.utilities.PlaintextOutputStreamFactory
|
||||
import org.session.libsignal.utilities.logging.Log
|
||||
|
||||
class AttachmentUploadJob(val attachmentID: Long, val threadID: String, val message: Message, val messageSendJobID: String) : Job {
|
||||
|
||||
override var delegate: JobDelegate? = null
|
||||
override var id: String? = null
|
||||
override var failureCount: Int = 0
|
||||
@ -34,9 +33,7 @@ class AttachmentUploadJob(val attachmentID: Long, val threadID: String, val mess
|
||||
val TAG = AttachmentUploadJob::class.simpleName
|
||||
val KEY: String = "AttachmentUploadJob"
|
||||
|
||||
val maxFailureCount: Int = 20
|
||||
|
||||
//keys used for database storage purpose
|
||||
// Keys used for database storage
|
||||
private val KEY_ATTACHMENT_ID = "attachment_id"
|
||||
private val KEY_THREAD_ID = "thread_id"
|
||||
private val KEY_MESSAGE = "message"
|
||||
@ -46,16 +43,12 @@ class AttachmentUploadJob(val attachmentID: Long, val threadID: String, val mess
|
||||
override fun execute() {
|
||||
try {
|
||||
val attachment = MessagingConfiguration.shared.messageDataProvider.getScaledSignalAttachmentStream(attachmentID)
|
||||
?: return handleFailure(Error.NoAttachment)
|
||||
?: return handleFailure(Error.NoAttachment)
|
||||
|
||||
var server = FileServerAPI.shared.server
|
||||
var shouldEncrypt = true
|
||||
val usePadding = false
|
||||
val openGroup = MessagingConfiguration.shared.storage.getOpenGroup(threadID)
|
||||
openGroup?.let {
|
||||
server = it.server
|
||||
shouldEncrypt = false
|
||||
}
|
||||
val server = if (openGroup != null) openGroup.server else FileServerAPI.shared.server
|
||||
val shouldEncrypt = (openGroup == null) // Encrypt if this isn't an open group
|
||||
|
||||
val attachmentKey = Util.getSecretBytes(64)
|
||||
val paddedLength = if (usePadding) PaddingInputStream.getPaddedSize(attachment.length) else attachment.length
|
||||
@ -67,9 +60,8 @@ class AttachmentUploadJob(val attachmentID: Long, val threadID: String, val mess
|
||||
|
||||
val uploadResult = FileServerAPI.shared.uploadAttachment(server, attachmentData)
|
||||
handleSuccess(attachment, attachmentKey, uploadResult)
|
||||
|
||||
} catch (e: java.lang.Exception) {
|
||||
if (e is Error && e == Error.NoAttachment) {
|
||||
if (e == Error.NoAttachment) {
|
||||
this.handlePermanentFailure(e)
|
||||
} else if (e is DotNetAPI.Error && !e.isRetryable) {
|
||||
this.handlePermanentFailure(e)
|
||||
@ -77,7 +69,6 @@ class AttachmentUploadJob(val attachmentID: Long, val threadID: String, val mess
|
||||
this.handleFailure(e)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun handleSuccess(attachment: SignalServiceAttachmentStream, attachmentKey: ByteArray, uploadResult: DotNetAPI.UploadResult) {
|
||||
@ -97,7 +88,7 @@ class AttachmentUploadJob(val attachmentID: Long, val threadID: String, val mess
|
||||
private fun handleFailure(e: Exception) {
|
||||
Log.w(TAG, "Attachment upload failed due to error: $this.")
|
||||
delegate?.handleJobFailed(this, e)
|
||||
if (failureCount + 1 == AttachmentUploadJob.maxFailureCount) {
|
||||
if (failureCount + 1 == maxFailureCount) {
|
||||
failAssociatedMessageSendJob(e)
|
||||
}
|
||||
}
|
||||
@ -111,10 +102,7 @@ class AttachmentUploadJob(val attachmentID: Long, val threadID: String, val mess
|
||||
}
|
||||
}
|
||||
|
||||
//database functions
|
||||
|
||||
override fun serialize(): Data {
|
||||
//serialize Message property
|
||||
val kryo = Kryo()
|
||||
kryo.isRegistrationRequired = false
|
||||
val serializedMessage = ByteArray(4096)
|
||||
@ -122,10 +110,10 @@ class AttachmentUploadJob(val attachmentID: Long, val threadID: String, val mess
|
||||
kryo.writeObject(output, message)
|
||||
output.close()
|
||||
return Data.Builder().putLong(KEY_ATTACHMENT_ID, attachmentID)
|
||||
.putString(KEY_THREAD_ID, threadID)
|
||||
.putByteArray(KEY_MESSAGE, serializedMessage)
|
||||
.putString(KEY_MESSAGE_SEND_JOB_ID, messageSendJobID)
|
||||
.build();
|
||||
.putString(KEY_THREAD_ID, threadID)
|
||||
.putByteArray(KEY_MESSAGE, serializedMessage)
|
||||
.putString(KEY_MESSAGE_SEND_JOB_ID, messageSendJobID)
|
||||
.build();
|
||||
}
|
||||
|
||||
override fun getFactoryKey(): String {
|
||||
@ -133,9 +121,9 @@ class AttachmentUploadJob(val attachmentID: Long, val threadID: String, val mess
|
||||
}
|
||||
|
||||
class Factory: Job.Factory<AttachmentUploadJob> {
|
||||
|
||||
override fun create(data: Data): AttachmentUploadJob {
|
||||
val serializedMessage = data.getByteArray(KEY_MESSAGE)
|
||||
//deserialize Message property
|
||||
val kryo = Kryo()
|
||||
val input = Input(serializedMessage)
|
||||
val message: Message = kryo.readObject(input, Message::class.java)
|
||||
|
@ -12,7 +12,6 @@ import org.session.libsession.utilities.ParcelableUtil;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
// TODO AC: For now parcelable objects utilize byteArrays field to store their data into.
|
||||
// Introduce a dedicated Map<String, byte[]> field specifically for parcelable needs.
|
||||
public class Data {
|
||||
|
||||
|
@ -8,15 +8,13 @@ interface Job {
|
||||
val maxFailureCount: Int
|
||||
|
||||
companion object {
|
||||
//keys used for database storage purpose
|
||||
// Keys used for database storage
|
||||
private val KEY_ID = "id"
|
||||
private val KEY_FAILURE_COUNT = "failure_count"
|
||||
}
|
||||
|
||||
fun execute()
|
||||
|
||||
//database functions
|
||||
|
||||
fun serialize(): Data
|
||||
|
||||
/**
|
||||
|
@ -1,6 +1,7 @@
|
||||
package org.session.libsession.messaging.jobs
|
||||
|
||||
interface JobDelegate {
|
||||
|
||||
fun handleJobSucceeded(job: Job)
|
||||
fun handleJobFailed(job: Job, error: Exception)
|
||||
fun handleJobFailedPermanently(job: Job, error: Exception)
|
||||
|
@ -14,19 +14,17 @@ import kotlin.math.min
|
||||
import kotlin.math.pow
|
||||
import kotlin.math.roundToLong
|
||||
|
||||
|
||||
class JobQueue : JobDelegate {
|
||||
private var hasResumedPendingJobs = false // Just for debugging
|
||||
|
||||
private val jobTimestampMap = ConcurrentHashMap<Long, AtomicInteger>()
|
||||
|
||||
private val dispatcher = Executors.newSingleThreadExecutor().asCoroutineDispatcher()
|
||||
private val scope = GlobalScope + SupervisorJob()
|
||||
private val queue = Channel<Job>(UNLIMITED)
|
||||
|
||||
val timer = Timer()
|
||||
|
||||
init {
|
||||
// process jobs
|
||||
// Process jobs
|
||||
scope.launch(dispatcher) {
|
||||
while (isActive) {
|
||||
queue.receive().let { job ->
|
||||
@ -49,7 +47,7 @@ class JobQueue : JobDelegate {
|
||||
|
||||
private fun addWithoutExecuting(job: Job) {
|
||||
// When adding multiple jobs in rapid succession, timestamps might not be good enough as a unique ID. To
|
||||
// deal with this we keep track of the number of jobs with a given timestamp and that to the end of the
|
||||
// deal with this we keep track of the number of jobs with a given timestamp and add that to the end of the
|
||||
// timestamp to make it a unique ID. We can't use a random number because we do still want to keep track
|
||||
// of the order in which the jobs were added.
|
||||
val currentTime = System.currentTimeMillis()
|
||||
@ -70,7 +68,7 @@ class JobQueue : JobDelegate {
|
||||
val allPendingJobs = MessagingConfiguration.shared.storage.getAllPendingJobs(type)
|
||||
allPendingJobs.sortedBy { it.id }.forEach { job ->
|
||||
Log.i("Jobs", "Resuming pending job of type: ${job::class.simpleName}.")
|
||||
queue.offer(job) // offer always called on unlimited capacity
|
||||
queue.offer(job) // Offer always called on unlimited capacity
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,6 @@ import org.session.libsession.messaging.sending_receiving.handle
|
||||
import org.session.libsignal.utilities.logging.Log
|
||||
|
||||
class MessageReceiveJob(val data: ByteArray, val isBackgroundPoll: Boolean, val openGroupMessageServerID: Long? = null, val openGroupID: String? = null) : Job {
|
||||
|
||||
override var delegate: JobDelegate? = null
|
||||
override var id: String? = null
|
||||
override var failureCount: Int = 0
|
||||
@ -20,7 +19,7 @@ class MessageReceiveJob(val data: ByteArray, val isBackgroundPoll: Boolean, val
|
||||
|
||||
private val RECEIVE_LOCK = Object()
|
||||
|
||||
//keys used for database storage purpose
|
||||
// Keys used for database storage
|
||||
private val KEY_DATA = "data"
|
||||
private val KEY_IS_BACKGROUND_POLL = "is_background_poll"
|
||||
private val KEY_OPEN_GROUP_MESSAGE_SERVER_ID = "openGroupMessageServerID"
|
||||
@ -68,8 +67,6 @@ class MessageReceiveJob(val data: ByteArray, val isBackgroundPoll: Boolean, val
|
||||
delegate?.handleJobFailed(this, e)
|
||||
}
|
||||
|
||||
//database functions
|
||||
|
||||
override fun serialize(): Data {
|
||||
val builder = Data.Builder().putByteArray(KEY_DATA, data)
|
||||
.putBoolean(KEY_IS_BACKGROUND_POLL, isBackgroundPoll)
|
||||
@ -83,6 +80,7 @@ class MessageReceiveJob(val data: ByteArray, val isBackgroundPoll: Boolean, val
|
||||
}
|
||||
|
||||
class Factory: Job.Factory<MessageReceiveJob> {
|
||||
|
||||
override fun create(data: Data): MessageReceiveJob {
|
||||
return MessageReceiveJob(data.getByteArray(KEY_DATA), data.getBoolean(KEY_IS_BACKGROUND_POLL), data.getLong(KEY_OPEN_GROUP_MESSAGE_SERVER_ID), data.getString(KEY_OPEN_GROUP_ID))
|
||||
}
|
||||
|
@ -11,7 +11,6 @@ import org.session.libsession.messaging.sending_receiving.MessageSender
|
||||
import org.session.libsignal.utilities.logging.Log
|
||||
|
||||
class MessageSendJob(val message: Message, val destination: Destination) : Job {
|
||||
|
||||
override var delegate: JobDelegate? = null
|
||||
override var id: String? = null
|
||||
override var failureCount: Int = 0
|
||||
@ -22,7 +21,7 @@ class MessageSendJob(val message: Message, val destination: Destination) : Job {
|
||||
val TAG = MessageSendJob::class.simpleName
|
||||
val KEY: String = "MessageSendJob"
|
||||
|
||||
//keys used for database storage purpose
|
||||
// Keys used for database storage
|
||||
private val KEY_MESSAGE = "message"
|
||||
private val KEY_DESTINATION = "destination"
|
||||
}
|
||||
@ -77,10 +76,7 @@ class MessageSendJob(val message: Message, val destination: Destination) : Job {
|
||||
delegate?.handleJobFailed(this, error)
|
||||
}
|
||||
|
||||
//database functions
|
||||
|
||||
override fun serialize(): Data {
|
||||
//serialize Message and Destination properties
|
||||
val kryo = Kryo()
|
||||
kryo.isRegistrationRequired = false
|
||||
val output = Output(ByteArray(4096), -1) // maxBufferSize '-1' will dynamically grow internally if we run out of room serializing the message
|
||||
@ -92,8 +88,8 @@ class MessageSendJob(val message: Message, val destination: Destination) : Job {
|
||||
output.close()
|
||||
val serializedDestination = output.toBytes()
|
||||
return Data.Builder().putByteArray(KEY_MESSAGE, serializedMessage)
|
||||
.putByteArray(KEY_DESTINATION, serializedDestination)
|
||||
.build();
|
||||
.putByteArray(KEY_DESTINATION, serializedDestination)
|
||||
.build();
|
||||
}
|
||||
|
||||
override fun getFactoryKey(): String {
|
||||
@ -101,10 +97,10 @@ class MessageSendJob(val message: Message, val destination: Destination) : Job {
|
||||
}
|
||||
|
||||
class Factory: Job.Factory<MessageSendJob> {
|
||||
|
||||
override fun create(data: Data): MessageSendJob {
|
||||
val serializedMessage = data.getByteArray(KEY_MESSAGE)
|
||||
val serializedDestination = data.getByteArray(KEY_DESTINATION)
|
||||
//deserialize Message and Destination properties
|
||||
val kryo = Kryo()
|
||||
var input = Input(serializedMessage)
|
||||
val message = kryo.readClassAndObject(input) as Message
|
||||
|
@ -26,7 +26,7 @@ class NotifyPNServerJob(val message: SnodeMessage) : Job {
|
||||
companion object {
|
||||
val KEY: String = "NotifyPNServerJob"
|
||||
|
||||
//keys used for database storage purpose
|
||||
// Keys used for database storage
|
||||
private val KEY_MESSAGE = "message"
|
||||
}
|
||||
|
||||
@ -61,18 +61,14 @@ class NotifyPNServerJob(val message: SnodeMessage) : Job {
|
||||
delegate?.handleJobFailed(this, error)
|
||||
}
|
||||
|
||||
//database functions
|
||||
|
||||
override fun serialize(): Data {
|
||||
//serialize SnodeMessage property
|
||||
val kryo = Kryo()
|
||||
kryo.isRegistrationRequired = false
|
||||
val serializedMessage = ByteArray(4096)
|
||||
val output = Output(serializedMessage)
|
||||
kryo.writeObject(output, message)
|
||||
output.close()
|
||||
return Data.Builder().putByteArray(KEY_MESSAGE, serializedMessage)
|
||||
.build();
|
||||
return Data.Builder().putByteArray(KEY_MESSAGE, serializedMessage).build();
|
||||
}
|
||||
|
||||
override fun getFactoryKey(): String {
|
||||
@ -80,9 +76,9 @@ class NotifyPNServerJob(val message: SnodeMessage) : Job {
|
||||
}
|
||||
|
||||
class Factory: Job.Factory<NotifyPNServerJob> {
|
||||
|
||||
override fun create(data: Data): NotifyPNServerJob {
|
||||
val serializedMessage = data.getByteArray(KEY_MESSAGE)
|
||||
//deserialize SnodeMessage property
|
||||
val kryo = Kryo()
|
||||
val input = Input(serializedMessage)
|
||||
val message: SnodeMessage = kryo.readObject(input, SnodeMessage::class.java)
|
||||
|
@ -1,7 +1,5 @@
|
||||
package org.session.libsession.messaging.jobs
|
||||
|
||||
import java.util.*
|
||||
|
||||
class SessionJobInstantiator(private val jobFactories: Map<String, Job.Factory<out Job>>) {
|
||||
|
||||
fun instantiate(jobFactoryKey: String, data: Data): Job {
|
||||
|
@ -1,7 +1,5 @@
|
||||
package org.session.libsession.messaging.jobs
|
||||
|
||||
import java.util.*
|
||||
|
||||
class SessionJobManagerFactories {
|
||||
|
||||
companion object {
|
||||
|
@ -28,15 +28,10 @@ class ClosedGroupControlMessage() : ControlMessage() {
|
||||
|
||||
var kind: Kind? = null
|
||||
|
||||
// Kind enum
|
||||
sealed class Kind {
|
||||
class New(var publicKey: ByteString, var name: String, var encryptionKeyPair: ECKeyPair?, var members: List<ByteString>, var admins: List<ByteString>) : Kind() {
|
||||
internal constructor(): this(ByteString.EMPTY, "", null, listOf(), listOf())
|
||||
}
|
||||
/// - Note: Deprecated in favor of more explicit group updates.
|
||||
class Update(var name: String, var members: List<ByteString>) : Kind() {
|
||||
internal constructor(): this("", listOf())
|
||||
}
|
||||
/// An encryption key pair encrypted for each member individually.
|
||||
///
|
||||
/// - Note: `publicKey` is only set when an encryption key pair is sent in a one-to-one context (i.e. not in a group).
|
||||
@ -53,18 +48,15 @@ class ClosedGroupControlMessage() : ControlMessage() {
|
||||
internal constructor(): this(listOf())
|
||||
}
|
||||
class MemberLeft() : Kind()
|
||||
class EncryptionKeyPairRequest(): Kind()
|
||||
|
||||
val description: String =
|
||||
when(this) {
|
||||
is New -> "new"
|
||||
is Update -> "update"
|
||||
is EncryptionKeyPair -> "encryptionKeyPair"
|
||||
is NameChange -> "nameChange"
|
||||
is MembersAdded -> "membersAdded"
|
||||
is MembersRemoved -> "membersRemoved"
|
||||
is MemberLeft -> "memberLeft"
|
||||
is EncryptionKeyPairRequest -> "encryptionKeyPairRequest"
|
||||
}
|
||||
}
|
||||
|
||||
@ -75,12 +67,11 @@ class ClosedGroupControlMessage() : ControlMessage() {
|
||||
if (!proto.hasDataMessage() || !proto.dataMessage.hasClosedGroupControlMessage()) return null
|
||||
val closedGroupControlMessageProto = proto.dataMessage?.closedGroupControlMessage!!
|
||||
val kind: Kind
|
||||
when(closedGroupControlMessageProto.type) {
|
||||
when (closedGroupControlMessageProto.type) {
|
||||
DataMessage.ClosedGroupControlMessage.Type.NEW -> {
|
||||
val publicKey = closedGroupControlMessageProto.publicKey ?: return null
|
||||
val name = closedGroupControlMessageProto.name ?: return null
|
||||
val encryptionKeyPairAsProto = closedGroupControlMessageProto.encryptionKeyPair ?: return null
|
||||
|
||||
try {
|
||||
val encryptionKeyPair = ECKeyPair(DjbECPublicKey(encryptionKeyPairAsProto.publicKey.toByteArray()), DjbECPrivateKey(encryptionKeyPairAsProto.privateKey.toByteArray()))
|
||||
kind = Kind.New(publicKey, name, encryptionKeyPair, closedGroupControlMessageProto.membersList, closedGroupControlMessageProto.adminsList)
|
||||
@ -89,10 +80,6 @@ class ClosedGroupControlMessage() : ControlMessage() {
|
||||
return null
|
||||
}
|
||||
}
|
||||
DataMessage.ClosedGroupControlMessage.Type.UPDATE -> {
|
||||
val name = closedGroupControlMessageProto.name ?: return null
|
||||
kind = Kind.Update(name, closedGroupControlMessageProto.membersList)
|
||||
}
|
||||
DataMessage.ClosedGroupControlMessage.Type.ENCRYPTION_KEY_PAIR -> {
|
||||
val publicKey = closedGroupControlMessageProto.publicKey
|
||||
val wrappers = closedGroupControlMessageProto.wrappersList.mapNotNull { KeyPairWrapper.fromProto(it) }
|
||||
@ -111,35 +98,28 @@ class ClosedGroupControlMessage() : ControlMessage() {
|
||||
DataMessage.ClosedGroupControlMessage.Type.MEMBER_LEFT -> {
|
||||
kind = Kind.MemberLeft()
|
||||
}
|
||||
DataMessage.ClosedGroupControlMessage.Type.ENCRYPTION_KEY_PAIR_REQUEST -> {
|
||||
kind = Kind.EncryptionKeyPairRequest()
|
||||
}
|
||||
}
|
||||
return ClosedGroupControlMessage(kind)
|
||||
}
|
||||
}
|
||||
|
||||
// constructor
|
||||
internal constructor(kind: Kind?) : this() {
|
||||
this.kind = kind
|
||||
}
|
||||
|
||||
// validation
|
||||
override fun isValid(): Boolean {
|
||||
if (!super.isValid()) return false
|
||||
val kind = kind ?: return false
|
||||
return when(kind) {
|
||||
is Kind.New -> {
|
||||
!kind.publicKey.isEmpty && kind.name.isNotEmpty() && kind.encryptionKeyPair!!.publicKey != null
|
||||
&& kind.encryptionKeyPair!!.privateKey != null && kind.members.isNotEmpty() && kind.admins.isNotEmpty()
|
||||
&& kind.encryptionKeyPair!!.privateKey != null && kind.members.isNotEmpty() && kind.admins.isNotEmpty()
|
||||
}
|
||||
is Kind.Update -> kind.name.isNotEmpty()
|
||||
is Kind.EncryptionKeyPair -> true
|
||||
is Kind.NameChange -> kind.name.isNotEmpty()
|
||||
is Kind.MembersAdded -> kind.members.isNotEmpty()
|
||||
is Kind.MembersRemoved -> kind.members.isNotEmpty()
|
||||
is Kind.MemberLeft -> true
|
||||
is Kind.EncryptionKeyPairRequest -> true
|
||||
}
|
||||
}
|
||||
|
||||
@ -163,11 +143,6 @@ class ClosedGroupControlMessage() : ControlMessage() {
|
||||
closedGroupControlMessage.addAllMembers(kind.members)
|
||||
closedGroupControlMessage.addAllAdmins(kind.admins)
|
||||
}
|
||||
is Kind.Update -> {
|
||||
closedGroupControlMessage.type = DataMessage.ClosedGroupControlMessage.Type.UPDATE
|
||||
closedGroupControlMessage.name = kind.name
|
||||
closedGroupControlMessage.addAllMembers(kind.members)
|
||||
}
|
||||
is Kind.EncryptionKeyPair -> {
|
||||
closedGroupControlMessage.type = DataMessage.ClosedGroupControlMessage.Type.ENCRYPTION_KEY_PAIR
|
||||
closedGroupControlMessage.publicKey = kind.publicKey
|
||||
@ -188,9 +163,6 @@ class ClosedGroupControlMessage() : ControlMessage() {
|
||||
is Kind.MemberLeft -> {
|
||||
closedGroupControlMessage.type = DataMessage.ClosedGroupControlMessage.Type.MEMBER_LEFT
|
||||
}
|
||||
is Kind.EncryptionKeyPairRequest -> {
|
||||
// TODO: closedGroupControlMessage.type = SignalServiceProtos.ClosedGroupUpdateV2.Type.ENCRYPTION_KEY_PAIR_REQUEST
|
||||
}
|
||||
}
|
||||
val contentProto = SignalServiceProtos.Content.newBuilder()
|
||||
val dataMessageProto = DataMessage.newBuilder()
|
||||
@ -199,7 +171,7 @@ class ClosedGroupControlMessage() : ControlMessage() {
|
||||
setGroupContext(dataMessageProto)
|
||||
// Expiration timer
|
||||
// TODO: We * want * expiration timer updates to be explicit. But currently Android will disable the expiration timer for a conversation
|
||||
// if it receives a message without the current expiration timer value attached to it...
|
||||
// if it receives a message without the current expiration timer value attached to it...
|
||||
dataMessageProto.expireTimer = Recipient.from(MessagingConfiguration.shared.context, Address.fromSerialized(GroupUtil.doubleEncodeGroupID(recipient!!)), false).expireMessages
|
||||
contentProto.dataMessage = dataMessageProto.build()
|
||||
return contentProto.build()
|
||||
|
@ -185,14 +185,14 @@ open class DotNetAPI {
|
||||
/**
|
||||
* Blocks the calling thread.
|
||||
*/
|
||||
fun downloadFile(destination: File, url: String, maxSize: Int, listener: SignalServiceAttachment.ProgressListener?) {
|
||||
fun downloadFile(destination: File, url: String, listener: SignalServiceAttachment.ProgressListener?) {
|
||||
val outputStream = FileOutputStream(destination) // Throws
|
||||
var remainingAttempts = 4
|
||||
var exception: Exception? = null
|
||||
while (remainingAttempts > 0) {
|
||||
remainingAttempts -= 1
|
||||
try {
|
||||
downloadFile(outputStream, url, maxSize, listener)
|
||||
downloadFile(outputStream, url, listener)
|
||||
exception = null
|
||||
break
|
||||
} catch (e: Exception) {
|
||||
@ -205,7 +205,7 @@ open class DotNetAPI {
|
||||
/**
|
||||
* Blocks the calling thread.
|
||||
*/
|
||||
fun downloadFile(outputStream: OutputStream, url: String, maxSize: Int, listener: SignalServiceAttachment.ProgressListener?) {
|
||||
fun downloadFile(outputStream: OutputStream, url: String, listener: SignalServiceAttachment.ProgressListener?) {
|
||||
// We need to throw a PushNetworkException or NonSuccessfulResponseCodeException
|
||||
// because the underlying Signal logic requires these to work correctly
|
||||
val oldPrefixedHost = "https://" + HttpUrl.get(url).host()
|
||||
@ -228,7 +228,7 @@ open class DotNetAPI {
|
||||
throw PushNetworkException("Missing response body.")
|
||||
}
|
||||
val body = Base64.decode(result)
|
||||
if (body.size > maxSize) {
|
||||
if (body.size > FileServerAPI.maxFileSize) {
|
||||
Log.d("Loki", "Attachment size limit exceeded.")
|
||||
throw PushNetworkException("Max response size exceeded.")
|
||||
}
|
||||
@ -239,7 +239,7 @@ open class DotNetAPI {
|
||||
while (bytes >= 0) {
|
||||
outputStream.write(buffer, 0, bytes)
|
||||
count += bytes
|
||||
if (count > maxSize) {
|
||||
if (count > FileServerAPI.maxFileSize) {
|
||||
Log.d("Loki", "Attachment size limit exceeded.")
|
||||
throw PushNetworkException("Max response size exceeded.")
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
package org.session.libsession.utilities;
|
||||
|
||||
|
||||
import java.util.concurrent.LinkedBlockingDeque;
|
||||
|
||||
public class LinkedBlockingLifoQueue<E> extends LinkedBlockingDeque<E> {
|
||||
|
@ -3,7 +3,6 @@ package org.session.libsession.utilities
|
||||
import android.telephony.PhoneNumberUtils
|
||||
import android.util.Patterns
|
||||
|
||||
|
||||
object NumberUtil {
|
||||
private val emailPattern = Patterns.EMAIL_ADDRESS
|
||||
|
||||
|
@ -14,6 +14,7 @@ class SSKEnvironment(
|
||||
val notificationManager: MessageNotifier,
|
||||
val messageExpirationManager: MessageExpirationManagerProtocol
|
||||
) {
|
||||
|
||||
interface TypingIndicatorsProtocol {
|
||||
fun didReceiveTypingStartedMessage(context: Context, threadId: Long, author: Address, device: Int)
|
||||
fun didReceiveTypingStoppedMessage(context: Context, threadId: Long, author: Address, device: Int, isReplacedByIncomingMessage: Boolean)
|
||||
|
@ -5,6 +5,7 @@ import org.session.libsignal.utilities.concurrent.ListenableFuture.Listener;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
public abstract class AssertedSuccessListener<T> implements Listener<T> {
|
||||
|
||||
@Override
|
||||
public void onFailure(ExecutionException e) {
|
||||
throw new AssertionError(e);
|
||||
|
@ -30,5 +30,4 @@ public final class DynamicLanguageContextWrapper {
|
||||
copy.setLocale(locale);
|
||||
return copy;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -7,8 +7,7 @@ import java.util.Locale;
|
||||
|
||||
public final class LanguageString {
|
||||
|
||||
private LanguageString() {
|
||||
}
|
||||
private LanguageString() { }
|
||||
|
||||
/**
|
||||
* @param languageString String in format language_REGION, e.g. en_US
|
||||
|
@ -1,6 +1,5 @@
|
||||
package org.session.libsession.utilities.preferences;
|
||||
|
||||
|
||||
import android.content.Context;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
@ -10,7 +10,6 @@ public abstract class SnackbarAsyncTask<Params>
|
||||
extends AsyncTask<Params, Void, Void>
|
||||
implements View.OnClickListener
|
||||
{
|
||||
|
||||
private final View view;
|
||||
private final String snackbarText;
|
||||
private final String snackbarActionText;
|
||||
|
@ -1,6 +1,5 @@
|
||||
package org.session.libsession.utilities.views;
|
||||
|
||||
|
||||
import android.view.ViewStub;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
Loading…
x
Reference in New Issue
Block a user