kotlin impl of SignalServiceAttachment classes
							parent
							
								
									d7b0c84f22
								
							
						
					
					
						commit
						26b2ead673
					
				| @ -1,75 +0,0 @@ | ||||
| package org.session.libsession.database.dto | ||||
| 
 | ||||
| import android.util.Size | ||||
| import com.google.protobuf.ByteString | ||||
| import org.session.libsignal.service.internal.push.SignalServiceProtos | ||||
| import kotlin.math.round | ||||
| 
 | ||||
| class DatabaseAttachmentDTO { | ||||
|     var attachmentId: Long = 0 | ||||
| 
 | ||||
|     var contentType: String? = null | ||||
| 
 | ||||
|     var fileName: String? = null | ||||
| 
 | ||||
|     var url: String? = null | ||||
| 
 | ||||
|     var caption: String? = null | ||||
| 
 | ||||
|     var size: Int = 0 | ||||
| 
 | ||||
|     var key: ByteString? = null | ||||
| 
 | ||||
|     var digest: ByteString? = null | ||||
| 
 | ||||
|     var flags: Int = 0 | ||||
| 
 | ||||
|     var width: Int = 0 | ||||
| 
 | ||||
|     var height: Int = 0 | ||||
| 
 | ||||
|     val isVoiceNote: Boolean = false | ||||
| 
 | ||||
|     var shouldHaveImageSize: Boolean = false | ||||
| 
 | ||||
|     val isUploaded: Boolean = false | ||||
| 
 | ||||
|     fun toProto(): SignalServiceProtos.AttachmentPointer? { | ||||
|         val builder = SignalServiceProtos.AttachmentPointer.newBuilder() | ||||
|         builder.contentType = this.contentType | ||||
| 
 | ||||
|         if (!this.fileName.isNullOrEmpty()) { | ||||
|             builder.fileName = this.fileName | ||||
|         } | ||||
|         if (!this.caption.isNullOrEmpty()) { | ||||
|             builder.caption = this.caption | ||||
|         } | ||||
| 
 | ||||
|         builder.size = this.size | ||||
|         builder.key = this.key | ||||
|         builder.digest = this.digest | ||||
|         builder.flags = if (this.isVoiceNote) SignalServiceProtos.AttachmentPointer.Flags.VOICE_MESSAGE.number else 0 | ||||
| 
 | ||||
|         //TODO I did copy the behavior of iOS below, not sure if that's relevant here... | ||||
|         if (this.shouldHaveImageSize) { | ||||
|             if (this.width < Int.MAX_VALUE && this.height < Int.MAX_VALUE) { | ||||
|                 val imageSize= Size(this.width, this.height) | ||||
|                 val imageWidth = round(imageSize.width.toDouble()) | ||||
|                 val imageHeight = round(imageSize.height.toDouble()) | ||||
|                 if (imageWidth > 0 && imageHeight > 0) { | ||||
|                     builder.width = imageWidth.toInt() | ||||
|                     builder.height = imageHeight.toInt() | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         builder.url = this.url | ||||
| 
 | ||||
|         try { | ||||
|             return builder.build() | ||||
|         } catch (e: Exception) { | ||||
|             return null | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| } | ||||
| @ -0,0 +1,123 @@ | ||||
| package org.session.libsession.messaging.sending_receiving.attachments | ||||
| 
 | ||||
| import com.google.protobuf.ByteString | ||||
| import org.session.libsignal.libsignal.util.guava.Optional | ||||
| import org.session.libsignal.service.api.messages.SignalServiceAttachment | ||||
| import java.io.InputStream | ||||
| 
 | ||||
| abstract class SignalServiceAttachment protected constructor(val contentType: String?) { | ||||
| 
 | ||||
|     var attachmentId: Long = 0 | ||||
|     var isGif: Boolean = false | ||||
|     var isImage: Boolean = false | ||||
|     var isVideo: Boolean = false | ||||
|     var isAudio: Boolean = false | ||||
|     var url: String? = null | ||||
|     var key: ByteString? = null | ||||
| 
 | ||||
|     abstract fun isStream(): Boolean | ||||
|     abstract fun isPointer(): Boolean | ||||
|     fun asStream(): SignalServiceAttachmentStream { | ||||
|         return this as SignalServiceAttachmentStream | ||||
|     } | ||||
| 
 | ||||
|     fun asPointer(): SignalServiceAttachmentPointer { | ||||
|         return this as SignalServiceAttachmentPointer | ||||
|     } | ||||
| 
 | ||||
|     fun shouldHaveImageSize(): Boolean { | ||||
|         return (isVideo || isImage || isGif); | ||||
|     } | ||||
| 
 | ||||
|     class Builder internal constructor() { | ||||
|         private var inputStream: InputStream? = null | ||||
|         private var contentType: String? = null | ||||
|         private var fileName: String? = null | ||||
|         private var length: Long = 0 | ||||
|         private var listener: SignalServiceAttachment.ProgressListener? = null | ||||
|         private var voiceNote = false | ||||
|         private var width = 0 | ||||
|         private var height = 0 | ||||
|         private var caption: String? = null | ||||
|         fun withStream(inputStream: InputStream?): Builder { | ||||
|             this.inputStream = inputStream | ||||
|             return this | ||||
|         } | ||||
| 
 | ||||
|         fun withContentType(contentType: String?): Builder { | ||||
|             this.contentType = contentType | ||||
|             return this | ||||
|         } | ||||
| 
 | ||||
|         fun withLength(length: Long): Builder { | ||||
|             this.length = length | ||||
|             return this | ||||
|         } | ||||
| 
 | ||||
|         fun withFileName(fileName: String?): Builder { | ||||
|             this.fileName = fileName | ||||
|             return this | ||||
|         } | ||||
| 
 | ||||
|         fun withListener(listener: SignalServiceAttachment.ProgressListener?): Builder { | ||||
|             this.listener = listener | ||||
|             return this | ||||
|         } | ||||
| 
 | ||||
|         fun withVoiceNote(voiceNote: Boolean): Builder { | ||||
|             this.voiceNote = voiceNote | ||||
|             return this | ||||
|         } | ||||
| 
 | ||||
|         fun withWidth(width: Int): Builder { | ||||
|             this.width = width | ||||
|             return this | ||||
|         } | ||||
| 
 | ||||
|         fun withHeight(height: Int): Builder { | ||||
|             this.height = height | ||||
|             return this | ||||
|         } | ||||
| 
 | ||||
|         fun withCaption(caption: String?): Builder { | ||||
|             this.caption = caption | ||||
|             return this | ||||
|         } | ||||
| 
 | ||||
|         fun build(): SignalServiceAttachmentStream { | ||||
|             requireNotNull(inputStream) { "Must specify stream!" } | ||||
|             requireNotNull(contentType) { "No content type specified!" } | ||||
|             require(length != 0L) { "No length specified!" } | ||||
|             return SignalServiceAttachmentStream(inputStream, contentType, length, Optional.fromNullable(fileName), voiceNote, Optional.absent(), width, height, Optional.fromNullable(caption), listener) | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * An interface to receive progress information on upload/download of | ||||
|      * an attachment. | ||||
|      */ | ||||
|     /*interface ProgressListener { | ||||
|         /** | ||||
|          * Called on a progress change event. | ||||
|          * | ||||
|          * @param total The total amount to transmit/receive in bytes. | ||||
|          * @param progress The amount that has been transmitted/received in bytes thus far | ||||
|          */ | ||||
|         fun onAttachmentProgress(total: Long, progress: Long) | ||||
|     }*/ | ||||
| 
 | ||||
|     companion object { | ||||
|         @JvmStatic | ||||
|         fun newStreamBuilder(): Builder { | ||||
|             return Builder() | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| // matches values in AttachmentDatabase.java | ||||
| enum class AttachmentState(val value: Int) { | ||||
|     DONE(0), | ||||
|     STARTED(1), | ||||
|     PENDING(2), | ||||
|     FAILED(3) | ||||
| } | ||||
| @ -0,0 +1,30 @@ | ||||
| /* | ||||
|  * Copyright (C) 2014-2017 Open Whisper Systems | ||||
|  * | ||||
|  * Licensed according to the LICENSE file in this repository. | ||||
|  */ | ||||
| package org.session.libsession.messaging.sending_receiving.attachments | ||||
| 
 | ||||
| import org.session.libsignal.libsignal.util.guava.Optional | ||||
| import org.session.libsignal.service.api.messages.SignalServiceAttachment | ||||
| 
 | ||||
| /** | ||||
|  * Represents a received SignalServiceAttachment "handle."  This | ||||
|  * is a pointer to the actual attachment content, which needs to be | ||||
|  * retrieved using [SignalServiceMessageReceiver.retrieveAttachment] | ||||
|  * | ||||
|  * @author Moxie Marlinspike | ||||
|  */ | ||||
| class SignalServiceAttachmentPointer(val id: Long, contentType: String?, val key: ByteArray?, | ||||
|                                      val size: Optional<Int>, val preview: Optional<ByteArray>, | ||||
|                                      val width: Int, val height: Int, | ||||
|                                      val digest: Optional<ByteArray>, val fileName: Optional<String>, | ||||
|                                      val voiceNote: Boolean, val caption: Optional<String>, val url: String) : SignalServiceAttachment(contentType) { | ||||
|     override fun isStream(): Boolean { | ||||
|         return false | ||||
|     } | ||||
| 
 | ||||
|     override fun isPointer(): Boolean { | ||||
|         return true | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,75 @@ | ||||
| /** | ||||
|  * Copyright (C) 2014-2016 Open Whisper Systems | ||||
|  * | ||||
|  * Licensed according to the LICENSE file in this repository. | ||||
|  */ | ||||
| package org.session.libsession.messaging.sending_receiving.attachments | ||||
| 
 | ||||
| import android.util.Size | ||||
| import com.google.protobuf.ByteString | ||||
| import org.session.libsignal.libsignal.util.guava.Optional | ||||
| import org.session.libsignal.service.internal.push.SignalServiceProtos | ||||
| import org.session.libsignal.service.api.messages.SignalServiceAttachment as SAttachment | ||||
| import java.io.InputStream | ||||
| import kotlin.math.round | ||||
| 
 | ||||
| /** | ||||
|  * Represents a local SignalServiceAttachment to be sent. | ||||
|  */ | ||||
| class SignalServiceAttachmentStream(val inputStream: InputStream?, contentType: String?, val length: Long, val fileName: Optional<String?>?, val voiceNote: Boolean, val preview: Optional<ByteArray?>, val width: Int, val height: Int, val caption: Optional<String?>, val listener: SAttachment.ProgressListener?) : SignalServiceAttachment(contentType) { | ||||
| 
 | ||||
|     constructor(inputStream: InputStream?, contentType: String?, length: Long, fileName: Optional<String?>?, voiceNote: Boolean, listener: SAttachment.ProgressListener?) : this(inputStream, contentType, length, fileName, voiceNote, Optional.absent<ByteArray?>(), 0, 0, Optional.absent<String?>(), listener) {} | ||||
| 
 | ||||
|     // Though now required, `digest` may be null for pre-existing records or from | ||||
|     // messages received from other clients | ||||
|     var digest: ByteArray? = null | ||||
| 
 | ||||
|     // This only applies for attachments being uploaded. | ||||
|     var isUploaded: Boolean = false | ||||
| 
 | ||||
|     override fun isStream(): Boolean { | ||||
|         return true | ||||
|     } | ||||
| 
 | ||||
|     override fun isPointer(): Boolean { | ||||
|         return false | ||||
|     } | ||||
| 
 | ||||
|     fun toProto(): SignalServiceProtos.AttachmentPointer? { | ||||
|         val builder = SignalServiceProtos.AttachmentPointer.newBuilder() | ||||
|         builder.contentType = this.contentType | ||||
| 
 | ||||
|         if (!this.fileName?.get().isNullOrEmpty()) { | ||||
|             builder.fileName = this.fileName?.get() | ||||
|         } | ||||
|         if (!this.caption.get().isNullOrEmpty()) { | ||||
|             builder.caption = this.caption.get() | ||||
|         } | ||||
| 
 | ||||
|         builder.size = this.length.toInt() | ||||
|         builder.key = this.key | ||||
|         builder.digest = ByteString.copyFrom(this.digest) | ||||
|         builder.flags = if (this.voiceNote) SignalServiceProtos.AttachmentPointer.Flags.VOICE_MESSAGE.number else 0 | ||||
| 
 | ||||
|         //TODO I did copy the behavior of iOS below, not sure if that's relevant here... | ||||
|         if (this.shouldHaveImageSize()) { | ||||
|             if (this.width < Int.MAX_VALUE && this.height < Int.MAX_VALUE) { | ||||
|                 val imageSize= Size(this.width, this.height) | ||||
|                 val imageWidth = round(imageSize.width.toDouble()) | ||||
|                 val imageHeight = round(imageSize.height.toDouble()) | ||||
|                 if (imageWidth > 0 && imageHeight > 0) { | ||||
|                     builder.width = imageWidth.toInt() | ||||
|                     builder.height = imageHeight.toInt() | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         builder.url = this.url | ||||
| 
 | ||||
|         try { | ||||
|             return builder.build() | ||||
|         } catch (e: Exception) { | ||||
|             return null | ||||
|         } | ||||
|     } | ||||
| } | ||||
					Loading…
					
					
				
		Reference in New Issue