kopia lustrzana https://github.com/ryukoposting/Signal-Android
Fix voice note draft not being generated on audio focus loss.
rodzic
150bbf181d
commit
4dcbbfdd63
|
@ -8,18 +8,18 @@ import android.os.ParcelFileDescriptor;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
import org.signal.core.util.ThreadUtil;
|
|
||||||
import org.signal.core.util.concurrent.SignalExecutors;
|
import org.signal.core.util.concurrent.SignalExecutors;
|
||||||
import org.signal.core.util.logging.Log;
|
import org.signal.core.util.logging.Log;
|
||||||
import org.thoughtcrime.securesms.components.voice.VoiceNoteDraft;
|
import org.thoughtcrime.securesms.components.voice.VoiceNoteDraft;
|
||||||
import org.thoughtcrime.securesms.providers.BlobProvider;
|
import org.thoughtcrime.securesms.providers.BlobProvider;
|
||||||
import org.thoughtcrime.securesms.util.MediaUtil;
|
import org.thoughtcrime.securesms.util.MediaUtil;
|
||||||
import org.thoughtcrime.securesms.util.concurrent.ListenableFuture;
|
|
||||||
import org.thoughtcrime.securesms.util.concurrent.SettableFuture;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
|
|
||||||
|
import io.reactivex.rxjava3.core.Single;
|
||||||
|
import io.reactivex.rxjava3.subjects.SingleSubject;
|
||||||
|
|
||||||
public class AudioRecorder {
|
public class AudioRecorder {
|
||||||
|
|
||||||
private static final String TAG = Log.tag(AudioRecorder.class);
|
private static final String TAG = Log.tag(AudioRecorder.class);
|
||||||
|
@ -32,14 +32,17 @@ public class AudioRecorder {
|
||||||
private Recorder recorder;
|
private Recorder recorder;
|
||||||
private Uri captureUri;
|
private Uri captureUri;
|
||||||
|
|
||||||
|
private SingleSubject<VoiceNoteDraft> recordingSubject;
|
||||||
|
|
||||||
public AudioRecorder(@NonNull Context context) {
|
public AudioRecorder(@NonNull Context context) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
audioFocusManager = AudioRecorderFocusManager.create(context, focusChange -> stopRecording());
|
audioFocusManager = AudioRecorderFocusManager.create(context, focusChange -> stopRecording());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void startRecording() {
|
public @NonNull Single<VoiceNoteDraft> startRecording() {
|
||||||
Log.i(TAG, "startRecording()");
|
Log.i(TAG, "startRecording()");
|
||||||
|
|
||||||
|
final SingleSubject<VoiceNoteDraft> recordingSingle = SingleSubject.create();
|
||||||
executor.execute(() -> {
|
executor.execute(() -> {
|
||||||
Log.i(TAG, "Running startRecording() + " + Thread.currentThread().getId());
|
Log.i(TAG, "Running startRecording() + " + Thread.currentThread().getId());
|
||||||
try {
|
try {
|
||||||
|
@ -53,27 +56,29 @@ public class AudioRecorder {
|
||||||
.forData(new ParcelFileDescriptor.AutoCloseInputStream(fds[0]), 0)
|
.forData(new ParcelFileDescriptor.AutoCloseInputStream(fds[0]), 0)
|
||||||
.withMimeType(MediaUtil.AUDIO_AAC)
|
.withMimeType(MediaUtil.AUDIO_AAC)
|
||||||
.createForDraftAttachmentAsync(context, () -> Log.i(TAG, "Write successful."), e -> Log.w(TAG, "Error during recording", e));
|
.createForDraftAttachmentAsync(context, () -> Log.i(TAG, "Write successful."), e -> Log.w(TAG, "Error during recording", e));
|
||||||
|
|
||||||
recorder = Build.VERSION.SDK_INT >= 26 ? new MediaRecorderWrapper() : new AudioCodec();
|
recorder = Build.VERSION.SDK_INT >= 26 ? new MediaRecorderWrapper() : new AudioCodec();
|
||||||
int focusResult = audioFocusManager.requestAudioFocus();
|
int focusResult = audioFocusManager.requestAudioFocus();
|
||||||
if (focusResult != AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
|
if (focusResult != AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
|
||||||
Log.w(TAG, "Could not gain audio focus. Received result code " + focusResult);
|
Log.w(TAG, "Could not gain audio focus. Received result code " + focusResult);
|
||||||
}
|
}
|
||||||
recorder.start(fds[1]);
|
recorder.start(fds[1]);
|
||||||
|
this.recordingSubject = recordingSingle;
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
|
recordingSingle.onError(e);
|
||||||
|
recorder = null;
|
||||||
Log.w(TAG, e);
|
Log.w(TAG, e);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
return recordingSingle;
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NonNull ListenableFuture<VoiceNoteDraft> stopRecording() {
|
public void stopRecording() {
|
||||||
Log.i(TAG, "stopRecording()");
|
Log.i(TAG, "stopRecording()");
|
||||||
|
|
||||||
final SettableFuture<VoiceNoteDraft> future = new SettableFuture<>();
|
|
||||||
|
|
||||||
executor.execute(() -> {
|
executor.execute(() -> {
|
||||||
if (recorder == null) {
|
if (recorder == null) {
|
||||||
sendToFuture(future, new IOException("MediaRecorder was never initialized successfully!"));
|
Log.e(TAG, "MediaRecorder was never initialized successfully!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,24 +87,15 @@ public class AudioRecorder {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
long size = MediaUtil.getMediaSize(context, captureUri);
|
long size = MediaUtil.getMediaSize(context, captureUri);
|
||||||
sendToFuture(future, new VoiceNoteDraft(captureUri, size));
|
recordingSubject.onSuccess(new VoiceNoteDraft(captureUri, size));
|
||||||
} catch (IOException ioe) {
|
} catch (IOException ioe) {
|
||||||
Log.w(TAG, ioe);
|
Log.w(TAG, ioe);
|
||||||
sendToFuture(future, ioe);
|
recordingSubject.onError(ioe);
|
||||||
}
|
}
|
||||||
|
|
||||||
recorder = null;
|
recordingSubject = null;
|
||||||
captureUri = null;
|
recorder = null;
|
||||||
|
captureUri = null;
|
||||||
});
|
});
|
||||||
|
|
||||||
return future;
|
|
||||||
}
|
|
||||||
|
|
||||||
private <T> void sendToFuture(final SettableFuture<T> future, final Exception exception) {
|
|
||||||
ThreadUtil.runOnMain(() -> future.setException(exception));
|
|
||||||
}
|
|
||||||
|
|
||||||
private <T> void sendToFuture(final SettableFuture<T> future, final T result) {
|
|
||||||
ThreadUtil.runOnMain(() -> future.set(result));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -141,9 +141,9 @@ public class InputPanel extends LinearLayout
|
||||||
this.recordTime = new RecordTime(findViewById(R.id.record_time),
|
this.recordTime = new RecordTime(findViewById(R.id.record_time),
|
||||||
findViewById(R.id.microphone),
|
findViewById(R.id.microphone),
|
||||||
TimeUnit.HOURS.toSeconds(1),
|
TimeUnit.HOURS.toSeconds(1),
|
||||||
() -> microphoneRecorderView.cancelAction());
|
() -> microphoneRecorderView.cancelAction(false));
|
||||||
|
|
||||||
this.recordLockCancel.setOnClickListener(v -> microphoneRecorderView.cancelAction());
|
this.recordLockCancel.setOnClickListener(v -> microphoneRecorderView.cancelAction(true));
|
||||||
|
|
||||||
if (SignalStore.settings().isPreferSystemEmoji()) {
|
if (SignalStore.settings().isPreferSystemEmoji()) {
|
||||||
mediaKeyboard.setVisibility(View.GONE);
|
mediaKeyboard.setVisibility(View.GONE);
|
||||||
|
@ -419,7 +419,7 @@ public class InputPanel extends LinearLayout
|
||||||
listener.onRecorderFinished();
|
listener.onRecorderFinished();
|
||||||
} else {
|
} else {
|
||||||
Toast.makeText(getContext(), R.string.InputPanel_tap_and_hold_to_record_a_voice_message_release_to_send, Toast.LENGTH_LONG).show();
|
Toast.makeText(getContext(), R.string.InputPanel_tap_and_hold_to_record_a_voice_message_release_to_send, Toast.LENGTH_LONG).show();
|
||||||
listener.onRecorderCanceled();
|
listener.onRecorderCanceled(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -433,14 +433,14 @@ public class InputPanel extends LinearLayout
|
||||||
if (ViewUtil.isLtr(this) && position <= 0.5 ||
|
if (ViewUtil.isLtr(this) && position <= 0.5 ||
|
||||||
ViewUtil.isRtl(this) && position >= 0.6)
|
ViewUtil.isRtl(this) && position >= 0.6)
|
||||||
{
|
{
|
||||||
this.microphoneRecorderView.cancelAction();
|
this.microphoneRecorderView.cancelAction(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onRecordCanceled() {
|
public void onRecordCanceled(boolean byUser) {
|
||||||
onRecordHideEvent();
|
onRecordHideEvent();
|
||||||
if (listener != null) listener.onRecorderCanceled();
|
if (listener != null) listener.onRecorderCanceled(byUser);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -452,7 +452,7 @@ public class InputPanel extends LinearLayout
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onPause() {
|
public void onPause() {
|
||||||
this.microphoneRecorderView.cancelAction();
|
this.microphoneRecorderView.cancelAction(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NonNull Observer<VoiceNotePlaybackState> getPlaybackStateObserver() {
|
public @NonNull Observer<VoiceNotePlaybackState> getPlaybackStateObserver() {
|
||||||
|
@ -527,6 +527,7 @@ public class InputPanel extends LinearLayout
|
||||||
voiceNoteDraftView.setDraft(voiceNoteDraft);
|
voiceNoteDraftView.setDraft(voiceNoteDraft);
|
||||||
voiceNoteDraftView.setVisibility(VISIBLE);
|
voiceNoteDraftView.setVisibility(VISIBLE);
|
||||||
hideNormalComposeViews();
|
hideNormalComposeViews();
|
||||||
|
fadeIn(buttonToggle);
|
||||||
buttonToggle.displayQuick(sendButton);
|
buttonToggle.displayQuick(sendButton);
|
||||||
} else {
|
} else {
|
||||||
voiceNoteDraftView.clearDraft();
|
voiceNoteDraftView.clearDraft();
|
||||||
|
@ -582,7 +583,7 @@ public class InputPanel extends LinearLayout
|
||||||
void onRecorderStarted();
|
void onRecorderStarted();
|
||||||
void onRecorderLocked();
|
void onRecorderLocked();
|
||||||
void onRecorderFinished();
|
void onRecorderFinished();
|
||||||
void onRecorderCanceled();
|
void onRecorderCanceled(boolean byUser);
|
||||||
void onRecorderPermissionRequired();
|
void onRecorderPermissionRequired();
|
||||||
void onEmojiToggle();
|
void onEmojiToggle();
|
||||||
void onLinkPreviewCanceled();
|
void onLinkPreviewCanceled();
|
||||||
|
|
|
@ -58,12 +58,14 @@ public final class MicrophoneRecorderView extends FrameLayout implements View.On
|
||||||
recordButton.setOnTouchListener(this);
|
recordButton.setOnTouchListener(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void cancelAction() {
|
public void cancelAction(boolean byUser) {
|
||||||
if (state != State.NOT_RUNNING) {
|
if (state != State.NOT_RUNNING) {
|
||||||
state = State.NOT_RUNNING;
|
state = State.NOT_RUNNING;
|
||||||
hideUi();
|
hideUi();
|
||||||
|
|
||||||
if (listener != null) listener.onRecordCanceled();
|
if (listener != null) {
|
||||||
|
listener.onRecordCanceled(byUser);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -138,7 +140,7 @@ public final class MicrophoneRecorderView extends FrameLayout implements View.On
|
||||||
public interface Listener {
|
public interface Listener {
|
||||||
void onRecordPressed();
|
void onRecordPressed();
|
||||||
void onRecordReleased();
|
void onRecordReleased();
|
||||||
void onRecordCanceled();
|
void onRecordCanceled(boolean byUser);
|
||||||
void onRecordLocked();
|
void onRecordLocked();
|
||||||
void onRecordMoved(float offsetX, float absoluteX);
|
void onRecordMoved(float offsetX, float absoluteX);
|
||||||
void onRecordPermissionRequired();
|
void onRecordPermissionRequired();
|
||||||
|
|
|
@ -84,7 +84,6 @@ import androidx.core.graphics.drawable.DrawableCompat;
|
||||||
import androidx.core.graphics.drawable.IconCompat;
|
import androidx.core.graphics.drawable.IconCompat;
|
||||||
import androidx.core.view.MenuItemCompat;
|
import androidx.core.view.MenuItemCompat;
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
import androidx.lifecycle.Lifecycle;
|
|
||||||
import androidx.lifecycle.Observer;
|
import androidx.lifecycle.Observer;
|
||||||
import androidx.lifecycle.ViewModelProvider;
|
import androidx.lifecycle.ViewModelProvider;
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
@ -326,6 +325,8 @@ import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
|
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
|
||||||
import io.reactivex.rxjava3.core.Flowable;
|
import io.reactivex.rxjava3.core.Flowable;
|
||||||
|
import io.reactivex.rxjava3.core.Single;
|
||||||
|
import io.reactivex.rxjava3.core.SingleObserver;
|
||||||
import io.reactivex.rxjava3.disposables.Disposable;
|
import io.reactivex.rxjava3.disposables.Disposable;
|
||||||
|
|
||||||
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
|
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
|
||||||
|
@ -416,6 +417,7 @@ public class ConversationParentFragment extends Fragment
|
||||||
|
|
||||||
private AttachmentManager attachmentManager;
|
private AttachmentManager attachmentManager;
|
||||||
private AudioRecorder audioRecorder;
|
private AudioRecorder audioRecorder;
|
||||||
|
private RecordingSession recordingSession;
|
||||||
private BroadcastReceiver securityUpdateReceiver;
|
private BroadcastReceiver securityUpdateReceiver;
|
||||||
private Stub<MediaKeyboard> emojiDrawerStub;
|
private Stub<MediaKeyboard> emojiDrawerStub;
|
||||||
private Stub<AttachmentKeyboard> attachmentKeyboardStub;
|
private Stub<AttachmentKeyboard> attachmentKeyboardStub;
|
||||||
|
@ -3286,7 +3288,7 @@ public class ConversationParentFragment extends Fragment
|
||||||
requireActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LOCKED);
|
requireActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LOCKED);
|
||||||
|
|
||||||
voiceNoteMediaController.pausePlayback();
|
voiceNoteMediaController.pausePlayback();
|
||||||
audioRecorder.startRecording();
|
recordingSession = new RecordingSession(audioRecorder.startRecording());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -3306,22 +3308,11 @@ public class ConversationParentFragment extends Fragment
|
||||||
requireActivity().getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
|
requireActivity().getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
|
||||||
requireActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
|
requireActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
|
||||||
|
|
||||||
ListenableFuture<VoiceNoteDraft> future = audioRecorder.stopRecording();
|
recordingSession.completeRecording();
|
||||||
future.addListener(new ListenableFuture.Listener<VoiceNoteDraft>() {
|
|
||||||
@Override
|
|
||||||
public void onSuccess(final @NonNull VoiceNoteDraft result) {
|
|
||||||
sendVoiceNote(result.getUri(), result.getSize());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onFailure(ExecutionException e) {
|
|
||||||
Toast.makeText(requireContext(), R.string.ConversationActivity_unable_to_record_audio, Toast.LENGTH_LONG).show();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onRecorderCanceled() {
|
public void onRecorderCanceled(boolean byUser) {
|
||||||
voiceRecorderWakeLock.release();
|
voiceRecorderWakeLock.release();
|
||||||
updateToggleButtonState();
|
updateToggleButtonState();
|
||||||
Vibrator vibrator = ServiceUtil.getVibrator(requireContext());
|
Vibrator vibrator = ServiceUtil.getVibrator(requireContext());
|
||||||
|
@ -3330,11 +3321,12 @@ public class ConversationParentFragment extends Fragment
|
||||||
requireActivity().getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
|
requireActivity().getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
|
||||||
requireActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
|
requireActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
|
||||||
|
|
||||||
ListenableFuture<VoiceNoteDraft> future = audioRecorder.stopRecording();
|
if (recordingSession != null) {
|
||||||
if (getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.RESUMED)) {
|
if (byUser) {
|
||||||
future.addListener(new DeleteCanceledVoiceNoteListener());
|
recordingSession.discardRecording();
|
||||||
} else {
|
} else {
|
||||||
draftViewModel.saveEphemeralVoiceNoteDraft(future);
|
recordingSession.saveDraft();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3590,14 +3582,55 @@ public class ConversationParentFragment extends Fragment
|
||||||
|
|
||||||
// Listeners
|
// Listeners
|
||||||
|
|
||||||
private final class DeleteCanceledVoiceNoteListener implements ListenableFuture.Listener<VoiceNoteDraft> {
|
private class RecordingSession implements SingleObserver<VoiceNoteDraft> {
|
||||||
@Override
|
|
||||||
public void onSuccess(final VoiceNoteDraft result) {
|
private boolean saveDraft = true;
|
||||||
draftViewModel.cancelEphemeralVoiceNoteDraft(result.asDraft());
|
private boolean shouldSend = false;
|
||||||
|
|
||||||
|
RecordingSession(Single<VoiceNoteDraft> observable) {
|
||||||
|
observable.observeOn(AndroidSchedulers.mainThread()).subscribe(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onFailure(ExecutionException e) {}
|
public void onSubscribe(@io.reactivex.rxjava3.annotations.NonNull Disposable d) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSuccess(@NonNull VoiceNoteDraft draft) {
|
||||||
|
if (shouldSend) {
|
||||||
|
sendVoiceNote(draft.getUri(), draft.getSize());
|
||||||
|
} else {
|
||||||
|
if (!saveDraft) {
|
||||||
|
draftViewModel.cancelEphemeralVoiceNoteDraft(draft.asDraft());
|
||||||
|
} else {
|
||||||
|
draftViewModel.saveEphemeralVoiceNoteDraft(draft.asDraft());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
recordingSession = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onError(Throwable t) {
|
||||||
|
Toast.makeText(requireContext(), R.string.ConversationActivity_unable_to_record_audio, Toast.LENGTH_LONG).show();
|
||||||
|
recordingSession = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void saveDraft() {
|
||||||
|
this.saveDraft = true;
|
||||||
|
this.shouldSend = false;
|
||||||
|
audioRecorder.stopRecording();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void discardRecording() {
|
||||||
|
this.saveDraft = false;
|
||||||
|
this.shouldSend = false;
|
||||||
|
audioRecorder.stopRecording();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void completeRecording() {
|
||||||
|
this.shouldSend = true;
|
||||||
|
audioRecorder.stopRecording();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class QuickCameraToggleListener implements OnClickListener {
|
private class QuickCameraToggleListener implements OnClickListener {
|
||||||
|
|
|
@ -5,7 +5,6 @@ import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
||||||
import io.reactivex.rxjava3.core.Flowable
|
import io.reactivex.rxjava3.core.Flowable
|
||||||
import io.reactivex.rxjava3.core.Single
|
import io.reactivex.rxjava3.core.Single
|
||||||
import org.thoughtcrime.securesms.components.location.SignalPlace
|
import org.thoughtcrime.securesms.components.location.SignalPlace
|
||||||
import org.thoughtcrime.securesms.components.voice.VoiceNoteDraft
|
|
||||||
import org.thoughtcrime.securesms.database.DraftTable.Draft
|
import org.thoughtcrime.securesms.database.DraftTable.Draft
|
||||||
import org.thoughtcrime.securesms.database.MentionUtil
|
import org.thoughtcrime.securesms.database.MentionUtil
|
||||||
import org.thoughtcrime.securesms.database.model.Mention
|
import org.thoughtcrime.securesms.database.model.Mention
|
||||||
|
@ -14,9 +13,7 @@ import org.thoughtcrime.securesms.mms.QuoteId
|
||||||
import org.thoughtcrime.securesms.recipients.Recipient
|
import org.thoughtcrime.securesms.recipients.Recipient
|
||||||
import org.thoughtcrime.securesms.recipients.RecipientId
|
import org.thoughtcrime.securesms.recipients.RecipientId
|
||||||
import org.thoughtcrime.securesms.util.Base64
|
import org.thoughtcrime.securesms.util.Base64
|
||||||
import org.thoughtcrime.securesms.util.concurrent.ListenableFuture
|
|
||||||
import org.thoughtcrime.securesms.util.rx.RxStore
|
import org.thoughtcrime.securesms.util.rx.RxStore
|
||||||
import java.util.concurrent.ExecutionException
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ViewModel responsible for holding Voice Note draft state. The intention is to allow
|
* ViewModel responsible for holding Voice Note draft state. The intention is to allow
|
||||||
|
@ -46,21 +43,9 @@ class DraftViewModel @JvmOverloads constructor(
|
||||||
store.update { it.copy(distributionType = distributionType) }
|
store.update { it.copy(distributionType = distributionType) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun saveEphemeralVoiceNoteDraft(voiceNoteDraftFuture: ListenableFuture<VoiceNoteDraft>) {
|
fun saveEphemeralVoiceNoteDraft(draft: Draft) {
|
||||||
store.update { draftState ->
|
store.update { draftState ->
|
||||||
val draft: VoiceNoteDraft? = try {
|
saveDrafts(draftState.copy(voiceNoteDraft = draft))
|
||||||
voiceNoteDraftFuture.get()
|
|
||||||
} catch (e: ExecutionException) {
|
|
||||||
null
|
|
||||||
} catch (e: InterruptedException) {
|
|
||||||
null
|
|
||||||
}
|
|
||||||
|
|
||||||
if (draft != null) {
|
|
||||||
saveDrafts(draftState.copy(voiceNoteDraft = draft.asDraft()))
|
|
||||||
} else {
|
|
||||||
draftState
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Ładowanie…
Reference in New Issue