Skip to content

Commit

Permalink
Merge tag 'v7.8.1' into molly-7.8
Browse files Browse the repository at this point in the history
  • Loading branch information
valldrac committed May 22, 2024
2 parents 711d31f + eb114de commit 8c2254d
Show file tree
Hide file tree
Showing 155 changed files with 12,562 additions and 8,249 deletions.
4 changes: 2 additions & 2 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ apply {
from("fix-profm.gradle")
}

val canonicalVersionCode = 1419
val canonicalVersionName = "7.7.2"
val canonicalVersionCode = 1421
val canonicalVersionName = "7.8.1"
val mollyRevision = 1

val postFixSize = 100
Expand Down
6 changes: 6 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -908,6 +908,12 @@
<data android:mimeType="vnd.android.cursor.item/vnd.org.thoughtcrime.securesms.call" />
</intent-filter>

<intent-filter tools:ignore="AppLinkUrlError">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="vnd.android.cursor.item/vnd.org.thoughtcrime.securesms.videocall" />
</intent-filter>

</activity>

<activity android:name=".mediasend.AvatarSelectionActivity"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package org.thoughtcrime.securesms
import android.content.Context
import android.view.View
import android.widget.TextView
import com.google.android.material.button.MaterialButton
import org.thoughtcrime.securesms.contacts.paged.ContactSearchAdapter
import org.thoughtcrime.securesms.contacts.paged.ContactSearchConfiguration
import org.thoughtcrime.securesms.contacts.paged.ContactSearchData
Expand All @@ -24,6 +25,8 @@ class ContactSelectionListAdapter(
init {
registerFactory(NewGroupModel::class.java, LayoutFactory({ NewGroupViewHolder(it, onClickCallbacks::onNewGroupClicked) }, R.layout.contact_selection_new_group_item))
registerFactory(InviteToSignalModel::class.java, LayoutFactory({ InviteToSignalViewHolder(it, onClickCallbacks::onInviteToSignalClicked) }, R.layout.contact_selection_invite_action_item))
registerFactory(FindContactsModel::class.java, LayoutFactory({ FindContactsViewHolder(it, onClickCallbacks::onFindContactsClicked) }, R.layout.contact_selection_find_contacts_item))
registerFactory(FindContactsBannerModel::class.java, LayoutFactory({ FindContactsBannerViewHolder(it, onClickCallbacks::onDismissFindContactsBannerClicked, onClickCallbacks::onFindContactsClicked) }, R.layout.contact_selection_find_contacts_banner_item))
registerFactory(RefreshContactsModel::class.java, LayoutFactory({ RefreshContactsViewHolder(it, onClickCallbacks::onRefreshContactsClicked) }, R.layout.contact_selection_refresh_action_item))
registerFactory(MoreHeaderModel::class.java, LayoutFactory({ MoreHeaderViewHolder(it) }, R.layout.contact_search_section_header))
registerFactory(EmptyModel::class.java, LayoutFactory({ EmptyViewHolder(it) }, R.layout.contact_selection_empty_state))
Expand All @@ -46,6 +49,16 @@ class ContactSelectionListAdapter(
override fun areContentsTheSame(newItem: RefreshContactsModel): Boolean = true
}

class FindContactsModel : MappingModel<FindContactsModel> {
override fun areItemsTheSame(newItem: FindContactsModel): Boolean = true
override fun areContentsTheSame(newItem: FindContactsModel): Boolean = true
}

class FindContactsBannerModel : MappingModel<FindContactsBannerModel> {
override fun areItemsTheSame(newItem: FindContactsBannerModel): Boolean = true
override fun areContentsTheSame(newItem: FindContactsBannerModel): Boolean = true
}

class FindByUsernameModel : MappingModel<FindByUsernameModel> {
override fun areItemsTheSame(newItem: FindByUsernameModel): Boolean = true
override fun areContentsTheSame(newItem: FindByUsernameModel): Boolean = true
Expand Down Expand Up @@ -86,6 +99,23 @@ class ContactSelectionListAdapter(
override fun bind(model: RefreshContactsModel) = Unit
}

private class FindContactsViewHolder(itemView: View, onClickListener: () -> Unit) : MappingViewHolder<FindContactsModel>(itemView) {
init {
itemView.setOnClickListener { onClickListener() }
}

override fun bind(model: FindContactsModel) = Unit
}

private class FindContactsBannerViewHolder(itemView: View, onDismissListener: () -> Unit, onClickListener: () -> Unit) : MappingViewHolder<FindContactsBannerModel>(itemView) {
init {
itemView.findViewById<MaterialButton>(R.id.no_thanks_button).setOnClickListener { onDismissListener() }
itemView.findViewById<MaterialButton>(R.id.allow_contacts_button).setOnClickListener { onClickListener() }
}

override fun bind(model: FindContactsBannerModel) = Unit
}

private class MoreHeaderViewHolder(itemView: View) : MappingViewHolder<MoreHeaderModel>(itemView) {

private val headerTextView: TextView = itemView.findViewById(R.id.section_header)
Expand Down Expand Up @@ -129,6 +159,8 @@ class ContactSelectionListAdapter(
INVITE_TO_SIGNAL("invite-to-signal"),
MORE_HEADING("more-heading"),
REFRESH_CONTACTS("refresh-contacts"),
FIND_CONTACTS("find-contacts"),
FIND_CONTACTS_BANNER("find-contacts-banner"),
FIND_BY_USERNAME("find-by-username"),
FIND_BY_PHONE_NUMBER("find-by-phone-number");

Expand All @@ -152,6 +184,8 @@ class ContactSelectionListAdapter(
ArbitraryRow.INVITE_TO_SIGNAL -> InviteToSignalModel()
ArbitraryRow.MORE_HEADING -> MoreHeaderModel()
ArbitraryRow.REFRESH_CONTACTS -> RefreshContactsModel()
ArbitraryRow.FIND_CONTACTS -> FindContactsModel()
ArbitraryRow.FIND_CONTACTS_BANNER -> FindContactsBannerModel()
ArbitraryRow.FIND_BY_PHONE_NUMBER -> FindByPhoneNumberModel()
ArbitraryRow.FIND_BY_USERNAME -> FindByUsernameModel()
}
Expand All @@ -162,6 +196,8 @@ class ContactSelectionListAdapter(
fun onNewGroupClicked()
fun onInviteToSignalClicked()
fun onRefreshContactsClicked()
fun onFindContactsClicked()
fun onDismissFindContactsBannerClicked()
fun onFindByPhoneNumberClicked()
fun onFindByUsernameClicked()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,13 +70,13 @@
import org.thoughtcrime.securesms.contacts.sync.ContactDiscovery;
import org.thoughtcrime.securesms.groups.SelectionLimits;
import org.thoughtcrime.securesms.groups.ui.GroupLimitDialog;
import org.thoughtcrime.securesms.keyvalue.SignalStore;
import org.thoughtcrime.securesms.permissions.Permissions;
import org.thoughtcrime.securesms.profiles.manage.UsernameRepository;
import org.thoughtcrime.securesms.profiles.manage.UsernameRepository.UsernameAciFetchResult;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.RecipientId;
import org.thoughtcrime.securesms.util.CommunicationActions;
import org.thoughtcrime.securesms.util.FeatureFlags;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.thoughtcrime.securesms.util.UsernameUtil;
import org.thoughtcrime.securesms.util.ViewUtil;
Expand Down Expand Up @@ -125,10 +125,6 @@ public final class ContactSelectionListFragment extends LoggingFragment {
private TextView emptyText;
private OnContactSelectedListener onContactSelectedListener;
private SwipeRefreshLayout swipeRefresh;
private View showContactsLayout;
private Button showContactsButton;
private TextView showContactsDescription;
private ProgressWheel showContactsProgress;
private String cursorFilter;
private RecyclerView recyclerView;
private RecyclerViewFastScroller fastScroller;
Expand Down Expand Up @@ -223,43 +219,25 @@ public void onActivityCreated(Bundle icicle) {
public void onStart() {
super.onStart();

Permissions.with(this)
.request(Manifest.permission.WRITE_CONTACTS, Manifest.permission.READ_CONTACTS)
.ifNecessary()
.onAllGranted(() -> {
if (!TextSecurePreferences.hasSuccessfullyRetrievedDirectory(getActivity())) {
handleContactPermissionGranted();
} else {
contactSearchMediator.refresh();
}
})
.onAnyDenied(() -> {
requireActivity().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);

if (safeArguments().getBoolean(RECENTS, requireActivity().getIntent().getBooleanExtra(RECENTS, false))) {
contactSearchMediator.refresh();
} else {
initializeNoContactsPermission();
}
})
.execute();
if (hasContactsPermissions(requireContext()) && !TextSecurePreferences.hasSuccessfullyRetrievedDirectory(getActivity())) {
handleContactPermissionGranted();
} else {
requireActivity().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
contactSearchMediator.refresh();
}
}

@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.contact_selection_list_fragment, container, false);

emptyText = view.findViewById(android.R.id.empty);
recyclerView = view.findViewById(R.id.recycler_view);
swipeRefresh = view.findViewById(R.id.swipe_refresh);
fastScroller = view.findViewById(R.id.fast_scroller);
showContactsLayout = view.findViewById(R.id.show_contacts_container);
showContactsButton = view.findViewById(R.id.show_contacts_button);
showContactsDescription = view.findViewById(R.id.show_contacts_description);
showContactsProgress = view.findViewById(R.id.progress);
chipRecycler = view.findViewById(R.id.chipRecycler);
constraintLayout = view.findViewById(R.id.container);
headerActionView = view.findViewById(R.id.header_action);
emptyText = view.findViewById(android.R.id.empty);
recyclerView = view.findViewById(R.id.recycler_view);
swipeRefresh = view.findViewById(R.id.swipe_refresh);
fastScroller = view.findViewById(R.id.fast_scroller);
chipRecycler = view.findViewById(R.id.chipRecycler);
constraintLayout = view.findViewById(R.id.container);
headerActionView = view.findViewById(R.id.header_action);

final LinearLayoutManager layoutManager = new LinearLayoutManager(requireContext());

Expand All @@ -269,6 +247,11 @@ public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
public boolean canReuseUpdatedViewHolder(@NonNull RecyclerView.ViewHolder viewHolder) {
return true;
}

@Override
public void onAnimationFinished(@NonNull RecyclerView.ViewHolder viewHolder) {
recyclerView.setAlpha(1f);
}
});

contactChipViewModel = new ViewModelProvider(this).get(ContactChipViewModel.class);
Expand Down Expand Up @@ -372,6 +355,19 @@ public void onAdapterListCommitted(int size) {
fixedContacts,
displayOptions,
new ContactSelectionListAdapter.OnContactSelectionClick() {
@Override
public void onDismissFindContactsBannerClicked() {
SignalStore.uiHints().markDismissedContactsPermissionBanner();
if (onRefreshListener != null) {
onRefreshListener.onRefresh();
}
}

@Override
public void onFindContactsClicked() {
requestContactPermissions();
}

@Override
public void onRefreshContactsClicked() {
if (onRefreshListener != null) {
Expand Down Expand Up @@ -498,6 +494,27 @@ public boolean isMulti() {
return isMulti;
}

private void requestContactPermissions() {
Permissions.with(this)
.request(Manifest.permission.WRITE_CONTACTS, Manifest.permission.READ_CONTACTS)
.ifNecessary()
.onAllGranted(() -> {
recyclerView.setAlpha(0.5f);
if (!TextSecurePreferences.hasSuccessfullyRetrievedDirectory(getActivity())) {
handleContactPermissionGranted();
} else {
contactSearchMediator.refresh();
if (onRefreshListener != null) {
swipeRefresh.setRefreshing(true);
onRefreshListener.onRefresh();
}
}
})
.onAnyDenied(() -> contactSearchMediator.refresh())
.withPermanentDenialDialog(getString(R.string.ContactSelectionListFragment_signal_requires_the_contacts_permission_in_order_to_display_your_contacts), null, R.string.ContactSelectionListFragment_allow_access_contacts, R.string.ContactSelectionListFragment_to_find_people, getParentFragmentManager())
.execute();
}

private void initializeCursor() {
recyclerView.addItemDecoration(new LetterHeaderDecoration(requireContext(), this::hideLetterHeaders));
recyclerView.setAdapter(contactSearchMediator.getAdapter());
Expand All @@ -521,28 +538,6 @@ private boolean hideLetterHeaders() {
return hasQueryFilter() || shouldDisplayRecents();
}

private void initializeNoContactsPermission() {
swipeRefresh.setVisibility(View.GONE);

showContactsLayout.setVisibility(View.VISIBLE);
showContactsProgress.setVisibility(View.INVISIBLE);
showContactsDescription.setText(R.string.contact_selection_list_fragment__signal_needs_access_to_your_contacts_in_order_to_display_them);
showContactsButton.setVisibility(View.VISIBLE);

showContactsButton.setOnClickListener(v -> {
Permissions.with(this)
.request(Manifest.permission.WRITE_CONTACTS, Manifest.permission.READ_CONTACTS)
.ifNecessary()
.withPermanentDenialDialog(getString(R.string.ContactSelectionListFragment_signal_requires_the_contacts_permission_in_order_to_display_your_contacts))
.onSomeGranted(permissions -> {
if (permissions.contains(Manifest.permission.WRITE_CONTACTS)) {
handleContactPermissionGranted();
}
})
.execute();
});
}

public void setQueryFilter(String filter) {
if (Objects.equals(filter, this.cursorFilter)) {
return;
Expand Down Expand Up @@ -583,7 +578,6 @@ private void onLoadFinished(int count) {
}

swipeRefresh.setVisibility(View.VISIBLE);
showContactsLayout.setVisibility(View.GONE);

emptyText.setText(R.string.contact_selection_group_activity__no_contacts);
boolean useFastScroller = count > 20;
Expand Down Expand Up @@ -614,12 +608,10 @@ private void handleContactPermissionGranted() {
new AsyncTask<Void, Void, Boolean>() {
@Override
protected void onPreExecute() {
swipeRefresh.setVisibility(View.GONE);
showContactsLayout.setVisibility(View.VISIBLE);
showContactsButton.setVisibility(View.INVISIBLE);
showContactsDescription.setText(R.string.ConversationListFragment_loading);
showContactsProgress.setVisibility(View.VISIBLE);
showContactsProgress.spin();
if (onRefreshListener != null) {
setRefreshing(true);
onRefreshListener.onRefresh();
}
}

@Override
Expand All @@ -636,14 +628,11 @@ protected Boolean doInBackground(Void... voids) {
@Override
protected void onPostExecute(Boolean result) {
if (result) {
showContactsLayout.setVisibility(View.GONE);
swipeRefresh.setVisibility(View.VISIBLE);
reset();
} else {
Context context = getContext();
if (context != null) {
Toast.makeText(getContext(), R.string.ContactSelectionListFragment_error_retrieving_contacts_check_your_network_connection, Toast.LENGTH_LONG).show();
initializeNoContactsPermission();
}
}
}
Expand Down Expand Up @@ -890,6 +879,13 @@ private void smoothScrollChipsToEnd() {
return ContactSearchConfiguration.build(builder -> {
builder.setQuery(contactSearchState.getQuery());

if (newConversationCallback != null &&
!hasContactsPermissions(requireContext()) &&
!SignalStore.uiHints().getDismissedContactsPermissionBanner() &&
!hasQuery) {
builder.arbitrary(ContactSelectionListAdapter.ArbitraryRepository.ArbitraryRow.FIND_CONTACTS_BANNER.getCode());
}

if (newConversationCallback != null && !hasQuery) {
builder.arbitrary(ContactSelectionListAdapter.ArbitraryRepository.ArbitraryRow.NEW_GROUP.getCode());
}
Expand Down Expand Up @@ -946,7 +942,7 @@ private void smoothScrollChipsToEnd() {
builder.username(newRowMode);
}

if ((newCallCallback != null || newConversationCallback != null) && !hasQuery) {
if ((newCallCallback != null || newConversationCallback != null)) {
addMoreSection(builder);
builder.withEmptyState(emptyBuilder -> {
emptyBuilder.addSection(ContactSearchConfiguration.Section.Empty.INSTANCE);
Expand All @@ -959,9 +955,17 @@ private void smoothScrollChipsToEnd() {
});
}

private boolean hasContactsPermissions(@NonNull Context context) {
return Permissions.hasAll(context, Manifest.permission.READ_CONTACTS, Manifest.permission.WRITE_CONTACTS);
}

private void addMoreSection(@NonNull ContactSearchConfiguration.Builder builder) {
builder.arbitrary(ContactSelectionListAdapter.ArbitraryRepository.ArbitraryRow.MORE_HEADING.getCode());
builder.arbitrary(ContactSelectionListAdapter.ArbitraryRepository.ArbitraryRow.REFRESH_CONTACTS.getCode());
if (hasContactsPermissions(requireContext())) {
builder.arbitrary(ContactSelectionListAdapter.ArbitraryRepository.ArbitraryRow.REFRESH_CONTACTS.getCode());
} else if (SignalStore.uiHints().getDismissedContactsPermissionBanner()) {
builder.arbitrary(ContactSelectionListAdapter.ArbitraryRepository.ArbitraryRow.FIND_CONTACTS.getCode());
}
builder.arbitrary(ContactSelectionListAdapter.ArbitraryRepository.ArbitraryRow.INVITE_TO_SIGNAL.getCode());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ public MenuItem getCameraSwitchItem() {

@Override
public void onClick(View v) {
// MOLLY: Camera permission request moved to DeviceAddFragment
getSupportFragmentManager().beginTransaction()
.replace(R.id.fragment_container, deviceAddFragment)
.addToBackStack(null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,9 +96,10 @@ public void onStart() {
Permissions.with(requireActivity())
.request(Manifest.permission.CAMERA)
.ifNecessary()
.withPermanentDenialDialog(getString(R.string.DeviceActivity_signal_needs_the_camera_permission_in_order_to_scan_a_qr_code))
.withRationaleDialog(getString(R.string.CameraXFragment_allow_access_camera), getString(R.string.CameraXFragment_to_scan_qr_code_allow_camera), R.drawable.symbol_camera_24)
.withPermanentDenialDialog(getString(R.string.DeviceActivity_signal_needs_the_camera_permission_in_order_to_scan_a_qr_code), null, R.string.CameraXFragment_allow_access_camera, R.string.CameraXFragment_to_scan_qr_codes, getParentFragmentManager())
.onAllGranted(this::startScanner)
.onAnyDenied(() -> Toast.makeText(requireContext(), R.string.DeviceActivity_unable_to_scan_a_qr_code_without_the_camera_permission, Toast.LENGTH_LONG).show())
.onAnyDenied(() -> Toast.makeText(requireContext(), R.string.CameraXFragment_signal_needs_camera_access_scan_qr_code, Toast.LENGTH_LONG).show())
.execute();
}

Expand Down
Loading

0 comments on commit 8c2254d

Please sign in to comment.