Prevent scheduling of sends when alarm permission is denied.

This commit is contained in:
Cody Henthorne 2023-02-02 09:51:45 -05:00 committed by Nicholas Tinsley
parent 987fafff92
commit 6a8e82ef91
4 changed files with 59 additions and 29 deletions

View file

@ -366,7 +366,8 @@ public class ConversationParentFragment extends Fragment
Material3OnScrollHelperBinder,
MessageDetailsFragment.Callback,
ScheduleMessageTimePickerBottomSheet.ScheduleCallback,
ConversationBottomSheetCallback
ConversationBottomSheetCallback,
ScheduleMessageDialogCallback
{
private static final int SHORTCUT_ICON_SIZE = Build.VERSION.SDK_INT >= 26 ? ViewUtil.dpToPx(72) : ViewUtil.dpToPx(48 + 16 * 2);
@ -2948,9 +2949,10 @@ public class ConversationParentFragment extends Fragment
}
private void sendMessage(@Nullable String metricId, long scheduledDate) {
if (scheduledDate != -1) {
ReenableScheduledMessagesDialogFragment.showIfNeeded(requireContext(), getChildFragmentManager());
if (scheduledDate != -1 && ReenableScheduledMessagesDialogFragment.showIfNeeded(requireContext(), getChildFragmentManager(), metricId, scheduledDate)) {
return;
}
if (inputPanel.isRecordingInLockedMode()) {
inputPanel.releaseRecordingLock();
return;
@ -3671,6 +3673,7 @@ public class ConversationParentFragment extends Fragment
});
}
@Override
public void onScheduleSend(long scheduledTime) {
sendMessage(null, scheduledTime);
}
@ -3685,6 +3688,11 @@ public class ConversationParentFragment extends Fragment
fragment.jumpToMessage(messageRecord);
}
@Override
public void onSchedulePermissionsGranted(@Nullable String metricId, long scheduledDate) {
sendMessage(metricId, scheduledDate);
}
// Listeners
private class RecordingSession implements SingleObserver<VoiceNoteDraft>, Disposable {

View file

@ -1,7 +1,6 @@
package org.thoughtcrime.securesms.conversation
import android.annotation.SuppressLint
import android.app.Activity
import android.content.Context
import android.content.Intent
import android.net.Uri
@ -13,13 +12,14 @@ import android.view.View
import android.view.ViewGroup
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import androidx.core.os.bundleOf
import androidx.fragment.app.FragmentManager
import org.thoughtcrime.securesms.R
import org.thoughtcrime.securesms.components.FixedRoundedCornerBottomSheetDialogFragment
import org.thoughtcrime.securesms.conversation.ScheduleMessageFtuxBottomSheetDialog.Companion.show
import org.thoughtcrime.securesms.keyvalue.SignalStore
import org.thoughtcrime.securesms.util.BottomSheetUtil
import org.thoughtcrime.securesms.util.ServiceUtil
import org.thoughtcrime.securesms.util.fragments.findListener
/**
* Bottom sheet dialog to prompt user to enable schedule alarms permission for scheduling messages
@ -35,7 +35,11 @@ class ReenableScheduledMessagesDialogFragment : FixedRoundedCornerBottomSheetDia
@SuppressLint("InlinedApi")
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
val launcher: ActivityResultLauncher<Intent> = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
if (it.resultCode == Activity.RESULT_OK) {
if (Build.VERSION.SDK_INT < 31 || ServiceUtil.getAlarmManager(context).canScheduleExactAlarms()) {
findListener<ScheduleMessageDialogCallback>()?.onSchedulePermissionsGranted(
requireArguments().getString(ScheduleMessageDialogCallback.ARGUMENT_METRIC_ID),
requireArguments().getLong(ScheduleMessageDialogCallback.ARGUMENT_SCHEDULED_DATE)
)
dismissAllowingStateLoss()
}
}
@ -47,12 +51,9 @@ class ReenableScheduledMessagesDialogFragment : FixedRoundedCornerBottomSheetDia
companion object {
@JvmStatic
fun showIfNeeded(context: Context, fragmentManager: FragmentManager) {
var hasPermission = true
if (Build.VERSION.SDK_INT >= 31) {
val alarmManager = ServiceUtil.getAlarmManager(context)
hasPermission = alarmManager.canScheduleExactAlarms()
}
fun showIfNeeded(context: Context, fragmentManager: FragmentManager, metricId: String?, scheduledDate: Long): Boolean {
val hasPermission = Build.VERSION.SDK_INT < 31 || ServiceUtil.getAlarmManager(context).canScheduleExactAlarms()
val fragment = if (!SignalStore.uiHints().hasSeenScheduledMessagesInfoSheet()) {
ScheduleMessageFtuxBottomSheetDialog()
} else if (!hasPermission) {
@ -60,7 +61,16 @@ class ReenableScheduledMessagesDialogFragment : FixedRoundedCornerBottomSheetDia
} else {
null
}
fragment?.apply {
arguments = bundleOf(
ScheduleMessageDialogCallback.ARGUMENT_METRIC_ID to metricId,
ScheduleMessageDialogCallback.ARGUMENT_SCHEDULED_DATE to scheduledDate
)
}
fragment?.show(fragmentManager, BottomSheetUtil.STANDARD_BOTTOM_SHEET_FRAGMENT_TAG)
return fragment != null
}
}
}

View file

@ -0,0 +1,13 @@
package org.thoughtcrime.securesms.conversation;
import javax.annotation.Nullable;
/**
* Interface for responding to scheduled message dialogs blocking the send flow for permissions check.
*/
public interface ScheduleMessageDialogCallback {
String ARGUMENT_METRIC_ID = "ARGUMENT_METRIC_ID";
String ARGUMENT_SCHEDULED_DATE = "ARGUMENT_SCHEDULED_DATE";
void onSchedulePermissionsGranted(@Nullable String metricId, long scheduledDate);
}

View file

@ -1,6 +1,5 @@
package org.thoughtcrime.securesms.conversation
import android.app.Activity
import android.content.Intent
import android.net.Uri
import android.os.Build
@ -11,14 +10,13 @@ import android.view.View
import android.view.ViewGroup
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import androidx.fragment.app.FragmentManager
import org.thoughtcrime.securesms.R
import org.thoughtcrime.securesms.components.FixedRoundedCornerBottomSheetDialogFragment
import org.thoughtcrime.securesms.components.ViewBinderDelegate
import org.thoughtcrime.securesms.databinding.ScheduleMessageFtuxBottomSheetBinding
import org.thoughtcrime.securesms.keyvalue.SignalStore
import org.thoughtcrime.securesms.util.BottomSheetUtil
import org.thoughtcrime.securesms.util.ServiceUtil
import org.thoughtcrime.securesms.util.fragments.findListener
class ScheduleMessageFtuxBottomSheetDialog : FixedRoundedCornerBottomSheetDialogFragment() {
override val peekHeightPercentage: Float = 0.66f
@ -34,29 +32,30 @@ class ScheduleMessageFtuxBottomSheetDialog : FixedRoundedCornerBottomSheetDialog
if (Build.VERSION.SDK_INT >= 31 && !ServiceUtil.getAlarmManager(context).canScheduleExactAlarms()) {
binding.reenableSettings.visibility = View.VISIBLE
binding.okay.visibility = View.GONE
val launcher: ActivityResultLauncher<Intent> = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
if (it.resultCode == Activity.RESULT_OK) {
dismissAllowingStateLoss()
if (Build.VERSION.SDK_INT < 31 || ServiceUtil.getAlarmManager(context).canScheduleExactAlarms()) {
proceedWithScheduledSend()
}
}
binding.enableScheduledMessagesGoToSettings.setOnClickListener {
SignalStore.uiHints().markHasSeenScheduledMessagesInfoSheet()
launcher.launch(Intent(Settings.ACTION_REQUEST_SCHEDULE_EXACT_ALARM, Uri.parse("package:" + requireContext().packageName)))
dismiss()
}
} else {
binding.okay.setOnClickListener {
proceedWithScheduledSend()
}
}
binding.okay.setOnClickListener {
SignalStore.uiHints().markHasSeenScheduledMessagesInfoSheet()
dismiss()
}
}
companion object {
@JvmStatic
fun show(fragmentManager: FragmentManager) {
val fragment = ScheduleMessageFtuxBottomSheetDialog()
fragment.show(fragmentManager, BottomSheetUtil.STANDARD_BOTTOM_SHEET_FRAGMENT_TAG)
}
private fun proceedWithScheduledSend() {
SignalStore.uiHints().markHasSeenScheduledMessagesInfoSheet()
findListener<ScheduleMessageDialogCallback>()?.onSchedulePermissionsGranted(
requireArguments().getString(ScheduleMessageDialogCallback.ARGUMENT_METRIC_ID),
requireArguments().getLong(ScheduleMessageDialogCallback.ARGUMENT_SCHEDULED_DATE)
)
dismissAllowingStateLoss()
}
}