mirror of
https://github.com/oxen-io/session-android.git
synced 2025-04-04 09:35:39 +00:00
SES-2688 SES-2689
Reworking permission logic Added the ability to copy build number from debug menu (requested by Miki)
This commit is contained in:
parent
fe7d3ef7fe
commit
150208cc56
@ -412,14 +412,9 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity im
|
|||||||
Permissions.with(this)
|
Permissions.with(this)
|
||||||
.request(android.Manifest.permission.WRITE_EXTERNAL_STORAGE)
|
.request(android.Manifest.permission.WRITE_EXTERNAL_STORAGE)
|
||||||
.maxSdkVersion(Build.VERSION_CODES.P)
|
.maxSdkVersion(Build.VERSION_CODES.P)
|
||||||
.withPermanentDenialDialog(Phrase.from(getApplicationContext(), R.string.permissionsStorageSaveDenied)
|
.withPermanentDenialDialog(getPermanentlyDeniedStorageText())
|
||||||
.put(APP_NAME_KEY, getString(R.string.app_name))
|
|
||||||
.format().toString())
|
|
||||||
.onAnyDenied(() -> {
|
.onAnyDenied(() -> {
|
||||||
String txt = Phrase.from(getApplicationContext(), R.string.permissionsStorageSaveDenied)
|
Toast.makeText(this, getPermanentlyDeniedStorageText(), Toast.LENGTH_LONG).show();
|
||||||
.put(APP_NAME_KEY, getString(R.string.app_name))
|
|
||||||
.format().toString();
|
|
||||||
Toast.makeText(this, txt, Toast.LENGTH_LONG).show();
|
|
||||||
})
|
})
|
||||||
.onAllGranted(() -> {
|
.onAllGranted(() -> {
|
||||||
SaveAttachmentTask saveTask = new SaveAttachmentTask(MediaPreviewActivity.this);
|
SaveAttachmentTask saveTask = new SaveAttachmentTask(MediaPreviewActivity.this);
|
||||||
@ -436,6 +431,12 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity im
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String getPermanentlyDeniedStorageText(){
|
||||||
|
return Phrase.from(getApplicationContext(), R.string.permissionsStorageDeniedLegacy)
|
||||||
|
.put(APP_NAME_KEY, getString(R.string.app_name))
|
||||||
|
.format().toString();
|
||||||
|
}
|
||||||
|
|
||||||
private void sendMediaSavedNotificationIfNeeded() {
|
private void sendMediaSavedNotificationIfNeeded() {
|
||||||
if (conversationRecipient.isGroupRecipient()) return;
|
if (conversationRecipient.isGroupRecipient()) return;
|
||||||
DataExtractionNotification message = new DataExtractionNotification(new DataExtractionNotification.Kind.MediaSaved(SnodeAPI.getNowWithOffset()));
|
DataExtractionNotification message = new DataExtractionNotification(new DataExtractionNotification.Kind.MediaSaved(SnodeAPI.getNowWithOffset()));
|
||||||
|
@ -2279,7 +2279,7 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
|
|||||||
Permissions.with(this)
|
Permissions.with(this)
|
||||||
.request(Manifest.permission.WRITE_EXTERNAL_STORAGE)
|
.request(Manifest.permission.WRITE_EXTERNAL_STORAGE)
|
||||||
.maxSdkVersion(Build.VERSION_CODES.P) // P is 28
|
.maxSdkVersion(Build.VERSION_CODES.P) // P is 28
|
||||||
.withPermanentDenialDialog(Phrase.from(applicationContext, R.string.permissionsStorageSaveDenied)
|
.withPermanentDenialDialog(Phrase.from(applicationContext, R.string.permissionsStorageDeniedLegacy)
|
||||||
.put(APP_NAME_KEY, getString(R.string.app_name))
|
.put(APP_NAME_KEY, getString(R.string.app_name))
|
||||||
.format().toString())
|
.format().toString())
|
||||||
.onAnyDenied {
|
.onAnyDenied {
|
||||||
@ -2289,7 +2289,7 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
|
|||||||
showSessionDialog {
|
showSessionDialog {
|
||||||
title(R.string.permissionsRequired)
|
title(R.string.permissionsRequired)
|
||||||
|
|
||||||
val txt = Phrase.from(applicationContext, R.string.permissionsStorageSaveDenied)
|
val txt = Phrase.from(applicationContext, R.string.permissionsStorageDeniedLegacy)
|
||||||
.put(APP_NAME_KEY, getString(R.string.app_name))
|
.put(APP_NAME_KEY, getString(R.string.app_name))
|
||||||
.format().toString()
|
.format().toString()
|
||||||
text(txt)
|
text(txt)
|
||||||
|
@ -245,51 +245,58 @@ public class AttachmentManager {
|
|||||||
|
|
||||||
public static void selectDocument(Activity activity, int requestCode) {
|
public static void selectDocument(Activity activity, int requestCode) {
|
||||||
Permissions.PermissionsBuilder builder = Permissions.with(activity);
|
Permissions.PermissionsBuilder builder = Permissions.with(activity);
|
||||||
|
Context c = activity.getApplicationContext();
|
||||||
|
|
||||||
// The READ_EXTERNAL_STORAGE permission is deprecated (and will AUTO-FAIL if requested!) on
|
// The READ_EXTERNAL_STORAGE permission is deprecated (and will AUTO-FAIL if requested!) on
|
||||||
// Android 13 and above (API 33 - 'Tiramisu') we must ask for READ_MEDIA_VIDEO/IMAGES/AUDIO instead.
|
// Android 13 and above (API 33 - 'Tiramisu') we must ask for READ_MEDIA_VIDEO/IMAGES/AUDIO instead.
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||||
builder = builder.request(Manifest.permission.READ_MEDIA_VIDEO)
|
builder = builder.request(Manifest.permission.READ_MEDIA_VIDEO)
|
||||||
.request(Manifest.permission.READ_MEDIA_IMAGES)
|
.request(Manifest.permission.READ_MEDIA_IMAGES)
|
||||||
.request(Manifest.permission.READ_MEDIA_AUDIO);
|
.request(Manifest.permission.READ_MEDIA_AUDIO)
|
||||||
|
.withRationaleDialog(
|
||||||
|
Phrase.from(c, R.string.permissionsStorageSend)
|
||||||
|
.put(APP_NAME_KEY, c.getString(R.string.app_name)).format().toString()
|
||||||
|
)
|
||||||
|
.withPermanentDenialDialog(
|
||||||
|
Phrase.from(c, R.string.permissionMusicAudioDenied)
|
||||||
|
.put(APP_NAME_KEY, c.getString(R.string.app_name))
|
||||||
|
.format().toString()
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
builder = builder.request(Manifest.permission.READ_EXTERNAL_STORAGE);
|
builder = builder.request(Manifest.permission.READ_EXTERNAL_STORAGE)
|
||||||
|
.withPermanentDenialDialog(
|
||||||
|
Phrase.from(c, R.string.permissionsStorageDeniedLegacy)
|
||||||
|
.put(APP_NAME_KEY, c.getString(R.string.app_name))
|
||||||
|
.format().toString()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Context c = activity.getApplicationContext();
|
builder.onAllGranted(() -> selectMediaType(activity, "*/*", null, requestCode)) // Note: We can use startActivityForResult w/ the ACTION_OPEN_DOCUMENT or ACTION_OPEN_DOCUMENT_TREE intent if we need to modernise this.
|
||||||
|
|
||||||
String needStoragePermissionTxt = Phrase.from(c, R.string.permissionsStorageSend).put(APP_NAME_KEY, c.getString(R.string.app_name)).format().toString();
|
|
||||||
|
|
||||||
String storagePermissionDeniedTxt = Phrase.from(c, R.string.permissionsStorageSaveDenied)
|
|
||||||
.put(APP_NAME_KEY, c.getString(R.string.app_name))
|
|
||||||
.format().toString();
|
|
||||||
|
|
||||||
builder.withPermanentDenialDialog(storagePermissionDeniedTxt)
|
|
||||||
.withRationaleDialog(needStoragePermissionTxt, R.drawable.ic_baseline_photo_library_24)
|
|
||||||
.onAllGranted(() -> selectMediaType(activity, "*/*", null, requestCode)) // Note: We can use startActivityForResult w/ the ACTION_OPEN_DOCUMENT or ACTION_OPEN_DOCUMENT_TREE intent if we need to modernise this.
|
|
||||||
.execute();
|
.execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void selectGallery(Activity activity, int requestCode, @NonNull Recipient recipient, @NonNull String body) {
|
public static void selectGallery(Activity activity, int requestCode, @NonNull Recipient recipient, @NonNull String body) {
|
||||||
|
|
||||||
Context c = activity.getApplicationContext();
|
Context c = activity.getApplicationContext();
|
||||||
String needStoragePermissionTxt = Phrase.from(c, R.string.permissionsStorageSend)
|
|
||||||
.put(APP_NAME_KEY, c.getString(R.string.app_name))
|
|
||||||
.format().toString();
|
|
||||||
String cameraPermissionDeniedTxt = Phrase.from(c, R.string.cameraGrantAccessDenied)
|
|
||||||
.put(APP_NAME_KEY, c.getString(R.string.app_name))
|
|
||||||
.format().toString();
|
|
||||||
|
|
||||||
Permissions.PermissionsBuilder builder = Permissions.with(activity);
|
Permissions.PermissionsBuilder builder = Permissions.with(activity);
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||||
builder = builder.request(Manifest.permission.READ_MEDIA_VIDEO)
|
builder = builder.request(Manifest.permission.READ_MEDIA_VIDEO)
|
||||||
.request(Manifest.permission.READ_MEDIA_IMAGES);
|
.request(Manifest.permission.READ_MEDIA_IMAGES)
|
||||||
|
.withPermanentDenialDialog(
|
||||||
|
Phrase.from(c, R.string.permissionsStorageDenied)
|
||||||
|
.put(APP_NAME_KEY, c.getString(R.string.app_name))
|
||||||
|
.format().toString()
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
builder = builder.request(Manifest.permission.READ_EXTERNAL_STORAGE);
|
builder = builder.request(Manifest.permission.READ_EXTERNAL_STORAGE)
|
||||||
|
.withPermanentDenialDialog(
|
||||||
|
Phrase.from(c, R.string.permissionsStorageDeniedLegacy)
|
||||||
|
.put(APP_NAME_KEY, c.getString(R.string.app_name))
|
||||||
|
.format().toString()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
builder.withPermanentDenialDialog(cameraPermissionDeniedTxt)
|
builder.onAllGranted(() -> activity.startActivityForResult(MediaSendActivity.buildGalleryIntent(activity, recipient, body), requestCode))
|
||||||
.withRationaleDialog(needStoragePermissionTxt, R.drawable.ic_baseline_photo_library_24)
|
|
||||||
.onAllGranted(() -> activity.startActivityForResult(MediaSendActivity.buildGalleryIntent(activity, recipient, body), requestCode))
|
|
||||||
.execute();
|
.execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package org.thoughtcrime.securesms.debugmenu
|
package org.thoughtcrime.securesms.debugmenu
|
||||||
|
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
|
import androidx.compose.foundation.clickable
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.ColumnScope
|
import androidx.compose.foundation.layout.ColumnScope
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
@ -19,6 +20,8 @@ import androidx.compose.runtime.Composable
|
|||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.platform.LocalClipboardManager
|
||||||
|
import androidx.compose.ui.text.AnnotatedString
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import network.loki.messenger.BuildConfig
|
import network.loki.messenger.BuildConfig
|
||||||
import network.loki.messenger.R
|
import network.loki.messenger.R
|
||||||
@ -45,7 +48,7 @@ fun DebugMenu(
|
|||||||
sendCommand: (DebugMenuViewModel.Commands) -> Unit,
|
sendCommand: (DebugMenuViewModel.Commands) -> Unit,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
onClose: () -> Unit
|
onClose: () -> Unit
|
||||||
){
|
) {
|
||||||
val snackbarHostState = remember { SnackbarHostState() }
|
val snackbarHostState = remember { SnackbarHostState() }
|
||||||
|
|
||||||
Scaffold(
|
Scaffold(
|
||||||
@ -56,7 +59,7 @@ fun DebugMenu(
|
|||||||
) { contentPadding ->
|
) { contentPadding ->
|
||||||
// display a snackbar when required
|
// display a snackbar when required
|
||||||
LaunchedEffect(uiState.snackMessage) {
|
LaunchedEffect(uiState.snackMessage) {
|
||||||
if(!uiState.snackMessage.isNullOrEmpty()){
|
if (!uiState.snackMessage.isNullOrEmpty()) {
|
||||||
snackbarHostState.showSnackbar(uiState.snackMessage)
|
snackbarHostState.showSnackbar(uiState.snackMessage)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -102,13 +105,22 @@ fun DebugMenu(
|
|||||||
.verticalScroll(rememberScrollState())
|
.verticalScroll(rememberScrollState())
|
||||||
) {
|
) {
|
||||||
// Info pane
|
// Info pane
|
||||||
DebugCell("App Info") {
|
val clipboardManager = LocalClipboardManager.current
|
||||||
Text(
|
val appVersion = "${BuildConfig.VERSION_NAME} (${BuildConfig.VERSION_CODE} - ${
|
||||||
text = "Version: ${BuildConfig.VERSION_NAME} (${BuildConfig.VERSION_CODE} - ${
|
|
||||||
BuildConfig.GIT_HASH.take(
|
BuildConfig.GIT_HASH.take(
|
||||||
6
|
6
|
||||||
)
|
)
|
||||||
})",
|
})"
|
||||||
|
|
||||||
|
DebugCell(
|
||||||
|
modifier = Modifier.clickable {
|
||||||
|
// clicking the cell copies the version number to the clipboard
|
||||||
|
clipboardManager.setText(AnnotatedString(appVersion))
|
||||||
|
},
|
||||||
|
title = "App Info"
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = "Version: $appVersion",
|
||||||
style = LocalType.current.base
|
style = LocalType.current.base
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -155,7 +167,7 @@ fun ColumnScope.DebugCell(
|
|||||||
|
|
||||||
@Preview
|
@Preview
|
||||||
@Composable
|
@Composable
|
||||||
fun PreviewDebugMenu(){
|
fun PreviewDebugMenu() {
|
||||||
PreviewTheme {
|
PreviewTheme {
|
||||||
DebugMenu(
|
DebugMenu(
|
||||||
uiState = DebugMenuViewModel.UIState(
|
uiState = DebugMenuViewModel.UIState(
|
||||||
|
@ -73,7 +73,7 @@ public class Permissions {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public PermissionsBuilder withRationaleDialog(@NonNull String message, @NonNull @DrawableRes int... headers) {
|
public PermissionsBuilder withRationaleDialog(@NonNull String message, @DrawableRes int... headers) {
|
||||||
this.rationalDialogHeader = headers;
|
this.rationalDialogHeader = headers;
|
||||||
this.rationaleDialogMessage = message;
|
this.rationaleDialogMessage = message;
|
||||||
return this;
|
return this;
|
||||||
@ -143,7 +143,7 @@ public class Permissions {
|
|||||||
|
|
||||||
if (!isInTargetSDKRange || permissionObject.hasAll(requestedPermissions)) {
|
if (!isInTargetSDKRange || permissionObject.hasAll(requestedPermissions)) {
|
||||||
executePreGrantedPermissionsRequest(request);
|
executePreGrantedPermissionsRequest(request);
|
||||||
} else if (rationaleDialogMessage != null && rationalDialogHeader != null) {
|
} else if (rationaleDialogMessage != null) {
|
||||||
executePermissionsRequestWithRationale(request);
|
executePermissionsRequestWithRationale(request);
|
||||||
} else {
|
} else {
|
||||||
executePermissionsRequest(request);
|
executePermissionsRequest(request);
|
||||||
|
@ -4,6 +4,7 @@ import android.content.Context
|
|||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
import android.util.TypedValue
|
import android.util.TypedValue
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.ImageView
|
import android.widget.ImageView
|
||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
@ -25,10 +26,13 @@ object RationaleDialog {
|
|||||||
onNegative: Runnable,
|
onNegative: Runnable,
|
||||||
@DrawableRes vararg drawables: Int
|
@DrawableRes vararg drawables: Int
|
||||||
): AlertDialog {
|
): AlertDialog {
|
||||||
val view = LayoutInflater.from(context).inflate(R.layout.permissions_rationale_dialog, null)
|
var customView: View? = null
|
||||||
|
if (!drawables.isEmpty()) {
|
||||||
|
customView = LayoutInflater.from(context).inflate(R.layout.permissions_rationale_dialog, null)
|
||||||
.apply { clipToOutline = true }
|
.apply { clipToOutline = true }
|
||||||
val header = view.findViewById<ViewGroup>(R.id.header_container)
|
val header = customView.findViewById<ViewGroup>(R.id.header_container)
|
||||||
view.findViewById<TextView>(R.id.message).text = message
|
|
||||||
|
customView.findViewById<TextView>(R.id.message).text = message
|
||||||
|
|
||||||
fun addIcon(id: Int) {
|
fun addIcon(id: Int) {
|
||||||
ImageView(context).apply {
|
ImageView(context).apply {
|
||||||
@ -50,9 +54,16 @@ object RationaleDialog {
|
|||||||
|
|
||||||
drawables.firstOrNull()?.let(::addIcon)
|
drawables.firstOrNull()?.let(::addIcon)
|
||||||
drawables.drop(1).forEach { addPlus(); addIcon(it) }
|
drawables.drop(1).forEach { addPlus(); addIcon(it) }
|
||||||
|
}
|
||||||
|
|
||||||
return context.showSessionDialog {
|
return context.showSessionDialog {
|
||||||
view(view)
|
// show the generic title when there are no icons
|
||||||
|
if(customView != null){
|
||||||
|
view(customView)
|
||||||
|
} else {
|
||||||
|
title(R.string.permissionsRequired)
|
||||||
|
text(message)
|
||||||
|
}
|
||||||
button(R.string.theContinue) { onPositive.run() }
|
button(R.string.theContinue) { onPositive.run() }
|
||||||
button(R.string.notNow) { onNegative.run() }
|
button(R.string.notNow) { onNegative.run() }
|
||||||
}
|
}
|
||||||
|
@ -98,10 +98,10 @@ class HelpSettingsFragment: CorrectedPreferenceFragment() {
|
|||||||
Permissions.with(this)
|
Permissions.with(this)
|
||||||
.request(Manifest.permission.WRITE_EXTERNAL_STORAGE)
|
.request(Manifest.permission.WRITE_EXTERNAL_STORAGE)
|
||||||
.maxSdkVersion(Build.VERSION_CODES.P)
|
.maxSdkVersion(Build.VERSION_CODES.P)
|
||||||
.withPermanentDenialDialog(requireContext().getSubbedString(R.string.permissionsStorageSaveDenied, APP_NAME_KEY to getString(R.string.app_name)))
|
.withPermanentDenialDialog(requireContext().getSubbedString(R.string.permissionsStorageDeniedLegacy, APP_NAME_KEY to getString(R.string.app_name)))
|
||||||
.onAnyDenied {
|
.onAnyDenied {
|
||||||
val c = requireContext()
|
val c = requireContext()
|
||||||
val txt = c.getSubbedString(R.string.permissionsStorageSaveDenied, APP_NAME_KEY to getString(R.string.app_name))
|
val txt = c.getSubbedString(R.string.permissionsStorageDeniedLegacy, APP_NAME_KEY to getString(R.string.app_name))
|
||||||
Toast.makeText(c, txt, Toast.LENGTH_LONG).show()
|
Toast.makeText(c, txt, Toast.LENGTH_LONG).show()
|
||||||
}
|
}
|
||||||
.onAllGranted {
|
.onAllGranted {
|
||||||
|
@ -63,7 +63,6 @@ import kotlinx.coroutines.launch
|
|||||||
import network.loki.messenger.R
|
import network.loki.messenger.R
|
||||||
import org.session.libsession.utilities.StringSubstitutionConstants.APP_NAME_KEY
|
import org.session.libsession.utilities.StringSubstitutionConstants.APP_NAME_KEY
|
||||||
import org.session.libsignal.utilities.Log
|
import org.session.libsignal.utilities.Log
|
||||||
import org.thoughtcrime.securesms.mediasend.MediaSendActivity
|
|
||||||
import org.thoughtcrime.securesms.permissions.Permissions
|
import org.thoughtcrime.securesms.permissions.Permissions
|
||||||
import org.thoughtcrime.securesms.ui.AlertDialog
|
import org.thoughtcrime.securesms.ui.AlertDialog
|
||||||
import org.thoughtcrime.securesms.ui.DialogButtonModel
|
import org.thoughtcrime.securesms.ui.DialogButtonModel
|
||||||
|
Loading…
x
Reference in New Issue
Block a user