Refresh contact search views.

fork-5.53.8
Alex Hart 2021-07-12 15:44:59 -03:00 zatwierdzone przez Greyson Parrelli
rodzic a4d458f969
commit a157c1ae1d
51 zmienionych plików z 1004 dodań i 513 usunięć

Wyświetl plik

@ -20,13 +20,13 @@ import android.content.Context;
import android.os.AsyncTask;
import android.os.Bundle;
import androidx.appcompat.widget.Toolbar;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import org.signal.core.util.logging.Log;
import org.thoughtcrime.securesms.components.ContactFilterToolbar;
import org.thoughtcrime.securesms.components.ContactFilterView;
import org.thoughtcrime.securesms.contacts.ContactsCursorLoader.DisplayMode;
import org.thoughtcrime.securesms.contacts.sync.DirectoryHelper;
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
import org.thoughtcrime.securesms.recipients.RecipientId;
import org.thoughtcrime.securesms.util.DynamicNoActionBarTheme;
import org.thoughtcrime.securesms.util.DynamicTheme;
@ -56,7 +56,8 @@ public abstract class ContactSelectionActivity extends PassphraseRequiredActivit
protected ContactSelectionListFragment contactsFragment;
private ContactFilterToolbar toolbar;
private Toolbar toolbar;
private ContactFilterView contactFilterView;
@Override
protected void onPreCreate() {
@ -73,6 +74,7 @@ public abstract class ContactSelectionActivity extends PassphraseRequiredActivit
setContentView(getIntent().getIntExtra(EXTRA_LAYOUT_RES_ID, R.layout.contact_selection_activity));
initializeContactFilterView();
initializeToolbar();
initializeResources();
initializeSearch();
@ -84,16 +86,23 @@ public abstract class ContactSelectionActivity extends PassphraseRequiredActivit
dynamicTheme.onResume(this);
}
protected ContactFilterToolbar getToolbar() {
protected Toolbar getToolbar() {
return toolbar;
}
protected ContactFilterView getContactFilterView() {
return contactFilterView;
}
private void initializeContactFilterView() {
this.contactFilterView = findViewById(R.id.contact_filter_edit_text);
}
private void initializeToolbar() {
this.toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(false);
getSupportActionBar().setDisplayShowTitleEnabled(false);
getSupportActionBar().setIcon(null);
getSupportActionBar().setLogo(null);
}
@ -104,7 +113,7 @@ public abstract class ContactSelectionActivity extends PassphraseRequiredActivit
}
private void initializeSearch() {
toolbar.setOnFilterChangedListener(filter -> contactsFragment.setQueryFilter(filter));
contactFilterView.setOnFilterChangedListener(filter -> contactsFragment.setQueryFilter(filter));
}
@Override
@ -155,7 +164,7 @@ public abstract class ContactSelectionActivity extends PassphraseRequiredActivit
ContactSelectionActivity activity = this.activity.get();
if (activity != null && !activity.isFinishing()) {
activity.toolbar.clear();
activity.contactFilterView.clear();
activity.contactsFragment.resetQueryFilter();
}
}

Wyświetl plik

