Old conversation list related classes removed.

This commit is contained in:
Anton Chekulaev
2020-12-07 13:30:52 +11:00
parent 8d17593d87
commit 1a498cebd8
21 changed files with 7 additions and 1793 deletions

View File

@@ -1,57 +0,0 @@
package org.thoughtcrime.securesms;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import network.loki.messenger.R;
public class BasicIntroFragment extends Fragment {
private static final String ARG_DRAWABLE = "drawable";
private static final String ARG_TEXT = "text";
private static final String ARG_SUBTEXT = "subtext";
private int drawable;
private int text;
private int subtext;
public static BasicIntroFragment newInstance(int drawable, int text, int subtext) {
BasicIntroFragment fragment = new BasicIntroFragment();
Bundle args = new Bundle();
args.putInt(ARG_DRAWABLE, drawable);
args.putInt(ARG_TEXT, text);
args.putInt(ARG_SUBTEXT, subtext);
fragment.setArguments(args);
return fragment;
}
public BasicIntroFragment() {}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
drawable = getArguments().getInt(ARG_DRAWABLE);
text = getArguments().getInt(ARG_TEXT );
subtext = getArguments().getInt(ARG_SUBTEXT );
}
}
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.color_fragment, container, false);
((ImageView)v.findViewById(R.id.watermark)).setImageResource(drawable);
((TextView)v.findViewById(R.id.blurb)).setText(text);
((TextView)v.findViewById(R.id.subblurb)).setText(subtext);
return v;
}
}

View File

@@ -1,207 +0,0 @@
/*
* Copyright (C) 2011 Whisper Systems
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.thoughtcrime.securesms;
import android.content.Context;
import android.database.Cursor;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import org.thoughtcrime.securesms.database.CursorRecyclerViewAdapter;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.ThreadDatabase;
import org.thoughtcrime.securesms.database.model.ThreadRecord;
import org.thoughtcrime.securesms.mms.GlideRequests;
import org.thoughtcrime.securesms.util.Conversions;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Collections;
import java.util.HashSet;
import java.util.Locale;
import java.util.Set;
import network.loki.messenger.R;
/**
* A CursorAdapter for building a list of conversation threads.
*
* @author Moxie Marlinspike
*/
class ConversationListAdapter extends CursorRecyclerViewAdapter<ConversationListAdapter.ViewHolder> {
private static final int MESSAGE_TYPE_SWITCH_ARCHIVE = 1;
private static final int MESSAGE_TYPE_THREAD = 2;
private static final int MESSAGE_TYPE_INBOX_ZERO = 3;
private final @NonNull ThreadDatabase threadDatabase;
private final @NonNull GlideRequests glideRequests;
private final @NonNull Locale locale;
private final @NonNull LayoutInflater inflater;
private final @Nullable ItemClickListener clickListener;
private final @NonNull MessageDigest digest;
private final Set<Long> batchSet = Collections.synchronizedSet(new HashSet<Long>());
private boolean batchMode = false;
private final Set<Long> typingSet = new HashSet<>();
protected static class ViewHolder extends RecyclerView.ViewHolder {
public <V extends View & BindableConversationListItem> ViewHolder(final @NonNull V itemView)
{
super(itemView);
}
public BindableConversationListItem getItem() {
return (BindableConversationListItem)itemView;
}
}
@Override
public long getItemId(@NonNull Cursor cursor) {
ThreadRecord record = getThreadRecord(cursor);
return Conversions.byteArrayToLong(digest.digest(record.getRecipient().getAddress().serialize().getBytes()));
}
@Override
protected long getFastAccessItemId(int position) {
return super.getFastAccessItemId(position);
}
ConversationListAdapter(@NonNull Context context,
@NonNull GlideRequests glideRequests,
@NonNull Locale locale,
@Nullable Cursor cursor,
@Nullable ItemClickListener clickListener)
{
super(context, cursor);
try {
this.glideRequests = glideRequests;
this.threadDatabase = DatabaseFactory.getThreadDatabase(context);
this.locale = locale;
this.inflater = LayoutInflater.from(context);
this.clickListener = clickListener;
this.digest = MessageDigest.getInstance("SHA1");
setHasStableIds(true);
} catch (NoSuchAlgorithmException nsae) {
throw new AssertionError("SHA-1 missing");
}
}
@Override
public ViewHolder onCreateItemViewHolder(ViewGroup parent, int viewType) {
if (viewType == MESSAGE_TYPE_SWITCH_ARCHIVE) {
ConversationListItemAction action = (ConversationListItemAction) inflater.inflate(R.layout.conversation_list_item_action,
parent, false);
action.setOnClickListener(v -> {
if (clickListener != null) clickListener.onSwitchToArchive();
});
return new ViewHolder(action);
} else if (viewType == MESSAGE_TYPE_INBOX_ZERO) {
return new ViewHolder((ConversationListItemInboxZero)inflater.inflate(R.layout.conversation_list_item_inbox_zero, parent, false));
} else {
final ConversationListItem item = (ConversationListItem)inflater.inflate(R.layout.conversation_list_item_view,
parent, false);
item.setOnClickListener(view -> {
if (clickListener != null) clickListener.onItemClick(item);
});
item.setOnLongClickListener(view -> {
if (clickListener != null) clickListener.onItemLongClick(item);
return true;
});
return new ViewHolder(item);
}
}
@Override
public void onItemViewRecycled(ViewHolder holder) {
holder.getItem().unbind();
}
@Override
public void onBindItemViewHolder(ViewHolder viewHolder, @NonNull Cursor cursor) {
viewHolder.getItem().bind(getThreadRecord(cursor), glideRequests, locale, typingSet, batchSet, batchMode);
}
@Override
public int getItemViewType(@NonNull Cursor cursor) {
ThreadRecord threadRecord = getThreadRecord(cursor);
if (threadRecord.getDistributionType() == ThreadDatabase.DistributionTypes.ARCHIVE) {
return MESSAGE_TYPE_SWITCH_ARCHIVE;
} else if (threadRecord.getDistributionType() == ThreadDatabase.DistributionTypes.INBOX_ZERO) {
return MESSAGE_TYPE_INBOX_ZERO;
} else {
return MESSAGE_TYPE_THREAD;
}
}
public void setTypingThreads(@NonNull Set<Long> threadsIds) {
typingSet.clear();
typingSet.addAll(threadsIds);
notifyDataSetChanged();
}
private ThreadRecord getThreadRecord(@NonNull Cursor cursor) {
return threadDatabase.readerFor(cursor).getCurrent();
}
void toggleThreadInBatchSet(long threadId) {
if (batchSet.contains(threadId)) {
batchSet.remove(threadId);
} else if (threadId != -1) {
batchSet.add(threadId);
}
}
Set<Long> getBatchSelections() {
return batchSet;
}
void initializeBatchMode(boolean toggle) {
this.batchMode = toggle;
unselectAllThreads();
}
private void unselectAllThreads() {
this.batchSet.clear();
this.notifyDataSetChanged();
}
void selectAllThreads() {
for (int i = 0; i < getItemCount(); i++) {
long threadId = getThreadRecord(getCursorAtPositionOrThrow(i)).getThreadId();
if (threadId != -1) batchSet.add(threadId);
}
this.notifyDataSetChanged();
}
interface ItemClickListener {
void onItemClick(ConversationListItem item);
void onItemLongClick(ConversationListItem item);
void onSwitchToArchive();
}
}

