Signal-Android/app/src/main/java/org/thoughtcrime/securesms/mediasend/CameraContactSelectionFragm...

192 wiersze
7.6 KiB
Java

package org.thoughtcrime.securesms.mediasend;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.SearchView;
import androidx.appcompat.widget.Toolbar;
import androidx.constraintlayout.widget.Group;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import org.thoughtcrime.securesms.InviteActivity;
import org.thoughtcrime.securesms.LoggingFragment;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.mms.GlideApp;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.util.DynamicTheme;
import org.thoughtcrime.securesms.util.ThemeUtil;
import java.util.List;
/**
* Fragment that selects Signal contacts. Intended to be used in the camera-first capture flow.
*/
public class CameraContactSelectionFragment extends LoggingFragment implements CameraContactAdapter.CameraContactListener {
private Controller controller;
private CameraContactSelectionViewModel contactViewModel;
private RecyclerView contactList;
private CameraContactAdapter contactAdapter;
private RecyclerView selectionList;
private CameraContactSelectionAdapter selectionAdapter;
private Toolbar toolbar;
private View sendButton;
private Group selectionFooterGroup;
private ViewGroup cameraContactsEmpty;
private View inviteButton;
public static Fragment newInstance() {
return new CameraContactSelectionFragment();
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
CameraContactSelectionViewModel.Factory factory = new CameraContactSelectionViewModel.Factory(new CameraContactsRepository(requireContext()));
this.contactViewModel = new ViewModelProvider(requireActivity(), factory).get(CameraContactSelectionViewModel.class);
}
@Override
public void onAttach(@NonNull Context context) {
super.onAttach(context);
if (!(getActivity() instanceof Controller)) {
throw new IllegalStateException("Parent activity must implement controller interface.");
}
controller = (Controller) getActivity();
}
@Override
public @Nullable View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
int theme = DynamicTheme.isDarkTheme(inflater.getContext()) ? R.style.TextSecure_DarkTheme
: R.style.TextSecure_LightTheme;
return ThemeUtil.getThemedInflater(inflater.getContext(), inflater, theme)
.inflate(R.layout.camera_contact_selection_fragment, container, false);
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
this.contactList = view.findViewById(R.id.camera_contacts_list);
this.selectionList = view.findViewById(R.id.camera_contacts_selected_list);
this.toolbar = view.findViewById(R.id.camera_contacts_toolbar);
this.sendButton = view.findViewById(R.id.camera_contacts_send_button);
this.selectionFooterGroup = view.findViewById(R.id.camera_contacts_footer_group);
this.cameraContactsEmpty = view.findViewById(R.id.camera_contacts_empty);
this.inviteButton = view.findViewById(R.id.camera_contacts_invite_button);
this.contactAdapter = new CameraContactAdapter(GlideApp.with(this), this);
this.selectionAdapter = new CameraContactSelectionAdapter();
contactList.setLayoutManager(new LinearLayoutManager(requireContext()));
contactList.setAdapter(contactAdapter);
selectionList.setLayoutManager(new LinearLayoutManager(requireContext(), LinearLayoutManager.HORIZONTAL, false));
selectionList.setAdapter(selectionAdapter);
((AppCompatActivity) requireActivity()).setSupportActionBar(toolbar);
((AppCompatActivity) requireActivity()).getSupportActionBar().setDisplayHomeAsUpEnabled(true);
toolbar.setNavigationOnClickListener(v -> requireActivity().onBackPressed());
inviteButton.setOnClickListener(v -> onInviteContactsClicked());
initViewModel();
}
@Override
public void onPrepareOptionsMenu(@NonNull Menu menu) {
requireActivity().getMenuInflater().inflate(R.menu.camera_contacts, menu);
MenuItem searchViewItem = menu.findItem(R.id.menu_search);
SearchView searchView = (SearchView) searchViewItem.getActionView();
SearchView.OnQueryTextListener queryListener = new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
contactViewModel.onQueryUpdated(query);
return true;
}
@Override
public boolean onQueryTextChange(String query) {
contactViewModel.onQueryUpdated(query);
return true;
}
};
searchViewItem.setOnActionExpandListener(new MenuItem.OnActionExpandListener() {
@Override
public boolean onMenuItemActionExpand(MenuItem item) {
searchView.setOnQueryTextListener(queryListener);
return true;
}
@Override
public boolean onMenuItemActionCollapse(MenuItem item) {
searchView.setOnQueryTextListener(null);
contactViewModel.onSearchClosed();
return true;
}
});
}
@Override
public void onContactClicked(@NonNull Recipient recipient) {
contactViewModel.onContactClicked(recipient);
}
@Override
public void onInviteContactsClicked() {
startActivity(new Intent(requireContext(), InviteActivity.class));
}
private void initViewModel() {
contactViewModel.getContacts().observe(getViewLifecycleOwner(), contactState -> {
if (contactState == null) return;
if (contactState.getContacts().isEmpty() && TextUtils.isEmpty(contactState.getQuery())) {
cameraContactsEmpty.setVisibility(View.VISIBLE);
contactList.setVisibility(View.GONE);
selectionFooterGroup.setVisibility(View.GONE);
} else {
cameraContactsEmpty.setVisibility(View.GONE);
contactList.setVisibility(View.VISIBLE);
sendButton.setOnClickListener(v -> controller.onCameraContactsSendClicked(contactState.getSelected()));
contactAdapter.setContacts(contactState.getContacts(), contactState.getSelected());
selectionAdapter.setRecipients(contactState.getSelected());
selectionFooterGroup.setVisibility(contactState.getSelected().isEmpty() ? View.GONE : View.VISIBLE);
}
});
contactViewModel.getError().observe(getViewLifecycleOwner(), error -> {
if (error == null) return;
if (error == CameraContactSelectionViewModel.Error.MAX_SELECTION) {
String message = getString(R.string.CameraContacts_you_can_share_with_a_maximum_of_n_conversations, CameraContactSelectionViewModel.MAX_SELECTION_COUNT);
Toast.makeText(requireContext(), message, Toast.LENGTH_SHORT).show();
}
});
}
public interface Controller {
void onCameraContactsSendClicked(@NonNull List<Recipient> recipients);
}
}