Enable quick toggle camera in CFV2 input panel.

This commit is contained in:
Alex Hart
2023-07-05 14:02:23 -03:00
committed by Greyson Parrelli
parent 81b2e9ccd2
commit 919531a82b
5 changed files with 65 additions and 26 deletions

View File

@@ -4,6 +4,7 @@ import android.animation.Animator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.drawable.ColorDrawable;
import android.hardware.Camera;
import android.net.Uri;
import android.text.SpannableString;
import android.text.format.DateUtils;
@@ -189,6 +190,8 @@ public class InputPanel extends LinearLayout
stickerSuggestion.setAdapter(stickerSuggestionAdapter);
editMessageCancel.setOnClickListener(v -> exitEditMessageMode());
quickCameraToggle.setVisibility(View.GONE);
}
public void setListener(final @NonNull Listener listener) {
@@ -196,6 +199,13 @@ public class InputPanel extends LinearLayout
mediaKeyboard.setOnClickListener(v -> listener.onEmojiToggle());
voiceNoteDraftView.setListener(listener);
if (Camera.getNumberOfCameras() > 0) {
quickCameraToggle.setOnClickListener(v -> listener.onQuickCameraToggleClicked());
quickCameraToggle.setVisibility(View.VISIBLE);
} else {
quickCameraToggle.setVisibility(View.GONE);
}
}
public void setMediaListener(@NonNull MediaListener listener) {
@@ -730,6 +740,7 @@ public class InputPanel extends LinearLayout
void onQuoteCleared();
void onEnterEditMode();
void onExitEditMode();
void onQuickCameraToggleClicked();
}
private static class SlideToCancel {

View File

@@ -1976,13 +1976,6 @@ public class ConversationParentFragment extends Fragment
composeText.setOnClickListener(composeKeyPressedListener);
composeText.setOnFocusChangeListener(composeKeyPressedListener);
if (Camera.getNumberOfCameras() > 0) {
quickCameraToggle.setVisibility(View.VISIBLE);
quickCameraToggle.setOnClickListener(new QuickCameraToggleListener());
} else {
quickCameraToggle.setVisibility(View.GONE);
}
searchNav.setEventListener(this);
inlineAttachmentButton.setOnClickListener(v -> handleAddAttachment());
@@ -3767,24 +3760,6 @@ public class ConversationParentFragment extends Fragment
}
}
private class QuickCameraToggleListener implements OnClickListener {
@Override
public void onClick(View v) {
Permissions.with(ConversationParentFragment.this)
.request(Manifest.permission.CAMERA)
.ifNecessary()
.withRationaleDialog(getString(R.string.ConversationActivity_to_capture_photos_and_video_allow_signal_access_to_the_camera), R.drawable.ic_camera_24)
.withPermanentDenialDialog(getString(R.string.ConversationActivity_signal_needs_the_camera_permission_to_take_photos_or_video))
.onAllGranted(() -> {
composeText.clearFocus();
startActivityForResult(MediaSelectionActivity.camera(requireActivity(), sendButton.getSelectedSendType(), recipient.getId(), inputPanel.getQuote().isPresent()), MEDIA_SENDER);
requireActivity().overridePendingTransition(R.anim.camera_slide_from_bottom, R.anim.stationary);
})
.onAnyDenied(() -> Toast.makeText(requireContext(), R.string.ConversationActivity_signal_needs_camera_permissions_to_take_photos_or_video, Toast.LENGTH_LONG).show())
.execute();
}
}
private class SendButtonListener implements OnClickListener, TextView.OnEditorActionListener {
@Override
public void onClick(View v) {
@@ -4272,6 +4247,22 @@ public class ConversationParentFragment extends Fragment
}
}
@Override
public void onQuickCameraToggleClicked() {
Permissions.with(ConversationParentFragment.this)
.request(Manifest.permission.CAMERA)
.ifNecessary()
.withRationaleDialog(getString(R.string.ConversationActivity_to_capture_photos_and_video_allow_signal_access_to_the_camera), R.drawable.ic_camera_24)
.withPermanentDenialDialog(getString(R.string.ConversationActivity_signal_needs_the_camera_permission_to_take_photos_or_video))
.onAllGranted(() -> {
composeText.clearFocus();
startActivityForResult(MediaSelectionActivity.camera(requireActivity(), sendButton.getSelectedSendType(), recipient.getId(), inputPanel.getQuote().isPresent()), MEDIA_SENDER);
requireActivity().overridePendingTransition(R.anim.camera_slide_from_bottom, R.anim.stationary);
})
.onAnyDenied(() -> Toast.makeText(requireContext(), R.string.ConversationActivity_signal_needs_camera_permissions_to_take_photos_or_video, Toast.LENGTH_LONG).show())
.execute();
}
@Override
public void onMessageActionToolbarOpened() {
searchViewItem.collapseActionView();

View File

@@ -12,6 +12,7 @@ import android.content.Context
import android.content.Intent
import android.net.Uri
import android.provider.ContactsContract
import android.widget.Toast
import androidx.activity.result.contract.ActivityResultContract
import androidx.core.content.IntentCompat
import androidx.fragment.app.Fragment
@@ -52,6 +53,7 @@ class ConversationActivityResultContracts(private val fragment: Fragment, privat
private val mediaGalleryLauncher = fragment.registerForActivityResult(MediaGallery) { result -> callbacks.onMediaSend(result) }
private val selectLocationLauncher = fragment.registerForActivityResult(SelectLocation) { result -> callbacks.onLocationSelected(result?.place, result?.uri) }
private val selectFileLauncher = fragment.registerForActivityResult(SelectFile) { result -> callbacks.onFileSelected(result) }
private val cameraLauncher = fragment.registerForActivityResult(MediaCapture) { result -> callbacks.onMediaSend(result) }
fun launchContactShareEditor(uri: Uri, chatColors: ChatColors) {
contactShareLauncher.launch(uri to chatColors)
@@ -77,6 +79,20 @@ class ConversationActivityResultContracts(private val fragment: Fragment, privat
.execute()
}
fun launchCamera(recipientId: RecipientId, isReply: Boolean) {
Permissions.with(fragment)
.request(Manifest.permission.CAMERA)
.ifNecessary()
.withRationaleDialog(fragment.getString(R.string.ConversationActivity_to_capture_photos_and_video_allow_signal_access_to_the_camera), R.drawable.symbol_camera_24)
.withPermanentDenialDialog(fragment.getString(R.string.ConversationActivity_signal_needs_the_camera_permission_to_take_photos_or_video))
.onAllGranted {
cameraLauncher.launch(MediaSelectionInput(emptyList(), recipientId, null, isReply))
fragment.requireActivity().overridePendingTransition(R.anim.camera_slide_from_bottom, R.anim.stationary)
}
.onAnyDenied { Toast.makeText(fragment.requireContext(), R.string.ConversationActivity_signal_needs_camera_permissions_to_take_photos_or_video, Toast.LENGTH_LONG).show() }
.execute()
}
fun launchMediaEditor(mediaList: List<Media>, recipientId: RecipientId, text: CharSequence?) {
mediaSelectionLauncher.launch(MediaSelectionInput(mediaList, recipientId, text))
}
@@ -131,6 +147,21 @@ class ConversationActivityResultContracts(private val fragment: Fragment, privat
}
}
private object MediaCapture : ActivityResultContract<MediaSelectionInput, MediaSendActivityResult?>() {
override fun createIntent(context: Context, input: MediaSelectionInput): Intent {
val (_, recipientId, _, isReply) = input
return MediaSelectionActivity.camera(context, MessageSendType.SignalMessageSendType, recipientId, isReply)
}
override fun parseResult(resultCode: Int, intent: Intent?): MediaSendActivityResult? {
return if (resultCode == Activity.RESULT_OK) {
intent?.let { MediaSendActivityResult.fromData(intent) }
} else {
null
}
}
}
private object MediaGallery : ActivityResultContract<MediaSelectionInput, MediaSendActivityResult?>() {
override fun createIntent(context: Context, input: MediaSelectionInput): Intent {
val (media, recipientId, text, isReply) = input

View File

@@ -1205,6 +1205,7 @@ class ConversationFragment :
composeText.setDraftText(data.draftText)
inputPanel.enterEditMessageMode(GlideApp.with(this), data.messageEdit, true)
}
is ShareOrDraftData.SetLocation -> attachmentManager.setLocation(data.location, MediaConstraints.getPushMediaConstraints())
is ShareOrDraftData.SetMedia -> {
composeText.setDraftText(data.text)
@@ -3395,6 +3396,12 @@ class ConversationFragment :
previousPages = null
}
}
override fun onQuickCameraToggleClicked() {
val recipientId = viewModel.recipientSnapshot?.id ?: return
composeText.clearFocus()
conversationActivityResultContracts.launchCamera(recipientId, inputPanel.quote.isPresent)
}
}
//endregion

View File

@@ -24,7 +24,6 @@ import org.thoughtcrime.securesms.database.model.MediaMmsMessageRecord
import org.thoughtcrime.securesms.database.model.MessageRecord
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies
import org.thoughtcrime.securesms.util.DateUtils
import org.thoughtcrime.securesms.util.LongClickMovementMethod
import org.thoughtcrime.securesms.util.Projection
import org.thoughtcrime.securesms.util.ProjectionList
import org.thoughtcrime.securesms.util.SignalLocalMetrics