View File

@@ -1,386 +0,0 @@
/*
* Copyright (C) 2014-2017 Open Whisper Systems
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.thoughtcrime.securesms;
import android.content.Context;
import android.content.res.ColorStateList;
import android.graphics.Typeface;
import android.graphics.drawable.RippleDrawable;
import android.os.Build.VERSION;
import android.os.Build.VERSION_CODES;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import android.text.style.StyleSpan;
import android.util.AttributeSet;
import android.view.View;
import android.widget.RelativeLayout;
import android.widget.TextView;
import org.thoughtcrime.securesms.components.ConversationItemAlertView;
import org.thoughtcrime.securesms.components.AvatarImageView;
import org.thoughtcrime.securesms.components.DeliveryStatusView;
import org.thoughtcrime.securesms.components.FromTextView;
import org.thoughtcrime.securesms.components.ThumbnailView;
import org.thoughtcrime.securesms.components.TypingIndicatorView;
import org.thoughtcrime.securesms.database.model.ThreadRecord;
import org.thoughtcrime.securesms.loki.utilities.MentionManagerUtilities;
import org.thoughtcrime.securesms.loki.utilities.MentionUtilities;
import org.thoughtcrime.securesms.mms.GlideRequests;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.RecipientModifiedListener;
import org.thoughtcrime.securesms.search.model.MessageResult;
import org.thoughtcrime.securesms.util.DateUtils;
import org.thoughtcrime.securesms.util.SearchUtil;
import org.thoughtcrime.securesms.util.ThemeUtil;
import org.thoughtcrime.securesms.util.Util;
import org.thoughtcrime.securesms.util.ViewUtil;
import java.util.Collections;
import java.util.Locale;
import java.util.Set;
import network.loki.messenger.R;
public class ConversationListItem extends RelativeLayout
implements RecipientModifiedListener,
BindableConversationListItem, Unbindable
{
@SuppressWarnings("unused")
private final static String TAG = ConversationListItem.class.getSimpleName();
private final static Typeface BOLD_TYPEFACE = Typeface.create("sans-serif-medium", Typeface.NORMAL);
private final static Typeface LIGHT_TYPEFACE = Typeface.create("sans-serif", Typeface.NORMAL);
private static final int MAX_SNIPPET_LENGTH = 500;
private Set<Long> selectedThreads;
private Recipient recipient;
private long threadId;
private GlideRequests glideRequests;
private View subjectContainer;
private TextView subjectView;
private TypingIndicatorView typingView;
private FromTextView fromView;
private TextView dateView;
private TextView archivedView;
private DeliveryStatusView deliveryStatusIndicator;
private ConversationItemAlertView alertView;
private TextView unreadIndicator;
private long lastSeen;
private int unreadCount;
private AvatarImageView contactPhotoImage;
private ThumbnailView thumbnailView;
private int distributionType;
public ConversationListItem(Context context) {
this(context, null);
}
public ConversationListItem(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
this.subjectContainer = findViewById(R.id.subject_container);
this.subjectView = findViewById(R.id.subject);
this.typingView = findViewById(R.id.typing_indicator);
this.fromView = findViewById(R.id.from);
this.dateView = findViewById(R.id.date);
this.deliveryStatusIndicator = findViewById(R.id.delivery_status);
this.alertView = findViewById(R.id.indicators_parent);
this.contactPhotoImage = findViewById(R.id.contact_photo_image);
this.thumbnailView = findViewById(R.id.thumbnail);
this.archivedView = findViewById(R.id.archived);
this.unreadIndicator = findViewById(R.id.unread_indicator);
thumbnailView.setClickable(false);
ViewUtil.setTextViewGravityStart(this.fromView, getContext());
ViewUtil.setTextViewGravityStart(this.subjectView, getContext());
}
@Override
public void bind(@NonNull ThreadRecord thread,
@NonNull GlideRequests glideRequests,
@NonNull Locale locale,
@NonNull Set<Long> typingThreads,
@NonNull Set<Long> selectedThreads,
boolean batchMode)
{
bind(thread, glideRequests, locale, typingThreads, selectedThreads, batchMode, null);
}
public void bind(@NonNull ThreadRecord thread,
@NonNull GlideRequests glideRequests,
@NonNull Locale locale,
@NonNull Set<Long> typingThreads,
@NonNull Set<Long> selectedThreads,
boolean batchMode,
@Nullable String highlightSubstring)
{
this.selectedThreads = selectedThreads;
this.recipient = thread.getRecipient();
this.threadId = thread.getThreadId();
this.glideRequests = glideRequests;
this.unreadCount = thread.getUnreadCount();
this.distributionType = thread.getDistributionType();
this.lastSeen = thread.getLastSeen();
this.recipient.addListener(this);
if (highlightSubstring != null) {
String name = recipient.isLocalNumber() ? getContext().getString(R.string.note_to_self) : recipient.getName();
this.fromView.setText(SearchUtil.getHighlightedSpan(locale, () -> new StyleSpan(Typeface.BOLD), name, highlightSubstring));
} else {
this.fromView.setText(recipient, unreadCount == 0);
}
if (typingThreads.contains(threadId)) {
this.subjectView.setVisibility(INVISIBLE);
this.typingView.setVisibility(VISIBLE);
this.typingView.startAnimation();
} else {
this.typingView.setVisibility(GONE);
this.typingView.stopAnimation();
this.subjectView.setVisibility(VISIBLE);
this.subjectView.setText(getTrimmedSnippet(thread.getDisplayBody(getContext())));
this.subjectView.setTypeface(unreadCount == 0 ? LIGHT_TYPEFACE : BOLD_TYPEFACE);
this.subjectView.setTextColor(unreadCount == 0 ? ThemeUtil.getThemedColor(getContext(), R.attr.conversation_list_item_subject_color)
: ThemeUtil.getThemedColor(getContext(), R.attr.conversation_list_item_unread_color));
}
if (thread.getDate() > 0) {
CharSequence date = DateUtils.getBriefRelativeTimeSpanString(getContext(), locale, thread.getDate());
dateView.setText(date);
dateView.setTypeface(unreadCount == 0 ? LIGHT_TYPEFACE : BOLD_TYPEFACE);
dateView.setTextColor(unreadCount == 0 ? ThemeUtil.getThemedColor(getContext(), R.attr.conversation_list_item_date_color)
: ThemeUtil.getThemedColor(getContext(), R.attr.conversation_list_item_unread_color));
}
if (thread.isArchived()) {
this.archivedView.setVisibility(View.VISIBLE);
} else {
this.archivedView.setVisibility(View.GONE);
}
setStatusIcons(thread);
setThumbnailSnippet(thread);
setBatchState(batchMode);
setRippleColor(recipient);
setUnreadIndicator(thread);
this.contactPhotoImage.setAvatar(glideRequests, recipient, true);
}
public void bind(@NonNull Recipient contact,
@NonNull GlideRequests glideRequests,
@NonNull Locale locale,
@Nullable String highlightSubstring)
{
this.selectedThreads = Collections.emptySet();
this.recipient = contact;
this.glideRequests = glideRequests;
this.recipient.addListener(this);
String name = recipient.isLocalNumber() ? getContext().getString(R.string.note_to_self) : recipient.getName();
fromView.setText(SearchUtil.getHighlightedSpan(locale, () -> new StyleSpan(Typeface.BOLD), name, highlightSubstring));
subjectView.setText(SearchUtil.getHighlightedSpan(locale, () -> new StyleSpan(Typeface.BOLD), contact.getAddress().toString(), highlightSubstring));
dateView.setText("");
archivedView.setVisibility(GONE);
unreadIndicator.setVisibility(GONE);
deliveryStatusIndicator.setNone();
alertView.setNone();
thumbnailView.setVisibility(GONE);
setBatchState(false);
setRippleColor(contact);
contactPhotoImage.setAvatar(glideRequests, recipient, true);
}
public void bind(@NonNull MessageResult messageResult,
@NonNull GlideRequests glideRequests,
@NonNull Locale locale,
@Nullable String highlightSubstring)
{
this.selectedThreads = Collections.emptySet();
this.recipient = messageResult.conversationRecipient;
this.glideRequests = glideRequests;
this.recipient.addListener(this);
fromView.setText(recipient, true);
subjectView.setText(SearchUtil.getHighlightedSpan(locale, () -> new StyleSpan(Typeface.BOLD), messageResult.bodySnippet, highlightSubstring));
dateView.setText(DateUtils.getBriefRelativeTimeSpanString(getContext(), locale, messageResult.receivedTimestampMs));
archivedView.setVisibility(GONE);
unreadIndicator.setVisibility(GONE);
deliveryStatusIndicator.setNone();
alertView.setNone();
thumbnailView.setVisibility(GONE);
setBatchState(false);
setRippleColor(recipient);
contactPhotoImage.setAvatar(glideRequests, recipient, true);
}
@Override
public void unbind() {
if (this.recipient != null) this.recipient.removeListener(this);
}
private void setBatchState(boolean batch) {
setSelected(batch && selectedThreads.contains(threadId));
}
public Recipient getRecipient() {
return recipient;
}
public long getThreadId() {
return threadId;
}
public int getUnreadCount() {
return unreadCount;
}
public int getDistributionType() {
return distributionType;
}
public long getLastSeen() {
return lastSeen;
}
private @NonNull CharSequence getTrimmedSnippet(@NonNull CharSequence snippet) {
MentionManagerUtilities.INSTANCE.populateUserPublicKeyCacheIfNeeded(threadId, getContext()); // TODO: Terrible place to do this, but okay for now
snippet = MentionUtilities.highlightMentions(snippet, threadId, getContext());
return snippet.length() <= MAX_SNIPPET_LENGTH ? snippet : snippet.subSequence(0, MAX_SNIPPET_LENGTH);
}
private void setThumbnailSnippet(ThreadRecord thread) {
if (thread.getSnippetUri() != null) {
this.thumbnailView.setVisibility(View.VISIBLE);
this.thumbnailView.setImageResource(glideRequests, thread.getSnippetUri());
LayoutParams subjectParams = (RelativeLayout.LayoutParams)this.subjectContainer .getLayoutParams();
subjectParams.addRule(RelativeLayout.LEFT_OF, R.id.thumbnail);
if (VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN_MR1) {
subjectParams.addRule(RelativeLayout.START_OF, R.id.thumbnail);
}
this.subjectContainer.setLayoutParams(subjectParams);
this.post(new ThumbnailPositioner(thumbnailView, archivedView, deliveryStatusIndicator, dateView));
} else {
this.thumbnailView.setVisibility(View.GONE);
LayoutParams subjectParams = (RelativeLayout.LayoutParams)this.subjectContainer.getLayoutParams();
subjectParams.addRule(RelativeLayout.LEFT_OF, R.id.status);
if (VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN_MR1) {
subjectParams.addRule(RelativeLayout.START_OF, R.id.status);
}
this.subjectContainer.setLayoutParams(subjectParams);
}
}
private void setStatusIcons(ThreadRecord thread) {
if (!thread.isOutgoing() || thread.isOutgoingCall() || thread.isVerificationStatusChange()) {
deliveryStatusIndicator.setNone();
alertView.setNone();
} else if (thread.isFailed()) {
deliveryStatusIndicator.setNone();
alertView.setFailed();
} else if (thread.isPendingInsecureSmsFallback()) {
deliveryStatusIndicator.setNone();
alertView.setPendingApproval();
} else {
alertView.setNone();
if (thread.isPending()) deliveryStatusIndicator.setPending();
else if (thread.isRemoteRead()) deliveryStatusIndicator.setRead();
else if (thread.isDelivered()) deliveryStatusIndicator.setDelivered();
else deliveryStatusIndicator.setSent();
}
}
private void setRippleColor(Recipient recipient) {
if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) {
((RippleDrawable)(getBackground()).mutate())
.setColor(ColorStateList.valueOf(recipient.getColor().toConversationColor(getContext())));
}
}
private void setUnreadIndicator(ThreadRecord thread) {
if (thread.isOutgoing() || thread.getUnreadCount() == 0) {
unreadIndicator.setVisibility(View.GONE);
return;
}
unreadIndicator.setText(String.valueOf(unreadCount));
unreadIndicator.setVisibility(View.VISIBLE);
}
@Override
public void onModified(final Recipient recipient) {
Util.runOnMain(() -> {
fromView.setText(recipient, unreadCount == 0);
contactPhotoImage.setAvatar(glideRequests, recipient, true);
setRippleColor(recipient);
});
}
private static class ThumbnailPositioner implements Runnable {
private final View thumbnailView;
private final View archivedView;
private final View deliveryStatusView;
private final View dateView;
ThumbnailPositioner(View thumbnailView, View archivedView, View deliveryStatusView, View dateView) {
this.thumbnailView = thumbnailView;
this.archivedView = archivedView;
this.deliveryStatusView = deliveryStatusView;
this.dateView = dateView;
}
@Override
public void run() {
LayoutParams thumbnailParams = (RelativeLayout.LayoutParams)thumbnailView.getLayoutParams();
if (archivedView.getVisibility() == View.VISIBLE &&
(archivedView.getWidth() + deliveryStatusView.getWidth()) > dateView.getWidth())
{
thumbnailParams.addRule(RelativeLayout.LEFT_OF, R.id.status);
if (VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN_MR1) {
thumbnailParams.addRule(RelativeLayout.START_OF, R.id.status);
}
} else {
thumbnailParams.addRule(RelativeLayout.LEFT_OF, R.id.date);
if (VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN_MR1) {
thumbnailParams.addRule(RelativeLayout.START_OF, R.id.date);
}
}
thumbnailView.setLayoutParams(thumbnailParams);
}
}
}

View File

@@ -1,58 +0,0 @@
package org.thoughtcrime.securesms;
import android.annotation.TargetApi;
import android.content.Context;
import android.os.Build;
import androidx.annotation.NonNull;
import android.util.AttributeSet;
import android.widget.LinearLayout;
import android.widget.TextView;
import org.thoughtcrime.securesms.database.model.ThreadRecord;
import org.thoughtcrime.securesms.mms.GlideRequests;
import org.thoughtcrime.securesms.util.ViewUtil;
import java.util.Locale;
import java.util.Set;
import network.loki.messenger.R;
public class ConversationListItemAction extends LinearLayout implements BindableConversationListItem {
private TextView description;
public ConversationListItemAction(Context context) {
super(context);
}
public ConversationListItemAction(Context context, AttributeSet attrs) {
super(context, attrs);
}
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public ConversationListItemAction(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
public void onFinishInflate() {
super.onFinishInflate();
this.description = ViewUtil.findById(this, R.id.description);
}
@Override
public void bind(@NonNull ThreadRecord thread,
@NonNull GlideRequests glideRequests,
@NonNull Locale locale,
@NonNull Set<Long> typingThreads,
@NonNull Set<Long> selectedThreads,
boolean batchMode)
{
this.description.setText(getContext().getString(R.string.ConversationListItemAction_archived_conversations_d, thread.getCount()));
}
@Override
public void unbind() {
}
}

View File

@@ -1,51 +0,0 @@
package org.thoughtcrime.securesms;
import android.content.Context;
import android.os.Build;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import android.util.AttributeSet;
import android.widget.LinearLayout;
import org.thoughtcrime.securesms.database.model.ThreadRecord;
import org.thoughtcrime.securesms.mms.GlideRequests;
import java.util.Locale;
import java.util.Set;
public class ConversationListItemInboxZero extends LinearLayout implements BindableConversationListItem{
public ConversationListItemInboxZero(Context context) {
super(context);
}
public ConversationListItemInboxZero(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
public ConversationListItemInboxZero(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public ConversationListItemInboxZero(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
@Override
public void unbind() {
}
@Override
public void bind(@NonNull ThreadRecord thread,
@NonNull GlideRequests glideRequests,
@NonNull Locale locale,
@NonNull Set<Long> typingThreads,
@NonNull Set<Long> selectedThreads,
boolean batchMode)
{
}
}

View File

@@ -1,29 +0,0 @@
package org.thoughtcrime.securesms;
import android.content.Intent;
import android.os.Bundle;
import network.loki.messenger.R;
public class CountrySelectionActivity extends BaseActivity
implements CountrySelectionFragment.CountrySelectedListener
{
@Override
public void onCreate(Bundle bundle) {
super.onCreate(bundle);
this.setContentView(R.layout.country_selection);
}
@Override
public void countrySelected(String countryName, int countryCode) {
Intent result = getIntent();
result.putExtra("country_name", countryName);
result.putExtra("country_code", countryCode);
this.setResult(RESULT_OK, result);
this.finish();
}
}

View File

@@ -1,102 +0,0 @@
package org.thoughtcrime.securesms;
import android.app.Activity;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.fragment.app.ListFragment;
import androidx.loader.app.LoaderManager;
import androidx.loader.content.Loader;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import org.thoughtcrime.securesms.database.loaders.CountryListLoader;
import java.util.ArrayList;
import java.util.Map;
import network.loki.messenger.R;
public class CountrySelectionFragment extends ListFragment implements LoaderManager.LoaderCallbacks<ArrayList<Map<String, String>>> {
private EditText countryFilter;
private CountrySelectedListener listener;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle bundle) {
return inflater.inflate(R.layout.country_selection_fragment, container, false);
}
@Override
public void onActivityCreated(Bundle bundle) {
super.onActivityCreated(bundle);
this.countryFilter = (EditText)getView().findViewById(R.id.country_search);
this.countryFilter.addTextChangedListener(new FilterWatcher());
getLoaderManager().initLoader(0, null, this).forceLoad();
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
this.listener = (CountrySelectedListener)activity;
}
@Override
public void onListItemClick(ListView listView, View view, int position, long id) {
Map<String, String> item = (Map<String, String>)this.getListAdapter().getItem(position);
if (this.listener != null) {
this.listener.countrySelected(item.get("country_name"),
Integer.parseInt(item.get("country_code").substring(1)));
}
}
@Override
public @NonNull Loader<ArrayList<Map<String, String>>> onCreateLoader(int arg0, Bundle arg1) {
return new CountryListLoader(getActivity());
}
@Override
public void onLoadFinished(@NonNull Loader<ArrayList<Map<String, String>>> loader,
ArrayList<Map<String, String>> results)
{
String[] from = {"country_name", "country_code"};
int[] to = {R.id.country_name, R.id.country_code};
this.setListAdapter(new SimpleAdapter(getActivity(), results, R.layout.country_list_item, from, to));
if (this.countryFilter != null && this.countryFilter.getText().length() != 0) {
((SimpleAdapter)getListAdapter()).getFilter().filter(this.countryFilter.getText().toString());
}
}
@Override
public void onLoaderReset(@NonNull Loader<ArrayList<Map<String, String>>> arg0) {
this.setListAdapter(null);
}
public interface CountrySelectedListener {
public void countrySelected(String countryName, int countryCode);
}
private class FilterWatcher implements TextWatcher {
@Override
public void afterTextChanged(Editable s) {
if (getListAdapter() != null) {
((SimpleAdapter)getListAdapter()).getFilter().filter(s.toString());
}
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
}
}

View File

@@ -1,197 +0,0 @@
package org.thoughtcrime.securesms;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Parcelable;
import android.view.View;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
import org.thoughtcrime.securesms.database.SmsMigrator.ProgressDescription;
import org.thoughtcrime.securesms.loki.activities.HomeActivity;
import org.thoughtcrime.securesms.service.ApplicationMigrationService;
import org.thoughtcrime.securesms.service.ApplicationMigrationService.ImportState;
import network.loki.messenger.R;
public class DatabaseMigrationActivity extends PassphraseRequiredActionBarActivity {
private final ImportServiceConnection serviceConnection = new ImportServiceConnection();
private final ImportStateHandler importStateHandler = new ImportStateHandler();
private final BroadcastReceiver completedReceiver = new NullReceiver();
private LinearLayout promptLayout;
private LinearLayout progressLayout;
private Button skipButton;
private Button importButton;
private ProgressBar progress;
private TextView progressLabel;
private ApplicationMigrationService importService;
private boolean isVisible = false;
@Override
protected void onCreate(Bundle bundle, boolean ready) {
setContentView(R.layout.database_migration_activity);
initializeResources();
initializeServiceBinding();
}
@Override
public void onResume() {
super.onResume();
isVisible = true;
registerForCompletedNotification();
}
@Override
public void onPause() {
super.onPause();
isVisible = false;
unregisterForCompletedNotification();
}
@Override
public void onDestroy() {
super.onDestroy();
shutdownServiceBinding();
}
@Override
public void onBackPressed() {
}
private void initializeServiceBinding() {
Intent intent = new Intent(this, ApplicationMigrationService.class);
bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
}
private void initializeResources() {
this.promptLayout = (LinearLayout)findViewById(R.id.prompt_layout);
this.progressLayout = (LinearLayout)findViewById(R.id.progress_layout);
this.skipButton = (Button) findViewById(R.id.skip_button);
this.importButton = (Button) findViewById(R.id.import_button);
this.progress = (ProgressBar) findViewById(R.id.import_progress);
this.progressLabel = (TextView) findViewById(R.id.import_status);
this.progressLayout.setVisibility(View.GONE);
this.promptLayout.setVisibility(View.GONE);
this.importButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(DatabaseMigrationActivity.this, ApplicationMigrationService.class);
intent.setAction(ApplicationMigrationService.MIGRATE_DATABASE);
intent.putExtra("master_secret", (Parcelable)getIntent().getParcelableExtra("master_secret"));
startService(intent);
promptLayout.setVisibility(View.GONE);
progressLayout.setVisibility(View.VISIBLE);
}
});
this.skipButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
ApplicationMigrationService.setDatabaseImported(DatabaseMigrationActivity.this);
handleImportComplete();
}
});
}
private void registerForCompletedNotification() {
IntentFilter filter = new IntentFilter();
filter.addAction(ApplicationMigrationService.COMPLETED_ACTION);
filter.setPriority(1000);
registerReceiver(completedReceiver, filter);
}
private void unregisterForCompletedNotification() {
unregisterReceiver(completedReceiver);
}
private void shutdownServiceBinding() {
unbindService(serviceConnection);
}
private void handleStateIdle() {
this.promptLayout.setVisibility(View.VISIBLE);
this.progressLayout.setVisibility(View.GONE);
}
private void handleStateProgress(ProgressDescription update) {
this.promptLayout.setVisibility(View.GONE);
this.progressLayout.setVisibility(View.VISIBLE);
this.progressLabel.setText(update.primaryComplete + "/" + update.primaryTotal);
double max = this.progress.getMax();
double primaryTotal = update.primaryTotal;
double primaryComplete = update.primaryComplete;
double secondaryTotal = update.secondaryTotal;
double secondaryComplete = update.secondaryComplete;
this.progress.setProgress((int)Math.round((primaryComplete / primaryTotal) * max));
this.progress.setSecondaryProgress((int)Math.round((secondaryComplete / secondaryTotal) * max));
}
private void handleImportComplete() {
if (isVisible) {
if (getIntent().hasExtra("next_intent")) {
startActivity((Intent)getIntent().getParcelableExtra("next_intent"));
} else {
startActivity(new Intent(this, HomeActivity.class));
}
}
finish();
}
private class ImportStateHandler extends Handler {
@Override
public void handleMessage(Message message) {
switch (message.what) {
case ImportState.STATE_IDLE: handleStateIdle(); break;
case ImportState.STATE_MIGRATING_IN_PROGRESS: handleStateProgress((ProgressDescription)message.obj); break;
case ImportState.STATE_MIGRATING_COMPLETE: handleImportComplete(); break;
}
}
}
private class ImportServiceConnection implements ServiceConnection {
@Override
public void onServiceConnected(ComponentName className, IBinder service) {
importService = ((ApplicationMigrationService.ApplicationMigrationBinder)service).getService();
importService.setImportStateHandler(importStateHandler);
ImportState state = importService.getState();
importStateHandler.obtainMessage(state.state, state.progress).sendToTarget();
}
@Override
public void onServiceDisconnected(ComponentName name) {
importService.setImportStateHandler(null);
}
}
private static class NullReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
abortBroadcast();
}
}
}

View File

@@ -67,7 +67,7 @@ class MessageDetailsRecipientAdapter extends BaseAdapter implements AbsListView.
@Override
public void onMovedToScrapHeap(View view) {
((MessageRecipientListItem)view).unbind();
((UserView)view).unbind();
}

View File

@@ -1,173 +0,0 @@
/*
* Copyright (C) 2014 Open Whisper Systems
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.thoughtcrime.securesms;
import android.content.Context;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import org.thoughtcrime.securesms.MessageDetailsRecipientAdapter.RecipientDeliveryStatus;
import org.thoughtcrime.securesms.components.AvatarImageView;
import org.thoughtcrime.securesms.components.DeliveryStatusView;
import org.thoughtcrime.securesms.components.FromTextView;
import org.thoughtcrime.securesms.database.documents.IdentityKeyMismatch;
import org.thoughtcrime.securesms.database.documents.NetworkFailure;
import org.thoughtcrime.securesms.database.model.MessageRecord;
import org.thoughtcrime.securesms.mms.GlideRequests;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.RecipientModifiedListener;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.thoughtcrime.securesms.util.Util;
import network.loki.messenger.R;
/**
* A simple view to show the recipients of a message
*
* @author Jake McGinty
*/
public class MessageRecipientListItem extends RelativeLayout
implements RecipientModifiedListener
{
@SuppressWarnings("unused")
private final static String TAG = MessageRecipientListItem.class.getSimpleName();
private RecipientDeliveryStatus member;
private GlideRequests glideRequests;
private FromTextView fromView;
private TextView errorDescription;
private TextView actionDescription;
private Button conflictButton;
private AvatarImageView contactPhotoImage;
private ImageView unidentifiedDeliveryIcon;
private DeliveryStatusView deliveryStatusView;
public MessageRecipientListItem(Context context) {
super(context);
}
public MessageRecipientListItem(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
this.fromView = findViewById(R.id.from);
this.errorDescription = findViewById(R.id.error_description);
this.actionDescription = findViewById(R.id.action_description);
this.contactPhotoImage = findViewById(R.id.contact_photo_image);
this.conflictButton = findViewById(R.id.conflict_button);
this.unidentifiedDeliveryIcon = findViewById(R.id.ud_indicator);
this.deliveryStatusView = findViewById(R.id.delivery_status);
}
public void set(final GlideRequests glideRequests,
final MessageRecord record,
final RecipientDeliveryStatus member,
final boolean isPushGroup)
{
this.glideRequests = glideRequests;
this.member = member;
member.getRecipient().addListener(this);
fromView.setText(member.getRecipient());
contactPhotoImage.setAvatar(glideRequests, member.getRecipient(), false);
setIssueIndicators(record, isPushGroup);
unidentifiedDeliveryIcon.setVisibility(TextSecurePreferences.isShowUnidentifiedDeliveryIndicatorsEnabled(getContext()) && member.isUnidentified() ? VISIBLE : GONE);
}
private void setIssueIndicators(final MessageRecord record,
final boolean isPushGroup)
{
final NetworkFailure networkFailure = getNetworkFailure(record);
final IdentityKeyMismatch keyMismatch = networkFailure == null ? getKeyMismatch(record) : null;
String errorText = "";
if (keyMismatch != null) {
conflictButton.setVisibility(View.VISIBLE);
errorText = getContext().getString(R.string.MessageDetailsRecipient_new_safety_number);
conflictButton.setOnClickListener(v -> new ConfirmIdentityDialog(getContext(), record, keyMismatch).show());
} else if ((networkFailure != null && !record.isPending()) || (!isPushGroup && record.isFailed())) {
conflictButton.setVisibility(View.GONE);
errorText = getContext().getString(R.string.MessageDetailsRecipient_failed_to_send);
} else {
if (record.isOutgoing()) {
if (member.getDeliveryStatus() == RecipientDeliveryStatus.Status.PENDING || member.getDeliveryStatus() == RecipientDeliveryStatus.Status.UNKNOWN) {
deliveryStatusView.setVisibility(View.GONE);
} else if (member.getDeliveryStatus() == RecipientDeliveryStatus.Status.READ) {
deliveryStatusView.setRead();
deliveryStatusView.setVisibility(View.VISIBLE);
} else if (member.getDeliveryStatus() == RecipientDeliveryStatus.Status.DELIVERED) {
deliveryStatusView.setDelivered();
deliveryStatusView.setVisibility(View.VISIBLE);
} else if (member.getDeliveryStatus() == RecipientDeliveryStatus.Status.SENT) {
deliveryStatusView.setSent();
deliveryStatusView.setVisibility(View.VISIBLE);
}
} else {
deliveryStatusView.setVisibility(View.GONE);
}
conflictButton.setVisibility(View.GONE);
}
errorDescription.setText(errorText);
errorDescription.setVisibility(TextUtils.isEmpty(errorText) ? View.GONE : View.VISIBLE);
}
private NetworkFailure getNetworkFailure(final MessageRecord record) {
if (record.hasNetworkFailures()) {
for (final NetworkFailure failure : record.getNetworkFailures()) {
if (failure.getAddress().equals(member.getRecipient().getAddress())) {
return failure;
}
}
}
return null;
}
private IdentityKeyMismatch getKeyMismatch(final MessageRecord record) {
if (record.isIdentityMismatchFailure()) {
for (final IdentityKeyMismatch mismatch : record.getIdentityKeyMismatches()) {
if (mismatch.getAddress().equals(member.getRecipient().getAddress())) {
return mismatch;
}
}
}
return null;
}
public void unbind() {
if (this.member != null && this.member.getRecipient() != null) this.member.getRecipient().removeListener(this);
}
@Override
public void onModified(final Recipient recipient) {
Util.runOnMain(() -> {
fromView.setText(recipient);
contactPhotoImage.setAvatar(glideRequests, recipient, false);
});
}
}

View File

@@ -99,8 +99,8 @@ class EditClosedGroupActivity : PassphraseRequiredActionBarActivity() {
lblGroupNameDisplay.text = originalName
cntGroupNameDisplay.setOnClickListener { isEditingName = true }
findViewById<Button>(R.id.btnCancelGroupNameEdit).setOnClickListener { isEditingName = false }
findViewById<Button>(R.id.btnSaveGroupNameEdit).setOnClickListener { saveName() }
findViewById<View>(R.id.btnCancelGroupNameEdit).setOnClickListener { isEditingName = false }
findViewById<View>(R.id.btnSaveGroupNameEdit).setOnClickListener { saveName() }
edtGroupName.setImeActionLabel(getString(R.string.save), EditorInfo.IME_ACTION_DONE)
edtGroupName.setOnEditorActionListener { _, actionId, _ ->
when (actionId) {

View File

@@ -81,5 +81,9 @@ class UserView : LinearLayout {
}
}
}
fun unbind() {
}
// endregion
}