mirror of
https://github.com/oxen-io/session-android.git
synced 2025-01-11 16:33:39 +00:00
Replaced signal ContactSelection things with loki ones.
Fixed sharing in session (we can only share to one user at a time).
This commit is contained in:
parent
7b8fbcea4e
commit
361dab24d6
@ -19,6 +19,6 @@
|
||||
<fragment android:id="@+id/contact_selection_list_fragment"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:name="org.thoughtcrime.securesms.ContactSelectionListFragment" />
|
||||
android:name="org.thoughtcrime.securesms.loki.redesign.fragments.ContactSelectionListFragment" />
|
||||
|
||||
</LinearLayout>
|
@ -1,92 +1,58 @@
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:orientation="vertical">
|
||||
|
||||
<android.support.v4.widget.SwipeRefreshLayout
|
||||
android:id="@+id/swipe_refresh"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<android.support.v7.widget.RecyclerView
|
||||
android:id="@+id/recycler_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:clipToPadding="false"
|
||||
android:scrollbars="vertical" />
|
||||
|
||||
<TextView android:id="@android:id/empty"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center|center_vertical"
|
||||
android:layout_marginTop="15dp"
|
||||
android:text="@string/contact_selection_group_activity__finding_contacts"
|
||||
android:textSize="20sp" />
|
||||
|
||||
</android.support.v4.widget.SwipeRefreshLayout>
|
||||
|
||||
<org.thoughtcrime.securesms.components.RecyclerViewFastScroller
|
||||
android:id="@+id/fast_scroller"
|
||||
android:layout_width="wrap_content"
|
||||
<LinearLayout
|
||||
android:id="@+id/emptyStateContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:visibility="gone"
|
||||
android:layout_gravity="end"/>
|
||||
android:layout_centerInParent="true"
|
||||
android:gravity="center_horizontal|center_vertical"
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout android:id="@+id/show_contacts_container"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:layout_gravity="center"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible">
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="You don't have any contacts yet"
|
||||
android:textColor="@color/text"
|
||||
android:textSize="@dimen/medium_font_size" />
|
||||
</LinearLayout>
|
||||
|
||||
<FrameLayout
|
||||
<LinearLayout
|
||||
android:id="@+id/mainContentContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<android.support.v4.widget.SwipeRefreshLayout
|
||||
android:id="@+id/swipeRefresh"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<com.pnikosis.materialishprogress.ProgressWheel
|
||||
android:id="@+id/progress"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:visibility="invisible"
|
||||
app:matProg_circleRadius="145dp"
|
||||
app:matProg_barWidth="6dp"
|
||||
app:matProg_rimColor="@color/signal_primary"
|
||||
app:matProg_barColor="@color/signal_primary_dark"
|
||||
app:matProg_progressIndeterminate="true"
|
||||
tools:visibility="visible"
|
||||
/>
|
||||
<android.support.v7.widget.RecyclerView
|
||||
android:id="@+id/recyclerView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:clipToPadding="false"
|
||||
android:scrollbars="vertical" />
|
||||
|
||||
<ImageView android:layout_gravity="center"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:src="@drawable/no_contacts"/>
|
||||
<TextView android:id="@android:id/empty"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center|center_vertical"
|
||||
android:layout_marginTop="15dp"
|
||||
android:text="@string/contact_selection_group_activity__finding_contacts"
|
||||
android:textSize="20sp" />
|
||||
|
||||
</android.support.v4.widget.SwipeRefreshLayout>
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
<TextView android:id="@+id/show_contacts_description"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="20dp"
|
||||
android:layout_marginStart="50dp"
|
||||
android:layout_marginEnd="50dp"
|
||||
android:textSize="15sp"
|
||||
android:lineSpacingMultiplier="1.3"
|
||||
android:gravity="center"
|
||||
android:text="@string/contact_selection_list_fragment__signal_needs_access_to_your_contacts_in_order_to_display_them"/>
|
||||
|
||||
<Button android:id="@+id/show_contacts_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="20dp"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:background="@color/signal_primary"
|
||||
android:textColor="@color/white"
|
||||
android:padding="10dp"
|
||||
android:text="@string/contact_selection_list_fragment__show_contacts"/>
|
||||
<org.thoughtcrime.securesms.components.RecyclerViewFastScroller
|
||||
android:id="@+id/fastScroller"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:visibility="gone"
|
||||
android:layout_gravity="end"/>
|
||||
</LinearLayout>
|
||||
|
||||
</FrameLayout>
|
||||
|
@ -94,7 +94,7 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:name="org.thoughtcrime.securesms.ContactSelectionListFragment"
|
||||
android:name="org.thoughtcrime.securesms.loki.redesign.fragments.ContactSelectionListFragment"
|
||||
tools:layout="@layout/contact_selection_list_fragment"/>
|
||||
|
||||
<LinearLayout android:layout_width="match_parent"
|
||||
|
@ -49,7 +49,7 @@
|
||||
android:layout_below="@id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:name="org.thoughtcrime.securesms.ContactSelectionListFragment" />
|
||||
android:name="org.thoughtcrime.securesms.loki.redesign.fragments.ContactSelectionListFragment" />
|
||||
|
||||
<org.thoughtcrime.securesms.components.SearchToolbar
|
||||
android:id="@+id/search_toolbar"
|
||||
|
@ -1663,12 +1663,14 @@
|
||||
<string name="session_restore_banner_dismiss_button_title">Dismiss</string>
|
||||
<string name="session_restore_banner_restore_button_title">Restore</string>
|
||||
|
||||
<!-- Loki -->
|
||||
|
||||
<!-- Session -->
|
||||
<string name="activity_register_public_key_copied_message">Copied to clipboard</string>
|
||||
<string name="activity_home_leave_group_dialog_message">Are you sure you want to leave this group?</string>
|
||||
<string name="activity_home_delete_conversation_dialog_message">Are you sure you want to delete this conversation?</string>
|
||||
<string name="activity_home_conversation_deleted_message">Conversation deleted</string>
|
||||
|
||||
<!-- ContactSelectionListLoader -->
|
||||
<string name="ContactSelectionListLoader_contacts">Contacts</string>
|
||||
<string name="ContactSelectionListLoader_closed_groups">Groups</string>
|
||||
<string name="ContactSelectionListLoader_open_groups">Public Chats</string>
|
||||
</resources>
|
||||
|
@ -20,11 +20,11 @@ import android.os.Bundle;
|
||||
import android.support.v4.widget.SwipeRefreshLayout;
|
||||
|
||||
import org.thoughtcrime.securesms.components.ContactFilterToolbar;
|
||||
import org.thoughtcrime.securesms.contacts.ContactsCursorLoader.DisplayMode;
|
||||
import org.thoughtcrime.securesms.loki.redesign.activities.ContactSelectionListLoader.DisplayMode;
|
||||
import org.thoughtcrime.securesms.loki.redesign.fragments.ContactSelectionListFragment;
|
||||
import org.thoughtcrime.securesms.util.DynamicLanguage;
|
||||
import org.thoughtcrime.securesms.util.DynamicNoActionBarTheme;
|
||||
import org.thoughtcrime.securesms.util.DynamicTheme;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.thoughtcrime.securesms.util.ViewUtil;
|
||||
|
||||
import network.loki.messenger.R;
|
||||
@ -36,8 +36,8 @@ import network.loki.messenger.R;
|
||||
*
|
||||
*/
|
||||
public abstract class ContactSelectionActivity extends PassphraseRequiredActionBarActivity
|
||||
implements SwipeRefreshLayout.OnRefreshListener,
|
||||
ContactSelectionListFragment.OnContactSelectedListener
|
||||
implements SwipeRefreshLayout.OnRefreshListener,
|
||||
ContactSelectionListFragment.OnContactSelectedListener
|
||||
{
|
||||
private static final String TAG = ContactSelectionActivity.class.getSimpleName();
|
||||
|
||||
@ -57,9 +57,7 @@ public abstract class ContactSelectionActivity extends PassphraseRequiredActionB
|
||||
@Override
|
||||
protected void onCreate(Bundle icicle, boolean ready) {
|
||||
if (!getIntent().hasExtra(ContactSelectionListFragment.DISPLAY_MODE)) {
|
||||
int displayMode = TextSecurePreferences.isSmsEnabled(this) ? DisplayMode.FLAG_ALL
|
||||
: DisplayMode.FLAG_PUSH | DisplayMode.FLAG_GROUPS;
|
||||
getIntent().putExtra(ContactSelectionListFragment.DISPLAY_MODE, displayMode);
|
||||
getIntent().putExtra(ContactSelectionListFragment.DISPLAY_MODE, DisplayMode.FLAG_ALL);
|
||||
}
|
||||
|
||||
setContentView(R.layout.contact_selection_activity);
|
||||
|
@ -1,303 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Open Whisper Systems
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.thoughtcrime.securesms;
|
||||
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.database.Cursor;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.LoaderManager;
|
||||
import android.support.v4.content.Loader;
|
||||
import android.support.v4.widget.SwipeRefreshLayout;
|
||||
import android.support.v7.widget.LinearLayoutManager;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.pnikosis.materialishprogress.ProgressWheel;
|
||||
|
||||
import org.thoughtcrime.securesms.components.RecyclerViewFastScroller;
|
||||
import org.thoughtcrime.securesms.contacts.ContactSelectionListAdapter;
|
||||
import org.thoughtcrime.securesms.contacts.ContactSelectionListItem;
|
||||
import org.thoughtcrime.securesms.contacts.ContactsCursorLoader;
|
||||
import org.thoughtcrime.securesms.contacts.ContactsCursorLoader.DisplayMode;
|
||||
import org.thoughtcrime.securesms.database.CursorRecyclerViewAdapter;
|
||||
import org.thoughtcrime.securesms.mms.GlideApp;
|
||||
import org.thoughtcrime.securesms.permissions.Permissions;
|
||||
import org.thoughtcrime.securesms.util.StickyHeaderDecoration;
|
||||
import org.thoughtcrime.securesms.util.ViewUtil;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import network.loki.messenger.R;
|
||||
|
||||
/**
|
||||
* Fragment for selecting a one or more contacts from a list.
|
||||
*
|
||||
* @author Moxie Marlinspike
|
||||
*
|
||||
*/
|
||||
public class ContactSelectionListFragment extends Fragment
|
||||
implements LoaderManager.LoaderCallbacks<Cursor>
|
||||
{
|
||||
@SuppressWarnings("unused")
|
||||
private static final String TAG = ContactSelectionListFragment.class.getSimpleName();
|
||||
|
||||
public static final String DISPLAY_MODE = "display_mode";
|
||||
public static final String MULTI_SELECT = "multi_select";
|
||||
public static final String REFRESHABLE = "refreshable";
|
||||
public static final String RECENTS = "recents";
|
||||
|
||||
private TextView emptyText;
|
||||
private Set<String> selectedContacts;
|
||||
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;
|
||||
|
||||
@Override
|
||||
public void onActivityCreated(Bundle icicle) {
|
||||
super.onActivityCreated(icicle);
|
||||
|
||||
initializeCursor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
|
||||
handleContactPermissionGranted();
|
||||
|
||||
// Permissions.with(this)
|
||||
// .request(Manifest.permission.WRITE_CONTACTS, Manifest.permission.READ_CONTACTS)
|
||||
// .ifNecessary()
|
||||
// .onAllGranted(() -> {
|
||||
// if (!TextSecurePreferences.hasSuccessfullyRetrievedDirectory(getActivity())) {
|
||||
// handleContactPermissionGranted();
|
||||
// } else {
|
||||
// this.getLoaderManager().initLoader(0, null, this);
|
||||
// }
|
||||
// })
|
||||
// .onAnyDenied(() -> {
|
||||
// getActivity().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
|
||||
//
|
||||
// if (getActivity().getIntent().getBooleanExtra(RECENTS, false)) {
|
||||
// getLoaderManager().initLoader(0, null, ContactSelectionListFragment.this);
|
||||
// } else {
|
||||
// initializeNoContactsPermission();
|
||||
// }
|
||||
// })
|
||||
// .execute();
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
View view = inflater.inflate(R.layout.contact_selection_list_fragment, container, false);
|
||||
|
||||
emptyText = ViewUtil.findById(view, android.R.id.empty);
|
||||
recyclerView = ViewUtil.findById(view, R.id.recycler_view);
|
||||
swipeRefresh = ViewUtil.findById(view, R.id.swipe_refresh);
|
||||
fastScroller = ViewUtil.findById(view, 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);
|
||||
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
|
||||
|
||||
swipeRefresh.setEnabled(getActivity().getIntent().getBooleanExtra(REFRESHABLE, true));
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
|
||||
Permissions.onRequestPermissionsResult(this, requestCode, permissions, grantResults);
|
||||
}
|
||||
|
||||
public @NonNull List<String> getSelectedContacts() {
|
||||
List<String> selected = new LinkedList<>();
|
||||
if (selectedContacts != null) {
|
||||
selected.addAll(selectedContacts);
|
||||
}
|
||||
|
||||
return selected;
|
||||
}
|
||||
|
||||
private boolean isMulti() {
|
||||
return getActivity().getIntent().getBooleanExtra(MULTI_SELECT, false);
|
||||
}
|
||||
|
||||
private void initializeCursor() {
|
||||
ContactSelectionListAdapter adapter = new ContactSelectionListAdapter(getActivity(),
|
||||
GlideApp.with(this),
|
||||
null,
|
||||
new ListClickListener(),
|
||||
isMulti());
|
||||
selectedContacts = adapter.getSelectedContacts();
|
||||
recyclerView.setAdapter(adapter);
|
||||
recyclerView.addItemDecoration(new StickyHeaderDecoration(adapter, true, true));
|
||||
}
|
||||
|
||||
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) {
|
||||
this.cursorFilter = filter;
|
||||
this.getLoaderManager().restartLoader(0, null, this);
|
||||
}
|
||||
|
||||
public void resetQueryFilter() {
|
||||
setQueryFilter(null);
|
||||
swipeRefresh.setRefreshing(false);
|
||||
}
|
||||
|
||||
public void setRefreshing(boolean refreshing) {
|
||||
swipeRefresh.setRefreshing(refreshing);
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
selectedContacts.clear();
|
||||
|
||||
if (!isDetached() && !isRemoving() && getActivity() != null && !getActivity().isFinishing()) {
|
||||
getLoaderManager().restartLoader(0, null, this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull Loader<Cursor> onCreateLoader(int id, Bundle args) {
|
||||
return new ContactsCursorLoader(getActivity(),
|
||||
getActivity().getIntent().getIntExtra(DISPLAY_MODE, DisplayMode.FLAG_ALL),
|
||||
cursorFilter, getActivity().getIntent().getBooleanExtra(RECENTS, false));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadFinished(@NonNull Loader<Cursor> loader, Cursor data) {
|
||||
swipeRefresh.setVisibility(View.VISIBLE);
|
||||
showContactsLayout.setVisibility(View.GONE);
|
||||
|
||||
((CursorRecyclerViewAdapter) recyclerView.getAdapter()).changeCursor(data);
|
||||
emptyText.setText(R.string.contact_selection_group_activity__no_contacts);
|
||||
boolean useFastScroller = (recyclerView.getAdapter().getItemCount() > 20);
|
||||
recyclerView.setVerticalScrollBarEnabled(!useFastScroller);
|
||||
if (useFastScroller) {
|
||||
fastScroller.setVisibility(View.VISIBLE);
|
||||
fastScroller.setRecyclerView(recyclerView);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoaderReset(@NonNull Loader<Cursor> loader) {
|
||||
((CursorRecyclerViewAdapter) recyclerView.getAdapter()).changeCursor(null);
|
||||
fastScroller.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
@SuppressLint("StaticFieldLeak")
|
||||
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();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Boolean doInBackground(Void... voids) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Boolean result) {
|
||||
if (result) {
|
||||
showContactsLayout.setVisibility(View.GONE);
|
||||
swipeRefresh.setVisibility(View.VISIBLE);
|
||||
reset();
|
||||
} else {
|
||||
Toast.makeText(getContext(), R.string.ContactSelectionListFragment_error_retrieving_contacts_check_your_network_connection, Toast.LENGTH_LONG).show();
|
||||
initializeNoContactsPermission();
|
||||
}
|
||||
}
|
||||
}.execute();
|
||||
}
|
||||
|
||||
private class ListClickListener implements ContactSelectionListAdapter.ItemClickListener {
|
||||
@Override
|
||||
public void onItemClick(ContactSelectionListItem contact) {
|
||||
if (!isMulti() || !selectedContacts.contains(contact.getNumber())) {
|
||||
selectedContacts.add(contact.getNumber());
|
||||
contact.setChecked(true);
|
||||
if (onContactSelectedListener != null) onContactSelectedListener.onContactSelected(contact.getNumber());
|
||||
} else {
|
||||
selectedContacts.remove(contact.getNumber());
|
||||
contact.setChecked(false);
|
||||
if (onContactSelectedListener != null) onContactSelectedListener.onContactDeselected(contact.getNumber());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setOnContactSelectedListener(OnContactSelectedListener onContactSelectedListener) {
|
||||
this.onContactSelectedListener = onContactSelectedListener;
|
||||
}
|
||||
|
||||
public void setOnRefreshListener(SwipeRefreshLayout.OnRefreshListener onRefreshListener) {
|
||||
this.swipeRefresh.setOnRefreshListener(onRefreshListener);
|
||||
}
|
||||
|
||||
public interface OnContactSelectedListener {
|
||||
void onContactSelected(String number);
|
||||
void onContactDeselected(String number);
|
||||
}
|
||||
|
||||
}
|
@ -43,7 +43,6 @@ import com.bumptech.glide.request.transition.Transition;
|
||||
import org.thoughtcrime.securesms.avatar.AvatarSelection;
|
||||
import org.thoughtcrime.securesms.components.PushRecipientsPanel;
|
||||
import org.thoughtcrime.securesms.components.PushRecipientsPanel.RecipientsPanelChangedListener;
|
||||
import org.thoughtcrime.securesms.contacts.ContactsCursorLoader.DisplayMode;
|
||||
import org.thoughtcrime.securesms.contacts.RecipientsEditor;
|
||||
import org.thoughtcrime.securesms.contacts.avatars.ContactColors;
|
||||
import org.thoughtcrime.securesms.contacts.avatars.ResourceContactPhoto;
|
||||
@ -57,6 +56,8 @@ import org.thoughtcrime.securesms.database.ThreadDatabase;
|
||||
import org.thoughtcrime.securesms.groups.GroupManager;
|
||||
import org.thoughtcrime.securesms.groups.GroupManager.GroupActionResult;
|
||||
import org.thoughtcrime.securesms.logging.Log;
|
||||
import org.thoughtcrime.securesms.loki.redesign.activities.ContactSelectionListLoader.DisplayMode;
|
||||
import org.thoughtcrime.securesms.loki.redesign.fragments.ContactSelectionListFragment;
|
||||
import org.thoughtcrime.securesms.mms.GlideApp;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.util.BitmapUtil;
|
||||
@ -321,11 +322,7 @@ public class GroupCreateActivity extends PassphraseRequiredActionBarActivity
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
Intent intent = new Intent(GroupCreateActivity.this, PushContactSelectionActivity.class);
|
||||
if (groupToUpdate.isPresent()) {
|
||||
intent.putExtra(ContactSelectionListFragment.DISPLAY_MODE, DisplayMode.FLAG_PUSH);
|
||||
} else {
|
||||
intent.putExtra(ContactSelectionListFragment.DISPLAY_MODE, DisplayMode.FLAG_PUSH | DisplayMode.FLAG_SMS);
|
||||
}
|
||||
intent.putExtra(ContactSelectionListFragment.DISPLAY_MODE, DisplayMode.FLAG_FRIENDS);
|
||||
startActivityForResult(intent, PICK_CONTACT);
|
||||
}
|
||||
}
|
||||
|
@ -26,9 +26,10 @@ import android.widget.Toast;
|
||||
|
||||
import org.thoughtcrime.securesms.components.ContactFilterToolbar;
|
||||
import org.thoughtcrime.securesms.components.ContactFilterToolbar.OnFilterChangedListener;
|
||||
import org.thoughtcrime.securesms.contacts.ContactsCursorLoader.DisplayMode;
|
||||
import org.thoughtcrime.securesms.database.Address;
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.loki.redesign.activities.ContactSelectionListLoader.DisplayMode;
|
||||
import org.thoughtcrime.securesms.loki.redesign.fragments.ContactSelectionListFragment;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.sms.MessageSender;
|
||||
import org.thoughtcrime.securesms.sms.OutgoingTextMessage;
|
||||
@ -40,7 +41,7 @@ import java.util.concurrent.ExecutionException;
|
||||
|
||||
import network.loki.messenger.R;
|
||||
|
||||
public class InviteActivity extends PassphraseRequiredActionBarActivity implements ContactSelectionListFragment.OnContactSelectedListener {
|
||||
public class InviteActivity extends PassphraseRequiredActionBarActivity {
|
||||
|
||||
private ContactSelectionListFragment contactsFragment;
|
||||
private EditText inviteText;
|
||||
@ -52,7 +53,7 @@ public class InviteActivity extends PassphraseRequiredActionBarActivity implemen
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState, boolean ready) {
|
||||
getIntent().putExtra(ContactSelectionListFragment.DISPLAY_MODE, DisplayMode.FLAG_SMS);
|
||||
getIntent().putExtra(ContactSelectionListFragment.DISPLAY_MODE, DisplayMode.FLAG_FRIENDS);
|
||||
getIntent().putExtra(ContactSelectionListFragment.MULTI_SELECT, true);
|
||||
getIntent().putExtra(ContactSelectionListFragment.REFRESHABLE, false);
|
||||
|
||||
@ -84,7 +85,6 @@ public class InviteActivity extends PassphraseRequiredActionBarActivity implemen
|
||||
if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) {
|
||||
heart.getViewTreeObserver().addOnPreDrawListener(new HeartPreDrawListener());
|
||||
}
|
||||
contactsFragment.setOnContactSelectedListener(this);
|
||||
shareButton.setOnClickListener(new ShareClickListener());
|
||||
smsButton.setOnClickListener(new SmsClickListener());
|
||||
smsCancelButton.setOnClickListener(new SmsCancelClickListener());
|
||||
@ -99,12 +99,10 @@ public class InviteActivity extends PassphraseRequiredActionBarActivity implemen
|
||||
return animation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onContactSelected(String number) {
|
||||
updateSmsButtonText();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onContactDeselected(String number) {
|
||||
updateSmsButtonText();
|
||||
}
|
||||
@ -132,7 +130,6 @@ public class InviteActivity extends PassphraseRequiredActionBarActivity implemen
|
||||
}
|
||||
|
||||
private void cancelSmsSelection() {
|
||||
contactsFragment.reset();
|
||||
updateSmsButtonText();
|
||||
ViewUtil.animateOut(smsSendFrame, slideOutAnimation, View.GONE);
|
||||
}
|
||||
@ -241,7 +238,6 @@ public class InviteActivity extends PassphraseRequiredActionBarActivity implemen
|
||||
ViewUtil.animateOut(smsSendFrame, slideOutAnimation, View.GONE).addListener(new Listener<Boolean>() {
|
||||
@Override
|
||||
public void onSuccess(Boolean result) {
|
||||
contactsFragment.reset();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -19,6 +19,8 @@ package org.thoughtcrime.securesms;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
|
||||
import org.thoughtcrime.securesms.loki.redesign.fragments.ContactSelectionListFragment;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
|
@ -29,19 +29,19 @@ import android.os.Process;
|
||||
import android.provider.OpenableColumns;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.widget.SwipeRefreshLayout;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import org.thoughtcrime.securesms.components.SearchToolbar;
|
||||
import org.thoughtcrime.securesms.contacts.ContactsCursorLoader.DisplayMode;
|
||||
import org.thoughtcrime.securesms.conversation.ConversationActivity;
|
||||
import org.thoughtcrime.securesms.database.Address;
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.database.ThreadDatabase;
|
||||
import org.thoughtcrime.securesms.logging.Log;
|
||||
import org.thoughtcrime.securesms.loki.redesign.activities.ContactSelectionListLoader.DisplayMode;
|
||||
import org.thoughtcrime.securesms.loki.redesign.fragments.ContactSelectionListFragment;
|
||||
import org.thoughtcrime.securesms.mediasend.Media;
|
||||
import org.thoughtcrime.securesms.mms.PartAuthority;
|
||||
import org.thoughtcrime.securesms.providers.BlobProvider;
|
||||
@ -52,7 +52,6 @@ import org.thoughtcrime.securesms.util.DynamicNoActionBarTheme;
|
||||
import org.thoughtcrime.securesms.util.DynamicTheme;
|
||||
import org.thoughtcrime.securesms.util.FileUtils;
|
||||
import org.thoughtcrime.securesms.util.MediaUtil;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.thoughtcrime.securesms.util.ViewUtil;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
@ -68,7 +67,7 @@ import network.loki.messenger.R;
|
||||
* @author Jake McGinty
|
||||
*/
|
||||
public class ShareActivity extends PassphraseRequiredActionBarActivity
|
||||
implements ContactSelectionListFragment.OnContactSelectedListener, SwipeRefreshLayout.OnRefreshListener
|
||||
implements ContactSelectionListFragment.OnContactSelectedListener
|
||||
{
|
||||
private static final String TAG = ShareActivity.class.getSimpleName();
|
||||
|
||||
@ -96,14 +95,10 @@ public class ShareActivity extends PassphraseRequiredActionBarActivity
|
||||
@Override
|
||||
protected void onCreate(Bundle icicle, boolean ready) {
|
||||
if (!getIntent().hasExtra(ContactSelectionListFragment.DISPLAY_MODE)) {
|
||||
getIntent().putExtra(ContactSelectionListFragment.DISPLAY_MODE,
|
||||
TextSecurePreferences.isSmsEnabled(this)
|
||||
? DisplayMode.FLAG_ALL
|
||||
: DisplayMode.FLAG_PUSH | DisplayMode.FLAG_GROUPS);
|
||||
getIntent().putExtra(ContactSelectionListFragment.DISPLAY_MODE, DisplayMode.FLAG_ALL);
|
||||
}
|
||||
|
||||
getIntent().putExtra(ContactSelectionListFragment.REFRESHABLE, false);
|
||||
getIntent().putExtra(ContactSelectionListFragment.RECENTS, true);
|
||||
|
||||
setContentView(R.layout.share_activity);
|
||||
|
||||
@ -170,7 +165,6 @@ public class ShareActivity extends PassphraseRequiredActionBarActivity
|
||||
searchAction = findViewById(R.id.search_action);
|
||||
contactsFragment = (ContactSelectionListFragment) getSupportFragmentManager().findFragmentById(R.id.contact_selection_list_fragment);
|
||||
contactsFragment.setOnContactSelectedListener(this);
|
||||
contactsFragment.setOnRefreshListener(this);
|
||||
}
|
||||
|
||||
private void initializeSearch() {
|
||||
@ -281,12 +275,6 @@ public class ShareActivity extends PassphraseRequiredActionBarActivity
|
||||
|
||||
@Override
|
||||
public void onContactDeselected(String number) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRefresh() {
|
||||
|
||||
}
|
||||
|
||||
@SuppressLint("StaticFieldLeak")
|
||||
|
@ -1,271 +0,0 @@
|
||||
/**
|
||||
* Copyright (C) 2014 Open Whisper Systems
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.thoughtcrime.securesms.contacts;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.database.Cursor;
|
||||
import android.provider.ContactsContract;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.text.SpannableString;
|
||||
import android.text.Spanned;
|
||||
import android.text.TextUtils;
|
||||
import android.text.style.ForegroundColorSpan;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import network.loki.messenger.R;
|
||||
import org.thoughtcrime.securesms.components.RecyclerViewFastScroller.FastScrollAdapter;
|
||||
import org.thoughtcrime.securesms.contacts.ContactSelectionListAdapter.HeaderViewHolder;
|
||||
import org.thoughtcrime.securesms.contacts.ContactSelectionListAdapter.ViewHolder;
|
||||
import org.thoughtcrime.securesms.database.Address;
|
||||
import org.thoughtcrime.securesms.database.CursorRecyclerViewAdapter;
|
||||
import org.thoughtcrime.securesms.mms.GlideRequests;
|
||||
import org.thoughtcrime.securesms.util.StickyHeaderDecoration.StickyHeaderAdapter;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* List adapter to display all contacts and their related information
|
||||
*
|
||||
* @author Jake McGinty
|
||||
*/
|
||||
public class ContactSelectionListAdapter extends CursorRecyclerViewAdapter<ViewHolder>
|
||||
implements FastScrollAdapter,
|
||||
StickyHeaderAdapter<HeaderViewHolder>
|
||||
{
|
||||
private final static String TAG = ContactSelectionListAdapter.class.getSimpleName();
|
||||
|
||||
private static final int VIEW_TYPE_CONTACT = 0;
|
||||
private static final int VIEW_TYPE_DIVIDER = 1;
|
||||
|
||||
private final static int STYLE_ATTRIBUTES[] = new int[]{R.attr.contact_selection_push_user,
|
||||
R.attr.contact_selection_lay_user};
|
||||
|
||||
private final boolean multiSelect;
|
||||
private final LayoutInflater li;
|
||||
private final TypedArray drawables;
|
||||
private final ItemClickListener clickListener;
|
||||
private final GlideRequests glideRequests;
|
||||
|
||||
private final Set<String> selectedContacts = new HashSet<>();
|
||||
|
||||
public abstract static class ViewHolder extends RecyclerView.ViewHolder {
|
||||
|
||||
public ViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
}
|
||||
|
||||
public abstract void bind(@NonNull GlideRequests glideRequests, int type, String name, String number, String label, int color, boolean multiSelect);
|
||||
public abstract void unbind(@NonNull GlideRequests glideRequests);
|
||||
public abstract void setChecked(boolean checked);
|
||||
}
|
||||
|
||||
public static class ContactViewHolder extends ViewHolder {
|
||||
ContactViewHolder(@NonNull final View itemView,
|
||||
@Nullable final ItemClickListener clickListener)
|
||||
{
|
||||
super(itemView);
|
||||
itemView.setOnClickListener(v -> {
|
||||
if (clickListener != null) clickListener.onItemClick(getView());
|
||||
});
|
||||
}
|
||||
|
||||
public ContactSelectionListItem getView() {
|
||||
return (ContactSelectionListItem) itemView;
|
||||
}
|
||||
|
||||
public void bind(@NonNull GlideRequests glideRequests, int type, String name, String number, String label, int color, boolean multiSelect) {
|
||||
getView().set(glideRequests, type, name, number, label, color, multiSelect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unbind(@NonNull GlideRequests glideRequests) {
|
||||
getView().unbind(glideRequests);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setChecked(boolean checked) {
|
||||
getView().setChecked(checked);
|
||||
}
|
||||
}
|
||||
|
||||
public static class DividerViewHolder extends ViewHolder {
|
||||
|
||||
private final TextView label;
|
||||
|
||||
DividerViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
this.label = itemView.findViewById(R.id.label);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bind(@NonNull GlideRequests glideRequests, int type, String name, String number, String label, int color, boolean multiSelect) {
|
||||
this.label.setText(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unbind(@NonNull GlideRequests glideRequests) {}
|
||||
|
||||
@Override
|
||||
public void setChecked(boolean checked) {}
|
||||
}
|
||||
|
||||
static class HeaderViewHolder extends RecyclerView.ViewHolder {
|
||||
HeaderViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
}
|
||||
}
|
||||
|
||||
public ContactSelectionListAdapter(@NonNull Context context,
|
||||
@NonNull GlideRequests glideRequests,
|
||||
@Nullable Cursor cursor,
|
||||
@Nullable ItemClickListener clickListener,
|
||||
boolean multiSelect)
|
||||
{
|
||||
super(context, cursor);
|
||||
this.li = LayoutInflater.from(context);
|
||||
this.glideRequests = glideRequests;
|
||||
this.drawables = context.obtainStyledAttributes(STYLE_ATTRIBUTES);
|
||||
this.multiSelect = multiSelect;
|
||||
this.clickListener = clickListener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getHeaderId(int i) {
|
||||
if (!isActiveCursor()) return -1;
|
||||
|
||||
int contactType = getContactType(i);
|
||||
|
||||
if (contactType == ContactsDatabase.DIVIDER_TYPE) return -1;
|
||||
return Util.hashCode(getHeaderString(i), getContactType(i));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ViewHolder onCreateItemViewHolder(ViewGroup parent, int viewType) {
|
||||
if (viewType == VIEW_TYPE_CONTACT) {
|
||||
return new ContactViewHolder(li.inflate(R.layout.contact_selection_list_item, parent, false), clickListener);
|
||||
} else {
|
||||
return new DividerViewHolder(li.inflate(R.layout.contact_selection_list_divider, parent, false));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindItemViewHolder(ViewHolder viewHolder, @NonNull Cursor cursor) {
|
||||
int contactType = cursor.getInt(cursor.getColumnIndexOrThrow(ContactsDatabase.CONTACT_TYPE_COLUMN));
|
||||
String name = cursor.getString(cursor.getColumnIndexOrThrow(ContactsDatabase.NAME_COLUMN));
|
||||
String number = cursor.getString(cursor.getColumnIndexOrThrow(ContactsDatabase.NUMBER_COLUMN));
|
||||
int numberType = cursor.getInt(cursor.getColumnIndexOrThrow(ContactsDatabase.NUMBER_TYPE_COLUMN));
|
||||
String label = cursor.getString(cursor.getColumnIndexOrThrow(ContactsDatabase.LABEL_COLUMN));
|
||||
String labelText = ContactsContract.CommonDataKinds.Phone.getTypeLabel(getContext().getResources(),
|
||||
numberType, label).toString();
|
||||
|
||||
int color = (contactType == ContactsDatabase.PUSH_TYPE) ? drawables.getColor(0, 0xa0000000) :
|
||||
drawables.getColor(1, 0xff000000);
|
||||
|
||||
viewHolder.unbind(glideRequests);
|
||||
viewHolder.bind(glideRequests, contactType, name, number, labelText, color, multiSelect);
|
||||
viewHolder.setChecked(selectedContacts.contains(number));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemViewType(@NonNull Cursor cursor) {
|
||||
if (cursor.getInt(cursor.getColumnIndexOrThrow(ContactsDatabase.CONTACT_TYPE_COLUMN)) == ContactsDatabase.DIVIDER_TYPE) {
|
||||
return VIEW_TYPE_DIVIDER;
|
||||
} else {
|
||||
return VIEW_TYPE_CONTACT;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public HeaderViewHolder onCreateHeaderViewHolder(ViewGroup parent) {
|
||||
return new HeaderViewHolder(LayoutInflater.from(getContext()).inflate(R.layout.contact_selection_recyclerview_header, parent, false));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindHeaderViewHolder(HeaderViewHolder viewHolder, int position) {
|
||||
((TextView)viewHolder.itemView).setText(getSpannedHeaderString(position));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onItemViewRecycled(ViewHolder holder) {
|
||||
holder.unbind(glideRequests);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence getBubbleText(int position) {
|
||||
return getHeaderString(position);
|
||||
}
|
||||
|
||||
public Set<String> getSelectedContacts() {
|
||||
return selectedContacts;
|
||||
}
|
||||
|
||||
private CharSequence getSpannedHeaderString(int position) {
|
||||
final String headerString = getHeaderString(position);
|
||||
if (isPush(position)) {
|
||||
SpannableString spannable = new SpannableString(headerString);
|
||||
spannable.setSpan(new ForegroundColorSpan(getContext().getResources().getColor(R.color.signal_primary)), 0, headerString.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
return spannable;
|
||||
} else {
|
||||
return headerString;
|
||||
}
|
||||
}
|
||||
|
||||
private @NonNull String getHeaderString(int position) {
|
||||
int contactType = getContactType(position);
|
||||
|
||||
if (contactType == ContactsDatabase.RECENT_TYPE || contactType == ContactsDatabase.DIVIDER_TYPE) {
|
||||
return " ";
|
||||
}
|
||||
|
||||
Cursor cursor = getCursorAtPositionOrThrow(position);
|
||||
String letter = cursor.getString(cursor.getColumnIndexOrThrow(ContactsDatabase.NAME_COLUMN));
|
||||
|
||||
if (!TextUtils.isEmpty(letter)) {
|
||||
String firstChar = letter.trim().substring(0, 1).toUpperCase();
|
||||
if (Character.isLetterOrDigit(firstChar.codePointAt(0))) {
|
||||
return firstChar;
|
||||
}
|
||||
}
|
||||
|
||||
return "#";
|
||||
}
|
||||
|
||||
private int getContactType(int position) {
|
||||
final Cursor cursor = getCursorAtPositionOrThrow(position);
|
||||
return cursor.getInt(cursor.getColumnIndexOrThrow(ContactsDatabase.CONTACT_TYPE_COLUMN));
|
||||
}
|
||||
|
||||
private boolean isPush(int position) {
|
||||
return getContactType(position) == ContactsDatabase.PUSH_TYPE;
|
||||
}
|
||||
|
||||
public interface ItemClickListener {
|
||||
void onItemClick(ContactSelectionListItem item);
|
||||
}
|
||||
}
|
@ -0,0 +1,85 @@
|
||||
package org.thoughtcrime.securesms.loki.redesign.activities
|
||||
|
||||
import android.content.Context
|
||||
import android.support.v7.widget.RecyclerView
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import kotlinx.android.synthetic.main.contact_selection_list_divider.view.*
|
||||
import network.loki.messenger.R
|
||||
import org.thoughtcrime.securesms.loki.redesign.views.UserView
|
||||
import org.thoughtcrime.securesms.mms.GlideRequests
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
|
||||
class ContactSelectionListAdapter(private val context: Context, private val isMulti: Boolean) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
||||
|
||||
private object ViewType {
|
||||
const val Contact = 0
|
||||
const val Divider = 1
|
||||
}
|
||||
|
||||
lateinit var glide: GlideRequests
|
||||
val selectedContacts = mutableSetOf<Recipient>()
|
||||
var items = listOf<ContactSelectionListLoaderItem>()
|
||||
set(value) { field = value; notifyDataSetChanged() }
|
||||
var contactClickListener: ContactClickListener? = null
|
||||
|
||||
class ViewHolder(val view: UserView) : RecyclerView.ViewHolder(view)
|
||||
class DividerViewHolder(val view: View): RecyclerView.ViewHolder(view)
|
||||
|
||||
override fun getItemCount(): Int {
|
||||
return items.size
|
||||
}
|
||||
|
||||
override fun getItemViewType(position: Int): Int {
|
||||
return when (items[position]) {
|
||||
is ContactSelectionListLoaderItem.Header -> ViewType.Divider
|
||||
else -> ViewType.Contact
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
||||
return if (viewType == ViewType.Contact) {
|
||||
ViewHolder(UserView(context))
|
||||
} else {
|
||||
val view = LayoutInflater.from(context).inflate(R.layout.contact_selection_list_divider, parent, false)
|
||||
DividerViewHolder(view)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(viewHolder: RecyclerView.ViewHolder, position: Int) {
|
||||
val item = items[position]
|
||||
if (viewHolder is ViewHolder) {
|
||||
item as ContactSelectionListLoaderItem.Contact
|
||||
viewHolder.view.setOnClickListener { contactClickListener?.onContactClick(item.recipient) }
|
||||
val isSelected = selectedContacts.contains(item.recipient)
|
||||
viewHolder.view.bind(item.recipient.address.serialize(), isSelected, glide)
|
||||
} else if (viewHolder is DividerViewHolder) {
|
||||
item as ContactSelectionListLoaderItem.Header
|
||||
viewHolder.view.label.text = item.name
|
||||
}
|
||||
}
|
||||
|
||||
fun onContactClick(recipient: Recipient) {
|
||||
if (selectedContacts.contains(recipient)) {
|
||||
selectedContacts.remove(recipient)
|
||||
contactClickListener?.onContactDeselected(recipient)
|
||||
} else {
|
||||
selectedContacts.add(recipient)
|
||||
contactClickListener?.onContactSelected(recipient)
|
||||
}
|
||||
val index = items.indexOfFirst {
|
||||
when (it) {
|
||||
is ContactSelectionListLoaderItem.Header -> false
|
||||
is ContactSelectionListLoaderItem.Contact -> it.recipient == recipient
|
||||
}
|
||||
}
|
||||
notifyItemChanged(index)
|
||||
}
|
||||
}
|
||||
|
||||
interface ContactClickListener {
|
||||
fun onContactClick(contact: Recipient)
|
||||
fun onContactSelected(contact: Recipient)
|
||||
fun onContactDeselected(contact: Recipient)
|
||||
}
|
@ -0,0 +1,80 @@
|
||||
package org.thoughtcrime.securesms.loki.redesign.activities
|
||||
|
||||
import android.content.Context
|
||||
import network.loki.messenger.R
|
||||
import org.thoughtcrime.securesms.loki.redesign.utilities.Contact
|
||||
import org.thoughtcrime.securesms.loki.redesign.utilities.ContactUtilities
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
import org.thoughtcrime.securesms.util.AsyncLoader
|
||||
|
||||
sealed class ContactSelectionListLoaderItem {
|
||||
class Header(val name: String): ContactSelectionListLoaderItem()
|
||||
class Contact(val recipient: Recipient): ContactSelectionListLoaderItem()
|
||||
|
||||
}
|
||||
|
||||
class ContactSelectionListLoader(context: Context, val mode: Int, val filter: String?) : AsyncLoader<List<ContactSelectionListLoaderItem>>(context) {
|
||||
object DisplayMode {
|
||||
const val FLAG_FRIENDS = 1
|
||||
const val FLAG_CLOSED_GROUPS = 1 shl 1
|
||||
const val FLAG_OPEN_GROUPS = 1 shl 2
|
||||
const val FLAG_ALL = FLAG_FRIENDS or FLAG_CLOSED_GROUPS or FLAG_OPEN_GROUPS
|
||||
}
|
||||
|
||||
private fun isFlagSet(flag: Int): Boolean {
|
||||
return mode and flag > 0
|
||||
}
|
||||
|
||||
override fun loadInBackground(): List<ContactSelectionListLoaderItem> {
|
||||
val contacts = ContactUtilities.getAllContacts(context).filter {
|
||||
if (filter.isNullOrEmpty()) return@filter true
|
||||
|
||||
it.recipient.toShortString().contains(filter.trim(), true) || it.recipient.address.serialize().contains(filter.trim(), true)
|
||||
}.sortedBy {
|
||||
it.recipient.toShortString()
|
||||
}
|
||||
|
||||
val list = mutableListOf<ContactSelectionListLoaderItem>()
|
||||
if (isFlagSet(DisplayMode.FLAG_CLOSED_GROUPS)) {
|
||||
list.addAll(getClosedGroups(contacts))
|
||||
}
|
||||
|
||||
if (isFlagSet(DisplayMode.FLAG_OPEN_GROUPS)) {
|
||||
list.addAll(getOpenGroups(contacts))
|
||||
}
|
||||
|
||||
if (isFlagSet(DisplayMode.FLAG_FRIENDS)) {
|
||||
list.addAll(getFriends(contacts))
|
||||
}
|
||||
|
||||
return list
|
||||
}
|
||||
|
||||
private fun getFriends(contacts: List<Contact>): List<ContactSelectionListLoaderItem> {
|
||||
return getItems(contacts, context.getString(R.string.ContactSelectionListLoader_contacts)) {
|
||||
!it.recipient.isGroupRecipient && it.isFriend && !it.isOurDevice && !it.isSlave
|
||||
}
|
||||
}
|
||||
|
||||
private fun getClosedGroups(contacts: List<Contact>): List<ContactSelectionListLoaderItem> {
|
||||
return getItems(contacts, context.getString(R.string.ContactSelectionListLoader_closed_groups)) {
|
||||
it.recipient.address.isSignalGroup
|
||||
}
|
||||
}
|
||||
|
||||
private fun getOpenGroups(contacts: List<Contact>): List<ContactSelectionListLoaderItem> {
|
||||
return getItems(contacts, context.getString(R.string.ContactSelectionListLoader_open_groups)) {
|
||||
it.recipient.address.isPublicChat
|
||||
}
|
||||
}
|
||||
|
||||
private fun getItems(contacts: List<Contact>, title: String, contactFilter: (Contact) -> Boolean): List<ContactSelectionListLoaderItem> {
|
||||
val items = contacts.filter(contactFilter).map {
|
||||
ContactSelectionListLoaderItem.Contact(it.recipient)
|
||||
}
|
||||
if (items.isEmpty()) return listOf()
|
||||
|
||||
val header = ContactSelectionListLoaderItem.Header(title)
|
||||
return listOf(header) + items
|
||||
}
|
||||
}
|
@ -0,0 +1,130 @@
|
||||
package org.thoughtcrime.securesms.loki.redesign.fragments
|
||||
|
||||
import android.os.Bundle
|
||||
import android.support.v4.app.Fragment
|
||||
import android.support.v4.app.LoaderManager
|
||||
import android.support.v4.content.Loader
|
||||
import android.support.v4.widget.SwipeRefreshLayout.OnRefreshListener
|
||||
import android.support.v7.widget.LinearLayoutManager
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import kotlinx.android.synthetic.main.contact_selection_list_fragment.*
|
||||
import network.loki.messenger.R
|
||||
import org.thoughtcrime.securesms.contacts.ContactsCursorLoader
|
||||
import org.thoughtcrime.securesms.loki.redesign.activities.ContactClickListener
|
||||
import org.thoughtcrime.securesms.loki.redesign.activities.ContactSelectionListAdapter
|
||||
import org.thoughtcrime.securesms.loki.redesign.activities.ContactSelectionListLoader
|
||||
import org.thoughtcrime.securesms.loki.redesign.activities.ContactSelectionListLoaderItem
|
||||
import org.thoughtcrime.securesms.mms.GlideApp
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
|
||||
class ContactSelectionListFragment : Fragment(), LoaderManager.LoaderCallbacks<List<ContactSelectionListLoaderItem>>, ContactClickListener {
|
||||
|
||||
companion object {
|
||||
@JvmField val DISPLAY_MODE = "display_mode"
|
||||
@JvmField val MULTI_SELECT = "multi_select"
|
||||
@JvmField val REFRESHABLE = "refreshable"
|
||||
}
|
||||
|
||||
val selectedContacts: List<String>
|
||||
get() = listAdapter.selectedContacts.map { it.address.serialize() }
|
||||
|
||||
private var items = listOf<ContactSelectionListLoaderItem>()
|
||||
set(value) { field = value; listAdapter.items = value }
|
||||
|
||||
private val listAdapter by lazy {
|
||||
val result = ContactSelectionListAdapter(activity!!, isMulti)
|
||||
result.glide = GlideApp.with(this)
|
||||
result.contactClickListener = this
|
||||
result
|
||||
}
|
||||
|
||||
private val isMulti: Boolean by lazy {
|
||||
activity!!.intent.getBooleanExtra(MULTI_SELECT, false)
|
||||
}
|
||||
|
||||
private var cursorFilter: String? = null
|
||||
|
||||
var onContactSelectedListener: OnContactSelectedListener? = null
|
||||
|
||||
override fun onActivityCreated(savedInstanceState: Bundle?) {
|
||||
super.onActivityCreated(savedInstanceState)
|
||||
|
||||
recyclerView.layoutManager = LinearLayoutManager(activity)
|
||||
recyclerView.adapter = listAdapter
|
||||
swipeRefresh.isEnabled = activity!!.intent.getBooleanExtra(REFRESHABLE, true)
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
LoaderManager.getInstance(this).initLoader(0, null, this)
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||
return inflater.inflate(R.layout.contact_selection_list_fragment, container, false)
|
||||
}
|
||||
|
||||
fun setQueryFilter(filter: String?) {
|
||||
cursorFilter = filter
|
||||
this.loaderManager.restartLoader<List<ContactSelectionListLoaderItem>>(0, null, this)
|
||||
}
|
||||
|
||||
fun resetQueryFilter() {
|
||||
setQueryFilter(null)
|
||||
swipeRefresh.isRefreshing = false
|
||||
}
|
||||
|
||||
fun setRefreshing(refreshing: Boolean) {
|
||||
swipeRefresh.isRefreshing = refreshing
|
||||
}
|
||||
|
||||
fun setOnRefreshListener(onRefreshListener: OnRefreshListener?) {
|
||||
this.swipeRefresh.setOnRefreshListener(onRefreshListener)
|
||||
}
|
||||
|
||||
override fun onCreateLoader(id: Int, args: Bundle?): Loader<List<ContactSelectionListLoaderItem>> {
|
||||
return ContactSelectionListLoader(activity!!,
|
||||
activity!!.intent.getIntExtra(DISPLAY_MODE, ContactsCursorLoader.DisplayMode.FLAG_ALL),
|
||||
cursorFilter)
|
||||
}
|
||||
|
||||
override fun onLoadFinished(loader: Loader<List<ContactSelectionListLoaderItem>>, items: List<ContactSelectionListLoaderItem>) {
|
||||
update(items)
|
||||
}
|
||||
|
||||
override fun onLoaderReset(loader: Loader<List<ContactSelectionListLoaderItem>>) {
|
||||
update(listOf())
|
||||
}
|
||||
|
||||
private fun update(items: List<ContactSelectionListLoaderItem>) {
|
||||
this.items = items
|
||||
mainContentContainer.visibility = if (items.isEmpty()) View.GONE else View.VISIBLE
|
||||
emptyStateContainer.visibility = if (items.isEmpty()) View.VISIBLE else View.GONE
|
||||
val useFastScroller = items.count() > 20
|
||||
recyclerView.isVerticalScrollBarEnabled = !useFastScroller
|
||||
if (useFastScroller) {
|
||||
fastScroller.visibility = View.VISIBLE
|
||||
fastScroller.setRecyclerView(recyclerView)
|
||||
} else {
|
||||
fastScroller.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
|
||||
override fun onContactClick(contact: Recipient) {
|
||||
listAdapter.onContactClick(contact)
|
||||
}
|
||||
|
||||
override fun onContactSelected(contact: Recipient) {
|
||||
onContactSelectedListener?.onContactSelected(contact.address.serialize())
|
||||
}
|
||||
|
||||
override fun onContactDeselected(contact: Recipient) {
|
||||
onContactSelectedListener?.onContactDeselected(contact.address.serialize())
|
||||
}
|
||||
|
||||
interface OnContactSelectedListener {
|
||||
fun onContactSelected(number: String?)
|
||||
fun onContactDeselected(number: String?)
|
||||
}
|
||||
}
|
@ -8,7 +8,6 @@ import org.whispersystems.signalservice.loki.messaging.LokiThreadFriendRequestSt
|
||||
|
||||
data class Contact(
|
||||
val recipient: Recipient,
|
||||
val threadId: Long,
|
||||
val isFriend: Boolean,
|
||||
val isSlave: Boolean,
|
||||
val isOurDevice: Boolean
|
||||
@ -35,6 +34,8 @@ object ContactUtilities {
|
||||
val lokiThreadDatabase = DatabaseFactory.getLokiThreadDatabase(context)
|
||||
val userHexEncodedPublicKey = TextSecurePreferences.getLocalNumber(context)
|
||||
val lokiAPIDatabase = DatabaseFactory.getLokiAPIDatabase(context)
|
||||
val groupDatabase = DatabaseFactory.getGroupDatabase(context)
|
||||
val lokiUserDatabase = DatabaseFactory.getLokiUserDatabase(context)
|
||||
|
||||
val ourDeviceLinks = lokiAPIDatabase.getDeviceLinks(userHexEncodedPublicKey)
|
||||
val ourDevices = ourDeviceLinks.flatMap {
|
||||
@ -43,23 +44,27 @@ object ContactUtilities {
|
||||
ourDevices.add(userHexEncodedPublicKey.toLowerCase())
|
||||
|
||||
val cursor = threadDatabase.conversationList
|
||||
val reader = threadDatabase.readerFor(cursor)
|
||||
val result = mutableSetOf<Contact>()
|
||||
while (reader.next != null) {
|
||||
val thread = reader.current
|
||||
val recipient = thread.recipient
|
||||
val hexEncodedPublicKey = recipient.address.serialize()
|
||||
threadDatabase.readerFor(cursor).use { reader ->
|
||||
while (reader.next != null) {
|
||||
val thread = reader.current
|
||||
val recipient = thread.recipient
|
||||
val address = recipient.address.serialize()
|
||||
|
||||
val isFriend = lokiThreadDatabase.getFriendRequestStatus(thread.threadId) == LokiThreadFriendRequestStatus.FRIENDS
|
||||
var isSlave = false
|
||||
if (!recipient.isGroupRecipient) {
|
||||
val deviceLinks = lokiAPIDatabase.getDeviceLinks(hexEncodedPublicKey)
|
||||
isSlave = deviceLinks.find { it.slaveHexEncodedPublicKey == hexEncodedPublicKey } != null
|
||||
val isOurDevice = ourDevices.contains(address)
|
||||
val isFriend = lokiThreadDatabase.getFriendRequestStatus(thread.threadId) == LokiThreadFriendRequestStatus.FRIENDS
|
||||
var isSlave = false
|
||||
var displayName = ""
|
||||
|
||||
if (!recipient.isGroupRecipient) {
|
||||
val deviceLinks = lokiAPIDatabase.getDeviceLinks(address)
|
||||
isSlave = deviceLinks.find { it.slaveHexEncodedPublicKey == address } != null
|
||||
}
|
||||
|
||||
result.add(Contact(recipient, isFriend, isSlave, isOurDevice))
|
||||
}
|
||||
val isOurDevice = ourDevices.contains(hexEncodedPublicKey)
|
||||
|
||||
result.add(Contact(recipient, thread.threadId, isFriend, isSlave, isOurDevice))
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
|
@ -455,7 +455,8 @@ public class Recipient implements RecipientModifiedListener {
|
||||
}
|
||||
|
||||
public synchronized String toShortString() {
|
||||
return (getName() == null ? address.serialize() : getName());
|
||||
String name = getName();
|
||||
return (name == null ? address.serialize() : name);
|
||||
}
|
||||
|
||||
public synchronized @NonNull Drawable getFallbackContactPhotoDrawable(Context context, boolean inverted) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user