That fuck shit the fascists are using
at master 192 lines 7.8 kB view raw
1package org.tm.archive.mediasend; 2 3import android.content.Context; 4import android.content.Intent; 5import android.os.Bundle; 6import android.text.TextUtils; 7import android.view.LayoutInflater; 8import android.view.Menu; 9import android.view.MenuItem; 10import android.view.View; 11import android.view.ViewGroup; 12import android.widget.Toast; 13 14import androidx.annotation.NonNull; 15import androidx.annotation.Nullable; 16import androidx.appcompat.app.AppCompatActivity; 17import androidx.appcompat.widget.SearchView; 18import androidx.appcompat.widget.Toolbar; 19import androidx.constraintlayout.widget.Group; 20import androidx.fragment.app.Fragment; 21import androidx.lifecycle.ViewModelProvider; 22import androidx.recyclerview.widget.LinearLayoutManager; 23import androidx.recyclerview.widget.RecyclerView; 24 25import com.bumptech.glide.Glide; 26 27import org.tm.archive.InviteActivity; 28import org.tm.archive.LoggingFragment; 29import org.tm.archive.R; 30import org.tm.archive.recipients.Recipient; 31import org.tm.archive.util.DynamicTheme; 32import org.tm.archive.util.ThemeUtil; 33 34import java.util.List; 35 36/** 37 * Fragment that selects Signal contacts. Intended to be used in the camera-first capture flow. 38 */ 39public class CameraContactSelectionFragment extends LoggingFragment implements CameraContactAdapter.CameraContactListener { 40 41 private Controller controller; 42 private CameraContactSelectionViewModel contactViewModel; 43 private RecyclerView contactList; 44 private CameraContactAdapter contactAdapter; 45 private RecyclerView selectionList; 46 private CameraContactSelectionAdapter selectionAdapter; 47 private Toolbar toolbar; 48 private View sendButton; 49 private Group selectionFooterGroup; 50 private ViewGroup cameraContactsEmpty; 51 private View inviteButton; 52 53 public static Fragment newInstance() { 54 return new CameraContactSelectionFragment(); 55 } 56 57 58 @Override 59 public void onCreate(@Nullable Bundle savedInstanceState) { 60 super.onCreate(savedInstanceState); 61 setHasOptionsMenu(true); 62 63 CameraContactSelectionViewModel.Factory factory = new CameraContactSelectionViewModel.Factory(new CameraContactsRepository(requireContext())); 64 65 this.contactViewModel = new ViewModelProvider(requireActivity(), factory).get(CameraContactSelectionViewModel.class); 66 } 67 68 @Override 69 public void onAttach(@NonNull Context context) { 70 super.onAttach(context); 71 if (!(getActivity() instanceof Controller)) { 72 throw new IllegalStateException("Parent activity must implement controller interface."); 73 } 74 controller = (Controller) getActivity(); 75 } 76 77 @Override 78 public @Nullable View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { 79 int theme = DynamicTheme.isDarkTheme(inflater.getContext()) ? R.style.TextSecure_DarkTheme 80 : R.style.TextSecure_LightTheme; 81 return ThemeUtil.getThemedInflater(inflater.getContext(), inflater, theme) 82 .inflate(R.layout.camera_contact_selection_fragment, container, false); 83 } 84 85 @Override 86 public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { 87 this.contactList = view.findViewById(R.id.camera_contacts_list); 88 this.selectionList = view.findViewById(R.id.camera_contacts_selected_list); 89 this.toolbar = view.findViewById(R.id.camera_contacts_toolbar); 90 this.sendButton = view.findViewById(R.id.camera_contacts_send_button); 91 this.selectionFooterGroup = view.findViewById(R.id.camera_contacts_footer_group); 92 this.cameraContactsEmpty = view.findViewById(R.id.camera_contacts_empty); 93 this.inviteButton = view.findViewById(R.id.camera_contacts_invite_button); 94 this.contactAdapter = new CameraContactAdapter(Glide.with(this), this); 95 this.selectionAdapter = new CameraContactSelectionAdapter(); 96 97 contactList.setLayoutManager(new LinearLayoutManager(requireContext())); 98 contactList.setAdapter(contactAdapter); 99 100 selectionList.setLayoutManager(new LinearLayoutManager(requireContext(), LinearLayoutManager.HORIZONTAL, false)); 101 selectionList.setAdapter(selectionAdapter); 102 103 ((AppCompatActivity) requireActivity()).setSupportActionBar(toolbar); 104 ((AppCompatActivity) requireActivity()).getSupportActionBar().setDisplayHomeAsUpEnabled(true); 105 toolbar.setNavigationOnClickListener(v -> requireActivity().onBackPressed()); 106 107 inviteButton.setOnClickListener(v -> onInviteContactsClicked()); 108 109 initViewModel(); 110 } 111 112 @Override 113 public void onPrepareOptionsMenu(@NonNull Menu menu) { 114 requireActivity().getMenuInflater().inflate(R.menu.camera_contacts, menu); 115 116 MenuItem searchViewItem = menu.findItem(R.id.menu_search); 117 SearchView searchView = (SearchView) searchViewItem.getActionView(); 118 SearchView.OnQueryTextListener queryListener = new SearchView.OnQueryTextListener() { 119 @Override 120 public boolean onQueryTextSubmit(String query) { 121 contactViewModel.onQueryUpdated(query); 122 return true; 123 } 124 125 @Override 126 public boolean onQueryTextChange(String query) { 127 contactViewModel.onQueryUpdated(query); 128 return true; 129 } 130 }; 131 132 searchViewItem.setOnActionExpandListener(new MenuItem.OnActionExpandListener() { 133 @Override 134 public boolean onMenuItemActionExpand(MenuItem item) { 135 searchView.setOnQueryTextListener(queryListener); 136 return true; 137 } 138 139 @Override 140 public boolean onMenuItemActionCollapse(MenuItem item) { 141 searchView.setOnQueryTextListener(null); 142 contactViewModel.onSearchClosed(); 143 return true; 144 } 145 }); 146 } 147 148 @Override 149 public void onContactClicked(@NonNull Recipient recipient) { 150 contactViewModel.onContactClicked(recipient); 151 } 152 153 @Override 154 public void onInviteContactsClicked() { 155 startActivity(new Intent(requireContext(), InviteActivity.class)); 156 } 157 158 private void initViewModel() { 159 contactViewModel.getContacts().observe(getViewLifecycleOwner(), contactState -> { 160 if (contactState == null) return; 161 162 if (contactState.getContacts().isEmpty() && TextUtils.isEmpty(contactState.getQuery())) { 163 cameraContactsEmpty.setVisibility(View.VISIBLE); 164 contactList.setVisibility(View.GONE); 165 selectionFooterGroup.setVisibility(View.GONE); 166 } else { 167 cameraContactsEmpty.setVisibility(View.GONE); 168 contactList.setVisibility(View.VISIBLE); 169 170 sendButton.setOnClickListener(v -> controller.onCameraContactsSendClicked(contactState.getSelected())); 171 172 contactAdapter.setContacts(contactState.getContacts(), contactState.getSelected()); 173 selectionAdapter.setRecipients(contactState.getSelected()); 174 175 selectionFooterGroup.setVisibility(contactState.getSelected().isEmpty() ? View.GONE : View.VISIBLE); 176 } 177 }); 178 179 contactViewModel.getError().observe(getViewLifecycleOwner(), error -> { 180 if (error == null) return; 181 182 if (error == CameraContactSelectionViewModel.Error.MAX_SELECTION) { 183 String message = getResources().getQuantityString(R.plurals.CameraContacts_you_can_share_with_a_maximum_of_n_conversations, CameraContactSelectionViewModel.MAX_SELECTION_COUNT, CameraContactSelectionViewModel.MAX_SELECTION_COUNT); 184 Toast.makeText(requireContext(), message, Toast.LENGTH_SHORT).show(); 185 } 186 }); 187 } 188 189 public interface Controller { 190 void onCameraContactsSendClicked(@NonNull List<Recipient> recipients); 191 } 192}