diff --git a/app/src/main/java/org/thoughtcrime/securesms/MediaPreviewActivity.java b/app/src/main/java/org/thoughtcrime/securesms/MediaPreviewActivity.java index ff6315ef6f..4fd99dd6c0 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/MediaPreviewActivity.java +++ b/app/src/main/java/org/thoughtcrime/securesms/MediaPreviewActivity.java @@ -408,7 +408,7 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity im MediaItem mediaItem = getCurrentMediaItem(); if (mediaItem == null) return; - SaveAttachmentTask.showWarningDialog(this, 1, () -> { + SaveAttachmentTask.showOneTimeWarningDialogOrSave(this, 1, () -> { Permissions.with(this) .request(android.Manifest.permission.WRITE_EXTERNAL_STORAGE) .maxSdkVersion(Build.VERSION_CODES.P) diff --git a/app/src/main/java/org/thoughtcrime/securesms/calls/WebRtcCallActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/calls/WebRtcCallActivity.kt index de3ebc9547..69bcef2242 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/calls/WebRtcCallActivity.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/calls/WebRtcCallActivity.kt @@ -29,7 +29,6 @@ import network.loki.messenger.R import network.loki.messenger.databinding.ActivityWebrtcBinding import org.apache.commons.lang3.time.DurationFormatUtils import org.session.libsession.messaging.contacts.Contact -import org.session.libsession.utilities.Address import org.session.libsession.utilities.StringSubstitutionConstants.APP_NAME_KEY import org.session.libsession.utilities.TextSecurePreferences import org.session.libsession.utilities.truncateIdForDisplay @@ -207,7 +206,6 @@ class WebRtcCallActivity : PassphraseRequiredActionBarActivity() { } } - // Substitute "Session" into the "{app_name} Call" text val sessionCallTV = findViewById(R.id.sessionCallText) sessionCallTV?.text = Phrase.from(this, R.string.callsSessionCall).put(APP_NAME_KEY, getString(R.string.app_name)).format() diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt index 6bba3121c1..850ca77396 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt @@ -103,6 +103,7 @@ import org.session.libsignal.utilities.guava.Optional import org.session.libsignal.utilities.hexEncodedPrivateKey import org.thoughtcrime.securesms.ApplicationContext import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity +import org.thoughtcrime.securesms.SessionDialogBuilder import org.thoughtcrime.securesms.attachments.ScreenshotObserver import org.thoughtcrime.securesms.audio.AudioRecorder import org.thoughtcrime.securesms.components.emoji.RecentEmojiPageModel @@ -2229,30 +2230,34 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe return } - // On Android versions below 30 we require the WRITE_EXTERNAL_STORAGE permission to save attachments. - // However, we would like to on more recent Android API versions there is scoped storage - // If we already have permission to write to external storage then just get on with it & return.. - // - // Android versions will j - if (Build.VERSION.SDK_INT < 30) { - // Save the attachment(s) then bail if we already have permission to do so - if (hasPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)) { - saveAttachments(message) - return - } - } else { - // On more modern versions of Android on API 30+ WRITE_EXTERNAL_STORAGE is no longer used and we can just - // save files to the public directories like "Downloads", "Pictures" etc. - but... we would still like to - // inform the user just _once_ that saving attachments means that other apps can access them - so we'll - val haveWarned = TextSecurePreferences.getHaveWarnedUserAboutSavingAttachments(this) - if (haveWarned) { + // Before saving an attachment, regardless of Android API version or permissions, we always want to ensure + // that we've warned the user just _once_ that any attachments they save can be accessed by other apps. + val haveWarned = TextSecurePreferences.getHaveWarnedUserAboutSavingAttachments(this) + if (haveWarned) { + + // On Android versions below 30 we require the WRITE_EXTERNAL_STORAGE permission to save attachments. + // However, we would like to on more recent Android API versions there is scoped storage + // If we already have permission to write to external storage then just get on with it & return.. + // + // Android versions will j + if (Build.VERSION.SDK_INT < 30) { + // Save the attachment(s) then bail if we already have permission to do so + if (hasPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)) { + saveAttachments(message) + return + } else { + /* Do nothing - which means we continue on to the SaveAttachmentTask part below where we ask for permissions */ + } + } else { + // On more modern versions of Android on API 30+ WRITE_EXTERNAL_STORAGE is no longer used and we can just + // save files to the public directories like "Downloads", "Pictures" etc. saveAttachments(message) return } } - // ..otherwise we must ask for it first. - SaveAttachmentTask.showWarningDialog(this) { + // ..otherwise we must ask for it first (only on Android APIs up to 28). + SaveAttachmentTask.showOneTimeWarningDialogOrSave(this) { Permissions.with(this) .request(Manifest.permission.WRITE_EXTERNAL_STORAGE) .maxSdkVersion(Build.VERSION_CODES.P) // P is 28 @@ -2262,6 +2267,7 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe .onAnyDenied { endActionMode() + // If permissions were denied inform the user that we can't proceed without them and offer to take the user to Settings showSessionDialog { title(R.string.permissionsRequired) diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/utilities/AttachmentManager.java b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/utilities/AttachmentManager.java index d269f1dcfc..221e1b76c2 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/utilities/AttachmentManager.java +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/utilities/AttachmentManager.java @@ -16,6 +16,7 @@ */ package org.thoughtcrime.securesms.conversation.v2.utilities; +import static com.google.android.gms.common.util.CollectionUtils.listOf; import static org.session.libsession.utilities.StringSubstitutionConstants.APP_NAME_KEY; import android.Manifest; @@ -256,9 +257,9 @@ public class AttachmentManager { } 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 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(); diff --git a/app/src/main/java/org/thoughtcrime/securesms/groups/EditClosedGroupActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/groups/EditClosedGroupActivity.kt index 485d93abf0..4aa086e147 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/groups/EditClosedGroupActivity.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/groups/EditClosedGroupActivity.kt @@ -3,6 +3,8 @@ package org.thoughtcrime.securesms.groups import android.content.Context import android.content.Intent import android.os.Bundle +import android.text.SpannableString +import android.text.style.StyleSpan import android.view.Menu import android.view.MenuItem import android.view.View @@ -175,10 +177,6 @@ class EditClosedGroupActivity : PassphraseRequiredActionBarActivity() { originalMembers.clear() originalMembers.addAll(members + zombies) updateMembers() - - // Now that we have the group members we can update the text on the member count - val memberCountTV = findViewById(R.id.editGroupMemberCount) - memberCountTV.text = resources.getQuantityString(R.plurals.members, members.size, members.size) } override fun onLoaderReset(loader: Loader) { diff --git a/app/src/main/java/org/thoughtcrime/securesms/ui/Util.kt b/app/src/main/java/org/thoughtcrime/securesms/ui/Util.kt index b49f9c6d60..b76e931db0 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/ui/Util.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/ui/Util.kt @@ -5,6 +5,7 @@ import android.content.Context import androidx.compose.runtime.Composable import androidx.compose.ui.platform.ComposeView import androidx.fragment.app.Fragment +import com.squareup.phrase.Phrase import org.thoughtcrime.securesms.ui.theme.SessionMaterialTheme fun Activity.setComposeContent(content: @Composable () -> Unit) { diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/SaveAttachmentTask.kt b/app/src/main/java/org/thoughtcrime/securesms/util/SaveAttachmentTask.kt index bd39f5f079..2f89ccbc43 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/util/SaveAttachmentTask.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/util/SaveAttachmentTask.kt @@ -44,7 +44,7 @@ class SaveAttachmentTask @JvmOverloads constructor(context: Context, count: Int @JvmStatic @JvmOverloads - fun showWarningDialog(context: Context, count: Int = 1, onAcceptListener: () -> Unit = {}) { + fun showOneTimeWarningDialogOrSave(context: Context, count: Int = 1, onAcceptListener: () -> Unit = {}) { // If we've already warned the user that saved attachments can be accessed by other apps // then we'll just perform the save.. val haveWarned = TextSecurePreferences.getHaveWarnedUserAboutSavingAttachments(context) @@ -58,10 +58,7 @@ class SaveAttachmentTask @JvmOverloads constructor(context: Context, count: Int iconAttribute(R.attr.dialog_alert_icon) text(context.getString(R.string.attachmentsWarning)) dangerButton(R.string.save) { - // Regardless of Android API version, we'll always warn the user that saved attachments - // can be accessed by other apps - but we'll only ever do this ONCE. When the user accepts - // this warning and agrees to proceed we write a shared pref flag and will never show this - // warning again due to the early-exit condition at the top of this method. + // Set our 'haveWarned' SharedPref and perform the save on accept TextSecurePreferences.setHaveWarnedUserAboutSavingAttachments(context) onAcceptListener() } diff --git a/app/src/main/res/layout/activity_edit_closed_group.xml b/app/src/main/res/layout/activity_edit_closed_group.xml index 7d8b18f123..006a493922 100644 --- a/app/src/main/res/layout/activity_edit_closed_group.xml +++ b/app/src/main/res/layout/activity_edit_closed_group.xml @@ -112,7 +112,7 @@ android:layout_marginEnd="@dimen/small_spacing" android:layout_marginBottom="@dimen/small_spacing" android:layout_weight="1" - android:text="{count} members" + android:text="@string/groupMembers" android:textColor="?android:textColorPrimary" android:textSize="@dimen/medium_font_size" /> diff --git a/app/src/main/res/menu/menu_done.xml b/app/src/main/res/menu/menu_done.xml index 6334d51e7b..833223833a 100644 --- a/app/src/main/res/menu/menu_done.xml +++ b/app/src/main/res/menu/menu_done.xml @@ -2,6 +2,7 @@ +