mirror of
https://github.com/signalapp/Signal-Android.git
synced 2025-12-22 20:18:36 +00:00
@@ -5,6 +5,7 @@ interface AudioRecordingHandler {
|
|||||||
fun onRecordReleased()
|
fun onRecordReleased()
|
||||||
fun onRecordCanceled(byUser: Boolean)
|
fun onRecordCanceled(byUser: Boolean)
|
||||||
fun onRecordLocked()
|
fun onRecordLocked()
|
||||||
|
fun onRecordSaved()
|
||||||
fun onRecordMoved(offsetX: Float, absoluteX: Float)
|
fun onRecordMoved(offsetX: Float, absoluteX: Float)
|
||||||
fun onRecordPermissionRequired()
|
fun onRecordPermissionRequired()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -62,7 +62,6 @@ import org.thoughtcrime.securesms.database.model.MmsMessageRecord;
|
|||||||
import org.thoughtcrime.securesms.database.model.Quote;
|
import org.thoughtcrime.securesms.database.model.Quote;
|
||||||
import org.thoughtcrime.securesms.database.model.StickerRecord;
|
import org.thoughtcrime.securesms.database.model.StickerRecord;
|
||||||
import org.thoughtcrime.securesms.keyboard.KeyboardPage;
|
import org.thoughtcrime.securesms.keyboard.KeyboardPage;
|
||||||
import org.thoughtcrime.securesms.keyvalue.SignalStore;
|
|
||||||
import org.thoughtcrime.securesms.linkpreview.LinkPreview;
|
import org.thoughtcrime.securesms.linkpreview.LinkPreview;
|
||||||
import org.thoughtcrime.securesms.linkpreview.LinkPreviewRepository;
|
import org.thoughtcrime.securesms.linkpreview.LinkPreviewRepository;
|
||||||
import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader;
|
import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader;
|
||||||
@@ -625,10 +624,21 @@ public class InputPanel extends ConstraintLayout
|
|||||||
if (listener != null) listener.onRecorderLocked();
|
if (listener != null) listener.onRecorderLocked();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onRecordSaved() {
|
||||||
|
Log.d(TAG, "Recording saved");
|
||||||
|
onRecordHideEvent();
|
||||||
|
if (listener != null) listener.onRecorderSaveDraft();
|
||||||
|
}
|
||||||
|
|
||||||
public void onPause() {
|
public void onPause() {
|
||||||
this.microphoneRecorderView.cancelAction(false);
|
this.microphoneRecorderView.cancelAction(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void onSaveRecordDraft() {
|
||||||
|
this.microphoneRecorderView.saveAction();
|
||||||
|
}
|
||||||
|
|
||||||
public @NonNull Observer<VoiceNotePlaybackState> getPlaybackStateObserver() {
|
public @NonNull Observer<VoiceNotePlaybackState> getPlaybackStateObserver() {
|
||||||
return voiceNoteDraftView.getPlaybackStateObserver();
|
return voiceNoteDraftView.getPlaybackStateObserver();
|
||||||
}
|
}
|
||||||
@@ -692,7 +702,7 @@ public class InputPanel extends ConstraintLayout
|
|||||||
return microphoneRecorderView.isRecordingLocked();
|
return microphoneRecorderView.isRecordingLocked();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void releaseRecordingLock() {
|
public void releaseRecordingLockAndSend() {
|
||||||
microphoneRecorderView.unlockAction();
|
microphoneRecorderView.unlockAction();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -794,6 +804,7 @@ public class InputPanel extends ConstraintLayout
|
|||||||
public interface Listener extends VoiceNoteDraftView.Listener {
|
public interface Listener extends VoiceNoteDraftView.Listener {
|
||||||
void onRecorderStarted();
|
void onRecorderStarted();
|
||||||
void onRecorderLocked();
|
void onRecorderLocked();
|
||||||
|
void onRecorderSaveDraft();
|
||||||
void onRecorderFinished();
|
void onRecorderFinished();
|
||||||
void onRecorderCanceled(boolean byUser);
|
void onRecorderCanceled(boolean byUser);
|
||||||
void onRecorderPermissionRequired();
|
void onRecorderPermissionRequired();
|
||||||
|
|||||||
@@ -70,6 +70,17 @@ public final class MicrophoneRecorderView extends FrameLayout implements View.On
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void saveAction() {
|
||||||
|
if (state != State.NOT_RUNNING) {
|
||||||
|
state = State.NOT_RUNNING;
|
||||||
|
hideUi();
|
||||||
|
|
||||||
|
if (handler != null) {
|
||||||
|
handler.onRecordSaved();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isRecordingLocked() {
|
public boolean isRecordingLocked() {
|
||||||
return state == State.RUNNING_LOCKED;
|
return state == State.RUNNING_LOCKED;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,19 +41,11 @@ class SendButton(context: Context, attributeSet: AttributeSet?) : AppCompatImage
|
|||||||
if (!isEnabled) {
|
if (!isEnabled) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
scheduledSendListener?.onSendScheduled()
|
||||||
val scheduleListener = scheduledSendListener
|
return true
|
||||||
|
|
||||||
return if (scheduleListener?.canSchedule() == true) {
|
|
||||||
scheduleListener.onSendScheduled()
|
|
||||||
true
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ScheduledSendListener {
|
interface ScheduledSendListener {
|
||||||
fun onSendScheduled()
|
fun onSendScheduled()
|
||||||
fun canSchedule(): Boolean
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1840,7 +1840,8 @@ class ConversationFragment :
|
|||||||
slide: Slide? = null,
|
slide: Slide? = null,
|
||||||
contacts: List<Contact> = emptyList(),
|
contacts: List<Contact> = emptyList(),
|
||||||
quote: QuoteModel? = null,
|
quote: QuoteModel? = null,
|
||||||
clearCompose: Boolean = true
|
clearCompose: Boolean = true,
|
||||||
|
scheduledDate: Long = -1
|
||||||
) {
|
) {
|
||||||
sendMessage(
|
sendMessage(
|
||||||
slideDeck = slide?.let { SlideDeck().apply { addSlide(slide) } },
|
slideDeck = slide?.let { SlideDeck().apply { addSlide(slide) } },
|
||||||
@@ -1852,7 +1853,8 @@ class ConversationFragment :
|
|||||||
messageToEdit = null,
|
messageToEdit = null,
|
||||||
quote = quote,
|
quote = quote,
|
||||||
linkPreviews = emptyList(),
|
linkPreviews = emptyList(),
|
||||||
bypassPreSendSafetyNumberCheck = true
|
bypassPreSendSafetyNumberCheck = true,
|
||||||
|
scheduledDate = scheduledDate
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1892,19 +1894,24 @@ class ConversationFragment :
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (inputPanel.isRecordingInLockedMode) {
|
if (inputPanel.isRecordingInLockedMode) {
|
||||||
inputPanel.releaseRecordingLock()
|
inputPanel.releaseRecordingLockAndSend()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (slideDeck == null) {
|
if (slideDeck == null) {
|
||||||
val voiceNote: DraftTable.Draft? = draftViewModel.voiceNoteDraft
|
val voiceNote: DraftTable.Draft? = draftViewModel.voiceNoteDraft
|
||||||
if (voiceNote != null) {
|
if (voiceNote != null) {
|
||||||
sendMessageWithoutComposeInput(slide = AudioSlide.createFromVoiceNoteDraft(voiceNote), clearCompose = true)
|
sendMessageWithoutComposeInput(
|
||||||
|
slide = AudioSlide.createFromVoiceNoteDraft(voiceNote),
|
||||||
|
quote = quote,
|
||||||
|
clearCompose = true,
|
||||||
|
scheduledDate = scheduledDate
|
||||||
|
)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (body.isNullOrBlank() && slideDeck?.containsMediaSlide() != true && preUploadResults.isEmpty() && contacts.isEmpty()) {
|
if (body.isBlank() && slideDeck?.containsMediaSlide() != true && preUploadResults.isEmpty() && contacts.isEmpty()) {
|
||||||
Log.i(TAG, "Unable to send due to empty message")
|
Log.i(TAG, "Unable to send due to empty message")
|
||||||
toast(R.string.ConversationActivity_message_is_empty_exclamation)
|
toast(R.string.ConversationActivity_message_is_empty_exclamation)
|
||||||
return
|
return
|
||||||
@@ -3970,6 +3977,10 @@ class ConversationFragment :
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onSendScheduled() {
|
override fun onSendScheduled() {
|
||||||
|
if (inputPanel.isRecordingInLockedMode) {
|
||||||
|
inputPanel.onSaveRecordDraft()
|
||||||
|
}
|
||||||
|
|
||||||
ScheduleMessageContextMenu.show(sendButton, (requireView() as ViewGroup)) { time ->
|
ScheduleMessageContextMenu.show(sendButton, (requireView() as ViewGroup)) { time ->
|
||||||
if (time == -1L) {
|
if (time == -1L) {
|
||||||
showSchedule(childFragmentManager)
|
showSchedule(childFragmentManager)
|
||||||
@@ -3978,10 +3989,6 @@ class ConversationFragment :
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun canSchedule(): Boolean {
|
|
||||||
return !(inputPanel.isRecordingInLockedMode || draftViewModel.voiceNoteDraft != null)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private inner class ComposeTextEventsListener :
|
private inner class ComposeTextEventsListener :
|
||||||
@@ -4126,6 +4133,11 @@ class ConversationFragment :
|
|||||||
voiceMessageRecordingDelegate.onRecorderCanceled(byUser)
|
voiceMessageRecordingDelegate.onRecorderCanceled(byUser)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onRecorderSaveDraft() {
|
||||||
|
voiceMessageRecordingDelegate.onRecordSaveDraft()
|
||||||
|
inputPanel.voiceNoteDraft = draftViewModel.voiceNoteDraft
|
||||||
|
}
|
||||||
|
|
||||||
override fun onRecorderPermissionRequired() {
|
override fun onRecorderPermissionRequired() {
|
||||||
Permissions
|
Permissions
|
||||||
.with(this@ConversationFragment)
|
.with(this@ConversationFragment)
|
||||||
|
|||||||
@@ -69,6 +69,12 @@ class VoiceMessageRecordingDelegate(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun onRecordSaveDraft() {
|
||||||
|
voiceRecorderWakeLock.release()
|
||||||
|
vibrateAndResetOrientation(50)
|
||||||
|
session?.saveDraft()
|
||||||
|
}
|
||||||
|
|
||||||
@Suppress("DEPRECATION")
|
@Suppress("DEPRECATION")
|
||||||
private fun vibrateAndResetOrientation(milliseconds: Long) {
|
private fun vibrateAndResetOrientation(milliseconds: Long) {
|
||||||
val activity = fragment.activity
|
val activity = fragment.activity
|
||||||
|
|||||||
Reference in New Issue
Block a user