diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationActivity.java b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationActivity.java index be261012cf..d6db6ec16d 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationActivity.java +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationActivity.java @@ -102,7 +102,6 @@ import org.session.libsession.utilities.recipients.RecipientModifiedListener; import org.session.libsession.utilities.ExpirationUtil; import org.session.libsession.utilities.GroupUtil; import org.session.libsession.utilities.MediaTypes; -import org.session.libsession.utilities.SSKEnvironment; import org.session.libsession.utilities.ServiceUtil; import org.session.libsession.utilities.TextSecurePreferences; import org.session.libsession.utilities.Util; @@ -165,8 +164,8 @@ import org.thoughtcrime.securesms.loki.views.MentionCandidateSelectionView; import org.thoughtcrime.securesms.loki.views.ProfilePictureView; import org.thoughtcrime.securesms.mediasend.Media; import org.thoughtcrime.securesms.mediasend.MediaSendActivity; -import org.thoughtcrime.securesms.mms.AttachmentManager; -import org.thoughtcrime.securesms.mms.AttachmentManager.MediaType; +import org.thoughtcrime.securesms.conversation.v2.utilities.AttachmentManager; +import org.thoughtcrime.securesms.conversation.v2.utilities.AttachmentManager.MediaType; import org.thoughtcrime.securesms.mms.AudioSlide; import org.thoughtcrime.securesms.mms.GifSlide; import org.thoughtcrime.securesms.mms.GlideApp; diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt index f7ffe3060e..a6e3c5f9d6 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt @@ -8,8 +8,9 @@ import android.database.Cursor import android.graphics.Rect import android.graphics.Typeface import android.net.Uri -import android.os.Bundle +import android.os.* import android.util.Log +import android.util.Pair import android.util.TypedValue import android.view.* import android.widget.RelativeLayout @@ -39,10 +40,15 @@ import org.session.libsession.messaging.messages.visible.VisibleMessage import org.session.libsession.messaging.open_groups.OpenGroupAPIV2 import org.session.libsession.messaging.sending_receiving.MessageSender import org.session.libsession.messaging.sending_receiving.attachments.Attachment +import org.session.libsession.utilities.MediaTypes +import org.session.libsession.utilities.ServiceUtil import org.session.libsession.utilities.TextSecurePreferences +import org.session.libsession.utilities.concurrent.AssertedSuccessListener import org.session.libsignal.utilities.ListenableFuture +import org.session.libsignal.utilities.guava.Optional import org.thoughtcrime.securesms.ApplicationContext import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity +import org.thoughtcrime.securesms.audio.AudioRecorder import org.thoughtcrime.securesms.contactshare.SimpleTextWatcher import org.thoughtcrime.securesms.conversation.v2.dialogs.* import org.thoughtcrime.securesms.conversation.v2.input_bar.InputBarButton @@ -52,6 +58,7 @@ import org.thoughtcrime.securesms.conversation.v2.input_bar.mentions.MentionCand import org.thoughtcrime.securesms.conversation.v2.menus.ConversationActionModeCallback import org.thoughtcrime.securesms.conversation.v2.menus.ConversationMenuHelper import org.thoughtcrime.securesms.conversation.v2.messages.VisibleMessageView +import org.thoughtcrime.securesms.conversation.v2.utilities.AttachmentManager import org.thoughtcrime.securesms.database.DatabaseFactory import org.thoughtcrime.securesms.database.DraftDatabase import org.thoughtcrime.securesms.database.DraftDatabase.Drafts @@ -65,6 +72,7 @@ import org.thoughtcrime.securesms.mediasend.Media import org.thoughtcrime.securesms.mediasend.MediaSendActivity import org.thoughtcrime.securesms.mms.* import org.thoughtcrime.securesms.notifications.MarkReadReceiver +import org.thoughtcrime.securesms.providers.BlobProvider import org.thoughtcrime.securesms.util.DateUtils import org.thoughtcrime.securesms.util.MediaUtil import java.util.* @@ -83,6 +91,9 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe private var actionMode: ActionMode? = null private var unreadCount = 0 // Attachments + private val audioRecorder = AudioRecorder(this) + private val stopAudioHandler = Handler(Looper.getMainLooper()) + private val stopVoiceMessageRecordingTask = Runnable { stopVoiceMessageRecording() } private val attachmentManager by lazy { AttachmentManager(this, this) } private var isLockViewExpanded = false private var isShowingAttachmentOptions = false @@ -621,6 +632,7 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe inputBarRecordingView.lock() } else { hideVoiceMessageUI() + stopVoiceMessageRecording() } } @@ -712,7 +724,7 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe } override fun onAttachmentChanged() { - // TODO: Do we need to do something here? + // Do nothing } override fun onActivityResult(requestCode: Int, resultCode: Int, intent: Intent?) { @@ -777,6 +789,31 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe private fun prepMediaForSending(uri: Uri, type: AttachmentManager.MediaType, width: Int?, height: Int?): ListenableFuture { return attachmentManager.setMedia(glide, uri, type, MediaConstraints.getPushMediaConstraints(), width ?: 0, height ?: 0) } + + override fun startRecordingVoiceMessage() { + window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) + audioRecorder.startRecording() + stopAudioHandler.postDelayed(stopVoiceMessageRecordingTask, 60000) // Limit voice messages to 1 minute each + } + + fun stopVoiceMessageRecording() { + window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) + val future = audioRecorder.stopRecording() + stopAudioHandler.removeCallbacks(stopVoiceMessageRecordingTask) + future.addListener(object : ListenableFuture.Listener> { + + override fun onSuccess(result: Pair) { + val audioSlide = AudioSlide(this@ConversationActivityV2, result.first, result.second!!, MediaTypes.AUDIO_AAC, true) + val slideDeck = SlideDeck() + slideDeck.addSlide(audioSlide) + sendAttachments(slideDeck.asAttachments(), null) + } + + override fun onFailure(e: ExecutionException) { + Toast.makeText(this@ConversationActivityV2, R.string.ConversationActivity_unable_to_record_audio, Toast.LENGTH_LONG).show() + } + }) + } // endregion // region General diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/input_bar/InputBar.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/input_bar/InputBar.kt index 2270aef2ee..86d39ffd83 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/input_bar/InputBar.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/input_bar/InputBar.kt @@ -52,7 +52,10 @@ class InputBar : RelativeLayout, InputBarEditTextDelegate, QuoteViewDelegate, Li // Microphone button microphoneOrSendButtonContainer.addView(microphoneButton) microphoneButton.layoutParams = RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT) - microphoneButton.onLongPress = { showVoiceMessageUI() } + microphoneButton.onLongPress = { + showVoiceMessageUI() + startRecordingVoiceMessage() + } microphoneButton.onMove = { delegate?.onMicrophoneButtonMove(it) } microphoneButton.onCancel = { delegate?.onMicrophoneButtonCancel(it) } microphoneButton.onUp = { delegate?.onMicrophoneButtonUp(it) } @@ -96,6 +99,10 @@ class InputBar : RelativeLayout, InputBarEditTextDelegate, QuoteViewDelegate, Li delegate?.showVoiceMessageUI() } + private fun startRecordingVoiceMessage() { + delegate?.startRecordingVoiceMessage() + } + // Drafting quotes and drafting link previews is mutually exclusive, i.e. you can't draft // a quote and a link preview at the same time. @@ -159,6 +166,7 @@ interface InputBarDelegate { fun inputBarEditTextContentChanged(newContent: CharSequence) fun toggleAttachmentOptions() fun showVoiceMessageUI() + fun startRecordingVoiceMessage() fun onMicrophoneButtonMove(event: MotionEvent) fun onMicrophoneButtonCancel(event: MotionEvent) fun onMicrophoneButtonUp(event: MotionEvent) diff --git a/app/src/main/java/org/thoughtcrime/securesms/mms/AttachmentManager.java b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/utilities/AttachmentManager.java similarity index 94% rename from app/src/main/java/org/thoughtcrime/securesms/mms/AttachmentManager.java rename to app/src/main/java/org/thoughtcrime/securesms/conversation/v2/utilities/AttachmentManager.java index 907b98d2b4..a5298305a0 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/mms/AttachmentManager.java +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/utilities/AttachmentManager.java @@ -14,7 +14,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package org.thoughtcrime.securesms.mms; +package org.thoughtcrime.securesms.conversation.v2.utilities; import android.Manifest; import android.annotation.SuppressLint; @@ -23,29 +23,31 @@ import android.content.ActivityNotFoundException; import android.content.Context; import android.content.Intent; import android.database.Cursor; -import android.graphics.PorterDuff; import android.net.Uri; import android.os.AsyncTask; -import android.provider.ContactsContract; import android.provider.MediaStore; import android.provider.OpenableColumns; import android.text.TextUtils; import android.util.Pair; -import android.view.View; import android.widget.Toast; import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import org.thoughtcrime.securesms.MediaPreviewActivity; -import org.thoughtcrime.securesms.loki.views.MessageAudioView; -import org.thoughtcrime.securesms.components.DocumentView; -import org.thoughtcrime.securesms.components.RemovableEditableMediaView; -import org.thoughtcrime.securesms.conversation.v2.utilities.ThumbnailView; import org.session.libsignal.utilities.NoExternalStorageException; import org.thoughtcrime.securesms.giph.ui.GiphyActivity; import org.session.libsignal.utilities.Log; import org.thoughtcrime.securesms.mediasend.MediaSendActivity; +import org.thoughtcrime.securesms.mms.AudioSlide; +import org.thoughtcrime.securesms.mms.DocumentSlide; +import org.thoughtcrime.securesms.mms.GifSlide; +import org.thoughtcrime.securesms.mms.GlideRequests; +import org.thoughtcrime.securesms.mms.ImageSlide; +import org.thoughtcrime.securesms.mms.MediaConstraints; +import org.thoughtcrime.securesms.mms.PartAuthority; +import org.thoughtcrime.securesms.mms.Slide; +import org.thoughtcrime.securesms.mms.SlideDeck; +import org.thoughtcrime.securesms.mms.VideoSlide; import org.thoughtcrime.securesms.permissions.Permissions; import org.thoughtcrime.securesms.providers.BlobProvider; import org.session.libsignal.utilities.ExternalStorageUtil; @@ -53,13 +55,8 @@ import org.thoughtcrime.securesms.util.FileProviderUtil; import org.thoughtcrime.securesms.util.MediaUtil; import org.session.libsignal.utilities.guava.Optional; -import org.session.libsession.messaging.sending_receiving.attachments.Attachment; import org.session.libsession.utilities.recipients.Recipient; -import org.session.libsession.utilities.ThemeUtil; -import org.session.libsession.utilities.ViewUtil; -import org.session.libsession.utilities.Stub; import org.session.libsignal.utilities.ListenableFuture; -import org.session.libsignal.utilities.ListenableFuture.Listener; import org.session.libsignal.utilities.SettableFuture; import java.io.File; @@ -67,7 +64,6 @@ import java.io.IOException; import java.util.Iterator; import java.util.LinkedList; import java.util.List; -import java.util.concurrent.ExecutionException; import network.loki.messenger.R; @@ -244,7 +240,8 @@ public class AttachmentManager { return result; } - public @NonNull SlideDeck buildSlideDeck() { + public @NonNull + SlideDeck buildSlideDeck() { SlideDeck deck = new SlideDeck(); if (slide.isPresent()) deck.addSlide(slide.get()); return deck;