From 4f3bb0a1a5829519a681ee031ebd77288315e96f Mon Sep 17 00:00:00 2001 From: ThomasSession Date: Mon, 29 Sep 2025 12:03:48 +1000 Subject: [PATCH 1/4] Proper data reference --- .../thoughtcrime/securesms/preferences/SettingsViewModel.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/preferences/SettingsViewModel.kt b/app/src/main/java/org/thoughtcrime/securesms/preferences/SettingsViewModel.kt index 0d9e575e78..e414d811b1 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/preferences/SettingsViewModel.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/preferences/SettingsViewModel.kt @@ -126,8 +126,8 @@ class SettingsViewModel @Inject constructor( } viewModelScope.launch { - OnionRequestAPI.hasPath.collect { - _uiState.update { it.copy(hasPath = it.hasPath) } + OnionRequestAPI.hasPath.collect { data -> + _uiState.update { it.copy(hasPath = data) } } } From 6a18d0500741aefe38ad08afd2462391af7f8794 Mon Sep 17 00:00:00 2001 From: SessionHero01 <180888785+SessionHero01@users.noreply.github.com> Date: Mon, 29 Sep 2025 13:37:29 +0800 Subject: [PATCH 2/4] [SES-4642] - Fix group left notification message not sent (#1557) --- .../securesms/groups/GroupLeavingWorker.kt | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/groups/GroupLeavingWorker.kt b/app/src/main/java/org/thoughtcrime/securesms/groups/GroupLeavingWorker.kt index 3bae207c07..d376e79242 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/groups/GroupLeavingWorker.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/groups/GroupLeavingWorker.kt @@ -62,6 +62,7 @@ class GroupLeavingWorker @AssistedInject constructor( if (group != null && !group.kicked && !weAreTheOnlyAdmin) { val address = Address.fromSerialized(groupId.hexString) + val statusChannel = Channel>() // Always send a "XXX left" message to the group if we can MessageSender.send( @@ -70,12 +71,12 @@ class GroupLeavingWorker @AssistedInject constructor( .setMemberLeftNotificationMessage(DataMessage.GroupUpdateMemberLeftNotificationMessage.getDefaultInstance()) .build() ), - address + address, + statusCallback = statusChannel, ) // If we are not the only admin, send a left message for other admin to handle the member removal // We'll have to wait for this message to be sent before going ahead to delete the group - val statusChannel = Channel>() MessageSender.send( GroupUpdated( GroupUpdateMessage.newBuilder() @@ -86,7 +87,10 @@ class GroupLeavingWorker @AssistedInject constructor( statusCallback = statusChannel ) - statusChannel.receive().getOrThrow() + // Wait for both messages to be sent + repeat(2) { + statusChannel.receive().getOrThrow() + } } // If we are the only admin, leaving this group will destroy the group From 62b90bd642cc8c62079e525e8e3ac862c6a8684c Mon Sep 17 00:00:00 2001 From: jbsession Date: Tue, 30 Sep 2025 08:04:57 +0800 Subject: [PATCH 3/4] SES-4640 : Ability to select more media in partial media permission (#1558) --- .../v2/utilities/AttachmentManager.java | 44 ++++++++++++++----- .../mediasend/MediaPickerFolderFragment.java | 25 +++++++++-- 2 files changed, 53 insertions(+), 16 deletions(-) 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 c79c393749..1abe337271 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 @@ -350,23 +350,34 @@ public static void selectGallery(Activity activity, int requestCode, @NonNull Ad } public static boolean hasFullAccess(Activity activity) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + return Permissions.hasAll(activity, + Manifest.permission.READ_MEDIA_IMAGES, + Manifest.permission.READ_MEDIA_VIDEO); + } else { + return Permissions.hasAll(activity, android.Manifest.permission.READ_EXTERNAL_STORAGE); + } + } + + public static boolean hasPartialAccess(@NonNull Context c) { return Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE && - Permissions.hasAll(activity, - Manifest.permission.READ_MEDIA_IMAGES, - Manifest.permission.READ_MEDIA_VIDEO); + Permissions.hasAll(c, Manifest.permission.READ_MEDIA_VISUAL_USER_SELECTED); } public static void managePhotoAccess(@NonNull Activity activity, @Nullable Runnable onAnyResult) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) { // API 34+ - Permissions.with(activity) - .request( - Manifest.permission.READ_MEDIA_IMAGES, - Manifest.permission.READ_MEDIA_VIDEO, - Manifest.permission.READ_MEDIA_VISUAL_USER_SELECTED - ).onAnyResult(() -> { - if (onAnyResult != null) onAnyResult.run(); - }) - .execute(); + if (hasPartialAccess(activity)) { + Permissions.with(activity) + .request( + Manifest.permission.READ_MEDIA_IMAGES, + Manifest.permission.READ_MEDIA_VIDEO, + Manifest.permission.READ_MEDIA_VISUAL_USER_SELECTED + ) + .onAnyResult(() -> { + if (onAnyResult != null) onAnyResult.run(); + }) + .execute(); + } } else { // older Android: no partial selector, send to App settings Intent i = new Intent(android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS) @@ -375,6 +386,15 @@ public static void managePhotoAccess(@NonNull Activity activity, @Nullable Runna } } + public static boolean shouldShowManagePhoto(@NonNull Activity activity){ + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE){ + return !hasFullAccess(activity) && hasPartialAccess(activity); + }else{ + // No partial access for <= API 33 + return false; + } + } + public static void selectAudio(Activity activity, int requestCode) { selectMediaType(activity, "audio/*", null, requestCode); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/mediasend/MediaPickerFolderFragment.java b/app/src/main/java/org/thoughtcrime/securesms/mediasend/MediaPickerFolderFragment.java index 71dd6a24a2..f060bf4424 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/mediasend/MediaPickerFolderFragment.java +++ b/app/src/main/java/org/thoughtcrime/securesms/mediasend/MediaPickerFolderFragment.java @@ -53,6 +53,7 @@ public class MediaPickerFolderFragment extends Fragment implements MediaPickerFo MediaPickerFolderAdapter adapter; + private MenuProvider manageMenuProvider; public static @NonNull MediaPickerFolderFragment newInstance(@NonNull Recipient recipient) { Bundle args = new Bundle(); @@ -133,9 +134,20 @@ private void initToolbar(Toolbar toolbar) { toolbar.setNavigationOnClickListener(v -> requireActivity().onBackPressed()); } - if(!AttachmentManager.hasFullAccess(requireActivity())){ - MenuHost menuHost = (MenuHost) requireActivity(); - menuHost.addMenuProvider(new MenuProvider() { + initToolbarOptions(); + } + + private void initToolbarOptions() { + MenuHost menuHost = (MenuHost) requireActivity(); + + // Always remove current provider first (if any) + if (manageMenuProvider != null) { + menuHost.removeMenuProvider(manageMenuProvider); + manageMenuProvider = null; + } + + if (AttachmentManager.shouldShowManagePhoto(requireActivity())) { + manageMenuProvider = new MenuProvider() { @Override public void onCreateMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) { inflater.inflate(R.menu.menu_media_add, menu); @@ -146,14 +158,19 @@ public boolean onMenuItemSelected(@NonNull MenuItem item) { if (item.getItemId() == R.id.mediapicker_menu_add) { AttachmentManager.managePhotoAccess(requireActivity(), () -> { if (!isAdded()) return; + viewModel.getFolders(requireContext()) .observe(getViewLifecycleOwner(), adapter::setFolders); + + initToolbarOptions(); }); return true; } return false; } - }, getViewLifecycleOwner(), Lifecycle.State.STARTED); + }; + + menuHost.addMenuProvider(manageMenuProvider, getViewLifecycleOwner(), Lifecycle.State.STARTED); } } From 7d207f35452df3a2860c668996927aa7642a402f Mon Sep 17 00:00:00 2001 From: ThomasSession Date: Tue, 30 Sep 2025 17:07:29 +1000 Subject: [PATCH 4/4] Bumped version code --- app/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index ec636eec2f..6a16900d05 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -26,7 +26,7 @@ configurations.configureEach { exclude(module = "commons-logging") } -val canonicalVersionCode = 420 +val canonicalVersionCode = 421 val canonicalVersionName = "1.28.0" val postFixSize = 10