Loading app/ui/src/main/java/com/fsck/k9/activity/K9Activity.java +1 −55 Original line number Diff line number Diff line package com.fsck.k9.activity; import android.Manifest; import android.content.pm.PackageManager; import android.os.Bundle; import androidx.annotation.LayoutRes; import androidx.annotation.StringRes; import androidx.core.app.ActivityCompat; import androidx.core.content.ContextCompat; import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.widget.Toolbar; import android.view.View; import com.fsck.k9.ui.R; import com.fsck.k9.ui.ThemeManager; import com.fsck.k9.ui.permissions.PermissionRationaleDialogFragment; import timber.log.Timber; public abstract class K9Activity extends AppCompatActivity { public static final int PERMISSIONS_REQUEST_READ_CONTACTS = 1; private static final String FRAGMENT_TAG_RATIONALE = "rationale"; private final K9ActivityCommon base = new K9ActivityCommon(this, ThemeType.DEFAULT); public ThemeManager getThemeManager() { Loading @@ -49,47 +38,4 @@ public abstract class K9Activity extends AppCompatActivity { } setSupportActionBar(toolbar); } public boolean hasPermission(Permission permission) { return ContextCompat.checkSelfPermission(this, permission.permission) == PackageManager.PERMISSION_GRANTED; } public void requestPermissionOrShowRationale(Permission permission) { if (ActivityCompat.shouldShowRequestPermissionRationale(this, permission.permission)) { PermissionRationaleDialogFragment dialogFragment = PermissionRationaleDialogFragment.newInstance(permission); dialogFragment.show(getSupportFragmentManager(), FRAGMENT_TAG_RATIONALE); } else { requestPermission(permission); } } public void requestPermission(Permission permission) { Timber.i("Requesting permission: " + permission.permission); ActivityCompat.requestPermissions(this, new String[] { permission.permission }, permission.requestCode); } public enum Permission { READ_CONTACTS( Manifest.permission.READ_CONTACTS, PERMISSIONS_REQUEST_READ_CONTACTS, R.string.permission_contacts_rationale_title, R.string.permission_contacts_rationale_message ); public final String permission; public final int requestCode; public final int rationaleTitle; public final int rationaleMessage; Permission(String permission, int requestCode, @StringRes int rationaleTitle, @StringRes int rationaleMessage) { this.permission = permission; this.requestCode = requestCode; this.rationaleTitle = rationaleTitle; this.rationaleMessage = rationaleMessage; } } } app/ui/src/main/java/com/fsck/k9/activity/MessageCompose.java +23 −1 Original line number Diff line number Diff line Loading @@ -110,7 +110,11 @@ import com.fsck.k9.ui.compose.QuotedMessageMvpView; import com.fsck.k9.ui.compose.QuotedMessagePresenter; import com.fsck.k9.ui.helper.SizeFormatter; import com.fsck.k9.ui.messagelist.DefaultFolderProvider; import com.fsck.k9.ui.permissions.K9PermissionUiHelper; import com.fsck.k9.ui.permissions.Permission; import com.fsck.k9.ui.permissions.PermissionUiHelper; import org.jetbrains.annotations.NotNull; import org.openintents.openpgp.OpenPgpApiManager; import org.openintents.openpgp.util.OpenPgpApi; import timber.log.Timber; Loading @@ -120,7 +124,7 @@ import timber.log.Timber; public class MessageCompose extends K9Activity implements OnClickListener, CancelListener, AttachmentDownloadCancelListener, OnFocusChangeListener, OnOpenPgpInlineChangeListener, OnOpenPgpSignOnlyChangeListener, MessageBuilder.Callback, AttachmentPresenter.AttachmentsChangedListener, OnOpenPgpDisableListener { AttachmentPresenter.AttachmentsChangedListener, OnOpenPgpDisableListener, PermissionUiHelper { private static final int DIALOG_SAVE_OR_DISCARD_DRAFT_MESSAGE = 1; private static final int DIALOG_CONFIRM_DISCARD_ON_BACK = 2; Loading Loading @@ -177,6 +181,8 @@ public class MessageCompose extends K9Activity implements OnClickListener, private final MessageLoaderHelperFactory messageLoaderHelperFactory = DI.get(MessageLoaderHelperFactory.class); private final DefaultFolderProvider defaultFolderProvider = DI.get(DefaultFolderProvider.class); private final PermissionUiHelper permissionUiHelper = new K9PermissionUiHelper(this); private QuotedMessagePresenter quotedMessagePresenter; private MessageLoaderHelper messageLoaderHelper; private AttachmentPresenter attachmentPresenter; Loading Loading @@ -1883,4 +1889,20 @@ public class MessageCompose extends K9Activity implements OnClickListener, return titleResource; } } @Override public boolean hasPermission(@NotNull Permission permission) { return permissionUiHelper.hasPermission(permission); } @Override public void requestPermissionOrShowRationale(@NotNull Permission permission) { permissionUiHelper.requestPermissionOrShowRationale(permission); } @Override public void requestPermission(@NotNull Permission permission) { permissionUiHelper.requestPermission(permission); } } app/ui/src/main/java/com/fsck/k9/activity/MessageList.java +24 −1 Original line number Diff line number Diff line Loading @@ -60,9 +60,15 @@ import com.fsck.k9.ui.messageview.MessageViewFragment; import com.fsck.k9.ui.messageview.MessageViewFragment.MessageViewFragmentListener; import com.fsck.k9.ui.messageview.PlaceholderFragment; import com.fsck.k9.ui.onboarding.OnboardingActivity; import com.fsck.k9.ui.permissions.K9PermissionUiHelper; import com.fsck.k9.ui.permissions.Permission; import com.fsck.k9.ui.permissions.PermissionUiHelper; import com.fsck.k9.view.ViewSwitcher; import com.fsck.k9.view.ViewSwitcher.OnSwitchCompleteListener; import com.mikepenz.materialdrawer.Drawer.OnDrawerListener; import org.jetbrains.annotations.NotNull; import timber.log.Timber; Loading @@ -72,7 +78,7 @@ import timber.log.Timber; * From this Activity the user can perform all standard message operations. */ public class MessageList extends K9Activity implements MessageListFragmentListener, MessageViewFragmentListener, OnBackStackChangedListener, OnSwitchCompleteListener { MessageViewFragmentListener, OnBackStackChangedListener, OnSwitchCompleteListener, PermissionUiHelper { private static final String EXTRA_SEARCH = "search_bytes"; private static final String EXTRA_NO_THREADING = "no_threading"; Loading Loading @@ -178,6 +184,8 @@ public class MessageList extends K9Activity implements MessageListFragmentListen private final NotificationChannelManager channelUtils = DI.get(NotificationChannelManager.class); private final DefaultFolderProvider defaultFolderProvider = DI.get(DefaultFolderProvider.class); private final PermissionUiHelper permissionUiHelper = new K9PermissionUiHelper(this); private ActionBar actionBar; private ActionBarDrawerToggle drawerToggle; private K9Drawer drawer; Loading Loading @@ -1622,4 +1630,19 @@ public class MessageList extends K9Activity implements MessageListFragmentListen drawer.deselect(); } } @Override public boolean hasPermission(@NotNull Permission permission) { return permissionUiHelper.hasPermission(permission); } @Override public void requestPermissionOrShowRationale(@NotNull Permission permission) { permissionUiHelper.requestPermissionOrShowRationale(permission); } @Override public void requestPermission(@NotNull Permission permission) { permissionUiHelper.requestPermission(permission); } } app/ui/src/main/java/com/fsck/k9/ui/permissions/Permission.kt 0 → 100644 +21 −0 Original line number Diff line number Diff line package com.fsck.k9.ui.permissions import android.Manifest import androidx.annotation.StringRes import com.fsck.k9.ui.R private const val PERMISSIONS_REQUEST_READ_CONTACTS = 1 enum class Permission( val permission: String, val requestCode: Int, @param:StringRes val rationaleTitle: Int, @param:StringRes val rationaleMessage: Int ) { READ_CONTACTS( Manifest.permission.READ_CONTACTS, PERMISSIONS_REQUEST_READ_CONTACTS, R.string.permission_contacts_rationale_title, R.string.permission_contacts_rationale_message ); } app/ui/src/main/java/com/fsck/k9/ui/permissions/PermissionRationaleDialogFragment.kt +11 −14 Original line number Diff line number Diff line Loading @@ -5,15 +5,13 @@ import android.app.Dialog import android.os.Bundle import androidx.core.os.bundleOf import androidx.fragment.app.DialogFragment import com.fsck.k9.activity.K9Activity import com.fsck.k9.activity.K9Activity.Permission import com.fsck.k9.ui.R /** * A dialog displaying a message to explain why the app requests a certain permission. * * Closing the dialog triggers a permission request. For this to work the Activity needs to be a subclass of * [K9Activity]. * Closing the dialog triggers a permission request. For this to work the Activity needs to implement * [PermissionUiHelper]. */ class PermissionRationaleDialogFragment : DialogFragment() { override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { Loading @@ -22,22 +20,21 @@ class PermissionRationaleDialogFragment : DialogFragment() { val permission = Permission.valueOf(permissionName) return AlertDialog.Builder(requireContext()).apply { setTitle(permission.rationaleTitle) setMessage(permission.rationaleMessage) setPositiveButton(R.string.okay_action) { _, _ -> val activity = requireActivity() as? K9Activity ?: throw AssertionError("PermissionRationaleDialogFragment can only be used with K9Activity") return AlertDialog.Builder(requireContext()) .setTitle(permission.rationaleTitle) .setMessage(permission.rationaleMessage) .setPositiveButton(R.string.okay_action) { _, _ -> val permissionUiHelper = requireActivity() as? PermissionUiHelper ?: throw AssertionError("Activities using PermissionRationaleDialogFragment need to " + "implement PermissionUiHelper") activity.requestPermission(permission) } permissionUiHelper.requestPermission(permission) }.create() } companion object { private const val ARG_PERMISSION = "permission" @JvmStatic fun newInstance(permission: Permission): PermissionRationaleDialogFragment { return PermissionRationaleDialogFragment().apply { arguments = bundleOf(ARG_PERMISSION to permission.name) Loading Loading
app/ui/src/main/java/com/fsck/k9/activity/K9Activity.java +1 −55 Original line number Diff line number Diff line package com.fsck.k9.activity; import android.Manifest; import android.content.pm.PackageManager; import android.os.Bundle; import androidx.annotation.LayoutRes; import androidx.annotation.StringRes; import androidx.core.app.ActivityCompat; import androidx.core.content.ContextCompat; import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.widget.Toolbar; import android.view.View; import com.fsck.k9.ui.R; import com.fsck.k9.ui.ThemeManager; import com.fsck.k9.ui.permissions.PermissionRationaleDialogFragment; import timber.log.Timber; public abstract class K9Activity extends AppCompatActivity { public static final int PERMISSIONS_REQUEST_READ_CONTACTS = 1; private static final String FRAGMENT_TAG_RATIONALE = "rationale"; private final K9ActivityCommon base = new K9ActivityCommon(this, ThemeType.DEFAULT); public ThemeManager getThemeManager() { Loading @@ -49,47 +38,4 @@ public abstract class K9Activity extends AppCompatActivity { } setSupportActionBar(toolbar); } public boolean hasPermission(Permission permission) { return ContextCompat.checkSelfPermission(this, permission.permission) == PackageManager.PERMISSION_GRANTED; } public void requestPermissionOrShowRationale(Permission permission) { if (ActivityCompat.shouldShowRequestPermissionRationale(this, permission.permission)) { PermissionRationaleDialogFragment dialogFragment = PermissionRationaleDialogFragment.newInstance(permission); dialogFragment.show(getSupportFragmentManager(), FRAGMENT_TAG_RATIONALE); } else { requestPermission(permission); } } public void requestPermission(Permission permission) { Timber.i("Requesting permission: " + permission.permission); ActivityCompat.requestPermissions(this, new String[] { permission.permission }, permission.requestCode); } public enum Permission { READ_CONTACTS( Manifest.permission.READ_CONTACTS, PERMISSIONS_REQUEST_READ_CONTACTS, R.string.permission_contacts_rationale_title, R.string.permission_contacts_rationale_message ); public final String permission; public final int requestCode; public final int rationaleTitle; public final int rationaleMessage; Permission(String permission, int requestCode, @StringRes int rationaleTitle, @StringRes int rationaleMessage) { this.permission = permission; this.requestCode = requestCode; this.rationaleTitle = rationaleTitle; this.rationaleMessage = rationaleMessage; } } }
app/ui/src/main/java/com/fsck/k9/activity/MessageCompose.java +23 −1 Original line number Diff line number Diff line Loading @@ -110,7 +110,11 @@ import com.fsck.k9.ui.compose.QuotedMessageMvpView; import com.fsck.k9.ui.compose.QuotedMessagePresenter; import com.fsck.k9.ui.helper.SizeFormatter; import com.fsck.k9.ui.messagelist.DefaultFolderProvider; import com.fsck.k9.ui.permissions.K9PermissionUiHelper; import com.fsck.k9.ui.permissions.Permission; import com.fsck.k9.ui.permissions.PermissionUiHelper; import org.jetbrains.annotations.NotNull; import org.openintents.openpgp.OpenPgpApiManager; import org.openintents.openpgp.util.OpenPgpApi; import timber.log.Timber; Loading @@ -120,7 +124,7 @@ import timber.log.Timber; public class MessageCompose extends K9Activity implements OnClickListener, CancelListener, AttachmentDownloadCancelListener, OnFocusChangeListener, OnOpenPgpInlineChangeListener, OnOpenPgpSignOnlyChangeListener, MessageBuilder.Callback, AttachmentPresenter.AttachmentsChangedListener, OnOpenPgpDisableListener { AttachmentPresenter.AttachmentsChangedListener, OnOpenPgpDisableListener, PermissionUiHelper { private static final int DIALOG_SAVE_OR_DISCARD_DRAFT_MESSAGE = 1; private static final int DIALOG_CONFIRM_DISCARD_ON_BACK = 2; Loading Loading @@ -177,6 +181,8 @@ public class MessageCompose extends K9Activity implements OnClickListener, private final MessageLoaderHelperFactory messageLoaderHelperFactory = DI.get(MessageLoaderHelperFactory.class); private final DefaultFolderProvider defaultFolderProvider = DI.get(DefaultFolderProvider.class); private final PermissionUiHelper permissionUiHelper = new K9PermissionUiHelper(this); private QuotedMessagePresenter quotedMessagePresenter; private MessageLoaderHelper messageLoaderHelper; private AttachmentPresenter attachmentPresenter; Loading Loading @@ -1883,4 +1889,20 @@ public class MessageCompose extends K9Activity implements OnClickListener, return titleResource; } } @Override public boolean hasPermission(@NotNull Permission permission) { return permissionUiHelper.hasPermission(permission); } @Override public void requestPermissionOrShowRationale(@NotNull Permission permission) { permissionUiHelper.requestPermissionOrShowRationale(permission); } @Override public void requestPermission(@NotNull Permission permission) { permissionUiHelper.requestPermission(permission); } }
app/ui/src/main/java/com/fsck/k9/activity/MessageList.java +24 −1 Original line number Diff line number Diff line Loading @@ -60,9 +60,15 @@ import com.fsck.k9.ui.messageview.MessageViewFragment; import com.fsck.k9.ui.messageview.MessageViewFragment.MessageViewFragmentListener; import com.fsck.k9.ui.messageview.PlaceholderFragment; import com.fsck.k9.ui.onboarding.OnboardingActivity; import com.fsck.k9.ui.permissions.K9PermissionUiHelper; import com.fsck.k9.ui.permissions.Permission; import com.fsck.k9.ui.permissions.PermissionUiHelper; import com.fsck.k9.view.ViewSwitcher; import com.fsck.k9.view.ViewSwitcher.OnSwitchCompleteListener; import com.mikepenz.materialdrawer.Drawer.OnDrawerListener; import org.jetbrains.annotations.NotNull; import timber.log.Timber; Loading @@ -72,7 +78,7 @@ import timber.log.Timber; * From this Activity the user can perform all standard message operations. */ public class MessageList extends K9Activity implements MessageListFragmentListener, MessageViewFragmentListener, OnBackStackChangedListener, OnSwitchCompleteListener { MessageViewFragmentListener, OnBackStackChangedListener, OnSwitchCompleteListener, PermissionUiHelper { private static final String EXTRA_SEARCH = "search_bytes"; private static final String EXTRA_NO_THREADING = "no_threading"; Loading Loading @@ -178,6 +184,8 @@ public class MessageList extends K9Activity implements MessageListFragmentListen private final NotificationChannelManager channelUtils = DI.get(NotificationChannelManager.class); private final DefaultFolderProvider defaultFolderProvider = DI.get(DefaultFolderProvider.class); private final PermissionUiHelper permissionUiHelper = new K9PermissionUiHelper(this); private ActionBar actionBar; private ActionBarDrawerToggle drawerToggle; private K9Drawer drawer; Loading Loading @@ -1622,4 +1630,19 @@ public class MessageList extends K9Activity implements MessageListFragmentListen drawer.deselect(); } } @Override public boolean hasPermission(@NotNull Permission permission) { return permissionUiHelper.hasPermission(permission); } @Override public void requestPermissionOrShowRationale(@NotNull Permission permission) { permissionUiHelper.requestPermissionOrShowRationale(permission); } @Override public void requestPermission(@NotNull Permission permission) { permissionUiHelper.requestPermission(permission); } }
app/ui/src/main/java/com/fsck/k9/ui/permissions/Permission.kt 0 → 100644 +21 −0 Original line number Diff line number Diff line package com.fsck.k9.ui.permissions import android.Manifest import androidx.annotation.StringRes import com.fsck.k9.ui.R private const val PERMISSIONS_REQUEST_READ_CONTACTS = 1 enum class Permission( val permission: String, val requestCode: Int, @param:StringRes val rationaleTitle: Int, @param:StringRes val rationaleMessage: Int ) { READ_CONTACTS( Manifest.permission.READ_CONTACTS, PERMISSIONS_REQUEST_READ_CONTACTS, R.string.permission_contacts_rationale_title, R.string.permission_contacts_rationale_message ); }
app/ui/src/main/java/com/fsck/k9/ui/permissions/PermissionRationaleDialogFragment.kt +11 −14 Original line number Diff line number Diff line Loading @@ -5,15 +5,13 @@ import android.app.Dialog import android.os.Bundle import androidx.core.os.bundleOf import androidx.fragment.app.DialogFragment import com.fsck.k9.activity.K9Activity import com.fsck.k9.activity.K9Activity.Permission import com.fsck.k9.ui.R /** * A dialog displaying a message to explain why the app requests a certain permission. * * Closing the dialog triggers a permission request. For this to work the Activity needs to be a subclass of * [K9Activity]. * Closing the dialog triggers a permission request. For this to work the Activity needs to implement * [PermissionUiHelper]. */ class PermissionRationaleDialogFragment : DialogFragment() { override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { Loading @@ -22,22 +20,21 @@ class PermissionRationaleDialogFragment : DialogFragment() { val permission = Permission.valueOf(permissionName) return AlertDialog.Builder(requireContext()).apply { setTitle(permission.rationaleTitle) setMessage(permission.rationaleMessage) setPositiveButton(R.string.okay_action) { _, _ -> val activity = requireActivity() as? K9Activity ?: throw AssertionError("PermissionRationaleDialogFragment can only be used with K9Activity") return AlertDialog.Builder(requireContext()) .setTitle(permission.rationaleTitle) .setMessage(permission.rationaleMessage) .setPositiveButton(R.string.okay_action) { _, _ -> val permissionUiHelper = requireActivity() as? PermissionUiHelper ?: throw AssertionError("Activities using PermissionRationaleDialogFragment need to " + "implement PermissionUiHelper") activity.requestPermission(permission) } permissionUiHelper.requestPermission(permission) }.create() } companion object { private const val ARG_PERMISSION = "permission" @JvmStatic fun newInstance(permission: Permission): PermissionRationaleDialogFragment { return PermissionRationaleDialogFragment().apply { arguments = bundleOf(ARG_PERMISSION to permission.name) Loading