@ -57,13 +57,14 @@ import com.pnikosis.materialishprogress.ProgressWheel;
import org.signal.core.util.logging.Log;
import org.thoughtcrime.securesms.components.RecyclerViewFastScroller;
import org.thoughtcrime.securesms.components.emoji.WarningTextView;
import org.thoughtcrime.securesms.components.recyclerview.ToolbarShadowAnimationHelper;
import org.thoughtcrime.securesms.contacts.AbstractContactsCursorLoader;
import org.thoughtcrime.securesms.contacts.ContactChip;
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.contacts.LetterHeaderDecoration;
import org.thoughtcrime.securesms.contacts.SelectedContact;
import org.thoughtcrime.securesms.contacts.sync.DirectoryHelper;
import org.thoughtcrime.securesms.groups.SelectionLimits;
@ -74,7 +75,6 @@ import org.thoughtcrime.securesms.permissions.Permissions;
import org.thoughtcrime.securesms.recipients.LiveRecipient;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.RecipientId;
import org.thoughtcrime.securesms.util.StickyHeaderDecoration;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.thoughtcrime.securesms.util.UsernameUtil;
import org.thoughtcrime.securesms.util.ViewUtil;
@ -131,9 +131,10 @@ public final class ContactSelectionListFragment extends LoggingFragment
private ContactSelectionListAdapter cursorRecyclerViewAdapter;
private ChipGroup chipGroup;
private HorizontalScrollView chipGroupScrollContainer;
private WarningTextView groupLimit;
private OnSelectionLimitReachedListener onSelectionLimitReachedListener;
private AbstractContactsCursorLoaderFactoryProvider cursorFactoryProvider;
private View shadowView;
private ToolbarShadowAnimationHelper toolbarShadowAnimationHelper;
@Nullable private FixedViewsAdapter headerAdapter;
@ -233,9 +234,12 @@ public final class ContactSelectionListFragment extends LoggingFragment
showContactsProgress = view.findViewById(R.id.progress);
chipGroup = view.findViewById(R.id.chipGroup);
chipGroupScrollContainer = view.findViewById(R.id.chipGroupScrollContainer);
groupLimit = view.findViewById(R.id.group_limit);
constraintLayout = view.findViewById(R.id.container);
shadowView = view.findViewById(R.id.toolbar_shadow);
toolbarShadowAnimationHelper = new ToolbarShadowAnimationHelper(shadowView);
recyclerView.addOnScrollListener(toolbarShadowAnimationHelper);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
recyclerView.setItemAnimator(new DefaultItemAnimator() {
@Override
@ -272,8 +276,6 @@ public final class ContactSelectionListFragment extends LoggingFragment
currentSelection = getCurrentSelection();
updateGroupLimit(getChipCount());
return view;
}
@ -281,13 +283,6 @@ public final class ContactSelectionListFragment extends LoggingFragment
return getArguments() != null ? getArguments() : new Bundle();
}
private void updateGroupLimit(int chipCount) {
int members = currentSelection.size() + chipCount;
groupLimit.setText(getResources().getQuantityString(R.plurals.ContactSelectionListFragment_d_members, members, members));
groupLimit.setVisibility(isMulti && !hideCount ? View.VISIBLE : View.GONE);
groupLimit.setWarning(selectionWarningLimitExceeded());
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
Permissions.onRequestPermissionsResult(this, requestCode, permissions, grantResults);
@ -309,6 +304,14 @@ public final class ContactSelectionListFragment extends LoggingFragment
return cursorRecyclerViewAdapter.getSelectedContactsCount();
}
public int getTotalMemberCount() {
if (cursorRecyclerViewAdapter == null) {
return 0;
}
return cursorRecyclerViewAdapter.getSelectedContactsCount() + cursorRecyclerViewAdapter.getCurrentContactsCount();
}
private Set<RecipientId> getCurrentSelection() {
List<RecipientId> currentSelection = safeArguments().getParcelableArrayList(CURRENT_SELECTION);
if (currentSelection == null) {
@ -349,8 +352,8 @@ public final class ContactSelectionListFragment extends LoggingFragment
concatenateAdapter.addAdapter(footerAdapter);
}
recyclerView.addItemDecoration(new LetterHeaderDecoration(requireContext(), this::hideLetterHeaders));
recyclerView.setAdapter(concatenateAdapter);
recyclerView.addItemDecoration(new StickyHeaderDecoration(concatenateAdapter, true, true, 0));
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
@ -361,6 +364,14 @@ public final class ContactSelectionListFragment extends LoggingFragment
}
}
});
if (onContactSelectedListener != null) {
onContactSelectedListener.onSelectionChanged();
}
}
private boolean hideLetterHeaders() {
return hasQueryFilter() || shouldDisplayRecents();
}
private View createInviteActionView(@NonNull ListCallback listCallback) {
@ -429,7 +440,7 @@ public final class ContactSelectionListFragment extends LoggingFragment
public @NonNull Loader<Cursor> onCreateLoader(int id, Bundle args) {
FragmentActivity activity = requireActivity();
int displayMode = safeArguments().getInt(DISPLAY_MODE, activity.getIntent().getIntExtra(DISPLAY_MODE, DisplayMode.FLAG_ALL));
boolean displayRecents = safeArguments().getBoolean(RECENTS, activity.getIntent().getBooleanExtra(RECENTS, false));
boolean displayRecents = shouldDisplayRecents();
if (cursorFactoryProvider != null) {
return cursorFactoryProvider.get().create();
@ -475,6 +486,10 @@ public final class ContactSelectionListFragment extends LoggingFragment
fastScroller.setVisibility(View.GONE);
}
private boolean shouldDisplayRecents() {
return safeArguments().getBoolean(RECENTS, requireActivity().getIntent().getBooleanExtra(RECENTS, false));
}
@SuppressLint("StaticFieldLeak")
private void handleContactPermissionGranted() {
final Context context = requireContext();
@ -606,12 +621,19 @@ public final class ContactSelectionListFragment extends LoggingFragment
if (isMulti) {
addChipForSelectedContact(selectedContact);
}
if (onContactSelectedListener != null) {
onContactSelectedListener.onSelectionChanged();
}
}
private void markContactUnselected(@NonNull SelectedContact selectedContact) {
cursorRecyclerViewAdapter.removeFromSelectedContacts(selectedContact);
cursorRecyclerViewAdapter.notifyItemRangeChanged(0, cursorRecyclerViewAdapter.getItemCount(), ContactSelectionListAdapter.PAYLOAD_SELECTION_CHANGE);
removeChipForContact(selectedContact);
if (onContactSelectedListener != null) {
onContactSelectedListener.onSelectionChanged();
}
}
private void removeChipForContact(@NonNull SelectedContact contact) {
@ -622,8 +644,6 @@ public final class ContactSelectionListFragment extends LoggingFragment
}
}
updateGroupLimit(getChipCount());
if (getChipCount() == 0) {
setChipGroupVisibility(ConstraintSet.GONE);
}
@ -673,7 +693,6 @@ public final class ContactSelectionListFragment extends LoggingFragment
private void addChip(@NonNull ContactChip chip) {
chipGroup.addView(chip);
updateGroupLimit(getChipCount());
if (selectionWarningLimitReachedExactly()) {
if (onSelectionLimitReachedListener != null) {
onSelectionLimitReachedListener.onSuggestedLimitReached(selectionLimit.getRecommendedLimit());
@ -726,6 +745,7 @@ public final class ContactSelectionListFragment extends LoggingFragment
/** @return True if the contact is allowed to be selected, otherwise false. */
boolean onBeforeContactSelected(Optional<RecipientId> recipientId, String number);
void onContactDeselected(Optional<RecipientId> recipientId, String number);
void onSelectionChanged();
}
public interface OnSelectionLimitReachedListener {

Wyświetl plik

@ -7,8 +7,6 @@ import android.graphics.PorterDuff;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
@ -24,8 +22,8 @@ import androidx.appcompat.widget.Toolbar;
import androidx.core.content.ContextCompat;
import androidx.interpolator.view.animation.FastOutSlowInInterpolator;
import org.thoughtcrime.securesms.components.ContactFilterToolbar;
import org.thoughtcrime.securesms.components.ContactFilterToolbar.OnFilterChangedListener;
import org.thoughtcrime.securesms.components.ContactFilterView;
import org.thoughtcrime.securesms.components.ContactFilterView.OnFilterChangedListener;
import org.thoughtcrime.securesms.contacts.ContactsCursorLoader.DisplayMode;
import org.thoughtcrime.securesms.contacts.SelectedContact;
import org.thoughtcrime.securesms.database.DatabaseFactory;
@ -100,7 +98,8 @@ public class InviteActivity extends PassphraseRequiredActivity implements Contac
View shareButton = findViewById(R.id.share_button);
Button smsButton = findViewById(R.id.sms_button);
Button smsCancelButton = findViewById(R.id.cancel_sms_button);
ContactFilterToolbar contactFilter = findViewById(R.id.contact_filter);
Toolbar smsToolbar = findViewById(R.id.sms_send_frame_toolbar);
ContactFilterView contactFilter = findViewById(R.id.contact_filter_edit_text);
inviteText = findViewById(R.id.invite_text);
smsSendFrame = findViewById(R.id.sms_send_frame);
@ -121,7 +120,7 @@ public class InviteActivity extends PassphraseRequiredActivity implements Contac
smsCancelButton.setOnClickListener(new SmsCancelClickListener());
smsSendButton.setOnClickListener(new SmsSendClickListener());
contactFilter.setOnFilterChangedListener(new ContactFilterChangedListener());
contactFilter.setNavigationIcon(R.drawable.ic_search_conversation_24);
smsToolbar.setNavigationIcon(R.drawable.ic_search_conversation_24);
if (Util.isDefaultSmsProvider(this)) {
shareButton.setOnClickListener(new ShareClickListener());
@ -150,6 +149,10 @@ public class InviteActivity extends PassphraseRequiredActivity implements Contac
updateSmsButtonText(contactsFragment.getSelectedContacts().size());
}
@Override
public void onSelectionChanged() {
}
private void sendSmsInvites() {
new SendSmsInvitesAsyncTask(this, inviteText.getText().toString())
.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,

Wyświetl plik

@ -56,6 +56,7 @@ public class NewConversationActivity extends ContactSelectionActivity
super.onCreate(bundle, ready);
assert getSupportActionBar() != null;
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setTitle(R.string.NewConversationActivity__new_message);
}
@Override
@ -96,6 +97,10 @@ public class NewConversationActivity extends ContactSelectionActivity
return true;
}
@Override
public void onSelectionChanged() {
}
private void launch(Recipient recipient) {
long existingThread = DatabaseFactory.getThreadDatabase(this).getThreadIdIfExistsFor(recipient.getId());
Intent intent = ConversationIntents.createBuilder(this, recipient.getId(), existingThread)

Wyświetl plik

@ -65,4 +65,8 @@ public class PushContactSelectionActivity extends ContactSelectionActivity {
setResult(RESULT_OK, resultIntent);
finish();
}
@Override
public void onSelectionChanged() {
}
}

Wyświetl plik

@ -5,7 +5,6 @@ import android.content.Intent;
import android.graphics.Color;
import android.os.Bundle;
import android.view.View;
import android.widget.ViewSwitcher;
import androidx.annotation.NonNull;
import androidx.annotation.StringRes;
@ -18,7 +17,7 @@ import com.google.android.material.snackbar.Snackbar;
import org.thoughtcrime.securesms.ContactSelectionListFragment;
import org.thoughtcrime.securesms.PassphraseRequiredActivity;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.components.ContactFilterToolbar;
import org.thoughtcrime.securesms.components.ContactFilterView;
import org.thoughtcrime.securesms.contacts.ContactsCursorLoader;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.RecipientId;
@ -47,27 +46,26 @@ public class BlockedUsersActivity extends PassphraseRequiredActivity implements
viewModel = ViewModelProviders.of(this, factory).get(BlockedUsersViewModel.class);
ViewSwitcher viewSwitcher = findViewById(R.id.toolbar_switcher);
Toolbar toolbar = findViewById(R.id.toolbar);
ContactFilterToolbar contactFilterToolbar = findViewById(R.id.filter_toolbar);
View container = findViewById(R.id.fragment_container);
Toolbar toolbar = findViewById(R.id.toolbar);
ContactFilterView contactFilterView = findViewById(R.id.contact_filter_edit_text);
View container = findViewById(R.id.fragment_container);
toolbar.setNavigationOnClickListener(unused -> onBackPressed());
contactFilterToolbar.setNavigationOnClickListener(unused -> onBackPressed());
contactFilterToolbar.setOnFilterChangedListener(query -> {
contactFilterView.setOnFilterChangedListener(query -> {
Fragment fragment = getSupportFragmentManager().findFragmentByTag(CONTACT_SELECTION_FRAGMENT);
if (fragment != null) {
((ContactSelectionListFragment) fragment).setQueryFilter(query);
}
});
contactFilterToolbar.setHint(R.string.BlockedUsersActivity__add_blocked_user);
contactFilterView.setHint(R.string.BlockedUsersActivity__add_blocked_user);
//noinspection CodeBlock2Expr
getSupportFragmentManager().addOnBackStackChangedListener(() -> {
viewSwitcher.setDisplayedChild(getSupportFragmentManager().getBackStackEntryCount());
if (getSupportFragmentManager().getBackStackEntryCount() == 1) {
contactFilterToolbar.focusAndShowKeyboard();
contactFilterView.setVisibility(View.VISIBLE);
contactFilterView.focusAndShowKeyboard();
} else {
contactFilterView.setVisibility(View.GONE);
}
});
@ -119,6 +117,10 @@ public class BlockedUsersActivity extends PassphraseRequiredActivity implements
}
@Override
public void onSelectionChanged() {
}
@Override
public void handleAddUserToBlockedList() {
ContactSelectionListFragment fragment = new ContactSelectionListFragment();
@ -164,6 +166,6 @@ public class BlockedUsersActivity extends PassphraseRequiredActivity implements
throw new IllegalArgumentException("Unsupported event type " + event);
}
Snackbar.make(view, getString(messageResId, displayName), Snackbar.LENGTH_SHORT).show();
Snackbar.make(view, getString(messageResId, displayName), Snackbar.LENGTH_SHORT).setTextColor(Color.WHITE).show();
}
}

Wyświetl plik

@ -10,6 +10,7 @@ import android.util.AttributeSet;
import android.view.TouchDelegate;
import android.view.View;
import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
@ -20,9 +21,8 @@ import androidx.core.widget.TextViewCompat;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.util.ServiceUtil;
import org.thoughtcrime.securesms.util.ViewUtil;
import org.thoughtcrime.securesms.util.views.DarkOverflowToolbar;
public final class ContactFilterToolbar extends DarkOverflowToolbar {
public final class ContactFilterView extends FrameLayout {
private OnFilterChangedListener listener;
private final EditText searchText;
@ -32,17 +32,17 @@ public final class ContactFilterToolbar extends DarkOverflowToolbar {
private final ImageView clearToggle;
private final LinearLayout toggleContainer;
public ContactFilterToolbar(Context context) {
public ContactFilterView(Context context) {
this(context, null);
}
public ContactFilterToolbar(Context context, AttributeSet attrs) {
public ContactFilterView(Context context, AttributeSet attrs) {
this(context, attrs, R.attr.toolbarStyle);
}
public ContactFilterToolbar(Context context, AttributeSet attrs, int defStyleAttr) {
public ContactFilterView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
inflate(context, R.layout.contact_filter_toolbar, this);
inflate(context, R.layout.contact_filter_view, this);
this.searchText = findViewById(R.id.search_view);
this.toggle = findViewById(R.id.button_toggle);
@ -99,8 +99,6 @@ public final class ContactFilterToolbar extends DarkOverflowToolbar {
}
});
setLogo(null);
setContentInsetStartWithNavigation(0);
expandTapArea(toggleContainer, dialpadToggle);
applyAttributes(searchText, context, attrs, defStyleAttr);
searchText.requestFocus();

Wyświetl plik

@ -0,0 +1,66 @@
package org.thoughtcrime.securesms.components.recyclerview
import androidx.recyclerview.widget.RecyclerView
/**
* Allows implementor to trigger an animation when the attached recyclerview is
* scrolled.
*/
abstract class OnScrollAnimationHelper : RecyclerView.OnScrollListener() {
private var lastAnimationState = AnimationState.NONE
protected open val duration: Long = 250L
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
val newAnimationState = getAnimationState(recyclerView)
if (newAnimationState == lastAnimationState) {
return
}
if (lastAnimationState == AnimationState.NONE) {
setImmediateState(recyclerView)
return
}
when (newAnimationState) {
AnimationState.NONE -> throw AssertionError()
AnimationState.HIDE -> hide(duration)
AnimationState.SHOW -> show(duration)
}
lastAnimationState = newAnimationState
}
fun setImmediateState(recyclerView: RecyclerView) {
val newAnimationState = getAnimationState(recyclerView)
when (newAnimationState) {
AnimationState.NONE -> throw AssertionError()
AnimationState.HIDE -> hide(0L)
AnimationState.SHOW -> show(0L)
}
lastAnimationState = newAnimationState
}
protected open fun getAnimationState(recyclerView: RecyclerView): AnimationState {
return if (recyclerView.canScrollVertically(-1)) AnimationState.SHOW else AnimationState.HIDE
}
/**
* Fired when the RecyclerView is able to be scrolled up
*/
protected abstract fun show(duration: Long)
/**
* Fired when the RecyclerView is not able to be scrolled up
*/
protected abstract fun hide(duration: Long)
enum class AnimationState {
NONE,
HIDE,
SHOW
}
}

Wyświetl plik

@ -0,0 +1,22 @@
package org.thoughtcrime.securesms.components.recyclerview
import android.view.View
/**
* Animates in and out a given view. This is intended to be used to show and hide a toolbar shadow,
* but makes no restrictions in this manner.
*/
open class ToolbarShadowAnimationHelper(private val toolbarShadow: View) : OnScrollAnimationHelper() {
override fun show(duration: Long) {
toolbarShadow.animate()
.setDuration(duration)
.alpha(1f)
}
override fun hide(duration: Long) {
toolbarShadow.animate()
.setDuration(duration)
.alpha(0f)
}
}

Wyświetl plik

@ -12,6 +12,8 @@ import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.RecyclerView
import org.thoughtcrime.securesms.R
import org.thoughtcrime.securesms.components.recyclerview.OnScrollAnimationHelper
import org.thoughtcrime.securesms.components.recyclerview.ToolbarShadowAnimationHelper
abstract class DSLSettingsFragment(
@StringRes private val titleId: Int = -1,
@ -66,72 +68,4 @@ abstract class DSLSettingsFragment(
}
}
}
abstract class OnScrollAnimationHelper : RecyclerView.OnScrollListener() {
private var lastAnimationState = AnimationState.NONE
protected open val duration: Long = 250L
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
val newAnimationState = getAnimationState(recyclerView)
if (newAnimationState == lastAnimationState) {
return
}
if (lastAnimationState == AnimationState.NONE) {
setImmediateState(recyclerView)
return
}
when (newAnimationState) {
AnimationState.NONE -> throw AssertionError()
AnimationState.HIDE -> hide(duration)
AnimationState.SHOW -> show(duration)
}
lastAnimationState = newAnimationState
}
fun setImmediateState(recyclerView: RecyclerView) {
val newAnimationState = getAnimationState(recyclerView)
when (newAnimationState) {
AnimationState.NONE -> throw AssertionError()
AnimationState.HIDE -> hide(0L)
AnimationState.SHOW -> show(0L)
}
lastAnimationState = newAnimationState
}
protected open fun getAnimationState(recyclerView: RecyclerView): AnimationState {
return if (recyclerView.canScrollVertically(-1)) AnimationState.SHOW else AnimationState.HIDE
}
protected abstract fun show(duration: Long)
protected abstract fun hide(duration: Long)
enum class AnimationState {
NONE,
HIDE,
SHOW
}
}
open class ToolbarShadowAnimationHelper(private val toolbarShadow: View) : OnScrollAnimationHelper() {
override fun show(duration: Long) {
toolbarShadow.animate()
.setDuration(duration)
.alpha(1f)
}
override fun hide(duration: Long) {
toolbarShadow.animate()
.setDuration(duration)
.alpha(0f)
}
}
}

Wyświetl plik

@ -31,6 +31,8 @@ import org.thoughtcrime.securesms.PushContactSelectionActivity
import org.thoughtcrime.securesms.R
import org.thoughtcrime.securesms.VerifyIdentityActivity
import org.thoughtcrime.securesms.components.AvatarImageView
import org.thoughtcrime.securesms.components.recyclerview.OnScrollAnimationHelper
import org.thoughtcrime.securesms.components.recyclerview.ToolbarShadowAnimationHelper
import org.thoughtcrime.securesms.components.settings.DSLConfiguration
import org.thoughtcrime.securesms.components.settings.DSLSettingsAdapter
import org.thoughtcrime.securesms.components.settings.DSLSettingsFragment

Wyświetl plik

@ -108,15 +108,31 @@ public class ContactRepository {
}
@WorkerThread
public Cursor querySignalContacts(@NonNull String query) {
public @NonNull Cursor querySignalContacts(@NonNull String query) {
return querySignalContacts(query, true);
}
@WorkerThread
public Cursor querySignalContacts(@NonNull String query, boolean includeSelf) {
Cursor cursor = TextUtils.isEmpty(query) ? recipientDatabase.getSignalContacts(includeSelf)
: recipientDatabase.querySignalContacts(query, includeSelf);
public @NonNull Cursor querySignalContacts(@NonNull String query, boolean includeSelf) {
Cursor cursor = TextUtils.isEmpty(query) ? recipientDatabase.getSignalContacts(includeSelf)
: recipientDatabase.querySignalContacts(query, includeSelf);
cursor = handleNoteToSelfQuery(query, includeSelf, cursor);
return new SearchCursorWrapper(cursor, SEARCH_CURSOR_MAPPERS);
}
@WorkerThread
public @NonNull Cursor queryNonGroupContacts(@NonNull String query, boolean includeSelf) {
Cursor cursor = TextUtils.isEmpty(query) ? recipientDatabase.getNonGroupContacts(includeSelf)
: recipientDatabase.queryNonGroupContacts(query, includeSelf);
cursor = handleNoteToSelfQuery(query, includeSelf, cursor);
return new SearchCursorWrapper(cursor, SEARCH_CURSOR_MAPPERS);
}
private @NonNull Cursor handleNoteToSelfQuery(@NonNull String query, boolean includeSelf, Cursor cursor) {
if (includeSelf && noteToSelfTitle.toLowerCase().contains(query.toLowerCase())) {
Recipient self = Recipient.self();
boolean nameMatch = self.getDisplayName(context).toLowerCase().contains(query.toLowerCase());
@ -130,8 +146,7 @@ public class ContactRepository {
cursor = cursor == null ? selfCursor : new MergeCursor(new Cursor[]{ cursor, selfCursor });
}
}
return new SearchCursorWrapper(cursor, SEARCH_CURSOR_MAPPERS);
return cursor;
}
@WorkerThread

Wyświetl plik

@ -1,16 +1,16 @@
/**
* Copyright (C) 2014 Open Whisper Systems
*
* <p>
* 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.
*
* <p>
* 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.
*
* <p>
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
@ -21,6 +21,7 @@ import android.database.Cursor;
import android.provider.ContactsContract;
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;
@ -29,7 +30,6 @@ import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;
import androidx.recyclerview.widget.RecyclerView;
import org.signal.core.util.logging.Log;
@ -40,12 +40,15 @@ import org.thoughtcrime.securesms.contacts.ContactSelectionListAdapter.ViewHolde
import org.thoughtcrime.securesms.database.CursorRecyclerViewAdapter;
import org.thoughtcrime.securesms.mms.GlideRequests;
import org.thoughtcrime.securesms.recipients.RecipientId;
import org.thoughtcrime.securesms.util.CharacterIterable;
import org.thoughtcrime.securesms.util.CursorUtil;
import org.thoughtcrime.securesms.util.StickyHeaderDecoration.StickyHeaderAdapter;
import org.thoughtcrime.securesms.util.Util;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
import java.util.Set;
/**
@ -54,8 +57,8 @@ import java.util.Set;
* @author Jake McGinty
*/
public class ContactSelectionListAdapter extends CursorRecyclerViewAdapter<ViewHolder>
implements FastScrollAdapter,
StickyHeaderAdapter<HeaderViewHolder>
implements FastScrollAdapter,
StickyHeaderAdapter<HeaderViewHolder>
{
@SuppressWarnings("unused")
private final static String TAG = Log.tag(ContactSelectionListAdapter.class);
@ -98,14 +101,28 @@ public class ContactSelectionListAdapter extends CursorRecyclerViewAdapter<ViewH
super(itemView);
}
public abstract void bind(@NonNull GlideRequests glideRequests, @Nullable RecipientId recipientId, int type, String name, String number, String label, String about, int color, boolean checkboxVisible);
public abstract void bind(@NonNull GlideRequests glideRequests, @Nullable RecipientId recipientId, int type, String name, String number, String label, String about, boolean checkboxVisible);
public abstract void unbind(@NonNull GlideRequests glideRequests);
public abstract void setChecked(boolean checked);
public void animateChecked(boolean checked) {
// Intentionally empty.
}
public abstract void setEnabled(boolean enabled);
public void setLetterHeaderCharacter(@Nullable String letterHeaderCharacter) {
// Intentionally empty.
}
}
public static class ContactViewHolder extends ViewHolder {
ContactViewHolder(@NonNull final View itemView,
public static class ContactViewHolder extends ViewHolder implements LetterHeaderDecoration.LetterHeaderItem {
private String letterHeader;
ContactViewHolder(@NonNull final View itemView,
@Nullable final ItemClickListener clickListener)
{
super(itemView);
@ -118,8 +135,8 @@ public class ContactSelectionListAdapter extends CursorRecyclerViewAdapter<ViewH
return (ContactSelectionListItem) itemView;
}
public void bind(@NonNull GlideRequests glideRequests, @Nullable RecipientId recipientId, int type, String name, String number, String label, String about, int color, boolean checkBoxVisible) {
getView().set(glideRequests, recipientId, type, name, number, label, about, color, checkBoxVisible);
public void bind(@NonNull GlideRequests glideRequests, @Nullable RecipientId recipientId, int type, String name, String number, String label, String about, boolean checkBoxVisible) {
getView().set(glideRequests, recipientId, type, name, number, label, about, checkBoxVisible);
}
@Override
@ -129,13 +146,28 @@ public class ContactSelectionListAdapter extends CursorRecyclerViewAdapter<ViewH
@Override
public void setChecked(boolean checked) {
getView().setChecked(checked);
getView().setChecked(checked, false);
}
@Override
public void animateChecked(boolean checked) {
getView().setChecked(checked, true);
}
@Override
public void setEnabled(boolean enabled) {
getView().setEnabled(enabled);
}
@Override
public @Nullable String getHeaderLetter() {
return letterHeader;
}
@Override
public void setLetterHeaderCharacter(@Nullable String letterHeaderCharacter) {
this.letterHeader = letterHeaderCharacter;
}
}
public static class DividerViewHolder extends ViewHolder {
@ -148,7 +180,7 @@ public class ContactSelectionListAdapter extends CursorRecyclerViewAdapter<ViewH
}
@Override
public void bind(@NonNull GlideRequests glideRequests, @Nullable RecipientId recipientId, int type, String name, String number, String label, String about, int color, boolean checkboxVisible) {
public void bind(@NonNull GlideRequests glideRequests, @Nullable RecipientId recipientId, int type, String name, String number, String label, String about, boolean checkboxVisible) {
this.label.setText(name);
}
@ -168,15 +200,15 @@ public class ContactSelectionListAdapter extends CursorRecyclerViewAdapter<ViewH
}
}
public ContactSelectionListAdapter(@NonNull Context context,
@NonNull GlideRequests glideRequests,
public ContactSelectionListAdapter(@NonNull Context context,
@NonNull GlideRequests glideRequests,
@Nullable Cursor cursor,
@Nullable ItemClickListener clickListener,
boolean multiSelect,
@NonNull Set<RecipientId> currentContacts)
{
super(context, cursor);
this.layoutInflater = LayoutInflater.from(context);
this.layoutInflater = LayoutInflater.from(context);
this.glideRequests = glideRequests;
this.multiSelect = multiSelect;
this.clickListener = clickListener;
@ -186,7 +218,7 @@ public class ContactSelectionListAdapter extends CursorRecyclerViewAdapter<ViewH
@Override
public long getHeaderId(int i) {
if (!isActiveCursor()) return -1;
else if (i == -1) return -1;
else if (i == -1) return -1;
int contactType = getContactType(i);
@ -215,15 +247,10 @@ public class ContactSelectionListAdapter extends CursorRecyclerViewAdapter<ViewH
String label = CursorUtil.requireString(cursor, ContactRepository.LABEL_COLUMN);
String labelText = ContactsContract.CommonDataKinds.Phone.getTypeLabel(getContext().getResources(),
numberType, label).toString();
boolean isPush = (contactType & ContactRepository.PUSH_TYPE) > 0;
int color = isPush ? ContextCompat.getColor(getContext(), R.color.signal_text_primary)
: ContextCompat.getColor(getContext(), R.color.signal_inverse_transparent_60);
boolean currentContact = currentContacts.contains(id);
viewHolder.unbind(glideRequests);
viewHolder.bind(glideRequests, id, contactType, name, number, labelText, about, color, multiSelect || currentContact);
viewHolder.bind(glideRequests, id, contactType, name, number, labelText, about, multiSelect || currentContact);
viewHolder.setEnabled(true);
if (currentContact) {
@ -234,6 +261,54 @@ public class ContactSelectionListAdapter extends CursorRecyclerViewAdapter<ViewH
} else {
viewHolder.setChecked(selectedContacts.contains(SelectedContact.forPhone(id, number)));
}
if (isContactRow(contactType)) {
int position = cursor.getPosition();
if (position == 0) {
viewHolder.setLetterHeaderCharacter(getHeaderLetterForDisplayName(cursor));
} else {
cursor.moveToPrevious();
int previousRowContactType = CursorUtil.requireInt(cursor, ContactRepository.CONTACT_TYPE_COLUMN);
if (!isContactRow(previousRowContactType)) {
cursor.moveToNext();
viewHolder.setLetterHeaderCharacter(getHeaderLetterForDisplayName(cursor));
} else {
String previousHeaderLetter = getHeaderLetterForDisplayName(cursor);
cursor.moveToNext();
String newHeaderLetter = getHeaderLetterForDisplayName(cursor);
if (Objects.equals(previousHeaderLetter, newHeaderLetter)) {
viewHolder.setLetterHeaderCharacter(null);
} else {
viewHolder.setLetterHeaderCharacter(newHeaderLetter);
}
}
}
}
}
private boolean isContactRow(int contactType) {
return (contactType & (ContactRepository.NEW_PHONE_TYPE | ContactRepository.NEW_USERNAME_TYPE | ContactRepository.DIVIDER_TYPE)) == 0;
}
private @Nullable String getHeaderLetterForDisplayName(@NonNull Cursor cursor) {
String name = CursorUtil.requireString(cursor, ContactRepository.NAME_COLUMN);
Iterator<String> characterIterator = new CharacterIterable(name).iterator();
if (!TextUtils.isEmpty(name) && characterIterator.hasNext()) {
String next = characterIterator.next();
if (Character.isLetter(next.codePointAt(0))) {
return next.toUpperCase();
} else {
return "#";
}
} else {
return null;
}
}
@Override
@ -250,12 +325,12 @@ public class ContactSelectionListAdapter extends CursorRecyclerViewAdapter<ViewH
viewHolder.setEnabled(true);
if (currentContacts.contains(id)) {
viewHolder.setChecked(true);
viewHolder.animateChecked(true);
viewHolder.setEnabled(false);
} else if (numberType == ContactRepository.NEW_USERNAME_TYPE) {
viewHolder.setChecked(selectedContacts.contains(SelectedContact.forUsername(id, number)));
viewHolder.animateChecked(selectedContacts.contains(SelectedContact.forUsername(id, number)));
} else {
viewHolder.setChecked(selectedContacts.contains(SelectedContact.forPhone(id, number)));
viewHolder.animateChecked(selectedContacts.contains(SelectedContact.forPhone(id, number)));
}
}
@ -275,7 +350,7 @@ public class ContactSelectionListAdapter extends CursorRecyclerViewAdapter<ViewH
@Override
public void onBindHeaderViewHolder(HeaderViewHolder viewHolder, int position, int type) {
((TextView)viewHolder.itemView).setText(getSpannedHeaderString(position));
((TextView) viewHolder.itemView).setText(getSpannedHeaderString(position));
}
@Override
@ -301,6 +376,10 @@ public class ContactSelectionListAdapter extends CursorRecyclerViewAdapter<ViewH
return selectedContacts.size();
}
public int getCurrentContactsCount() {
return currentContacts.size();
}
private CharSequence getSpannedHeaderString(int position) {
final String headerString = getHeaderString(position);
if (isPush(position)) {

Wyświetl plik

@ -34,6 +34,7 @@ public class ContactSelectionListItem extends LinearLayout implements RecipientF
private FromTextView nameView;
private TextView labelView;
private CheckBox checkBox;
private View smsTag;
private String number;
private String chipName;
@ -61,6 +62,7 @@ public class ContactSelectionListItem extends LinearLayout implements RecipientF
this.labelView = findViewById(R.id.label);
this.nameView = findViewById(R.id.name);
this.checkBox = findViewById(R.id.check_box);
this.smsTag = findViewById(R.id.sms_tag);
ViewUtil.setTextViewGravityStart(this.nameView, getContext());
}
@ -72,7 +74,6 @@ public class ContactSelectionListItem extends LinearLayout implements RecipientF
String number,
String label,
String about,
int color,
boolean checkboxVisible)
{
this.glideRequests = glideRequests;
@ -92,10 +93,15 @@ public class ContactSelectionListItem extends LinearLayout implements RecipientF
name = this.recipient.get().getDisplayName(getContext());
}
boolean isPush = (contactType & ContactRepository.PUSH_TYPE) > 0;
if (isPush) {
smsTag.setVisibility(GONE);
} else {
smsTag.setVisibility(VISIBLE);
}
Recipient recipientSnapshot = recipient != null ? recipient.get() : null;
this.nameView.setTextColor(color);
this.numberView.setTextColor(color);
if (recipientSnapshot == null || recipientSnapshot.isResolving()) {
this.contactPhotoImage.setAvatar(glideRequests, null, false);
setText(null, type, name, number, label, about);
@ -107,8 +113,20 @@ public class ContactSelectionListItem extends LinearLayout implements RecipientF
this.checkBox.setVisibility(checkboxVisible ? View.VISIBLE : View.GONE);
}
public void setChecked(boolean selected) {
this.checkBox.setChecked(selected);
public void setChecked(boolean selected, boolean animate) {
boolean wasSelected = checkBox.isChecked();
if (wasSelected != selected) {
checkBox.setChecked(selected);
float alpha = selected ? 1f : 0f;
if (animate) {
checkBox.animate().setDuration(250L).alpha(alpha);
} else {
checkBox.animate().cancel();
checkBox.setAlpha(alpha);
}
}
}
@Override
@ -146,7 +164,7 @@ public class ContactSelectionListItem extends LinearLayout implements RecipientF
} else {
this.numberView.setText(!Util.isEmpty(about) ? about : number);
this.nameView.setEnabled(true);
this.labelView.setText(label != null && !label.equals("null") ? label : "");
this.labelView.setText(label != null && !label.equals("null") ? getResources().getString(R.string.ContactSelectionListItem__dot_s, label) : "");
this.labelView.setVisibility(View.VISIBLE);
}

Wyświetl plik

@ -16,7 +16,6 @@
*/
package org.thoughtcrime.securesms.contacts;
import android.Manifest;
import android.content.Context;
import android.database.Cursor;
import android.database.MatrixCursor;
@ -30,7 +29,6 @@ import org.thoughtcrime.securesms.database.GroupDatabase;
import org.thoughtcrime.securesms.database.RecipientDatabase;
import org.thoughtcrime.securesms.database.ThreadDatabase;
import org.thoughtcrime.securesms.database.model.ThreadRecord;
import org.thoughtcrime.securesms.permissions.Permissions;
import org.thoughtcrime.securesms.phonenumbers.NumberUtil;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.RecipientId;
@ -126,7 +124,9 @@ public class ContactsCursorLoader extends AbstractContactsCursorLoader {
List<Cursor> contacts = getContactsCursors();
if (!isCursorListEmpty(contacts)) {
cursorList.add(ContactsCursorRows.forContactsHeader(getContext()));
if (!getFilter().isEmpty() || recents) {
cursorList.add(ContactsCursorRows.forContactsHeader(getContext()));
}
cursorList.addAll(contacts);
}
}
@ -195,19 +195,14 @@ public class ContactsCursorLoader extends AbstractContactsCursorLoader {
private List<Cursor> getContactsCursors() {
List<Cursor> cursorList = new ArrayList<>(2);
if (!Permissions.hasAny(getContext(), Manifest.permission.READ_CONTACTS, Manifest.permission.WRITE_CONTACTS)) {
return cursorList;
}
if (pushEnabled(mode)) {
cursorList.add(contactRepository.querySignalContacts(getFilter(), selfEnabled(mode)));
}
if (pushEnabled(mode) && smsEnabled(mode)) {
cursorList.add(contactRepository.queryNonSignalContacts(getFilter()));
cursorList.add(contactRepository.queryNonGroupContacts(getFilter(), selfEnabled(mode)));
} else if (pushEnabled(mode)) {
cursorList.add(contactRepository.querySignalContacts(getFilter(), selfEnabled(mode)));
} else if (smsEnabled(mode)) {
cursorList.add(filterNonPushContacts(contactRepository.queryNonSignalContacts(getFilter())));
cursorList.add(contactRepository.queryNonSignalContacts(getFilter()));
}
return cursorList;
}
@ -240,25 +235,6 @@ public class ContactsCursorLoader extends AbstractContactsCursorLoader {
}
}
private @NonNull Cursor filterNonPushContacts(@NonNull Cursor cursor) {
try {
final long startMillis = System.currentTimeMillis();
final MatrixCursor matrix = ContactsCursorRows.createMatrixCursor();
while (cursor.moveToNext()) {
final RecipientId id = RecipientId.from(cursor.getLong(cursor.getColumnIndexOrThrow(ContactRepository.ID_COLUMN)));
final Recipient recipient = Recipient.resolved(id);
if (recipient.resolve().getRegistered() != RecipientDatabase.RegisteredState.REGISTERED) {
matrix.addRow(ContactsCursorRows.forNonPushContact(cursor));
}
}
Log.i(TAG, "filterNonPushContacts() -> " + (System.currentTimeMillis() - startMillis) + "ms");
return matrix;
} finally {
cursor.close();
}
}
private static boolean isCursorListEmpty(List<Cursor> list) {
int sum = 0;
for (Cursor cursor : list) {

Wyświetl plik

@ -0,0 +1,86 @@
package org.thoughtcrime.securesms.contacts
import android.content.Context
import android.graphics.Canvas
import android.graphics.Paint
import android.graphics.Rect
import android.graphics.Typeface
import android.view.LayoutInflater
import android.view.View
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.RecyclerView
import org.thoughtcrime.securesms.R
import org.thoughtcrime.securesms.util.ViewUtil
/**
* ItemDecoration which paints a letter header at the appropriate location above a LetterHeaderItem.
*/
class LetterHeaderDecoration(private val context: Context, private val hideDecoration: () -> Boolean) : RecyclerView.ItemDecoration() {
private val textBounds = Rect()
private val bounds = Rect()
private val padTop = ViewUtil.dpToPx(16)
private val padStart = context.resources.getDimensionPixelSize(R.dimen.dsl_settings_gutter)
private var dividerHeight = -1
private val textPaint = Paint().apply {
color = ContextCompat.getColor(context, R.color.signal_text_primary)
isAntiAlias = true
style = Paint.Style.FILL
typeface = Typeface.create("sans-serif-medium", Typeface.BOLD)
textAlign = Paint.Align.LEFT
textSize = ViewUtil.spToPx(16f).toFloat()
}
override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State) {
val viewHolder = parent.getChildViewHolder(view)
if (hideDecoration() || viewHolder !is LetterHeaderItem || viewHolder.getHeaderLetter() == null) {
outRect.set(0, 0, 0, 0)
return
}
if (dividerHeight == -1) {
val v = LayoutInflater.from(context).inflate(R.layout.dsl_section_header, parent, false)
v.measure(0, 0)
dividerHeight = v.measuredHeight
}
outRect.set(0, dividerHeight, 0, 0)
}
override fun onDrawOver(canvas: Canvas, parent: RecyclerView, state: RecyclerView.State) {
if (hideDecoration()) {
return
}
val childCount = parent.childCount
val isRtl = parent.layoutDirection == View.LAYOUT_DIRECTION_RTL
for (i in 0 until childCount) {
val child = parent.getChildAt(i)
val holder = parent.getChildViewHolder(child)
val headerLetter = if (holder is LetterHeaderItem) holder.getHeaderLetter() else null
if (headerLetter != null) {
parent.getDecoratedBoundsWithMargins(child, bounds)
textPaint.getTextBounds(headerLetter, 0, headerLetter.length, textBounds)
val x = if (isRtl) getLayoutBoundsRTL() else getLayoutBoundsLTR()
val y = bounds.top + padTop - textBounds.top
canvas.save()
canvas.drawText(headerLetter, x.toFloat(), y.toFloat(), textPaint)
canvas.restore()
}
}
}
private fun getLayoutBoundsLTR() = bounds.left + padStart
private fun getLayoutBoundsRTL() = bounds.right - padStart - textBounds.width()
interface LetterHeaderItem {
fun getHeaderLetter(): String?
}
}

Wyświetl plik

@ -186,7 +186,7 @@ public class RecipientDatabase extends Database {
};
private static final String[] ID_PROJECTION = new String[]{ID};
private static final String[] SEARCH_PROJECTION = new String[]{ID, SYSTEM_JOINED_NAME, PHONE, EMAIL, SYSTEM_PHONE_LABEL, SYSTEM_PHONE_TYPE, REGISTERED, ABOUT, ABOUT_EMOJI, EXTRAS, GROUPS_IN_COMMON, "COALESCE(" + nullIfEmpty(PROFILE_JOINED_NAME) + ", " + nullIfEmpty(PROFILE_GIVEN_NAME) + ") AS " + SEARCH_PROFILE_NAME, "COALESCE(" + nullIfEmpty(SYSTEM_JOINED_NAME) + ", " + nullIfEmpty(SYSTEM_GIVEN_NAME) + ", " + nullIfEmpty(PROFILE_JOINED_NAME) + ", " + nullIfEmpty(PROFILE_GIVEN_NAME) + ", " + nullIfEmpty(USERNAME) + ") AS " + SORT_NAME};
private static final String[] SEARCH_PROJECTION = new String[]{ID, SYSTEM_JOINED_NAME, PHONE, EMAIL, SYSTEM_PHONE_LABEL, SYSTEM_PHONE_TYPE, REGISTERED, ABOUT, ABOUT_EMOJI, EXTRAS, GROUPS_IN_COMMON, "COALESCE(" + nullIfEmpty(PROFILE_JOINED_NAME) + ", " + nullIfEmpty(PROFILE_GIVEN_NAME) + ") AS " + SEARCH_PROFILE_NAME, "LOWER(COALESCE(" + nullIfEmpty(SYSTEM_JOINED_NAME) + ", " + nullIfEmpty(SYSTEM_GIVEN_NAME) + ", " + nullIfEmpty(PROFILE_JOINED_NAME) + ", " + nullIfEmpty(PROFILE_GIVEN_NAME) + ", " + nullIfEmpty(USERNAME) + ")) AS " + SORT_NAME};
public static final String[] SEARCH_PROJECTION_NAMES = new String[]{ID, SYSTEM_JOINED_NAME, PHONE, EMAIL, SYSTEM_PHONE_LABEL, SYSTEM_PHONE_TYPE, REGISTERED, ABOUT, ABOUT_EMOJI, EXTRAS, GROUPS_IN_COMMON, SEARCH_PROFILE_NAME, SORT_NAME};
private static final String[] TYPED_RECIPIENT_PROJECTION = Stream.of(RECIPIENT_PROJECTION)
.map(columnName -> TABLE_NAME + "." + columnName)
@ -2392,6 +2392,50 @@ public class RecipientDatabase extends Database {
return databaseHelper.getReadableDatabase().query(TABLE_NAME, SEARCH_PROJECTION, selection, args, null, null, orderBy);
}
public @Nullable Cursor getNonGroupContacts(boolean includeSelf) {
String selection = BLOCKED + " = ? AND " +
GROUP_ID + " IS NULL AND " +
"(" + SYSTEM_JOINED_NAME + " NOT NULL OR " + PROFILE_SHARING + " = ?) AND " +
"(" + SORT_NAME + " NOT NULL OR " + USERNAME + " NOT NULL)";
String[] args;
if (includeSelf) {
args = SqlUtil.buildArgs("0", "1");
} else {
selection += " AND " + ID + " != ?";
args = SqlUtil.buildArgs("0", "1", Recipient.self().getId().serialize());
}
String orderBy = SORT_NAME + ", " + SYSTEM_JOINED_NAME + ", " + SEARCH_PROFILE_NAME + ", " + USERNAME + ", " + PHONE;
return databaseHelper.getReadableDatabase().query(TABLE_NAME, SEARCH_PROJECTION, selection, args, null, null, orderBy);
}
public @Nullable Cursor queryNonGroupContacts(@NonNull String query, boolean includeSelf) {
query = buildCaseInsensitiveGlobPattern(query);
String selection = BLOCKED + " = ? AND " +
GROUP_ID + " IS NULL AND " +
"(" + SYSTEM_JOINED_NAME + " NOT NULL OR " + PROFILE_SHARING + " = ?) AND " +
"(" +
PHONE + " GLOB ? OR " +
SORT_NAME + " GLOB ? OR " +
USERNAME + " GLOB ?" +
")";
String[] args;
if (includeSelf) {
args = SqlUtil.buildArgs("0", "1", query, query, query);
} else {
selection += " AND " + ID + " != ?";
args = SqlUtil.buildArgs("0", "1", query, query, query, Recipient.self().getId().toLong());
}
String orderBy = SORT_NAME + ", " + SYSTEM_JOINED_NAME + ", " + SEARCH_PROFILE_NAME + ", " + PHONE;
return databaseHelper.getReadableDatabase().query(TABLE_NAME, SEARCH_PROJECTION, selection, args, null, null, orderBy);
}
public @Nullable Cursor queryAllContacts(@NonNull String query) {
query = buildCaseInsensitiveGlobPattern(query);
@ -2402,7 +2446,7 @@ public class RecipientDatabase extends Database {
PHONE + " GLOB ? OR " +
EMAIL + " GLOB ?" +
")";
String[] args = new String[] { "0", query, query, query, query };
String[] args = SqlUtil.buildArgs("0", query, query, query, query);
return databaseHelper.getReadableDatabase().query(TABLE_NAME, SEARCH_PROJECTION, selection, args, null, null, null);
}

Wyświetl plik

@ -14,7 +14,6 @@ import org.thoughtcrime.securesms.ContactSelectionActivity;
import org.thoughtcrime.securesms.ContactSelectionListFragment;
import org.thoughtcrime.securesms.PushContactSelectionActivity;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.contacts.ContactsCursorLoader;
import org.thoughtcrime.securesms.groups.GroupId;
import org.thoughtcrime.securesms.groups.SelectionLimits;
import org.thoughtcrime.securesms.recipients.Recipient;
@ -83,7 +82,7 @@ public class AddMembersActivity extends PushContactSelectionActivity {
}
if (contactsFragment.hasQueryFilter()) {
getToolbar().clear();
getContactFilterView().clear();
}
enableDone();
@ -94,7 +93,7 @@ public class AddMembersActivity extends PushContactSelectionActivity {
@Override
public void onContactDeselected(Optional<RecipientId> recipientId, String number) {
if (contactsFragment.hasQueryFilter()) {
getToolbar().clear();
getContactFilterView().clear();
}
if (contactsFragment.getSelectedContactsCount() < 1) {
@ -102,6 +101,16 @@ public class AddMembersActivity extends PushContactSelectionActivity {
}
}
@Override
public void onSelectionChanged() {
int selectedContactsCount = contactsFragment.getTotalMemberCount() + 1;
if (selectedContactsCount == 0) {
getToolbar().setTitle(getString(R.string.AddMembersActivity__add_members));
} else {
getToolbar().setTitle(getResources().getQuantityString(R.plurals.CreateGroupActivity__d_members, selectedContactsCount, selectedContactsCount));
}
}
private void enableDone() {
done.setEnabled(true);
done.animate().alpha(1f);

Wyświetl plik

@ -64,7 +64,7 @@ public final class AddToGroupsActivity extends ContactSelectionActivity {
next = findViewById(R.id.next);
getToolbar().setHint(contactsFragment.isMulti() ? R.string.AddToGroupActivity_add_to_groups : R.string.AddToGroupActivity_add_to_group);
getContactFilterView().setHint(contactsFragment.isMulti() ? R.string.AddToGroupActivity_add_to_groups : R.string.AddToGroupActivity_add_to_group);
next.setVisibility(contactsFragment.isMulti() ? View.VISIBLE : View.GONE);
@ -134,7 +134,7 @@ public final class AddToGroupsActivity extends ContactSelectionActivity {
@Override
public void onContactDeselected(Optional<RecipientId> recipientId, String number) {
if (contactsFragment.hasQueryFilter()) {
getToolbar().clear();
getContactFilterView().clear();
}
if (contactsFragment.getSelectedContactsCount() < MINIMUM_GROUP_SELECT_SIZE) {
@ -142,6 +142,10 @@ public final class AddToGroupsActivity extends ContactSelectionActivity {
}
}
@Override
public void onSelectionChanged() {
}
private void enableNext() {
next.setEnabled(true);
next.animate().alpha(1f);

Wyświetl plik

@ -22,7 +22,6 @@ import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.contacts.ContactsCursorLoader;
import org.thoughtcrime.securesms.contacts.sync.DirectoryHelper;
import org.thoughtcrime.securesms.database.RecipientDatabase;
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
import org.thoughtcrime.securesms.groups.GroupsV2CapabilityChecker;
import org.thoughtcrime.securesms.groups.ui.creategroup.details.AddGroupDetailsActivity;
import org.thoughtcrime.securesms.keyvalue.SignalStore;
@ -100,7 +99,7 @@ public class CreateGroupActivity extends ContactSelectionActivity {
@Override
public boolean onBeforeContactSelected(Optional<RecipientId> recipientId, String number) {
if (contactsFragment.hasQueryFilter()) {
getToolbar().clear();
getContactFilterView().clear();
}
shrinkSkip();
@ -111,7 +110,7 @@ public class CreateGroupActivity extends ContactSelectionActivity {
@Override
public void onContactDeselected(Optional<RecipientId> recipientId, String number) {
if (contactsFragment.hasQueryFilter()) {
getToolbar().clear();
getContactFilterView().clear();
}
if (contactsFragment.getSelectedContactsCount() == 0) {
@ -119,6 +118,16 @@ public class CreateGroupActivity extends ContactSelectionActivity {
}
}
@Override
public void onSelectionChanged() {
int selectedContactsCount = contactsFragment.getTotalMemberCount();
if (selectedContactsCount == 0) {
getToolbar().setTitle(getString(R.string.CreateGroupActivity__select_members));
} else {
getToolbar().setTitle(getResources().getQuantityString(R.plurals.CreateGroupActivity__d_members, selectedContactsCount, selectedContactsCount));
}
}
private void extendSkip() {
next.setIconGravity(MaterialButton.ICON_GRAVITY_END);
next.extend();

Wyświetl plik

@ -5,6 +5,7 @@ import android.view.View;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.Toolbar;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentTransaction;
import androidx.navigation.Navigation;
@ -12,7 +13,7 @@ import androidx.navigation.Navigation;
import org.thoughtcrime.securesms.ContactSelectionListFragment;
import org.thoughtcrime.securesms.LoggingFragment;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.components.ContactFilterToolbar;
import org.thoughtcrime.securesms.components.ContactFilterView;
import org.thoughtcrime.securesms.contacts.ContactsCursorLoader.DisplayMode;
import org.thoughtcrime.securesms.conversation.ConversationIntents;
import org.thoughtcrime.securesms.database.DatabaseFactory;
@ -27,7 +28,8 @@ import org.whispersystems.libsignal.util.guava.Optional;
public class PaymentRecipientSelectionFragment extends LoggingFragment implements ContactSelectionListFragment.OnContactSelectedListener, ContactSelectionListFragment.ScrollCallback {
private ContactFilterToolbar toolbar;
private Toolbar toolbar;
private ContactFilterView contactFilterView;
private ContactSelectionListFragment contactsFragment;
public PaymentRecipientSelectionFragment() {
@ -39,6 +41,8 @@ public class PaymentRecipientSelectionFragment extends LoggingFragment implement
toolbar = view.findViewById(R.id.payment_recipient_selection_fragment_toolbar);
toolbar.setNavigationOnClickListener(v -> Navigation.findNavController(v).popBackStack());
contactFilterView = view.findViewById(R.id.contact_filter_edit_text);
Bundle arguments = new Bundle();
arguments.putBoolean(ContactSelectionListFragment.REFRESHABLE, false);
arguments.putInt(ContactSelectionListFragment.DISPLAY_MODE, DisplayMode.FLAG_PUSH | DisplayMode.FLAG_HIDE_NEW);
@ -59,7 +63,7 @@ public class PaymentRecipientSelectionFragment extends LoggingFragment implement
}
private void initializeSearch() {
toolbar.setOnFilterChangedListener(filter -> contactsFragment.setQueryFilter(filter));
contactFilterView.setOnFilterChangedListener(filter -> contactsFragment.setQueryFilter(filter));
}
@Override
@ -76,6 +80,10 @@ public class PaymentRecipientSelectionFragment extends LoggingFragment implement
@Override
public void onContactDeselected(@NonNull Optional<RecipientId> recipientId, @Nullable String number) { }
@Override
public void onSelectionChanged() {
}
@Override
public void onBeginScroll() {
hideKeyboard();

Wyświetl plik

@ -190,6 +190,10 @@ public class ShareActivity extends PassphraseRequiredActivity
viewModel.onContactDeselected(new ShareContact(recipientId, number));
}
@Override
public void onSelectionChanged() {
}
private void animateInSelection() {
contactsRecyclerDivider.animate()
.alpha(1f)

Wyświetl plik

@ -59,6 +59,13 @@ public class RecyclerViewConcatenateAdapter extends RecyclerView.Adapter<Recycle
mergeAdapter.notifyDataSetChanged();
}
@Override
public void onItemRangeChanged(int positionStart, int itemCount, Object payload) {
int subAdapterOffset = mergeAdapter.getSubAdapterFirstGlobalPosition(adapter);
mergeAdapter.notifyItemRangeChanged(subAdapterOffset + positionStart, itemCount, payload);
}
@Override
public void onItemRangeChanged(int positionStart, int itemCount) {
int subAdapterOffset = mergeAdapter.getSubAdapterFirstGlobalPosition(adapter);
@ -248,6 +255,14 @@ public class RecyclerViewConcatenateAdapter extends RecyclerView.Adapter<Recycle
throw new AssertionError("Adapter not found in list of adapters");
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position, @NonNull List<Object> payloads) {
ChildAdapterPositionPair childAdapterPositionPair = getLocalPosition(position);
RecyclerView.Adapter adapter = childAdapterPositionPair.getAdapter();
//noinspection unchecked
adapter.onBindViewHolder(holder, childAdapterPositionPair.localPosition, payloads);
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int position) {
ChildAdapterPositionPair childAdapterPositionPair = getLocalPosition(position);

Wyświetl plik

@ -5,7 +5,7 @@
<item>
<shape android:shape="oval">
<solid android:color="@color/core_grey_75" />
<stroke android:width="1dp" android:color="@color/white" />
<stroke android:width="2dp" android:color="@color/signal_background_primary" />
</shape>
</item>
<item android:drawable="@drawable/ic_check_outline_22" />
@ -16,7 +16,7 @@
<item>
<shape android:shape="oval">
<solid android:color="@color/core_ultramarine_light" />
<stroke android:width="1dp" android:color="@color/white" />
<stroke android:width="2dp" android:color="@color/signal_background_primary" />
</shape>
</item>
<item android:drawable="@drawable/ic_check_outline_22" />

Wyświetl plik

@ -7,7 +7,7 @@
</item>
<item
android:bottom="10dp"
android:drawable="@drawable/ic_invite_ultramarine_28"
android:drawable="@drawable/ic_invite_inverse_28"
android:left="10dp"
android:right="10dp"
android:top="10dp" />

Wyświetl plik

@ -7,7 +7,7 @@
</item>
<item
android:bottom="10dp"
android:drawable="@drawable/ic_group_outline_ultramarine_28"
android:drawable="@drawable/ic_group_outline_new_28"
android:left="10dp"
android:right="10dp"
android:top="10dp" />

Wyświetl plik

@ -5,7 +5,7 @@
<item>
<shape android:shape="oval">
<solid android:color="@color/core_grey_25" />
<stroke android:width="1dp" android:color="@color/white" />
<stroke android:width="2dp" android:color="@color/white" />
</shape>
</item>
<item android:drawable="@drawable/ic_check_outline_22" />
@ -16,7 +16,7 @@
<item>
<shape android:shape="oval">
<solid android:color="@color/core_ultramarine" />
<stroke android:width="1dp" android:color="@color/white" />
<stroke android:width="2dp" android:color="@color/white" />
</shape>
</item>
<item android:drawable="@drawable/ic_check_outline_22" />

Wyświetl plik

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="@color/signal_inverse_primary" />
<size android:height="10dp" />
<corners android:radius="2dp" />
</shape>

Wyświetl plik

@ -4,6 +4,6 @@
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@color/core_ultramarine"
android:fillColor="@color/signal_inverse_primary"
android:pathData="M19.513,9.942a4.25,4.25 0,1 0,-6.538 -0.013,4.749 4.749,0 0,0 -1.336,0.618 4.242,4.242 0,1 0,-7.152 4.395A4.744,4.744 0,0 0,1 19.5L1,21L2.5,21L2.5,19.5a3.254,3.254 0,0 1,3.25 -3.25h4A3.254,3.254 0,0 1,13 19.5L13,21h1.5L14.5,19.5a4.744,4.744 0,0 0,-3.487 -4.558A4.21,4.21 0,0 0,12 12.25c0,-0.029 -0.008,-0.055 -0.008,-0.083a3.259,3.259 0,0 1,2.258 -0.917h4A3.254,3.254 0,0 1,21.5 14.5L21.5,16L23,16L23,14.5A4.744,4.744 0,0 0,19.513 9.942ZM7.75,15a2.75,2.75 0,1 1,2.75 -2.75A2.75,2.75 0,0 1,7.75 15ZM16.25,10A2.75,2.75 0,1 1,19 7.25,2.75 2.75,0 0,1 16.25,10Z" />
</vector>

Wyświetl plik

@ -7,7 +7,7 @@
</item>
<item
android:bottom="10dp"
android:drawable="@drawable/ic_invite_ultramarine_28"
android:drawable="@drawable/ic_invite_inverse_28"
android:left="10dp"
android:right="10dp"
android:top="10dp" />

Wyświetl plik

@ -4,19 +4,19 @@
android:viewportWidth="28"
android:viewportHeight="28">
<path
android:fillColor="@color/core_ultramarine"
android:fillColor="@color/signal_inverse_primary"
android:fillType="evenOdd"
android:pathData="M14,2c7.429,0 13,4.875 13,11.143A10.3,10.3 0,0 1,23.791 20.6l0.662,4.47c0,0.012 0,0.024 0,0.035a0.348,0.348 0,0 1,-0.348 0.349,0.377 0.377,0 0,1 -0.113,-0.02l-0.059,-0.028 -4.547,-2.064A15.4,15.4 0,0 1,14 24.286c-7.429,0 -13,-4.875 -13,-11.143S6.571,2 14,2m0,1.5C7.444,3.5 2.5,7.646 2.5,13.143S7.444,22.786 14,22.786a13.872,13.872 0,0 0,4.864 -0.849l0.58,-0.217 0.565,0.256 2.647,1.2 -0.349,-2.359 -0.113,-0.76 0.552,-0.536a8.743,8.743 0,0 0,2.754 -6.38C25.5,7.646 20.556,3.5 14,3.5" />
<path
android:fillColor="@color/core_ultramarine"
android:fillColor="@color/signal_inverse_primary"
android:fillType="evenOdd"
android:pathData="M20,12a1.5,1.5 0,1 1,-1.5 1.5A1.5,1.5 0,0 1,20 12" />
<path
android:fillColor="@color/core_ultramarine"
android:fillColor="@color/signal_inverse_primary"
android:fillType="evenOdd"
android:pathData="M14,12a1.5,1.5 0,1 1,-1.5 1.5A1.5,1.5 0,0 1,14 12" />
<path
android:fillColor="@color/core_ultramarine"
android:fillColor="@color/signal_inverse_primary"
android:fillType="evenOdd"
android:pathData="M8,12a1.5,1.5 0,1 1,-1.5 1.5A1.5,1.5 0,0 1,8 12" />
</vector>

Wyświetl plik

@ -6,9 +6,9 @@
</shape>
</item>
<item
android:bottom="10dp"
android:drawable="@drawable/ic_group_outline_ultramarine_28"
android:left="10dp"
android:right="10dp"
android:top="10dp" />
android:bottom="12dp"
android:drawable="@drawable/ic_group_outline_new_28"
android:left="12dp"
android:right="12dp"
android:top="12dp" />
</layer-list>

Wyświetl plik

@ -4,6 +4,6 @@
android:topRightRadius="44dp"
android:bottomLeftRadius="44dp"
android:bottomRightRadius="0dp"/>
<solid android:color="#FF0288D1" />
<solid android:color="@color/signal_accent_primary" />
<size android:height="88dp" android:width="88dp" />
</shape>

Wyświetl plik

@ -3,14 +3,14 @@
<item android:state_selected="true">
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<corners android:radius="2dp"/>
<solid android:color="#FF0288D1"/>
<solid android:color="@color/signal_accent_primary"/>
<size android:height="32dp" android:width="4dp"/>
</shape>
</item>
<item>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<corners android:radius="2dp"/>
<solid android:color="#FF737373"/>
<solid android:color="@color/signal_inverse_primary"/>
<size android:height="32dp" android:width="4dp"/>
</shape>
</item>

Wyświetl plik

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" >
<solid android:color="@color/signal_background_secondary"/>
<corners android:radius="30dp"/>
</shape>

Wyświetl plik

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<size android:width="2dp" />
<solid android:color="@color/signal_text_primary" />
</shape>

Wyświetl plik

@ -10,15 +10,27 @@
android:layout_gravity="center"
android:orientation="vertical">
<org.thoughtcrime.securesms.components.ContactFilterToolbar
<org.thoughtcrime.securesms.util.views.DarkOverflowToolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:elevation="4dp"
android:minHeight="?attr/actionBarSize"
android:theme="?attr/actionBarStyle"
app:contentInsetStartWithNavigation="0dp"
app:navigationIcon="@drawable/ic_arrow_left_24" />
android:layout_height="56dp"
android:theme="?attr/settingsToolbarStyle"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:navigationIcon="@drawable/ic_arrow_left_24"
app:titleTextAppearance="@style/Signal.Text.Title"
app:title="@string/AddMembersActivity__add_members" />
<org.thoughtcrime.securesms.components.ContactFilterView
android:id="@+id/contact_filter_edit_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/dsl_settings_gutter"
android:layout_marginTop="4dp"
android:layout_marginBottom="12dp"
android:layout_marginRight="@dimen/dsl_settings_gutter"
android:minHeight="44dp" />
<fragment
android:id="@+id/contact_selection_list_fragment"

Wyświetl plik

@ -7,27 +7,38 @@
android:layout_gravity="center"
android:orientation="vertical">
<org.thoughtcrime.securesms.components.ContactFilterToolbar
<org.thoughtcrime.securesms.util.views.DarkOverflowToolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:elevation="4dp"
android:minHeight="?attr/actionBarSize"
android:theme="?attr/actionBarStyle"
app:contentInsetStartWithNavigation="0dp"
android:layout_height="56dp"
android:theme="?attr/settingsToolbarStyle"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:navigationIcon="@drawable/ic_arrow_left_24"
app:showDialpad="false" />
app:title="@string/AddToGroupActivity_add_to_a_group"
app:titleTextAppearance="@style/Signal.Text.Title" />
<org.thoughtcrime.securesms.components.ContactFilterView
android:id="@+id/contact_filter_edit_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/dsl_settings_gutter"
android:layout_marginTop="4dp"
android:layout_marginRight="@dimen/dsl_settings_gutter"
android:minHeight="44dp"
app:layout_constraintTop_toBottomOf="@id/toolbar" />
<fragment
android:id="@+id/contact_selection_list_fragment"
android:name="org.thoughtcrime.securesms.ContactSelectionListFragment"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginTop="12dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/toolbar" />
app:layout_constraintTop_toBottomOf="@id/contact_filter_edit_text" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/next"

Wyświetl plik

@ -1,36 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ViewSwitcher
android:id="@+id/toolbar_switcher"
<org.thoughtcrime.securesms.util.views.DarkOverflowToolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="56dp"
android:theme="?attr/settingsToolbarStyle"
app:navigationIcon="@drawable/ic_arrow_left_24"
app:titleTextAppearance="@style/Signal.Text.Title"
app:title="@string/BlockedUsersActivity__blocked_users" />
<org.thoughtcrime.securesms.components.ContactFilterView
android:id="@+id/contact_filter_edit_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inAnimation="@anim/fade_in"
android:outAnimation="@anim/fade_out">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:theme="?attr/actionBarStyle"
app:navigationIcon="@drawable/ic_arrow_left_24"
app:title="@string/BlockedUsersActivity__blocked_users" />
<org.thoughtcrime.securesms.components.ContactFilterToolbar
android:id="@+id/filter_toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:elevation="4dp"
android:minHeight="?attr/actionBarSize"
android:theme="?attr/actionBarStyle"
app:contentInsetStartWithNavigation="0dp"
app:navigationIcon="@drawable/ic_arrow_left_24" />
</ViewSwitcher>
android:layout_marginLeft="@dimen/dsl_settings_gutter"
android:layout_marginTop="4dp"
android:layout_marginRight="@dimen/dsl_settings_gutter"
android:layout_marginBottom="12dp"
android:minHeight="44dp"
android:visibility="gone"
tools:visibility="visible" />
<FrameLayout
android:id="@+id/fragment_container"

Wyświetl plik

@ -1,80 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<LinearLayout android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<LinearLayout android:id="@+id/toggle_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<EditText android:id="@+id/search_view"
android:layout_height="wrap_content"
android:layout_width="0px"
android:layout_weight="1"
android:hint="@string/contact_selection_activity__enter_name_or_number"
android:inputType="textPersonName"
android:textAppearance="@style/TextSecure.TitleTextStyle"
android:background="@android:color/transparent"
android:layout_gravity="center_vertical"
android:gravity="center_vertical"
android:textCursorDrawable="@null"
android:fontFamily="sans-serif"/>
<org.thoughtcrime.securesms.components.AnimatingToggle
android:id="@+id/button_toggle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:paddingStart="10dp"
android:paddingEnd="10dp"
android:gravity="center">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/search_dialpad"
android:contentDescription="@string/contact_filter_toolbar__show_dial_pad_description"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:gravity="center_vertical"
android:clickable="true"
android:focusable="true"
android:tint="@color/signal_icon_tint_primary"
android:background="?actionBarItemBackground"
app:srcCompat="@drawable/ic_number_pad_conversation_filter_24" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/search_keyboard"
android:contentDescription="@string/contact_filter_toolbar__show_keyboard_description"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:gravity="center_vertical"
android:clickable="true"
android:visibility="gone"
android:focusable="true"
android:tint="@color/signal_icon_tint_primary"
android:background="?actionBarItemBackground"
app:srcCompat="@drawable/ic_keyboard_24" />
<ImageView android:id="@+id/search_clear"
android:contentDescription="@string/contact_filter_toolbar__clear_entered_text_description"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:gravity="center_vertical"
android:clickable="true"
android:visibility="gone"
android:background="?actionBarItemBackground"
app:srcCompat="@drawable/ic_x_conversation_filter_24" />
</org.thoughtcrime.securesms.components.AnimatingToggle>
</LinearLayout>
</LinearLayout>
</merge>

Wyświetl plik

@ -0,0 +1,84 @@
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/rounded_rectangle_secondary"
android:minHeight="44dp"
android:orientation="horizontal"
android:paddingStart="16dp"
android:paddingEnd="6dp">
<LinearLayout
android:id="@+id/toggle_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<EditText
android:id="@+id/search_view"
android:layout_width="0px"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_weight="1"
android:background="@android:color/transparent"
android:fontFamily="sans-serif"
android:gravity="center_vertical"
android:hint="@string/ContactFilterView__search_name_or_number"
android:inputType="textPersonName"
android:lineSpacingExtra="6sp"
android:textAppearance="@style/TextSecure.TitleTextStyle"
android:textColorHint="@color/signal_text_secondary"
android:textCursorDrawable="@drawable/search_cursor" />
<org.thoughtcrime.securesms.components.AnimatingToggle
android:id="@+id/button_toggle"
android:layout_width="44dp"
android:layout_height="44dp"
android:layout_gravity="center">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/search_dialpad"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:background="?actionBarItemBackground"
android:clickable="true"
android:contentDescription="@string/contact_filter_toolbar__show_dial_pad_description"
android:focusable="true"
android:tint="@color/signal_icon_tint_primary"
app:srcCompat="@drawable/ic_number_pad_conversation_filter_24" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/search_keyboard"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:background="?actionBarItemBackground"
android:clickable="true"
android:contentDescription="@string/contact_filter_toolbar__show_keyboard_description"
android:focusable="true"
android:tint="@color/signal_icon_tint_primary"
android:visibility="gone"
app:srcCompat="@drawable/ic_keyboard_24" />
<ImageView
android:id="@+id/search_clear"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:background="?actionBarItemBackground"
android:clickable="true"
android:contentDescription="@string/contact_filter_toolbar__clear_entered_text_description"
android:visibility="gone"
app:srcCompat="@drawable/ic_x_conversation_filter_24" />
</org.thoughtcrime.securesms.components.AnimatingToggle>
</LinearLayout>
</LinearLayout>
</merge>

Wyświetl plik

@ -1,24 +1,38 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout android:layout_gravity="center"
android:layout_height="fill_parent"
android:layout_width="fill_parent"
android:orientation="vertical"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_gravity="center"
android:orientation="vertical">
<org.thoughtcrime.securesms.components.ContactFilterToolbar
android:id="@+id/toolbar"
android:layout_height="?attr/actionBarSize"
android:layout_width="match_parent"
android:minHeight="?attr/actionBarSize"
android:elevation="4dp"
android:theme="?attr/actionBarStyle"
app:navigationIcon="@drawable/ic_arrow_left_24"
app:contentInsetStartWithNavigation="0dp"/>
<org.thoughtcrime.securesms.util.views.DarkOverflowToolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="56dp"
android:theme="?attr/settingsToolbarStyle"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:navigationIcon="@drawable/ic_arrow_left_24"
app:titleTextAppearance="@style/Signal.Text.Title"
app:title="@string/NewConversationActivity__new_message" />
<fragment android:id="@+id/contact_selection_list_fragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:name="org.thoughtcrime.securesms.ContactSelectionListFragment" />
<org.thoughtcrime.securesms.components.ContactFilterView
android:id="@+id/contact_filter_edit_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/dsl_settings_gutter"
android:layout_marginTop="4dp"
android:layout_marginRight="@dimen/dsl_settings_gutter"
android:layout_marginBottom="12dp"
android:minHeight="44dp" />
<fragment
android:id="@+id/contact_selection_list_fragment"
android:name="org.thoughtcrime.securesms.ContactSelectionListFragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>

Wyświetl plik

@ -1,18 +1,34 @@
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
style="@style/Signal.Text.Body"
android:layout_width="match_parent"
android:layout_height="@dimen/contact_selection_item_height"
android:drawablePadding="16dp"
android:ellipsize="marquee"
android:fontFamily="sans-serif-medium"
android:gravity="center_vertical|start"
android:labelFor="@id/action_icon"
android:paddingStart="@dimen/selection_item_header_width"
android:singleLine="true"
android:text="@string/contact_selection_activity__invite_to_signal"
android:textAlignment="viewStart"
app:drawableStartCompat="@drawable/ic_invite_circle"
tools:ignore="RtlSymmetry" />
android:layout_height="wrap_content"
android:minHeight="@dimen/contact_selection_item_height"
android:paddingStart="@dimen/dsl_settings_gutter"
android:paddingEnd="@dimen/dsl_settings_gutter">
<ImageView
android:id="@+id/invite_image"
android:layout_width="40dp"
android:layout_height="40dp"
android:importantForAccessibility="no"
android:src="@drawable/ic_invite_circle"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/invite_text"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:ellipsize="marquee"
android:labelFor="@id/action_icon"
android:singleLine="true"
android:text="@string/contact_selection_activity__invite_to_signal"
android:textAppearance="@style/Signal.Text.Body"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/invite_image"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

Wyświetl plik

@ -1,14 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<org.thoughtcrime.securesms.components.emoji.EmojiTextView
xmlns:android="http://schemas.android.com/apk/res/android"
<org.thoughtcrime.securesms.components.emoji.EmojiTextView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/label"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/camera_contacts_horizontal_margin"
android:layout_marginEnd="@dimen/camera_contacts_horizontal_margin"
android:layout_marginTop="16dp"
android:layout_marginBottom="24dp"
style="@style/Signal.Text.Preview"
android:fontFamily="sans-serif-medium"
tools:text="@string/CameraContacts_recent_contacts"/>
android:minHeight="48dp"
android:paddingStart="@dimen/dsl_settings_gutter"
android:paddingTop="16dp"
android:paddingEnd="@dimen/dsl_settings_gutter"
android:paddingBottom="12dp"
android:textAppearance="@style/TextAppearance.Signal.Body1.Bold"
android:textStyle="bold"
tools:text="@string/CameraContacts_recent_contacts" />

Wyświetl plik

@ -21,6 +21,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
android:scrollbarThumbVertical="@drawable/contact_selection_scrollbar_thumb"
android:scrollbars="vertical"
tools:listitem="@layout/contact_selection_list_item" />
@ -110,53 +111,54 @@
</LinearLayout>
<org.thoughtcrime.securesms.components.emoji.WarningTextView
android:id="@+id/group_limit"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:textAppearance="@style/TextAppearance.Signal.Body2"
android:visibility="gone"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:warning_text_color="@color/core_red"
tools:text="999/999"
tools:visibility="visible" />
<HorizontalScrollView
android:id="@+id/chipGroupScrollContainer"
android:layout_width="match_parent"
android:layout_height="56dp"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:paddingBottom="8dp"
android:paddingStart="@dimen/dsl_settings_gutter"
android:paddingEnd="@dimen/dsl_settings_gutter"
android:scrollbars="none"
android:visibility="gone"
android:clipChildren="false"
android:clipToPadding="false"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/group_limit"
app:layout_constraintTop_toTopOf="parent"
tools:visibility="visible">
<com.google.android.material.chip.ChipGroup
android:id="@+id/chipGroup"
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="56dp"
android:layout_marginEnd="96dp"
android:animateLayoutChanges="true"
app:singleLine="true">
android:layout_height="match_parent">
<com.google.android.material.chip.Chip
<com.google.android.material.chip.ChipGroup
android:id="@+id/chipGroup"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"
tools:text="Example"
tools:visibility="visible" />
android:layout_gravity="center_vertical"
android:layout_marginEnd="96dp"
android:animateLayoutChanges="true"
app:singleLine="true">
</com.google.android.material.chip.ChipGroup>
<com.google.android.material.chip.Chip
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"
tools:text="Example"
tools:visibility="visible" />
</com.google.android.material.chip.ChipGroup>
</FrameLayout>
</HorizontalScrollView>
<View
android:id="@+id/toolbar_shadow"
android:layout_width="match_parent"
android:layout_height="5dp"
android:alpha="0"
android:background="@drawable/toolbar_shadow"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@id/swipe_refresh" />
</androidx.constraintlayout.widget.ConstraintLayout>

Wyświetl plik

@ -1,93 +1,107 @@
<?xml version="1.0" encoding="utf-8"?>
<org.thoughtcrime.securesms.contacts.ContactSelectionListItem xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="@dimen/contact_selection_item_height"
android:orientation="horizontal"
android:gravity="center_vertical"
android:focusable="true"
android:layout_height="wrap_content"
android:background="@drawable/conversation_item_background"
android:paddingStart="@dimen/selection_item_header_width"
android:paddingEnd="24dp">
android:focusable="true"
android:gravity="center_vertical"
android:minHeight="@dimen/contact_selection_item_height"
android:orientation="horizontal"
android:paddingStart="@dimen/dsl_settings_gutter"
android:paddingEnd="@dimen/dsl_settings_gutter">
<FrameLayout
android:layout_width="52dp"
android:layout_height="52dp">
android:layout_width="44dp"
android:layout_height="44dp"
android:layout_marginTop="2dp">
<org.thoughtcrime.securesms.components.AvatarImageView
android:id="@+id/contact_photo_image"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_gravity="center_vertical"
android:foreground="@drawable/contact_photo_background"
android:cropToPadding="true"
android:contentDescription="@string/SingleContactSelectionActivity_contact_photo"
tools:src="@color/blue_600"
tools:ignore="UnusedAttribute" />
android:cropToPadding="true"
android:foreground="@drawable/contact_photo_background"
tools:ignore="UnusedAttribute"
tools:src="@color/blue_600" />
<androidx.appcompat.widget.AppCompatCheckBox
android:id="@+id/check_box"
android:background="@drawable/contact_selection_checkbox"
android:button="@null"
android:layout_width="22dp"
android:layout_height="22dp"
android:layout_gravity="bottom|end"
android:focusable="false"
android:clickable="false" />
android:background="@drawable/contact_selection_checkbox"
android:button="@null"
android:alpha="0"
android:clickable="false"
android:focusable="false" />
</FrameLayout>
<LinearLayout android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:orientation="vertical">
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:layout_marginEnd="16dp"
android:layout_weight="1"
android:orientation="vertical">
<org.thoughtcrime.securesms.components.FromTextView
android:id="@+id/name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:checkMark="?android:attr/listChoiceIndicatorMultiple"
android:singleLine="true"
android:ellipsize="marquee"
android:textAppearance="@style/TextAppearance.Signal.Body1.Bold"
tools:text="@sample/contacts.json/data/name" />
android:id="@+id/name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:checkMark="?android:attr/listChoiceIndicatorMultiple"
android:ellipsize="marquee"
android:singleLine="true"
android:textAppearance="@style/TextAppearance.Signal.Body1"
android:textColor="@color/signal_text_primary"
tools:text="@sample/contacts.json/data/name" />
<LinearLayout android:id="@+id/number_container"
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<LinearLayout
android:id="@+id/number_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<org.thoughtcrime.securesms.components.emoji.EmojiTextView
android:id="@+id/number"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textDirection="ltr"
android:singleLine="true"
android:ellipsize="marquee"
android:textAppearance="@style/TextAppearance.Signal.Body2"
android:textColor="@color/signal_text_secondary"
android:textSize="14sp"
android:fontFamily="sans-serif-light"
app:emoji_forceCustom="true"
tools:text="@sample/contacts.json/data/number" />
android:id="@+id/number"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="marquee"
android:singleLine="true"
android:textAppearance="@style/TextAppearance.Signal.Body2"
android:textColor="@color/signal_text_secondary"
android:textDirection="ltr"
app:emoji_forceCustom="true"
tools:text="@sample/contacts.json/data/number" />
<TextView android:id="@+id/label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingStart="10dip"
android:ellipsize="end"
android:singleLine="true"
android:textAppearance="@style/TextAppearance.Signal.Body2"
android:textColor="@color/signal_text_secondary"
android:fontFamily="sans-serif-light"
tools:text="@sample/contacts.json/data/label"
tools:ignore="RtlSymmetry" />
<TextView
android:id="@+id/label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:paddingStart="4dp"
android:singleLine="true"
android:textAppearance="@style/TextAppearance.Signal.Body2"
android:textColor="@color/signal_text_secondary"
tools:ignore="RtlSymmetry"
tools:text="· Mobile" />
</LinearLayout>
</LinearLayout>
<TextView
android:id="@+id/sms_tag"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center"
android:text="@string/ContactSelectionListItem__sms"
android:textAppearance="@style/TextAppearance.Signal.Body2"
android:textColor="@color/signal_text_secondary"
android:visibility="gone" />
</org.thoughtcrime.securesms.contacts.ContactSelectionListItem>

Wyświetl plik

@ -1,18 +1,34 @@
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
style="@style/Signal.Text.Body"
android:layout_width="match_parent"
android:layout_height="@dimen/contact_selection_item_height"
android:drawablePadding="16dp"
android:ellipsize="marquee"
android:fontFamily="sans-serif-medium"
android:gravity="center_vertical|start"
android:labelFor="@id/action_icon"
android:paddingStart="@dimen/selection_item_header_width"
android:singleLine="true"
android:text="@string/contact_selection_activity__new_group"
android:textAlignment="viewStart"
app:drawableStartCompat="@drawable/ic_new_group_circle"
tools:ignore="RtlSymmetry" />
android:layout_height="wrap_content"
android:minHeight="@dimen/contact_selection_item_height"
android:paddingStart="@dimen/dsl_settings_gutter"
android:paddingEnd="@dimen/dsl_settings_gutter">
<ImageView
android:id="@+id/invite_image"
android:layout_width="40dp"
android:layout_height="40dp"
android:importantForAccessibility="no"
android:src="@drawable/ic_new_group_circle"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/invite_text"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:ellipsize="marquee"
android:labelFor="@id/action_icon"
android:singleLine="true"
android:text="@string/contact_selection_activity__new_group"
android:textAppearance="@style/Signal.Text.Body"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/invite_image"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

Wyświetl plik

@ -6,26 +6,38 @@
android:layout_gravity="center"
android:orientation="vertical">
<org.thoughtcrime.securesms.components.ContactFilterToolbar
<org.thoughtcrime.securesms.util.views.DarkOverflowToolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:elevation="4dp"
android:minHeight="?attr/actionBarSize"
android:theme="?attr/actionBarStyle"
app:contentInsetStartWithNavigation="0dp"
android:layout_height="56dp"
android:theme="?attr/settingsToolbarStyle"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:navigationIcon="@drawable/ic_arrow_left_24" />
app:navigationIcon="@drawable/ic_arrow_left_24"
app:titleTextAppearance="@style/Signal.Text.Title"
app:title="@string/CreateGroupActivity__select_members" />
<org.thoughtcrime.securesms.components.ContactFilterView
android:id="@+id/contact_filter_edit_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/dsl_settings_gutter"
android:layout_marginTop="4dp"
android:layout_marginRight="@dimen/dsl_settings_gutter"
android:minHeight="44dp"
app:layout_constraintTop_toBottomOf="@id/toolbar" />
<fragment
android:id="@+id/contact_selection_list_fragment"
android:name="org.thoughtcrime.securesms.ContactSelectionListFragment"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginTop="12dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/toolbar" />
app:layout_constraintTop_toBottomOf="@id/contact_filter_edit_text" />
<com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
android:id="@+id/next"

Wyświetl plik

@ -91,14 +91,27 @@
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@id/toolbar">
<org.thoughtcrime.securesms.components.ContactFilterToolbar
android:id="@+id/contact_filter"
android:layout_height="?attr/actionBarSize"
<org.thoughtcrime.securesms.util.views.DarkOverflowToolbar
android:id="@+id/sms_send_frame_toolbar"
android:layout_width="match_parent"
android:minHeight="?attr/actionBarSize"
android:background="@color/core_ultramarine"
android:elevation="4dp"
app:searchTextStyle="@style/TextSecure.TitleTextStyle.Light" />
android:layout_height="56dp"
android:theme="?attr/settingsToolbarStyle"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:navigationIcon="@drawable/ic_arrow_left_24"
app:title="@string/InviteActivity_invite_to_signal"
app:titleTextAppearance="@style/Signal.Text.Title" />
<org.thoughtcrime.securesms.components.ContactFilterView
android:id="@+id/contact_filter_edit_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/dsl_settings_gutter"
android:layout_marginTop="4dp"
android:layout_marginBottom="12dp"
android:layout_marginRight="@dimen/dsl_settings_gutter"
android:minHeight="44dp" />
<fragment android:id="@+id/contact_selection_list_fragment"
android:layout_width="match_parent"

Wyświetl plik

@ -10,15 +10,28 @@
android:layout_gravity="center"
android:orientation="vertical">
<org.thoughtcrime.securesms.components.ContactFilterToolbar
<org.thoughtcrime.securesms.util.views.DarkOverflowToolbar
android:id="@+id/payment_recipient_selection_fragment_toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:elevation="4dp"
android:minHeight="?attr/actionBarSize"
android:theme="?attr/actionBarStyle"
app:contentInsetStartWithNavigation="0dp"
app:navigationIcon="@drawable/ic_arrow_left_24" />
android:layout_height="56dp"
android:theme="?attr/settingsToolbarStyle"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:navigationIcon="@drawable/ic_arrow_left_24"
app:titleTextAppearance="@style/Signal.Text.Title"
app:title="@string/PaymentRecipientSelectionFragment__new_payment" />
<org.thoughtcrime.securesms.components.ContactFilterView
android:id="@+id/contact_filter_edit_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/dsl_settings_gutter"
android:layout_marginTop="4dp"
android:layout_marginBottom="12dp"
android:layout_marginRight="@dimen/dsl_settings_gutter"
android:minHeight="44dp" />
<FrameLayout
android:id="@+id/contact_selection_list_fragment_holder"

Wyświetl plik

@ -383,6 +383,7 @@
<!-- CreateGroupActivity -->
<string name="CreateGroupActivity_some_contacts_cannot_be_in_legacy_groups">Some contacts cannot be in legacy groups.</string>
<string name="CreateGroupActivity__select_members">Select members</string>
<!-- CreateProfileActivity -->
<string name="CreateProfileActivity__profile">Profile</string>
@ -513,6 +514,7 @@
<string name="AddToGroupActivity_add_to_groups">Add to groups</string>
<string name="AddToGroupActivity_this_person_cant_be_added_to_legacy_groups">This person can\'t be added to legacy groups.</string>
<string name="AddToGroupActivity_add">Add</string>
<string name="AddToGroupActivity_add_to_a_group">Add to a group</string>
<!-- ChooseNewAdminActivity -->
<string name="ChooseNewAdminActivity_choose_new_admin">Choose new admin</string>
@ -668,6 +670,7 @@
<item quantity="other">Add %3$d members to \"%2$s\"?</item>
</plurals>
<string name="AddMembersActivity__add">Add</string>
<string name="AddMembersActivity__add_members">Add members</string>
<!-- AddGroupDetailsFragment -->
<string name="AddGroupDetailsFragment__name_this_group">Name this group</string>
@ -3240,6 +3243,10 @@
<!-- CreateGroupActivity -->
<string name="CreateGroupActivity__skip">Skip</string>
<plurals name="CreateGroupActivity__d_members">
<item quantity="one">%1$d member</item>
<item quantity="other">%1$d members</item>
</plurals>
<!-- ShareActivity -->
<string name="ShareActivity__share">Share</string>
@ -3608,9 +3615,22 @@
<string name="PlaybackSpeedToggleTextView__1x">1x</string>
<string name="PlaybackSpeedToggleTextView__2x">2x</string>
<!-- PaymentRecipientSelectionFragment -->
<string name="PaymentRecipientSelectionFragment__new_payment">New payment</string>
<!-- NewConversationActivity -->
<string name="NewConversationActivity__new_message">New message</string>
<!-- ContactFilterView -->
<string name="ContactFilterView__search_name_or_number">Search name or number</string>
<!-- VoiceNotePlayerView -->
<string name="VoiceNotePlayerView__s_dot_s">%1$s · %2$s</string>
<!-- ContactSelectionListItem -->
<string name="ContactSelectionListItem__sms">SMS</string>
<string name="ContactSelectionListItem__dot_s">· %1$s</string>
<!-- EOF -->
</resources>