That fuck shit the fascists are using
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}