From 5e3cb706c46c9cdcbebcfea561daff284e155ba2 Mon Sep 17 00:00:00 2001 From: Anton Chekulaev Date: Wed, 2 Dec 2020 23:01:04 +1100 Subject: [PATCH] Unused code cleanup. --- app/src/main/AndroidManifest.xml | 7 - .../thoughtcrime/securesms/ShareActivity.java | 2 - .../securesms/components/HourglassView.java | 85 -- .../securesms/components/ImageDivet.java | 105 --- .../components/PushRecipientsPanel.java | 168 ---- .../securesms/components/RatingManager.java | 88 --- .../components/RecyclerViewFastScroller.java | 213 ----- .../components/SharedContactView.java | 230 ------ .../components/SquareLinearLayout.java | 35 - .../components/reminder/Reminder.java | 57 -- .../components/reminder/ReminderView.java | 94 --- .../securesms/contacts/ArrayListCursor.java | 169 ---- .../contacts/ContactIdentityManager.java | 24 - .../contacts/ContactIdentityManagerICS.java | 76 -- .../contacts/ContactsCursorLoader.java | 64 +- .../securesms/contacts/ContactsDatabase.java | 729 ------------------ .../securesms/contacts/NameAndNumber.java | 35 - .../securesms/contacts/RecipientsAdapter.java | 154 ---- .../securesms/contacts/RecipientsEditor.java | 416 ---------- .../contactshare/ContactFieldAdapter.java | 227 ------ .../contactshare/ContactNameEditActivity.java | 138 ---- .../ContactNameEditViewModel.java | 132 ---- .../contactshare/ContactRepository.java | 389 ---------- .../ContactShareEditActivity.java | 140 ---- .../contactshare/ContactShareEditAdapter.java | 95 --- .../ContactShareEditViewModel.java | 113 --- .../securesms/contactshare/ContactUtil.java | 165 ---- .../conversation/ConversationActivity.java | 32 +- .../ConversationPopupActivity.java | 7 - .../ConversationSearchViewModel.java | 1 - .../conversation/ConversationTitleView.java | 154 ---- .../securesms/database/DatabaseFactory.java | 7 - .../securesms/database/RecipientDatabase.java | 21 +- .../SignalCommunicationModule.java | 19 +- .../devicelist/DeviceNameProtos.java | 619 --------------- .../securesms/events/RedPhoneEvent.java | 51 -- .../securesms/events/ReminderUpdateEvent.java | 5 - .../securesms/jobs/RefreshAttributesJob.java | 3 +- .../lock/RegistrationLockDialog.java | 236 ------ .../lock/RegistrationLockReminders.java | 51 -- .../AppProtectionPreferenceFragment.java | 16 +- .../securesms/recipients/Recipient.java | 17 - .../recipients/RecipientProvider.java | 2 - .../securesms/search/SearchRepository.java | 4 - .../securesms/util/TextSecurePreferences.java | 38 - app/src/main/protobuf/DeviceName.proto | 15 - .../res/layout/activity_contact_name_edit.xml | 71 -- .../main/res/layout/conversation_activity.xml | 7 - ...onversation_activity_reminderview_stub.xml | 6 - ...versation_item_received_shared_contact.xml | 11 - .../conversation_item_sent_shared_contact.xml | 10 - .../res/layout/conversation_title_view.xml | 83 -- .../main/res/layout/push_recipients_panel.xml | 30 - .../registration_lock_reminder_view.xml | 53 -- app/src/main/res/values/attrs.xml | 7 - 55 files changed, 45 insertions(+), 5681 deletions(-) delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/components/HourglassView.java delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/components/ImageDivet.java delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/components/PushRecipientsPanel.java delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/components/RatingManager.java delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/components/RecyclerViewFastScroller.java delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/components/SharedContactView.java delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/components/SquareLinearLayout.java delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/components/reminder/Reminder.java delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/components/reminder/ReminderView.java delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/contacts/ArrayListCursor.java delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/contacts/ContactIdentityManager.java delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/contacts/ContactIdentityManagerICS.java delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/contacts/ContactsDatabase.java delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/contacts/NameAndNumber.java delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/contacts/RecipientsAdapter.java delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/contacts/RecipientsEditor.java delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/contactshare/ContactFieldAdapter.java delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/contactshare/ContactNameEditActivity.java delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/contactshare/ContactNameEditViewModel.java delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/contactshare/ContactRepository.java delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/contactshare/ContactShareEditActivity.java delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/contactshare/ContactShareEditAdapter.java delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/contactshare/ContactShareEditViewModel.java delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationTitleView.java delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/devicelist/DeviceNameProtos.java delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/events/RedPhoneEvent.java delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/events/ReminderUpdateEvent.java delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/lock/RegistrationLockDialog.java delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/lock/RegistrationLockReminders.java delete mode 100644 app/src/main/protobuf/DeviceName.proto delete mode 100644 app/src/main/res/layout/activity_contact_name_edit.xml delete mode 100644 app/src/main/res/layout/conversation_activity_reminderview_stub.xml delete mode 100644 app/src/main/res/layout/conversation_item_received_shared_contact.xml delete mode 100644 app/src/main/res/layout/conversation_item_sent_shared_contact.xml delete mode 100644 app/src/main/res/layout/conversation_title_view.xml delete mode 100644 app/src/main/res/layout/push_recipients_panel.xml delete mode 100644 app/src/main/res/layout/registration_lock_reminder_view.xml diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 024d2704f..72d3509fa 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -399,13 +399,6 @@ - - . - */ -package org.thoughtcrime.securesms.components; - -import android.content.Context; - -import androidx.annotation.NonNull; -import android.text.TextUtils; -import android.util.AttributeSet; -import android.view.LayoutInflater; -import android.view.View; -import android.widget.AdapterView; -import android.widget.RelativeLayout; - -import network.loki.messenger.R; -import org.thoughtcrime.securesms.contacts.RecipientsAdapter; -import org.thoughtcrime.securesms.contacts.RecipientsEditor; -import org.thoughtcrime.securesms.database.Address; -import org.thoughtcrime.securesms.recipients.Recipient; -import org.thoughtcrime.securesms.recipients.RecipientModifiedListener; - -import java.util.LinkedList; -import java.util.List; -import java.util.StringTokenizer; - -/** - * Panel component combining both an editable field with a button for - * a list-based contact selector. - * - * @author Moxie Marlinspike - */ -public class PushRecipientsPanel extends RelativeLayout implements RecipientModifiedListener { - private final String TAG = PushRecipientsPanel.class.getSimpleName(); - private RecipientsPanelChangedListener panelChangeListener; - - private RecipientsEditor recipientsText; - private View panel; - - private static final int RECIPIENTS_MAX_LENGTH = 312; - - public PushRecipientsPanel(Context context) { - super(context); - initialize(); - } - - public PushRecipientsPanel(Context context, AttributeSet attrs) { - super(context, attrs); - initialize(); - } - - public PushRecipientsPanel(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - initialize(); - } - - public List getRecipients() { - String rawText = recipientsText.getText().toString(); - return getRecipientsFromString(getContext(), rawText, true); - } - - public void disable() { - recipientsText.setText(""); - panel.setVisibility(View.GONE); - } - - public void setPanelChangeListener(RecipientsPanelChangedListener panelChangeListener) { - this.panelChangeListener = panelChangeListener; - } - - private void initialize() { - LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); - inflater.inflate(R.layout.push_recipients_panel, this, true); - - View imageButton = findViewById(R.id.contacts_button); - ((MarginLayoutParams) imageButton.getLayoutParams()).topMargin = 0; - - panel = findViewById(R.id.recipients_panel); - initRecipientsEditor(); - } - - private void initRecipientsEditor() { - - this.recipientsText = (RecipientsEditor)findViewById(R.id.recipients_text); - - List recipients = getRecipients(); - - for (Recipient recipient : recipients) { - recipient.addListener(this); - } - - recipientsText.setAdapter(new RecipientsAdapter(this.getContext())); - recipientsText.populate(recipients); - - recipientsText.setOnFocusChangeListener(new FocusChangedListener()); - recipientsText.setOnItemClickListener(new AdapterView.OnItemClickListener() { - @Override - public void onItemClick(AdapterView adapterView, View view, int i, long l) { - if (panelChangeListener != null) { - panelChangeListener.onRecipientsPanelUpdate(getRecipients()); - } - recipientsText.setText(""); - } - }); - } - - private @NonNull List getRecipientsFromString(Context context, @NonNull String rawText, boolean asynchronous) { - StringTokenizer tokenizer = new StringTokenizer(rawText, ","); - List recipients = new LinkedList<>(); - - while (tokenizer.hasMoreTokens()) { - String token = tokenizer.nextToken().trim(); - - if (!TextUtils.isEmpty(token)) { - if (hasBracketedNumber(token)) recipients.add(Recipient.from(context, Address.fromExternal(context, parseBracketedNumber(token)), asynchronous)); - else recipients.add(Recipient.from(context, Address.fromExternal(context, token), asynchronous)); - } - } - - return recipients; - } - - private boolean hasBracketedNumber(String recipient) { - int openBracketIndex = recipient.indexOf('<'); - - return (openBracketIndex != -1) && - (recipient.indexOf('>', openBracketIndex) != -1); - } - - private String parseBracketedNumber(String recipient) { - int begin = recipient.indexOf('<'); - int end = recipient.indexOf('>', begin); - String value = recipient.substring(begin + 1, end); - - return value; - } - - @Override - public void onModified(Recipient recipient) { - recipientsText.populate(getRecipients()); - } - - private class FocusChangedListener implements View.OnFocusChangeListener { - public void onFocusChange(View v, boolean hasFocus) { - if (!hasFocus && (panelChangeListener != null)) { - panelChangeListener.onRecipientsPanelUpdate(getRecipients()); - } - } - } - - public interface RecipientsPanelChangedListener { - public void onRecipientsPanelUpdate(List recipients); - } - -} \ No newline at end of file diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/RatingManager.java b/app/src/main/java/org/thoughtcrime/securesms/components/RatingManager.java deleted file mode 100644 index 7114f240d..000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/components/RatingManager.java +++ /dev/null @@ -1,88 +0,0 @@ -package org.thoughtcrime.securesms.components; - -import android.content.ActivityNotFoundException; -import android.content.Context; -import android.content.DialogInterface; -import android.content.Intent; -import android.content.pm.PackageManager; -import android.net.Uri; -import androidx.appcompat.app.AlertDialog; -import org.thoughtcrime.securesms.logging.Log; -import android.widget.Toast; - -import network.loki.messenger.R; -import org.thoughtcrime.securesms.util.TextSecurePreferences; - -import java.util.concurrent.TimeUnit; - -public class RatingManager { - - private static final int DAYS_SINCE_INSTALL_THRESHOLD = 7; - private static final int DAYS_UNTIL_REPROMPT_THRESHOLD = 4; - - private static final String TAG = RatingManager.class.getSimpleName(); - - public static void showRatingDialogIfNecessary(Context context) { - if (!TextSecurePreferences.isRatingEnabled(context)) return; - - long daysSinceInstall = getDaysSinceInstalled(context); - long laterTimestamp = TextSecurePreferences.getRatingLaterTimestamp(context); - - if (daysSinceInstall >= DAYS_SINCE_INSTALL_THRESHOLD && - System.currentTimeMillis() >= laterTimestamp) - { - showRatingDialog(context); - } - } - - private static void showRatingDialog(final Context context) { - new AlertDialog.Builder(context) - .setTitle(R.string.RatingManager_rate_this_app) - .setMessage(R.string.RatingManager_if_you_enjoy_using_this_app_please_take_a_moment) - .setPositiveButton(R.string.RatingManager_rate_now, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - TextSecurePreferences.setRatingEnabled(context, false); - startPlayStore(context); - } - }) - .setNegativeButton(R.string.RatingManager_no_thanks, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - TextSecurePreferences.setRatingEnabled(context, false); - } - }) - .setNeutralButton(R.string.RatingManager_later, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - long waitUntil = System.currentTimeMillis() + TimeUnit.DAYS.toMillis(DAYS_UNTIL_REPROMPT_THRESHOLD); - TextSecurePreferences.setRatingLaterTimestamp(context, waitUntil); - } - }) - .show(); - } - - private static void startPlayStore(Context context) { - Uri uri = Uri.parse("market://details?id=" + context.getPackageName()); - try { - context.startActivity(new Intent(Intent.ACTION_VIEW, uri)); - } catch (ActivityNotFoundException e) { - Log.w(TAG, e); - Toast.makeText(context, R.string.RatingManager_whoops_the_play_store_app_does_not_appear_to_be_installed, Toast.LENGTH_LONG).show(); - } - } - - private static long getDaysSinceInstalled(Context context) { - try { - long installTimestamp = context.getPackageManager() - .getPackageInfo(context.getPackageName(), 0) - .firstInstallTime; - - return TimeUnit.MILLISECONDS.toDays(System.currentTimeMillis() - installTimestamp); - } catch (PackageManager.NameNotFoundException e) { - Log.w(TAG, e); - return 0; - } - } - -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/RecyclerViewFastScroller.java b/app/src/main/java/org/thoughtcrime/securesms/components/RecyclerViewFastScroller.java deleted file mode 100644 index 50d9d4d3d..000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/components/RecyclerViewFastScroller.java +++ /dev/null @@ -1,213 +0,0 @@ -/** - * Modified version of - * https://github.com/AndroidDeveloperLB/LollipopContactsRecyclerViewFastScroller - * - * Their license: - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.thoughtcrime.securesms.components; - -import android.animation.Animator; -import android.animation.AnimatorListenerAdapter; -import android.animation.ObjectAnimator; -import android.annotation.TargetApi; -import android.content.Context; -import android.os.Build.VERSION; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.recyclerview.widget.LinearLayoutManager; -import androidx.recyclerview.widget.RecyclerView; -import android.util.AttributeSet; -import android.view.MotionEvent; -import android.view.View; -import android.view.ViewTreeObserver; -import android.widget.LinearLayout; -import android.widget.TextView; - -import network.loki.messenger.R; -import org.thoughtcrime.securesms.util.Util; -import org.thoughtcrime.securesms.util.ViewUtil; - -public class RecyclerViewFastScroller extends LinearLayout { - private static final int BUBBLE_ANIMATION_DURATION = 100; - private static final int TRACK_SNAP_RANGE = 5; - - private @NonNull TextView bubble; - private @NonNull View handle; - private @Nullable RecyclerView recyclerView; - - private int height; - private ObjectAnimator currentAnimator; - - private final RecyclerView.OnScrollListener onScrollListener = new RecyclerView.OnScrollListener() { - @Override - public void onScrolled(@NonNull final RecyclerView recyclerView, final int dx, final int dy) { - if (handle.isSelected()) return; - final int offset = recyclerView.computeVerticalScrollOffset(); - final int range = recyclerView.computeVerticalScrollRange(); - final int extent = recyclerView.computeVerticalScrollExtent(); - final int offsetRange = Math.max(range - extent, 1); - setBubbleAndHandlePosition((float) Util.clamp(offset, 0, offsetRange) / offsetRange); - } - }; - - public interface FastScrollAdapter { - CharSequence getBubbleText(int pos); - } - - public RecyclerViewFastScroller(final Context context) { - this(context, null); - } - - public RecyclerViewFastScroller(final Context context, final AttributeSet attrs) { - super(context, attrs); - setOrientation(HORIZONTAL); - setClipChildren(false); - setScrollContainer(true); - inflate(context, R.layout.recycler_view_fast_scroller, this); - bubble = ViewUtil.findById(this, R.id.fastscroller_bubble); - handle = ViewUtil.findById(this, R.id.fastscroller_handle); - } - - @Override - protected void onSizeChanged(int w, int h, int oldw, int oldh) { - super.onSizeChanged(w, h, oldw, oldh); - height = h; - } - - @Override - @TargetApi(11) - public boolean onTouchEvent(@NonNull MotionEvent event) { - final int action = event.getAction(); - switch (action) { - case MotionEvent.ACTION_DOWN: - if (event.getX() < ViewUtil.getX(handle) - handle.getPaddingLeft() || - event.getY() < ViewUtil.getY(handle) - handle.getPaddingTop() || - event.getY() > ViewUtil.getY(handle) + handle.getHeight() + handle.getPaddingBottom()) - { - return false; - } - if (currentAnimator != null) { - currentAnimator.cancel(); - } - if (bubble.getVisibility() != VISIBLE) { - showBubble(); - } - handle.setSelected(true); - case MotionEvent.ACTION_MOVE: - final float y = event.getY(); - setBubbleAndHandlePosition(y / height); - setRecyclerViewPosition(y); - return true; - case MotionEvent.ACTION_UP: - case MotionEvent.ACTION_CANCEL: - handle.setSelected(false); - hideBubble(); - return true; - } - return super.onTouchEvent(event); - } - - public void setRecyclerView(final @NonNull RecyclerView recyclerView) { - if (this.recyclerView != null) { - this.recyclerView.removeOnScrollListener(onScrollListener); - } - this.recyclerView = recyclerView; - recyclerView.addOnScrollListener(onScrollListener); - recyclerView.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { - @Override - public boolean onPreDraw() { - recyclerView.getViewTreeObserver().removeOnPreDrawListener(this); - if (handle.isSelected()) return true; - final int verticalScrollOffset = recyclerView.computeVerticalScrollOffset(); - final int verticalScrollRange = recyclerView.computeVerticalScrollRange(); - float proportion = (float)verticalScrollOffset / ((float)verticalScrollRange - height); - setBubbleAndHandlePosition(height * proportion); - return true; - } - }); - } - - @Override - protected void onDetachedFromWindow() { - super.onDetachedFromWindow(); - if (recyclerView != null) - recyclerView.removeOnScrollListener(onScrollListener); - } - - private void setRecyclerViewPosition(float y) { - if (recyclerView != null) { - final int itemCount = recyclerView.getAdapter().getItemCount(); - float proportion; - if (ViewUtil.getY(handle) == 0) { - proportion = 0f; - } else if (ViewUtil.getY(handle) + handle.getHeight() >= height - TRACK_SNAP_RANGE) { - proportion = 1f; - } else { - proportion = y / (float)height; - } - - final int targetPos = Util.clamp((int)(proportion * (float)itemCount), 0, itemCount - 1); - ((LinearLayoutManager) recyclerView.getLayoutManager()).scrollToPositionWithOffset(targetPos, 0); - final CharSequence bubbleText = ((FastScrollAdapter) recyclerView.getAdapter()).getBubbleText(targetPos); - bubble.setText(bubbleText); - } - } - - private void setBubbleAndHandlePosition(float y) { - final int handleHeight = handle.getHeight(); - final int bubbleHeight = bubble.getHeight(); - final int handleY = Util.clamp((int)((height - handleHeight) * y), 0, height - handleHeight); - ViewUtil.setY(handle, handleY); - ViewUtil.setY(bubble, Util.clamp(handleY - bubbleHeight - bubble.getPaddingBottom() + handleHeight, - 0, - height - bubbleHeight)); - } - - @TargetApi(11) - private void showBubble() { - bubble.setVisibility(VISIBLE); - if (VERSION.SDK_INT >= 11) { - if (currentAnimator != null) currentAnimator.cancel(); - currentAnimator = ObjectAnimator.ofFloat(bubble, "alpha", 0f, 1f).setDuration(BUBBLE_ANIMATION_DURATION); - currentAnimator.start(); - } - } - - @TargetApi(11) - private void hideBubble() { - if (VERSION.SDK_INT >= 11) { - if (currentAnimator != null) currentAnimator.cancel(); - currentAnimator = ObjectAnimator.ofFloat(bubble, "alpha", 1f, 0f).setDuration(BUBBLE_ANIMATION_DURATION); - currentAnimator.addListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animation) { - super.onAnimationEnd(animation); - bubble.setVisibility(INVISIBLE); - currentAnimator = null; - } - - @Override - public void onAnimationCancel(Animator animation) { - super.onAnimationCancel(animation); - bubble.setVisibility(INVISIBLE); - currentAnimator = null; - } - }); - currentAnimator.start(); - } else { - bubble.setVisibility(INVISIBLE); - } - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/SharedContactView.java b/app/src/main/java/org/thoughtcrime/securesms/components/SharedContactView.java deleted file mode 100644 index 5fea44e4f..000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/components/SharedContactView.java +++ /dev/null @@ -1,230 +0,0 @@ -package org.thoughtcrime.securesms.components; - -import android.content.Context; -import android.content.res.TypedArray; -import android.graphics.Canvas; -import android.graphics.Color; -import android.net.Uri; -import android.os.Build; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.annotation.RequiresApi; -import android.util.AttributeSet; -import android.view.View; -import android.widget.ImageView; -import android.widget.LinearLayout; -import android.widget.TextView; - -import com.annimon.stream.Stream; -import com.bumptech.glide.load.engine.DiskCacheStrategy; - -import network.loki.messenger.R; -import org.thoughtcrime.securesms.contactshare.ContactUtil; -import org.thoughtcrime.securesms.contactshare.Contact; -import org.thoughtcrime.securesms.database.RecipientDatabase; -import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader.DecryptableUri; -import org.thoughtcrime.securesms.mms.GlideRequests; -import org.thoughtcrime.securesms.recipients.Recipient; -import org.thoughtcrime.securesms.recipients.RecipientModifiedListener; -import org.thoughtcrime.securesms.util.Util; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Locale; -import java.util.Map; - -public class SharedContactView extends LinearLayout implements RecipientModifiedListener { - - private ImageView avatarView; - private TextView nameView; - private TextView numberView; - private TextView actionButtonView; - private ConversationItemFooter footer; - - private Contact contact; - private Locale locale; - private GlideRequests glideRequests; - private EventListener eventListener; - private CornerMask cornerMask; - private int bigCornerRadius; - private int smallCornerRadius; - - private final Map activeRecipients = new HashMap<>(); - - public SharedContactView(Context context) { - super(context); - initialize(null); - } - - public SharedContactView(Context context, @Nullable AttributeSet attrs) { - super(context, attrs); - initialize(attrs); - } - - public SharedContactView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - initialize(attrs); - } - - @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) - public SharedContactView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { - super(context, attrs, defStyleAttr, defStyleRes); - initialize(attrs); - } - - private void initialize(@Nullable AttributeSet attrs) { - inflate(getContext(), R.layout.shared_contact_view, this); - - avatarView = findViewById(R.id.contact_avatar); - nameView = findViewById(R.id.contact_name); - numberView = findViewById(R.id.contact_number); - actionButtonView = findViewById(R.id.contact_action_button); - footer = findViewById(R.id.contact_footer); - - cornerMask = new CornerMask(this); - bigCornerRadius = getResources().getDimensionPixelOffset(R.dimen.message_corner_radius); - smallCornerRadius = getResources().getDimensionPixelOffset(R.dimen.message_corner_collapse_radius); - - if (attrs != null) { - TypedArray typedArray = getContext().getTheme().obtainStyledAttributes(attrs, R.styleable.SharedContactView, 0, 0); - int titleColor = typedArray.getInt(R.styleable.SharedContactView_contact_titleColor, Color.BLACK); - int captionColor = typedArray.getInt(R.styleable.SharedContactView_contact_captionColor, Color.BLACK); - int iconColor = typedArray.getInt(R.styleable.SharedContactView_contact_footerIconColor, Color.BLACK); - float footerAlpha = typedArray.getFloat(R.styleable.SharedContactView_contact_footerAlpha, 1); - typedArray.recycle(); - - nameView.setTextColor(titleColor); - numberView.setTextColor(captionColor); - footer.setTextColor(captionColor); - footer.setIconColor(iconColor); - footer.setAlpha(footerAlpha); - } - } - - @Override - protected void dispatchDraw(Canvas canvas) { - super.dispatchDraw(canvas); - cornerMask.mask(canvas); - } - - public void setContact(@NonNull Contact contact, @NonNull GlideRequests glideRequests, @NonNull Locale locale) { - this.glideRequests = glideRequests; - this.locale = locale; - this.contact = contact; - - Stream.of(activeRecipients.values()).forEach(recipient -> recipient.removeListener(this)); - this.activeRecipients.clear(); - - presentContact(contact); - presentAvatar(contact.getAvatarAttachment() != null ? contact.getAvatarAttachment().getDataUri() : null); - presentActionButtons(ContactUtil.getRecipients(getContext(), contact)); - } - - public void setSingularStyle() { - cornerMask.setBottomLeftRadius(bigCornerRadius); - cornerMask.setBottomRightRadius(bigCornerRadius); - } - - public void setClusteredIncomingStyle() { - cornerMask.setBottomLeftRadius(smallCornerRadius); - cornerMask.setBottomRightRadius(bigCornerRadius); - } - - public void setClusteredOutgoingStyle() { - cornerMask.setBottomLeftRadius(bigCornerRadius); - cornerMask.setBottomRightRadius(smallCornerRadius); - } - - public void setEventListener(@NonNull EventListener eventListener) { - this.eventListener = eventListener; - } - - public @NonNull View getAvatarView() { - return avatarView; - } - - public ConversationItemFooter getFooter() { - return footer; - } - - @Override - public void onModified(Recipient recipient) { - Util.runOnMain(() -> presentActionButtons(Collections.singletonList(recipient))); - } - - private void presentContact(@Nullable Contact contact) { - if (contact != null) { - nameView.setText(ContactUtil.getDisplayName(contact)); - numberView.setText(ContactUtil.getDisplayNumber(contact, locale)); - } else { - nameView.setText(""); - numberView.setText(""); - } - } - - private void presentAvatar(@Nullable Uri uri) { - if (uri != null) { - glideRequests.load(new DecryptableUri(uri)) - .fallback(R.drawable.ic_contact_picture) - .circleCrop() - .diskCacheStrategy(DiskCacheStrategy.ALL) - .dontAnimate() - .into(avatarView); - } else { - glideRequests.load(R.drawable.ic_contact_picture) - .circleCrop() - .diskCacheStrategy(DiskCacheStrategy.ALL) - .into(avatarView); - } - } - - private void presentActionButtons(@NonNull List recipients) { - for (Recipient recipient : recipients) { - activeRecipients.put(recipient.getAddress().serialize(), recipient); - } - - List pushUsers = new ArrayList<>(recipients.size()); - List systemUsers = new ArrayList<>(recipients.size()); - - for (Recipient recipient : activeRecipients.values()) { - recipient.addListener(this); - - if (recipient.getRegistered() == RecipientDatabase.RegisteredState.REGISTERED) { - pushUsers.add(recipient); - } else if (recipient.isSystemContact()) { - systemUsers.add(recipient); - } - } - - if (!pushUsers.isEmpty()) { - actionButtonView.setText(R.string.SharedContactView_message); - actionButtonView.setOnClickListener(v -> { - if (eventListener != null) { - eventListener.onMessageClicked(pushUsers); - } - }); - } else if (!systemUsers.isEmpty()) { - actionButtonView.setText(R.string.SharedContactView_invite_to_signal); - actionButtonView.setOnClickListener(v -> { - if (eventListener != null) { - eventListener.onInviteClicked(systemUsers); - } - }); - } else { - actionButtonView.setText(R.string.SharedContactView_add_to_contacts); - actionButtonView.setOnClickListener(v -> { - if (eventListener != null && contact != null) { - eventListener.onAddToContactsClicked(contact); - } - }); - } - } - - public interface EventListener { - void onAddToContactsClicked(@NonNull Contact contact); - void onInviteClicked(@NonNull List choices); - void onMessageClicked(@NonNull List choices); - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/SquareLinearLayout.java b/app/src/main/java/org/thoughtcrime/securesms/components/SquareLinearLayout.java deleted file mode 100644 index ea24fb7c2..000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/components/SquareLinearLayout.java +++ /dev/null @@ -1,35 +0,0 @@ -package org.thoughtcrime.securesms.components; - -import android.annotation.TargetApi; -import android.content.Context; -import android.os.Build.VERSION_CODES; -import android.util.AttributeSet; -import android.widget.LinearLayout; - -public class SquareLinearLayout extends LinearLayout { - @SuppressWarnings("unused") - public SquareLinearLayout(Context context) { - super(context); - } - - @SuppressWarnings("unused") - public SquareLinearLayout(Context context, AttributeSet attrs) { - super(context, attrs); - } - - @TargetApi(VERSION_CODES.HONEYCOMB) @SuppressWarnings("unused") - public SquareLinearLayout(Context context, AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - } - - @TargetApi(VERSION_CODES.LOLLIPOP) @SuppressWarnings("unused") - public SquareLinearLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { - super(context, attrs, defStyleAttr, defStyleRes); - } - - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - //noinspection SuspiciousNameCombination - super.onMeasure(widthMeasureSpec, widthMeasureSpec); - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/reminder/Reminder.java b/app/src/main/java/org/thoughtcrime/securesms/components/reminder/Reminder.java deleted file mode 100644 index be0c86717..000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/components/reminder/Reminder.java +++ /dev/null @@ -1,57 +0,0 @@ -package org.thoughtcrime.securesms.components.reminder; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import android.view.View.OnClickListener; - -public abstract class Reminder { - private CharSequence title; - private CharSequence text; - - private OnClickListener okListener; - private OnClickListener dismissListener; - - public Reminder(@Nullable CharSequence title, - @NonNull CharSequence text) - { - this.title = title; - this.text = text; - } - - public @Nullable CharSequence getTitle() { - return title; - } - - public CharSequence getText() { - return text; - } - - public OnClickListener getOkListener() { - return okListener; - } - - public OnClickListener getDismissListener() { - return dismissListener; - } - - public void setOkListener(OnClickListener okListener) { - this.okListener = okListener; - } - - public void setDismissListener(OnClickListener dismissListener) { - this.dismissListener = dismissListener; - } - - public boolean isDismissable() { - return true; - } - - public @NonNull Importance getImportance() { - return Importance.NORMAL; - } - - - public enum Importance { - NORMAL, ERROR - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/reminder/ReminderView.java b/app/src/main/java/org/thoughtcrime/securesms/components/reminder/ReminderView.java deleted file mode 100644 index af59bf4ff..000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/components/reminder/ReminderView.java +++ /dev/null @@ -1,94 +0,0 @@ -package org.thoughtcrime.securesms.components.reminder; - -import android.annotation.TargetApi; -import android.content.Context; -import android.os.Build.VERSION_CODES; -import android.text.TextUtils; -import android.util.AttributeSet; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ImageButton; -import android.widget.LinearLayout; -import android.widget.TextView; - -import network.loki.messenger.R; -import org.thoughtcrime.securesms.util.ViewUtil; - -/** - * View to display actionable reminders to the user - */ -public class ReminderView extends LinearLayout { - private ViewGroup container; - private ImageButton closeButton; - private TextView title; - private TextView text; - private OnDismissListener dismissListener; - - public ReminderView(Context context) { - super(context); - initialize(); - } - - public ReminderView(Context context, AttributeSet attrs) { - super(context, attrs); - initialize(); - } - - @TargetApi(VERSION_CODES.HONEYCOMB) - public ReminderView(Context context, AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - initialize(); - } - - private void initialize() { - LayoutInflater.from(getContext()).inflate(R.layout.reminder_header, this, true); - container = ViewUtil.findById(this, R.id.container); - closeButton = ViewUtil.findById(this, R.id.cancel); - title = ViewUtil.findById(this, R.id.reminder_title); - text = ViewUtil.findById(this, R.id.reminder_text); - } - - public void showReminder(final Reminder reminder) { - if (!TextUtils.isEmpty(reminder.getTitle())) { - title.setText(reminder.getTitle()); - title.setVisibility(VISIBLE); - } else { - title.setText(""); - title.setVisibility(GONE); - } - text.setText(reminder.getText()); - container.setBackgroundResource(reminder.getImportance() == Reminder.Importance.ERROR ? R.drawable.reminder_background_error - : R.drawable.reminder_background_normal); - - setOnClickListener(reminder.getOkListener()); - - closeButton.setVisibility(reminder.isDismissable() ? View.VISIBLE : View.GONE); - closeButton.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - hide(); - if (reminder.getDismissListener() != null) reminder.getDismissListener().onClick(v); - if (dismissListener != null) dismissListener.onDismiss(); - } - }); - - container.setVisibility(View.VISIBLE); - } - - public void setOnDismissListener(OnDismissListener dismissListener) { - this.dismissListener = dismissListener; - } - - public void requestDismiss() { - closeButton.performClick(); - } - - public void hide() { - container.setVisibility(View.GONE); - } - - public interface OnDismissListener { - void onDismiss(); - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/contacts/ArrayListCursor.java b/app/src/main/java/org/thoughtcrime/securesms/contacts/ArrayListCursor.java deleted file mode 100644 index 23b06cedd..000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/contacts/ArrayListCursor.java +++ /dev/null @@ -1,169 +0,0 @@ -package org.thoughtcrime.securesms.contacts; -/* - * Copyright (C) 2006 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import android.database.AbstractCursor; -import android.database.CursorWindow; - -import java.lang.System; -import java.util.ArrayList; - -/** - * A convenience class that presents a two-dimensional ArrayList - * as a Cursor. - */ -public class ArrayListCursor extends AbstractCursor { - private String[] mColumnNames; - private ArrayList[] mRows; - - @SuppressWarnings({"unchecked"}) - public ArrayListCursor(String[] columnNames, ArrayList rows) { - int colCount = columnNames.length; - boolean foundID = false; - // Add an _id column if not in columnNames - for (int i = 0; i < colCount; ++i) { - if (columnNames[i].compareToIgnoreCase("_id") == 0) { - mColumnNames = columnNames; - foundID = true; - break; - } - } - - if (!foundID) { - mColumnNames = new String[colCount + 1]; - System.arraycopy(columnNames, 0, mColumnNames, 0, columnNames.length); - mColumnNames[colCount] = "_id"; - } - - int rowCount = rows.size(); - mRows = new ArrayList[rowCount]; - - for (int i = 0; i < rowCount; ++i) { - mRows[i] = rows.get(i); - if (!foundID) { - mRows[i].add(i); - } - } - } - - @Override - public void fillWindow(int position, CursorWindow window) { - if (position < 0 || position > getCount()) { - return; - } - - window.acquireReference(); - try { - int oldpos = mPos; - mPos = position - 1; - window.clear(); - window.setStartPosition(position); - int columnNum = getColumnCount(); - window.setNumColumns(columnNum); - while (moveToNext() && window.allocRow()) { - for (int i = 0; i < columnNum; i++) { - final Object data = mRows[mPos].get(i); - if (data != null) { - if (data instanceof byte[]) { - byte[] field = (byte[]) data; - if (!window.putBlob(field, mPos, i)) { - window.freeLastRow(); - break; - } - } else { - String field = data.toString(); - if (!window.putString(field, mPos, i)) { - window.freeLastRow(); - break; - } - } - } else { - if (!window.putNull(mPos, i)) { - window.freeLastRow(); - break; - } - } - } - } - - mPos = oldpos; - } catch (IllegalStateException e){ - // simply ignore it - } finally { - window.releaseReference(); - } - } - - @Override - public int getCount() { - return mRows.length; - } - - public boolean deleteRow() { - return false; - } - - @Override - public String[] getColumnNames() { - return mColumnNames; - } - - @Override - public byte[] getBlob(int columnIndex) { - return (byte[]) mRows[mPos].get(columnIndex); - } - - @Override - public String getString(int columnIndex) { - Object cell = mRows[mPos].get(columnIndex); - return (cell == null) ? null : cell.toString(); - } - - @Override - public short getShort(int columnIndex) { - Number num = (Number) mRows[mPos].get(columnIndex); - return num.shortValue(); - } - - @Override - public int getInt(int columnIndex) { - Number num = (Number) mRows[mPos].get(columnIndex); - return num.intValue(); - } - - @Override - public long getLong(int columnIndex) { - Number num = (Number) mRows[mPos].get(columnIndex); - return num.longValue(); - } - - @Override - public float getFloat(int columnIndex) { - Number num = (Number) mRows[mPos].get(columnIndex); - return num.floatValue(); - } - - @Override - public double getDouble(int columnIndex) { - Number num = (Number) mRows[mPos].get(columnIndex); - return num.doubleValue(); - } - - @Override - public boolean isNull(int columnIndex) { - return mRows[mPos].get(columnIndex) == null; - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/contacts/ContactIdentityManager.java b/app/src/main/java/org/thoughtcrime/securesms/contacts/ContactIdentityManager.java deleted file mode 100644 index 27b9ec846..000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/contacts/ContactIdentityManager.java +++ /dev/null @@ -1,24 +0,0 @@ -package org.thoughtcrime.securesms.contacts; - -import android.content.Context; -import android.net.Uri; - -import java.util.List; - -public abstract class ContactIdentityManager { - - public static ContactIdentityManager getInstance(Context context) { - return new ContactIdentityManagerICS(context); - } - - protected final Context context; - - public ContactIdentityManager(Context context) { - this.context = context.getApplicationContext(); - } - - public abstract Uri getSelfIdentityUri(); - public abstract boolean isSelfIdentityAutoDetected(); - public abstract List getSelfIdentityRawContactIds(); - -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/contacts/ContactIdentityManagerICS.java b/app/src/main/java/org/thoughtcrime/securesms/contacts/ContactIdentityManagerICS.java deleted file mode 100644 index c81bacfd6..000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/contacts/ContactIdentityManagerICS.java +++ /dev/null @@ -1,76 +0,0 @@ -package org.thoughtcrime.securesms.contacts; - -import android.content.Context; -import android.database.Cursor; -import android.net.Uri; -import android.provider.ContactsContract; -import android.provider.ContactsContract.Contacts; -import android.provider.ContactsContract.PhoneLookup; - -import java.util.LinkedList; -import java.util.List; - -class ContactIdentityManagerICS extends ContactIdentityManager { - - public ContactIdentityManagerICS(Context context) { - super(context); - } - - @Override - public Uri getSelfIdentityUri() { - String[] PROJECTION = new String[] { - PhoneLookup.DISPLAY_NAME, - PhoneLookup.LOOKUP_KEY, - PhoneLookup._ID, - }; - - Cursor cursor = null; - - try { - cursor = context.getContentResolver().query(ContactsContract.Profile.CONTENT_URI, - PROJECTION, null, null, null); - - if (cursor != null && cursor.moveToFirst()) { - return Contacts.getLookupUri(cursor.getLong(2), cursor.getString(1)); - } - } finally { - if (cursor != null) - cursor.close(); - } - - return null; - } - - @Override - public boolean isSelfIdentityAutoDetected() { - return true; - } - - @Override - public List getSelfIdentityRawContactIds() { - List results = new LinkedList(); - - String[] PROJECTION = new String[] { - ContactsContract.Profile._ID - }; - - Cursor cursor = null; - - try { - cursor = context.getContentResolver().query(ContactsContract.Profile.CONTENT_RAW_CONTACTS_URI, - PROJECTION, null, null, null); - - if (cursor == null || cursor.getCount() == 0) - return null; - - while (cursor.moveToNext()) { - results.add(cursor.getLong(0)); - } - - return results; - } finally { - if (cursor != null) - cursor.close(); - } - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/contacts/ContactsCursorLoader.java b/app/src/main/java/org/thoughtcrime/securesms/contacts/ContactsCursorLoader.java index a229ca838..cf4c85e9c 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/contacts/ContactsCursorLoader.java +++ b/app/src/main/java/org/thoughtcrime/securesms/contacts/ContactsCursorLoader.java @@ -26,14 +26,11 @@ import androidx.loader.content.CursorLoader; import android.text.TextUtils; import network.loki.messenger.R; -import org.thoughtcrime.securesms.database.Address; + import org.thoughtcrime.securesms.database.DatabaseFactory; 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.logging.Log; -import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.util.NumberUtil; import java.util.ArrayList; @@ -45,9 +42,20 @@ import java.util.List; * @author Jake McGinty */ public class ContactsCursorLoader extends CursorLoader { - private static final String TAG = ContactsCursorLoader.class.getSimpleName(); + static final int NORMAL_TYPE = 0; + static final int PUSH_TYPE = 1; + static final int NEW_TYPE = 2; + static final int RECENT_TYPE = 3; + static final int DIVIDER_TYPE = 4; + + static final String CONTACT_TYPE_COLUMN = "contact_type"; + static final String LABEL_COLUMN = "label"; + static final String NUMBER_TYPE_COLUMN = "number_type"; + static final String NUMBER_COLUMN = "number"; + static final String NAME_COLUMN = "name"; + public static final class DisplayMode { public static final int FLAG_PUSH = 1; public static final int FLAG_SMS = 1 << 1; @@ -55,11 +63,11 @@ public class ContactsCursorLoader extends CursorLoader { public static final int FLAG_ALL = FLAG_PUSH | FLAG_SMS | FLAG_GROUPS; } - private static final String[] CONTACT_PROJECTION = new String[]{ContactsDatabase.NAME_COLUMN, - ContactsDatabase.NUMBER_COLUMN, - ContactsDatabase.NUMBER_TYPE_COLUMN, - ContactsDatabase.LABEL_COLUMN, - ContactsDatabase.CONTACT_TYPE_COLUMN}; + private static final String[] CONTACT_PROJECTION = new String[]{NAME_COLUMN, + NUMBER_COLUMN, + NUMBER_TYPE_COLUMN, + LABEL_COLUMN, + CONTACT_TYPE_COLUMN}; private static final int RECENT_CONVERSATION_MAX = 25; @@ -158,7 +166,7 @@ public class ContactsCursorLoader extends CursorLoader { "", ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE, "", - ContactsDatabase.DIVIDER_TYPE }); + DIVIDER_TYPE }); return groupHeader; } @@ -175,17 +183,14 @@ public class ContactsCursorLoader extends CursorLoader { threadRecord.getRecipient().getAddress().serialize(), ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE, "", - ContactsDatabase.RECENT_TYPE }); + RECENT_TYPE }); } } return recentConversations; } private List getContactsCursors() { - ContactsDatabase contactsDatabase = DatabaseFactory.getContactsDatabase(getContext()); - List cursorList = new ArrayList<>(2); - - return cursorList; + return new ArrayList<>(2); /* if (!Permissions.hasAny(getContext(), Manifest.permission.READ_CONTACTS, Manifest.permission.WRITE_CONTACTS)) { return cursorList; @@ -213,7 +218,7 @@ public class ContactsCursorLoader extends CursorLoader { groupRecord.getEncodedId(), ContactsContract.CommonDataKinds.Phone.TYPE_CUSTOM, "", - ContactsDatabase.NORMAL_TYPE }); + NORMAL_TYPE }); } } return groupContacts; @@ -225,33 +230,10 @@ public class ContactsCursorLoader extends CursorLoader { filter, ContactsContract.CommonDataKinds.Phone.TYPE_CUSTOM, "\u21e2", - ContactsDatabase.NEW_TYPE }); + NEW_TYPE }); return newNumberCursor; } - private @NonNull Cursor filterNonPushContacts(@NonNull Cursor cursor) { - try { - final long startMillis = System.currentTimeMillis(); - final MatrixCursor matrix = new MatrixCursor(CONTACT_PROJECTION); - while (cursor.moveToNext()) { - final String number = cursor.getString(cursor.getColumnIndexOrThrow(ContactsDatabase.NUMBER_COLUMN)); - final Recipient recipient = Recipient.from(getContext(), Address.fromExternal(getContext(), number), false); - - if (recipient.resolve().getRegistered() != RecipientDatabase.RegisteredState.REGISTERED) { - matrix.addRow(new Object[]{cursor.getString(cursor.getColumnIndexOrThrow(ContactsDatabase.NAME_COLUMN)), - number, - cursor.getString(cursor.getColumnIndexOrThrow(ContactsDatabase.NUMBER_TYPE_COLUMN)), - cursor.getString(cursor.getColumnIndexOrThrow(ContactsDatabase.LABEL_COLUMN)), - ContactsDatabase.NORMAL_TYPE}); - } - } - Log.i(TAG, "filterNonPushContacts() -> " + (System.currentTimeMillis() - startMillis) + "ms"); - return matrix; - } finally { - cursor.close(); - } - } - private static boolean isCursorListEmpty(List list) { int sum = 0; for (Cursor cursor : list) { diff --git a/app/src/main/java/org/thoughtcrime/securesms/contacts/ContactsDatabase.java b/app/src/main/java/org/thoughtcrime/securesms/contacts/ContactsDatabase.java deleted file mode 100644 index a4d406a4c..000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/contacts/ContactsDatabase.java +++ /dev/null @@ -1,729 +0,0 @@ -/* - * Copyright (C) 2013 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 . - */ -package org.thoughtcrime.securesms.contacts; - -import android.accounts.Account; -import android.annotation.SuppressLint; -import android.content.ContentProviderOperation; -import android.content.ContentResolver; -import android.content.Context; -import android.content.OperationApplicationException; -import android.database.Cursor; -import android.database.CursorWrapper; -import android.database.MatrixCursor; -import android.database.MergeCursor; -import android.net.Uri; -import android.os.Build; -import android.os.RemoteException; -import android.provider.BaseColumns; -import android.provider.ContactsContract; -import android.provider.ContactsContract.RawContacts; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import android.text.TextUtils; -import android.util.Pair; - -import network.loki.messenger.R; -import org.thoughtcrime.securesms.database.Address; -import org.thoughtcrime.securesms.logging.Log; -import org.thoughtcrime.securesms.util.TextSecurePreferences; -import org.thoughtcrime.securesms.util.Util; -import org.session.libsignal.libsignal.util.guava.Optional; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -/** - * Database to supply all types of contacts that TextSecure needs to know about - * - * @author Jake McGinty - */ -public class ContactsDatabase { - - private static final String TAG = ContactsDatabase.class.getSimpleName(); - private static final String CONTACT_MIMETYPE = "vnd.android.cursor.item/vnd.org.thoughtcrime.securesms.contact"; - private static final String CALL_MIMETYPE = "vnd.android.cursor.item/vnd.org.thoughtcrime.securesms.call"; - private static final String SYNC = "__TS"; - - static final String NAME_COLUMN = "name"; - static final String NUMBER_COLUMN = "number"; - static final String NUMBER_TYPE_COLUMN = "number_type"; - static final String LABEL_COLUMN = "label"; - static final String CONTACT_TYPE_COLUMN = "contact_type"; - - static final int NORMAL_TYPE = 0; - static final int PUSH_TYPE = 1; - static final int NEW_TYPE = 2; - static final int RECENT_TYPE = 3; - static final int DIVIDER_TYPE = 4; - - private final Context context; - - public ContactsDatabase(Context context) { - this.context = context; - } - - public synchronized void removeDeletedRawContacts(@NonNull Account account) { - Uri currentContactsUri = RawContacts.CONTENT_URI.buildUpon() - .appendQueryParameter(RawContacts.ACCOUNT_NAME, account.name) - .appendQueryParameter(RawContacts.ACCOUNT_TYPE, account.type) - .appendQueryParameter(ContactsContract.CALLER_IS_SYNCADAPTER, "true") - .build(); - - String[] projection = new String[] {BaseColumns._ID, RawContacts.SYNC1}; - - try (Cursor cursor = context.getContentResolver().query(currentContactsUri, projection, RawContacts.DELETED + " = ?", new String[] {"1"}, null)) { - while (cursor != null && cursor.moveToNext()) { - long rawContactId = cursor.getLong(0); - Log.i(TAG, "Deleting raw contact: " + cursor.getString(1) + ", " + rawContactId); - - context.getContentResolver().delete(currentContactsUri, RawContacts._ID + " = ?", new String[] {String.valueOf(rawContactId)}); - } - } - } - - public synchronized void setRegisteredUsers(@NonNull Account account, - @NonNull List
registeredAddressList, - boolean remove) - throws RemoteException, OperationApplicationException - { - Set
registeredAddressSet = new HashSet<>(registeredAddressList); - ArrayList operations = new ArrayList<>(); - Map currentContacts = getSignalRawContacts(account); - List> registeredChunks = Util.chunk(registeredAddressList, 50); - - for (List
registeredChunk : registeredChunks) { - for (Address registeredAddress : registeredChunk) { - if (!currentContacts.containsKey(registeredAddress)) { - Optional systemContactInfo = getSystemContactInfo(registeredAddress); - - if (systemContactInfo.isPresent()) { - Log.i(TAG, "Adding number: " + registeredAddress); - addTextSecureRawContact(operations, account, systemContactInfo.get().number, - systemContactInfo.get().name, systemContactInfo.get().id); - } - } - } - if (!operations.isEmpty()) { - context.getContentResolver().applyBatch(ContactsContract.AUTHORITY, operations); - operations.clear(); - } - } - - for (Map.Entry currentContactEntry : currentContacts.entrySet()) { - if (!registeredAddressSet.contains(currentContactEntry.getKey())) { - if (remove) { - Log.i(TAG, "Removing number: " + currentContactEntry.getKey()); - removeTextSecureRawContact(operations, account, currentContactEntry.getValue().getId()); - } - } else if (!currentContactEntry.getValue().isVoiceSupported()) { - Log.i(TAG, "Adding voice support: " + currentContactEntry.getKey()); - addContactVoiceSupport(operations, currentContactEntry.getKey(), currentContactEntry.getValue().getId()); - } else if (!Util.isStringEquals(currentContactEntry.getValue().getRawDisplayName(), - currentContactEntry.getValue().getAggregateDisplayName())) - { - Log.i(TAG, "Updating display name: " + currentContactEntry.getKey()); - updateDisplayName(operations, currentContactEntry.getValue().getAggregateDisplayName(), currentContactEntry.getValue().getId(), currentContactEntry.getValue().getDisplayNameSource()); - } - } - - if (!operations.isEmpty()) { - applyOperationsInBatches(context.getContentResolver(), ContactsContract.AUTHORITY, operations, 50); - } - } - - @SuppressLint("Recycle") - public @NonNull Cursor querySystemContacts(@Nullable String filter) { - Uri uri; - - if (!TextUtils.isEmpty(filter)) { - uri = Uri.withAppendedPath(ContactsContract.CommonDataKinds.Phone.CONTENT_FILTER_URI, Uri.encode(filter)); - } else { - uri = ContactsContract.CommonDataKinds.Phone.CONTENT_URI; - } - - if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - uri = uri.buildUpon().appendQueryParameter(ContactsContract.REMOVE_DUPLICATE_ENTRIES, "true").build(); - } - - String[] projection = new String[]{ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME, - ContactsContract.CommonDataKinds.Phone.NUMBER, - ContactsContract.CommonDataKinds.Phone.TYPE, - ContactsContract.CommonDataKinds.Phone.LABEL}; - - String sort = ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME + " COLLATE LOCALIZED ASC"; - - Map projectionMap = new HashMap() {{ - put(NAME_COLUMN, ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME); - put(NUMBER_COLUMN, ContactsContract.CommonDataKinds.Phone.NUMBER); - put(NUMBER_TYPE_COLUMN, ContactsContract.CommonDataKinds.Phone.TYPE); - put(LABEL_COLUMN, ContactsContract.CommonDataKinds.Phone.LABEL); - }}; - - String formattedNumber = "REPLACE(REPLACE(REPLACE(REPLACE(data1,' ',''),'-',''),'(',''),')','')"; - String excludeSelection = "(" + formattedNumber +" NOT IN " + - "(SELECT data1 FROM view_data WHERE "+formattedNumber+" = data1) " + - "OR "+formattedNumber+" = data1)" + - "AND " + formattedNumber + "NOT IN (SELECT "+formattedNumber+" FROM view_data where mimetype = '"+CONTACT_MIMETYPE+"')" ; - - String fallbackSelection = ContactsContract.Data.SYNC2 + " IS NULL OR " + ContactsContract.Data.SYNC2 + " != '" + SYNC + "'"; - - Cursor cursor; - - try { - cursor = context.getContentResolver().query(uri, projection, excludeSelection, null, sort); - } catch (Exception e) { - Log.w(TAG, e); - cursor = context.getContentResolver().query(uri, projection, fallbackSelection, null, sort); - } - - return new ProjectionMappingCursor(cursor, projectionMap, new Pair<>(CONTACT_TYPE_COLUMN, NORMAL_TYPE)); - } - - @SuppressLint("Recycle") - public @NonNull Cursor queryTextSecureContacts(String filter) { - String[] projection = new String[] {ContactsContract.Contacts.DISPLAY_NAME, - ContactsContract.Data.DATA1}; - - String sort = ContactsContract.Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC"; - - Map projectionMap = new HashMap(){{ - put(NAME_COLUMN, ContactsContract.Contacts.DISPLAY_NAME); - put(NUMBER_COLUMN, ContactsContract.Data.DATA1); - }}; - - Cursor cursor; - - if (TextUtils.isEmpty(filter)) { - cursor = context.getContentResolver().query(ContactsContract.Data.CONTENT_URI, - projection, - ContactsContract.Data.MIMETYPE + " = ?", - new String[] {CONTACT_MIMETYPE}, - sort); - } else { - cursor = context.getContentResolver().query(ContactsContract.Data.CONTENT_URI, - projection, - ContactsContract.Data.MIMETYPE + " = ? AND (" + ContactsContract.Contacts.DISPLAY_NAME + " LIKE ? OR " + ContactsContract.Data.DATA1 + " LIKE ?)", - new String[] {CONTACT_MIMETYPE, - "%" + filter + "%", "%" + filter + "%"}, - sort); - - if (context.getString(R.string.note_to_self).toLowerCase().contains(filter.toLowerCase())) { - Optional self = getSystemContactInfo(Address.fromSerialized(TextSecurePreferences.getLocalNumber(context))); - boolean shouldAdd = true; - - if (self.isPresent()) { - boolean nameMatch = self.get().name != null && self.get().name.toLowerCase().contains(filter.toLowerCase()); - boolean numberMatch = self.get().number != null && self.get().number.contains(filter); - - shouldAdd = !nameMatch && !numberMatch; - } - - if (shouldAdd) { - MatrixCursor selfCursor = new MatrixCursor(projection); - selfCursor.addRow(new Object[]{ context.getString(R.string.note_to_self), TextSecurePreferences.getLocalNumber(context)}); - - cursor = cursor == null ? selfCursor : new MergeCursor(new Cursor[]{ cursor, selfCursor }); - } - } - } - - return new ProjectionMappingCursor(cursor, projectionMap, - new Pair<>(LABEL_COLUMN, "TextSecure"), - new Pair<>(NUMBER_TYPE_COLUMN, 0), - new Pair<>(CONTACT_TYPE_COLUMN, PUSH_TYPE)); - - } - - public @Nullable Cursor getNameDetails(long contactId) { - String[] projection = new String[] { ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, - ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME, - ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME, - ContactsContract.CommonDataKinds.StructuredName.PREFIX, - ContactsContract.CommonDataKinds.StructuredName.SUFFIX, - ContactsContract.CommonDataKinds.StructuredName.MIDDLE_NAME }; - String selection = ContactsContract.Data.CONTACT_ID + " = ? AND " + ContactsContract.Data.MIMETYPE + " = ?"; - String[] args = new String[] { String.valueOf(contactId), ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE }; - - return context.getContentResolver().query(ContactsContract.Data.CONTENT_URI, - projection, - selection, - args, - null); - } - - public @Nullable String getOrganizationName(long contactId) { - String[] projection = new String[] { ContactsContract.CommonDataKinds.Organization.COMPANY }; - String selection = ContactsContract.Data.CONTACT_ID + " = ? AND " + ContactsContract.Data.MIMETYPE + " = ?"; - String[] args = new String[] { String.valueOf(contactId), ContactsContract.CommonDataKinds.Organization.CONTENT_ITEM_TYPE }; - - try (Cursor cursor = context.getContentResolver().query(ContactsContract.Data.CONTENT_URI, - projection, - selection, - args, - null)) - { - if (cursor != null && cursor.moveToFirst()) { - return cursor.getString(0); - } - } - - return null; - } - - public @Nullable Cursor getPhoneDetails(long contactId) { - String[] projection = new String[] { ContactsContract.CommonDataKinds.Phone.NUMBER, - ContactsContract.CommonDataKinds.Phone.TYPE, - ContactsContract.CommonDataKinds.Phone.LABEL }; - String selection = ContactsContract.Data.CONTACT_ID + " = ? AND " + ContactsContract.Data.MIMETYPE + " = ?"; - String[] args = new String[] { String.valueOf(contactId), ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE }; - - return context.getContentResolver().query(ContactsContract.Data.CONTENT_URI, - projection, - selection, - args, - null); - } - - public @Nullable Cursor getEmailDetails(long contactId) { - String[] projection = new String[] { ContactsContract.CommonDataKinds.Email.ADDRESS, - ContactsContract.CommonDataKinds.Email.TYPE, - ContactsContract.CommonDataKinds.Email.LABEL }; - String selection = ContactsContract.Data.CONTACT_ID + " = ? AND " + ContactsContract.Data.MIMETYPE + " = ?"; - String[] args = new String[] { String.valueOf(contactId), ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE }; - - return context.getContentResolver().query(ContactsContract.Data.CONTENT_URI, - projection, - selection, - args, - null); - } - - public @Nullable Cursor getPostalAddressDetails(long contactId) { - String[] projection = new String[] { ContactsContract.CommonDataKinds.StructuredPostal.TYPE, - ContactsContract.CommonDataKinds.StructuredPostal.LABEL, - ContactsContract.CommonDataKinds.StructuredPostal.STREET, - ContactsContract.CommonDataKinds.StructuredPostal.POBOX, - ContactsContract.CommonDataKinds.StructuredPostal.NEIGHBORHOOD, - ContactsContract.CommonDataKinds.StructuredPostal.CITY, - ContactsContract.CommonDataKinds.StructuredPostal.REGION, - ContactsContract.CommonDataKinds.StructuredPostal.POSTCODE, - ContactsContract.CommonDataKinds.StructuredPostal.COUNTRY }; - String selection = ContactsContract.Data.CONTACT_ID + " = ? AND " + ContactsContract.Data.MIMETYPE + " = ?"; - String[] args = new String[] { String.valueOf(contactId), ContactsContract.CommonDataKinds.StructuredPostal.CONTENT_ITEM_TYPE }; - - return context.getContentResolver().query(ContactsContract.Data.CONTENT_URI, - projection, - selection, - args, - null); - } - - public @Nullable Uri getAvatarUri(long contactId) { - String[] projection = new String[] { ContactsContract.CommonDataKinds.Photo.PHOTO_URI }; - String selection = ContactsContract.Data.CONTACT_ID + " = ? AND " + ContactsContract.Data.MIMETYPE + " = ?"; - String[] args = new String[] { String.valueOf(contactId), ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE }; - - try (Cursor cursor = context.getContentResolver().query(ContactsContract.Data.CONTENT_URI, - projection, - selection, - args, - null)) - { - if (cursor != null && cursor.moveToFirst()) { - String uri = cursor.getString(0); - if (uri != null) { - return Uri.parse(uri); - } - } - } - - return null; - } - - - - private void addContactVoiceSupport(List operations, - @NonNull Address address, long rawContactId) - { - operations.add(ContentProviderOperation.newUpdate(RawContacts.CONTENT_URI) - .withSelection(RawContacts._ID + " = ?", new String[] {String.valueOf(rawContactId)}) - .withValue(RawContacts.SYNC4, "true") - .build()); - - operations.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI.buildUpon().appendQueryParameter(ContactsContract.CALLER_IS_SYNCADAPTER, "true").build()) - .withValue(ContactsContract.Data.RAW_CONTACT_ID, rawContactId) - .withValue(ContactsContract.Data.MIMETYPE, CALL_MIMETYPE) - .withValue(ContactsContract.Data.DATA1, address.toPhoneString()) - .withValue(ContactsContract.Data.DATA2, context.getString(R.string.app_name)) - .withValue(ContactsContract.Data.DATA3, context.getString(R.string.ContactsDatabase_signal_call_s, address.toPhoneString())) - .withYieldAllowed(true) - .build()); - } - - private void updateDisplayName(List operations, - @Nullable String displayName, - long rawContactId, int displayNameSource) - { - Uri dataUri = ContactsContract.Data.CONTENT_URI.buildUpon() - .appendQueryParameter(ContactsContract.CALLER_IS_SYNCADAPTER, "true") - .build(); - - if (displayNameSource != ContactsContract.DisplayNameSources.STRUCTURED_NAME) { - operations.add(ContentProviderOperation.newInsert(dataUri) - .withValue(ContactsContract.CommonDataKinds.StructuredName.RAW_CONTACT_ID, rawContactId) - .withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, displayName) - .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE) - .build()); - } else { - operations.add(ContentProviderOperation.newUpdate(dataUri) - .withSelection(ContactsContract.CommonDataKinds.StructuredName.RAW_CONTACT_ID + " = ? AND " + ContactsContract.Data.MIMETYPE + " = ?", - new String[] {String.valueOf(rawContactId), ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE}) - .withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, displayName) - .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE) - .build()); - } - } - - private void addTextSecureRawContact(List operations, - Account account, String e164number, String displayName, - long aggregateId) - { - int index = operations.size(); - Uri dataUri = ContactsContract.Data.CONTENT_URI.buildUpon() - .appendQueryParameter(ContactsContract.CALLER_IS_SYNCADAPTER, "true") - .build(); - - operations.add(ContentProviderOperation.newInsert(RawContacts.CONTENT_URI) - .withValue(RawContacts.ACCOUNT_NAME, account.name) - .withValue(RawContacts.ACCOUNT_TYPE, account.type) - .withValue(RawContacts.SYNC1, e164number) - .withValue(RawContacts.SYNC4, String.valueOf(true)) - .build()); - - operations.add(ContentProviderOperation.newInsert(dataUri) - .withValueBackReference(ContactsContract.CommonDataKinds.StructuredName.RAW_CONTACT_ID, index) - .withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, displayName) - .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE) - .build()); - - operations.add(ContentProviderOperation.newInsert(dataUri) - .withValueBackReference(ContactsContract.CommonDataKinds.Phone.RAW_CONTACT_ID, index) - .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE) - .withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, e164number) - .withValue(ContactsContract.CommonDataKinds.Phone.TYPE, ContactsContract.CommonDataKinds.Phone.TYPE_OTHER) - .withValue(ContactsContract.Data.SYNC2, SYNC) - .build()); - - operations.add(ContentProviderOperation.newInsert(dataUri) - .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, index) - .withValue(ContactsContract.Data.MIMETYPE, CONTACT_MIMETYPE) - .withValue(ContactsContract.Data.DATA1, e164number) - .withValue(ContactsContract.Data.DATA2, context.getString(R.string.app_name)) - .withValue(ContactsContract.Data.DATA3, context.getString(R.string.ContactsDatabase_message_s, e164number)) - .withYieldAllowed(true) - .build()); - - operations.add(ContentProviderOperation.newInsert(dataUri) - .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, index) - .withValue(ContactsContract.Data.MIMETYPE, CALL_MIMETYPE) - .withValue(ContactsContract.Data.DATA1, e164number) - .withValue(ContactsContract.Data.DATA2, context.getString(R.string.app_name)) - .withValue(ContactsContract.Data.DATA3, context.getString(R.string.ContactsDatabase_signal_call_s, e164number)) - .withYieldAllowed(true) - .build()); - - operations.add(ContentProviderOperation.newUpdate(ContactsContract.AggregationExceptions.CONTENT_URI) - .withValue(ContactsContract.AggregationExceptions.RAW_CONTACT_ID1, aggregateId) - .withValueBackReference(ContactsContract.AggregationExceptions.RAW_CONTACT_ID2, index) - .withValue(ContactsContract.AggregationExceptions.TYPE, ContactsContract.AggregationExceptions.TYPE_KEEP_TOGETHER) - .build()); - } - - private void removeTextSecureRawContact(List operations, - Account account, long rowId) - { - operations.add(ContentProviderOperation.newDelete(RawContacts.CONTENT_URI.buildUpon() - .appendQueryParameter(RawContacts.ACCOUNT_NAME, account.name) - .appendQueryParameter(RawContacts.ACCOUNT_TYPE, account.type) - .appendQueryParameter(ContactsContract.CALLER_IS_SYNCADAPTER, "true").build()) - .withYieldAllowed(true) - .withSelection(BaseColumns._ID + " = ?", new String[] {String.valueOf(rowId)}) - .build()); - } - - private @NonNull Map getSignalRawContacts(@NonNull Account account) { - Uri currentContactsUri = RawContacts.CONTENT_URI.buildUpon() - .appendQueryParameter(RawContacts.ACCOUNT_NAME, account.name) - .appendQueryParameter(RawContacts.ACCOUNT_TYPE, account.type).build(); - - Map signalContacts = new HashMap<>(); - Cursor cursor = null; - - try { - String[] projection = new String[] {BaseColumns._ID, RawContacts.SYNC1, RawContacts.SYNC4, RawContacts.CONTACT_ID, RawContacts.DISPLAY_NAME_PRIMARY, RawContacts.DISPLAY_NAME_SOURCE}; - - cursor = context.getContentResolver().query(currentContactsUri, projection, null, null, null); - - while (cursor != null && cursor.moveToNext()) { - Address currentAddress = Address.fromExternal(context, cursor.getString(1)); - long rawContactId = cursor.getLong(0); - long contactId = cursor.getLong(3); - String supportsVoice = cursor.getString(2); - String rawContactDisplayName = cursor.getString(4); - String aggregateDisplayName = getDisplayName(contactId); - int rawContactDisplayNameSource = cursor.getInt(5); - - signalContacts.put(currentAddress, new SignalContact(rawContactId, supportsVoice, rawContactDisplayName, aggregateDisplayName, rawContactDisplayNameSource)); - } - } finally { - if (cursor != null) - cursor.close(); - } - - return signalContacts; - } - - private Optional getSystemContactInfo(@NonNull Address address) - { - if (!address.isPhone()) return Optional.absent(); - - Uri uri = Uri.withAppendedPath(ContactsContract.PhoneLookup.CONTENT_FILTER_URI, Uri.encode(address.toPhoneString())); - String[] projection = {ContactsContract.PhoneLookup.NUMBER, - ContactsContract.PhoneLookup._ID, - ContactsContract.PhoneLookup.DISPLAY_NAME}; - Cursor numberCursor = null; - Cursor idCursor = null; - - try { - numberCursor = context.getContentResolver().query(uri, projection, null, null, null); - - while (numberCursor != null && numberCursor.moveToNext()) { - String systemNumber = numberCursor.getString(0); - Address systemAddress = Address.fromExternal(context, systemNumber); - - if (systemAddress.equals(address)) { - idCursor = context.getContentResolver().query(RawContacts.CONTENT_URI, - new String[] {RawContacts._ID}, - RawContacts.CONTACT_ID + " = ? ", - new String[] {String.valueOf(numberCursor.getLong(1))}, - null); - - if (idCursor != null && idCursor.moveToNext()) { - return Optional.of(new SystemContactInfo(numberCursor.getString(2), - numberCursor.getString(0), - idCursor.getLong(0))); - } - } - } - } finally { - if (numberCursor != null) numberCursor.close(); - if (idCursor != null) idCursor.close(); - } - - return Optional.absent(); - } - - private @Nullable String getDisplayName(long contactId) { - Cursor cursor = context.getContentResolver().query(ContactsContract.Contacts.CONTENT_URI, - new String[]{ContactsContract.Contacts.DISPLAY_NAME}, - ContactsContract.Contacts._ID + " = ?", - new String[] {String.valueOf(contactId)}, - null); - - try { - if (cursor != null && cursor.moveToFirst()) { - return cursor.getString(0); - } else { - return null; - } - } finally { - if (cursor != null) cursor.close(); - } - } - - private void applyOperationsInBatches(@NonNull ContentResolver contentResolver, - @NonNull String authority, - @NonNull List operations, - int batchSize) - throws OperationApplicationException, RemoteException - { - List> batches = Util.chunk(operations, batchSize); - for (List batch : batches) { - contentResolver.applyBatch(authority, new ArrayList<>(batch)); - } - } - - private static class ProjectionMappingCursor extends CursorWrapper { - - private final Map projectionMap; - private final Pair[] extras; - - @SafeVarargs - ProjectionMappingCursor(Cursor cursor, - Map projectionMap, - Pair... extras) - { - super(cursor); - this.projectionMap = projectionMap; - this.extras = extras; - } - - @Override - public int getColumnCount() { - return super.getColumnCount() + extras.length; - } - - @Override - public int getColumnIndex(String columnName) { - for (int i=0;i= baseColumnCount) { - int offset = columnIndex - baseColumnCount; - return extras[offset].first; - } - - return getReverseProjection(super.getColumnName(columnIndex)); - } - - @Override - public String[] getColumnNames() { - String[] names = super.getColumnNames(); - String[] allNames = new String[names.length + extras.length]; - - for (int i=0;i= super.getColumnCount()) { - int offset = columnIndex - super.getColumnCount(); - return (Integer)extras[offset].second; - } - - return super.getInt(columnIndex); - } - - @Override - public String getString(int columnIndex) { - if (columnIndex >= super.getColumnCount()) { - int offset = columnIndex - super.getColumnCount(); - return (String)extras[offset].second; - } - - return super.getString(columnIndex); - } - - - private @Nullable String getReverseProjection(String columnName) { - for (Map.Entry entry : projectionMap.entrySet()) { - if (entry.getValue().equals(columnName)) { - return entry.getKey(); - } - } - - return null; - } - } - - private static class SystemContactInfo { - private final String name; - private final String number; - private final long id; - - private SystemContactInfo(String name, String number, long id) { - this.name = name; - this.number = number; - this.id = id; - } - } - - private static class SignalContact { - - private final long id; - @Nullable private final String supportsVoice; - @Nullable private final String rawDisplayName; - @Nullable private final String aggregateDisplayName; - private final int displayNameSource; - - SignalContact(long id, - @Nullable String supportsVoice, - @Nullable String rawDisplayName, - @Nullable String aggregateDisplayName, - int displayNameSource) - { - this.id = id; - this.supportsVoice = supportsVoice; - this.rawDisplayName = rawDisplayName; - this.aggregateDisplayName = aggregateDisplayName; - this.displayNameSource = displayNameSource; - } - - public long getId() { - return id; - } - - boolean isVoiceSupported() { - return "true".equals(supportsVoice); - } - - @Nullable - String getRawDisplayName() { - return rawDisplayName; - } - - @Nullable - String getAggregateDisplayName() { - return aggregateDisplayName; - } - - int getDisplayNameSource() { - return displayNameSource; - } - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/contacts/NameAndNumber.java b/app/src/main/java/org/thoughtcrime/securesms/contacts/NameAndNumber.java deleted file mode 100644 index b9e0e1fb0..000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/contacts/NameAndNumber.java +++ /dev/null @@ -1,35 +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 . - */ -package org.thoughtcrime.securesms.contacts; - -/** - * Name and number tuple. - * - * @author Moxie Marlinspike - * - */ -public class NameAndNumber { - public String name; - public String number; - - public NameAndNumber(String name, String number) { - this.name = name; - this.number = number; - } - - public NameAndNumber() {} -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/contacts/RecipientsAdapter.java b/app/src/main/java/org/thoughtcrime/securesms/contacts/RecipientsAdapter.java deleted file mode 100644 index 430d580cc..000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/contacts/RecipientsAdapter.java +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Copyright (C) 2008 Esmertec AG. - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.thoughtcrime.securesms.contacts; - -import android.content.ContentResolver; -import android.content.Context; -import android.database.Cursor; -import android.text.Annotation; -import android.text.Spannable; -import android.text.SpannableString; -import android.text.TextUtils; -import android.view.View; -import android.widget.ResourceCursorAdapter; -import android.widget.TextView; - -import org.thoughtcrime.securesms.recipients.RecipientsFormatter; - -import network.loki.messenger.R; - -/** - * This adapter is used to filter contacts on both name and number. - */ -public class RecipientsAdapter extends ResourceCursorAdapter { - - public static final int CONTACT_ID_INDEX = 1; - public static final int TYPE_INDEX = 2; - public static final int NUMBER_INDEX = 3; - public static final int LABEL_INDEX = 4; - public static final int NAME_INDEX = 5; - - private final Context mContext; - private final ContentResolver mContentResolver; - private ContactAccessor mContactAccessor; - - public RecipientsAdapter(Context context) { - super(context, R.layout.recipient_filter_item, null); - mContext = context; - mContentResolver = context.getContentResolver(); - mContactAccessor = ContactAccessor.getInstance(); - } - - @Override - public final CharSequence convertToString(Cursor cursor) { - String name = cursor.getString(RecipientsAdapter.NAME_INDEX); - int type = cursor.getInt(RecipientsAdapter.TYPE_INDEX); - String number = cursor.getString(RecipientsAdapter.NUMBER_INDEX).trim(); - - String label = cursor.getString(RecipientsAdapter.LABEL_INDEX); - CharSequence displayLabel = mContactAccessor.phoneTypeToString(mContext, type, label); - - if (number.length() == 0) { - return number; - } - - if (name == null) { - name = ""; - } else { - // Names with commas are the bane of the recipient editor's existence. - // We've worked around them by using spans, but there are edge cases - // where the spans get deleted. Furthermore, having commas in names - // can be confusing to the user since commas are used as separators - // between recipients. The best solution is to simply remove commas - // from names. - name = name.replace(", ", " ") - .replace(",", " "); // Make sure we leave a space between parts of names. - } - - String nameAndNumber = RecipientsFormatter.formatNameAndNumber(name, number); - - SpannableString out = new SpannableString(nameAndNumber); - int len = out.length(); - - if (!TextUtils.isEmpty(name)) { - out.setSpan(new Annotation("name", name), 0, len, - Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); - } else { - out.setSpan(new Annotation("name", number), 0, len, - Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); - } - - String person_id = cursor.getString(RecipientsAdapter.CONTACT_ID_INDEX); - out.setSpan(new Annotation("person_id", person_id), 0, len, - Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); - out.setSpan(new Annotation("label", displayLabel.toString()), 0, len, - Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); - out.setSpan(new Annotation("number", number), 0, len, - Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); - - return out; - } - - @Override - public final void bindView(View view, Context context, Cursor cursor) { - TextView name = (TextView) view.findViewById(R.id.name); - name.setText(cursor.getString(NAME_INDEX)); - - TextView label = (TextView) view.findViewById(R.id.label); - int type = cursor.getInt(TYPE_INDEX); - label.setText(mContactAccessor.phoneTypeToString(mContext, type, cursor.getString(LABEL_INDEX))); - - TextView number = (TextView) view.findViewById(R.id.number); - number.setText("(" + cursor.getString(NUMBER_INDEX) + ")"); - } - - @Override - public Cursor runQueryOnBackgroundThread(CharSequence constraint) { - return null; - } - - /** - * Returns true if all the characters are meaningful as digits - * in a phone number -- letters, digits, and a few punctuation marks. - */ - public static boolean usefulAsDigits(CharSequence cons) { - int len = cons.length(); - - for (int i = 0; i < len; i++) { - char c = cons.charAt(i); - - if ((c >= '0') && (c <= '9')) { - continue; - } - if ((c == ' ') || (c == '-') || (c == '(') || (c == ')') || (c == '.') || (c == '+') - || (c == '#') || (c == '*')) { - continue; - } - if ((c >= 'A') && (c <= 'Z')) { - continue; - } - if ((c >= 'a') && (c <= 'z')) { - continue; - } - - return false; - } - - return true; - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/contacts/RecipientsEditor.java b/app/src/main/java/org/thoughtcrime/securesms/contacts/RecipientsEditor.java deleted file mode 100644 index 2f46eff3d..000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/contacts/RecipientsEditor.java +++ /dev/null @@ -1,416 +0,0 @@ -/* - * Copyright (C) 2008 Esmertec AG. - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.thoughtcrime.securesms.contacts; - -import android.content.Context; -import androidx.appcompat.widget.AppCompatMultiAutoCompleteTextView; -import android.telephony.PhoneNumberUtils; -import android.text.Annotation; -import android.text.Editable; -import android.text.Layout; -import android.text.Spannable; -import android.text.SpannableString; -import android.text.SpannableStringBuilder; -import android.text.Spanned; -import android.text.TextUtils; -import android.text.TextWatcher; -import android.util.AttributeSet; -import android.view.ContextMenu.ContextMenuInfo; -import android.view.MotionEvent; -import android.view.inputmethod.EditorInfo; -import android.widget.MultiAutoCompleteTextView; - -import org.thoughtcrime.securesms.recipients.Recipient; -import org.thoughtcrime.securesms.recipients.RecipientsFormatter; - -import java.util.ArrayList; -import java.util.List; - -/** - * Provide UI for editing the recipients of multi-media messages. - */ -public class RecipientsEditor extends AppCompatMultiAutoCompleteTextView { - private int mLongPressedPosition = -1; - private final RecipientsEditorTokenizer mTokenizer; - private char mLastSeparator = ','; - private Context mContext; - - public RecipientsEditor(Context context, AttributeSet attrs) { - super(context, attrs); - mContext = context; - mTokenizer = new RecipientsEditorTokenizer(context, this); - setTokenizer(mTokenizer); - // For the focus to move to the message body when soft Next is pressed - setImeOptions(EditorInfo.IME_ACTION_NEXT); - - /* - * The point of this TextWatcher is that when the user chooses - * an address completion from the AutoCompleteTextView menu, it - * is marked up with Annotation objects to tie it back to the - * address book entry that it came from. If the user then goes - * back and edits that part of the text, it no longer corresponds - * to that address book entry and needs to have the Annotations - * claiming that it does removed. - */ - addTextChangedListener(new TextWatcher() { - private Annotation[] mAffected; - - public void beforeTextChanged(CharSequence s, int start, - int count, int after) { - mAffected = ((Spanned) s).getSpans(start, start + count, - Annotation.class); - } - - public void onTextChanged(CharSequence s, int start, - int before, int after) { - if (before == 0 && after == 1) { // inserting a character - char c = s.charAt(start); - if (c == ',' || c == ';') { - // Remember the delimiter the user typed to end this recipient. We'll - // need it shortly in terminateToken(). - mLastSeparator = c; - } - } - } - - public void afterTextChanged(Editable s) { - if (mAffected != null) { - for (Annotation a : mAffected) { - s.removeSpan(a); - } - } - - mAffected = null; - } - }); - } - - @Override - public boolean enoughToFilter() { - if (!super.enoughToFilter()) { - return false; - } - // If the user is in the middle of editing an existing recipient, don't offer the - // auto-complete menu. Without this, when the user selects an auto-complete menu item, - // it will get added to the list of recipients so we end up with the old before-editing - // recipient and the new post-editing recipient. As a precedent, gmail does not show - // the auto-complete menu when editing an existing recipient. - int end = getSelectionEnd(); - int len = getText().length(); - - return end == len; - } - - public int getRecipientCount() { - return mTokenizer.getNumbers().size(); - } - - public List getNumbers() { - return mTokenizer.getNumbers(); - } - -// public Recipients constructContactsFromInput() { -// return RecipientFactory.getRecipientsFromString(mContext, mTokenizer.getRawString(), false); -// } - - private boolean isValidAddress(String number, boolean isMms) { - /*if (isMms) { - return MessageUtils.isValidMmsAddress(number); - } else {*/ - // TODO: PhoneNumberUtils.isWellFormedSmsAddress() only check if the number is a valid - // GSM SMS address. If the address contains a dialable char, it considers it a well - // formed SMS addr. CDMA doesn't work that way and has a different parser for SMS - // address (see CdmaSmsAddress.parse(String address)). We should definitely fix this!!! - return PhoneNumberUtils.isWellFormedSmsAddress(number); - } - - public boolean hasValidRecipient(boolean isMms) { - for (String number : mTokenizer.getNumbers()) { - if (isValidAddress(number, isMms)) - return true; - } - return false; - } - - /*public boolean hasInvalidRecipient(boolean isMms) { - for (String number : mTokenizer.getNumbers()) { - if (!isValidAddress(number, isMms)) { - /* TODO if (MmsConfig.getEmailGateway() == null) { - return true; - } else if (!MessageUtils.isAlias(number)) { - return true; - } - } - } - return false; - }*/ - - public String formatInvalidNumbers(boolean isMms) { - StringBuilder sb = new StringBuilder(); - for (String number : mTokenizer.getNumbers()) { - if (!isValidAddress(number, isMms)) { - if (sb.length() != 0) { - sb.append(", "); - } - sb.append(number); - } - } - return sb.toString(); - } - - /*public boolean containsEmail() { - if (TextUtils.indexOf(getText(), '@') == -1) - return false; - - List numbers = mTokenizer.getNumbers(); - for (String number : numbers) { - if (Mms.isEmailAddress(number)) - return true; - } - return false; - }*/ - - public static CharSequence contactToToken(Recipient c) { - String name = c.getName(); - String number = c.getAddress().serialize(); - SpannableString s = new SpannableString(RecipientsFormatter.formatNameAndNumber(name, number)); - int len = s.length(); - - if (len == 0) { - return s; - } - - s.setSpan(new Annotation("number", c.getAddress().serialize()), 0, len, - Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); - - return s; - } - - public void populate(List list) { - SpannableStringBuilder sb = new SpannableStringBuilder(); - - for (Recipient c : list) { - if (sb.length() != 0) { - sb.append(", "); - } - - sb.append(contactToToken(c)); - } - - setText(sb); - } - - private int pointToPosition(int x, int y) { - x -= getCompoundPaddingLeft(); - y -= getExtendedPaddingTop(); - - x += getScrollX(); - y += getScrollY(); - - Layout layout = getLayout(); - if (layout == null) { - return -1; - } - - int line = layout.getLineForVertical(y); - int off = layout.getOffsetForHorizontal(line, x); - - return off; - } - - @Override - public boolean onTouchEvent(MotionEvent ev) { - final int action = ev.getAction(); - final int x = (int) ev.getX(); - final int y = (int) ev.getY(); - - if (action == MotionEvent.ACTION_DOWN) { - mLongPressedPosition = pointToPosition(x, y); - } - - return super.onTouchEvent(ev); - } - - private static String getNumberAt(Spanned sp, int start, int end, Context context) { - return getFieldAt("number", sp, start, end, context); - } - - private static int getSpanLength(Spanned sp, int start, int end, Context context) { - // TODO: there's a situation where the span can lose its annotations: - // - add an auto-complete contact - // - add another auto-complete contact - // - delete that second contact and keep deleting into the first - // - we lose the annotation and can no longer get the span. - // Need to fix this case because it breaks auto-complete contacts with commas in the name. - Annotation[] a = sp.getSpans(start, end, Annotation.class); - if (a.length > 0) { - return sp.getSpanEnd(a[0]); - } - return 0; - } - - private static String getFieldAt(String field, Spanned sp, int start, int end, - Context context) { - Annotation[] a = sp.getSpans(start, end, Annotation.class); - String fieldValue = getAnnotation(a, field); - if (TextUtils.isEmpty(fieldValue)) { - fieldValue = TextUtils.substring(sp, start, end); - } - return fieldValue; - - } - - private static String getAnnotation(Annotation[] a, String key) { - for (int i = 0; i < a.length; i++) { - if (a[i].getKey().equals(key)) { - return a[i].getValue(); - } - } - - return ""; - } - - private class RecipientsEditorTokenizer - implements MultiAutoCompleteTextView.Tokenizer { - private final MultiAutoCompleteTextView mList; - private final Context mContext; - - RecipientsEditorTokenizer(Context context, MultiAutoCompleteTextView list) { - mList = list; - mContext = context; - } - - /** - * Returns the start of the token that ends at offset - * cursor within text. - * It is a method from the MultiAutoCompleteTextView.Tokenizer interface. - */ - public int findTokenStart(CharSequence text, int cursor) { - int i = cursor; - char c; - - while (i > 0 && (c = text.charAt(i - 1)) != ',' && c != ';') { - i--; - } - while (i < cursor && text.charAt(i) == ' ') { - i++; - } - - return i; - } - - /** - * Returns the end of the token (minus trailing punctuation) - * that begins at offset cursor within text. - * It is a method from the MultiAutoCompleteTextView.Tokenizer interface. - */ - public int findTokenEnd(CharSequence text, int cursor) { - int i = cursor; - int len = text.length(); - char c; - - while (i < len) { - if ((c = text.charAt(i)) == ',' || c == ';') { - return i; - } else { - i++; - } - } - - return len; - } - - /** - * Returns text, modified, if necessary, to ensure that - * it ends with a token terminator (for example a space or comma). - * It is a method from the MultiAutoCompleteTextView.Tokenizer interface. - */ - public CharSequence terminateToken(CharSequence text) { - int i = text.length(); - - while (i > 0 && text.charAt(i - 1) == ' ') { - i--; - } - - char c; - if (i > 0 && ((c = text.charAt(i - 1)) == ',' || c == ';')) { - return text; - } else { - // Use the same delimiter the user just typed. - // This lets them have a mixture of commas and semicolons in their list. - String separator = mLastSeparator + " "; - if (text instanceof Spanned) { - SpannableString sp = new SpannableString(text + separator); - TextUtils.copySpansFrom((Spanned) text, 0, text.length(), - Object.class, sp, 0); - return sp; - } else { - return text + separator; - } - } - } - public String getRawString() { - return mList.getText().toString(); - } - public List getNumbers() { - Spanned sp = mList.getText(); - int len = sp.length(); - List list = new ArrayList(); - - int start = 0; - int i = 0; - while (i < len + 1) { - char c; - if ((i == len) || ((c = sp.charAt(i)) == ',') || (c == ';')) { - if (i > start) { - list.add(getNumberAt(sp, start, i, mContext)); - - // calculate the recipients total length. This is so if the name contains - // commas or semis, we'll skip over the whole name to the next - // recipient, rather than parsing this single name into multiple - // recipients. - int spanLen = getSpanLength(sp, start, i, mContext); - if (spanLen > i) { - i = spanLen; - } - } - - i++; - - while ((i < len) && (sp.charAt(i) == ' ')) { - i++; - } - - start = i; - } else { - i++; - } - } - - return list; - } - } - - static class RecipientContextMenuInfo implements ContextMenuInfo { - final Recipient recipient; - - RecipientContextMenuInfo(Recipient r) { - recipient = r; - } - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/contactshare/ContactFieldAdapter.java b/app/src/main/java/org/thoughtcrime/securesms/contactshare/ContactFieldAdapter.java deleted file mode 100644 index 2d439405d..000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/contactshare/ContactFieldAdapter.java +++ /dev/null @@ -1,227 +0,0 @@ -package org.thoughtcrime.securesms.contactshare; - -import android.content.Context; -import android.net.Uri; -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 android.widget.CheckBox; -import android.widget.ImageView; -import android.widget.TextView; - -import com.annimon.stream.Stream; - -import network.loki.messenger.R; -import org.thoughtcrime.securesms.contactshare.Contact.Phone; -import org.thoughtcrime.securesms.mms.GlideRequests; - -import java.util.ArrayList; -import java.util.List; -import java.util.Locale; - -import static org.thoughtcrime.securesms.contactshare.Contact.*; - -class ContactFieldAdapter extends RecyclerView.Adapter { - - private final Locale locale; - private final boolean selectable; - private final List fields; - private final GlideRequests glideRequests; - - public ContactFieldAdapter(@NonNull Locale locale, @NonNull GlideRequests glideRequests, boolean selectable) { - this.locale = locale; - this.glideRequests = glideRequests; - this.selectable = selectable; - this.fields = new ArrayList<>(); - } - - @Override - public @NonNull ContactFieldViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { - return new ContactFieldViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_selectable_contact_field, parent, false)); - } - - @Override - public void onBindViewHolder(@NonNull ContactFieldViewHolder holder, int position) { - holder.bind(fields.get(position), glideRequests, selectable); - } - - @Override - public void onViewRecycled(@NonNull ContactFieldViewHolder holder) { - holder.recycle(); - } - - @Override - public int getItemCount() { - return fields.size(); - } - - void setFields(@NonNull Context context, - @Nullable Avatar avatar, - @NonNull List phoneNumbers, - @NonNull List emails, - @NonNull List postalAddresses) - { - fields.clear(); - - if (avatar != null) { - fields.add(new Field(avatar)); - } - - fields.addAll(Stream.of(phoneNumbers).map(phone -> new Field(context, phone, locale)).toList()); - fields.addAll(Stream.of(emails).map(email -> new Field(context, email)).toList()); - fields.addAll(Stream.of(postalAddresses).map(address -> new Field(context, address)).toList()); - - notifyDataSetChanged(); - } - - static class ContactFieldViewHolder extends RecyclerView.ViewHolder { - - private final TextView value; - private final TextView label; - private final ImageView icon; - private final ImageView avatar; - private final CheckBox checkBox; - - ContactFieldViewHolder(View itemView) { - super(itemView); - - value = itemView.findViewById(R.id.contact_field_value); - label = itemView.findViewById(R.id.contact_field_label); - icon = itemView.findViewById(R.id.contact_field_icon); - avatar = itemView.findViewById(R.id.contact_field_avatar); - checkBox = itemView.findViewById(R.id.contact_field_checkbox); - } - - void bind(@NonNull Field field, @NonNull GlideRequests glideRequests, boolean selectable) { - value.setMaxLines(field.maxLines); - value.setText(field.value); - label.setText(field.label); - icon.setImageResource(field.iconResId); - - if (field.iconUri != null) { - avatar.setVisibility(View.VISIBLE); - glideRequests.load(field.iconUri).circleCrop().into(avatar); - } else { - avatar.setVisibility(View.GONE); - } - - if (selectable) { - checkBox.setVisibility(View.VISIBLE); - checkBox.setOnCheckedChangeListener(null); - checkBox.setChecked(field.isSelected()); - checkBox.setOnCheckedChangeListener((buttonView, isChecked) -> field.setSelected(isChecked)); - } else { - checkBox.setVisibility(View.GONE); - checkBox.setOnCheckedChangeListener(null); - } - } - - void recycle() { - checkBox.setOnCheckedChangeListener(null); - } - } - - static class Field { - - final String value; - final String label; - final int iconResId; - final int maxLines; - final Selectable selectable; - - @Nullable - final Uri iconUri; - - Field(@NonNull Context context, @NonNull Phone phoneNumber, @NonNull Locale locale) { - this.value = ContactUtil.getPrettyPhoneNumber(phoneNumber, locale); - this.iconResId = R.drawable.ic_call_white_24dp; - this.iconUri = null; - this.maxLines = 1; - this.selectable = phoneNumber; - - switch (phoneNumber.getType()) { - case HOME: - label = context.getString(R.string.ContactShareEditActivity_type_home); - break; - case MOBILE: - label = context.getString(R.string.ContactShareEditActivity_type_mobile); - break; - case WORK: - label = context.getString(R.string.ContactShareEditActivity_type_work); - break; - case CUSTOM: - label = phoneNumber.getLabel() != null ? phoneNumber.getLabel() : ""; - break; - default: - label = ""; - } - } - - Field(@NonNull Context context, @NonNull Email email) { - this.value = email.getEmail(); - this.iconResId = R.drawable.baseline_email_white_24; - this.iconUri = null; - this.maxLines = 1; - this.selectable = email; - - switch (email.getType()) { - case HOME: - label = context.getString(R.string.ContactShareEditActivity_type_home); - break; - case MOBILE: - label = context.getString(R.string.ContactShareEditActivity_type_mobile); - break; - case WORK: - label = context.getString(R.string.ContactShareEditActivity_type_work); - break; - case CUSTOM: - label = email.getLabel() != null ? email.getLabel() : ""; - break; - default: - label = ""; - } - } - - Field(@NonNull Context context, @NonNull PostalAddress postalAddress) { - this.value = postalAddress.toString(); - this.iconResId = R.drawable.ic_location_on_white_24dp; - this.iconUri = null; - this.maxLines = 3; - this.selectable = postalAddress; - - switch (postalAddress.getType()) { - case HOME: - label = context.getString(R.string.ContactShareEditActivity_type_home); - break; - case WORK: - label = context.getString(R.string.ContactShareEditActivity_type_work); - break; - case CUSTOM: - label = postalAddress.getLabel() != null ? postalAddress.getLabel() : context.getString(R.string.ContactShareEditActivity_type_missing); - break; - default: - label = context.getString(R.string.ContactShareEditActivity_type_missing); - } - } - - Field(@NonNull Avatar avatar) { - this.value = ""; - this.iconResId = R.drawable.baseline_account_circle_white_24; - this.iconUri = avatar.getAttachment() != null ? avatar.getAttachment().getDataUri() : null; - this.maxLines = 1; - this.selectable = avatar; - this.label = ""; - } - - void setSelected(boolean selected) { - selectable.setSelected(selected); - } - - boolean isSelected() { - return selectable.isSelected(); - } - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/contactshare/ContactNameEditActivity.java b/app/src/main/java/org/thoughtcrime/securesms/contactshare/ContactNameEditActivity.java deleted file mode 100644 index 29309c096..000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/contactshare/ContactNameEditActivity.java +++ /dev/null @@ -1,138 +0,0 @@ -package org.thoughtcrime.securesms.contactshare; - -import androidx.lifecycle.ViewModelProviders; -import android.content.Context; -import android.content.Intent; -import android.os.Bundle; -import androidx.annotation.NonNull; -import androidx.appcompat.widget.Toolbar; -import android.widget.TextView; - -import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity; -import network.loki.messenger.R; -import org.thoughtcrime.securesms.util.DynamicLanguage; -import org.thoughtcrime.securesms.util.DynamicNoActionBarTheme; -import org.thoughtcrime.securesms.util.DynamicTheme; - -import static org.thoughtcrime.securesms.contactshare.Contact.*; - -public class ContactNameEditActivity extends PassphraseRequiredActionBarActivity { - - public static final String KEY_NAME = "name"; - public static final String KEY_CONTACT_INDEX = "contact_index"; - - private final DynamicTheme dynamicTheme = new DynamicNoActionBarTheme(); - private final DynamicLanguage dynamicLanguage = new DynamicLanguage(); - - private TextView displayNameView; - private ContactNameEditViewModel viewModel; - - static Intent getIntent(@NonNull Context context, @NonNull Name name, int contactPosition) { - Intent intent = new Intent(context, ContactNameEditActivity.class); - intent.putExtra(KEY_NAME, name); - intent.putExtra(KEY_CONTACT_INDEX, contactPosition); - return intent; - } - - @Override - protected void onPreCreate() { - dynamicTheme.onCreate(this); - dynamicLanguage.onCreate(this); - } - - @Override - protected void onCreate(Bundle savedInstanceState, boolean ready) { - super.onCreate(savedInstanceState, ready); - - if (getIntent() == null) { - throw new IllegalStateException("You must supply extras to this activity. Please use the #getIntent() method."); - } - - Name name = getIntent().getParcelableExtra(KEY_NAME); - if (name == null) { - throw new IllegalStateException("You must supply a name to this activity. Please use the #getIntent() method."); - } - - setContentView(R.layout.activity_contact_name_edit); - - initializeToolbar(); - initializeViews(name); - - viewModel = ViewModelProviders.of(this).get(ContactNameEditViewModel.class); - viewModel.setName(name); - viewModel.getDisplayName().observe(this, displayNameView::setText); - } - - @Override - protected void onResume() { - super.onResume(); - dynamicTheme.onResume(this); - dynamicLanguage.onResume(this); - } - - private void initializeToolbar() { - Toolbar toolbar = findViewById(R.id.toolbar); - setSupportActionBar(toolbar); - - toolbar.setTitle(""); - toolbar.setNavigationIcon(R.drawable.ic_check_white_24dp); - toolbar.setNavigationOnClickListener(v -> { - Intent resultIntent = new Intent(); - resultIntent.putExtra(KEY_NAME, viewModel.getName()); - resultIntent.putExtra(KEY_CONTACT_INDEX, getIntent().getIntExtra(KEY_CONTACT_INDEX, -1)); - setResult(RESULT_OK, resultIntent); - finish(); - }); - } - - private void initializeViews(@NonNull Name name) { - displayNameView = findViewById(R.id.name_edit_display_name); - - TextView givenName = findViewById(R.id.name_edit_given_name); - TextView familyName = findViewById(R.id.name_edit_family_name); - TextView middleName = findViewById(R.id.name_edit_middle_name); - TextView prefix = findViewById(R.id.name_edit_prefix); - TextView suffix = findViewById(R.id.name_edit_suffix); - - givenName.setText(name.getGivenName()); - familyName.setText(name.getFamilyName()); - middleName.setText(name.getMiddleName()); - prefix.setText(name.getPrefix()); - suffix.setText(name.getSuffix()); - - givenName.addTextChangedListener(new SimpleTextWatcher() { - @Override - public void onTextChanged(String text) { - viewModel.updateGivenName(text); - } - }); - - familyName.addTextChangedListener(new SimpleTextWatcher() { - @Override - public void onTextChanged(String text) { - viewModel.updateFamilyName(text); - } - }); - - middleName.addTextChangedListener(new SimpleTextWatcher() { - @Override - public void onTextChanged(String text) { - viewModel.updateMiddleName(text); - } - }); - - prefix.addTextChangedListener(new SimpleTextWatcher() { - @Override - public void onTextChanged(String text) { - viewModel.updatePrefix(text); - } - }); - - suffix.addTextChangedListener(new SimpleTextWatcher() { - @Override - public void onTextChanged(String text) { - viewModel.updateSuffix(text); - } - }); - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/contactshare/ContactNameEditViewModel.java b/app/src/main/java/org/thoughtcrime/securesms/contactshare/ContactNameEditViewModel.java deleted file mode 100644 index 860d28715..000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/contactshare/ContactNameEditViewModel.java +++ /dev/null @@ -1,132 +0,0 @@ -package org.thoughtcrime.securesms.contactshare; - -import androidx.lifecycle.LiveData; -import androidx.lifecycle.MutableLiveData; -import androidx.lifecycle.ViewModel; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import android.text.TextUtils; - -import static org.thoughtcrime.securesms.contactshare.Contact.*; - -public class ContactNameEditViewModel extends ViewModel { - - private final MutableLiveData displayName; - - private String givenName; - private String familyName; - private String middleName; - private String prefix; - private String suffix; - - public ContactNameEditViewModel() { - this.displayName = new MutableLiveData<>(); - } - - void setName(@NonNull Name name) { - givenName = name.getGivenName(); - familyName = name.getFamilyName(); - middleName = name.getMiddleName(); - prefix = name.getPrefix(); - suffix = name.getSuffix(); - - displayName.postValue(buildDisplayName()); - } - - Name getName() { - return new Name(displayName.getValue(), givenName, familyName, prefix, suffix, middleName); - } - - LiveData getDisplayName() { - return displayName; - } - - void updateGivenName(@NonNull String givenName) { - this.givenName = givenName; - displayName.postValue(buildDisplayName()); - } - - void updateFamilyName(@NonNull String familyName) { - this.familyName = familyName; - displayName.postValue(buildDisplayName()); - } - - void updatePrefix(@NonNull String prefix) { - this.prefix = prefix; - displayName.postValue(buildDisplayName()); - } - - void updateSuffix(@NonNull String suffix) { - this.suffix = suffix; - displayName.postValue(buildDisplayName()); - } - - void updateMiddleName(@NonNull String middleName) { - this.middleName = middleName; - displayName.postValue(buildDisplayName()); - } - - private String buildDisplayName() { - boolean isCJKV = isCJKV(givenName) && isCJKV(middleName) && isCJKV(familyName) && isCJKV(prefix) && isCJKV(suffix); - if (isCJKV) { - return joinString(familyName, givenName, prefix, suffix, middleName); - } - return joinString(prefix, givenName, middleName, familyName, suffix); - } - - private String joinString(String... values) { - StringBuilder builder = new StringBuilder(); - - for (String value : values) { - if (!TextUtils.isEmpty(value)) { - builder.append(value).append(' '); - } - } - - return builder.toString().trim(); - } - - private boolean isCJKV(@Nullable String value) { - if (TextUtils.isEmpty(value)) { - return true; - } - - for (int offset = 0; offset < value.length(); ) { - int codepoint = Character.codePointAt(value, offset); - - if (!isCodepointCJKV(codepoint)) { - return false; - } - - offset += Character.charCount(codepoint); - } - - return true; - } - - private boolean isCodepointCJKV(int codepoint) { - if (codepoint == (int)' ') return true; - - Character.UnicodeBlock block = Character.UnicodeBlock.of(codepoint); - - return Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS.equals(block) || - Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A.equals(block) || - Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B.equals(block) || - Character.UnicodeBlock.CJK_COMPATIBILITY.equals(block) || - Character.UnicodeBlock.CJK_COMPATIBILITY_FORMS.equals(block) || - Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS.equals(block) || - Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS_SUPPLEMENT.equals(block) || - Character.UnicodeBlock.CJK_RADICALS_SUPPLEMENT.equals(block) || - Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION.equals(block) || - Character.UnicodeBlock.ENCLOSED_CJK_LETTERS_AND_MONTHS.equals(block) || - Character.UnicodeBlock.KANGXI_RADICALS.equals(block) || - Character.UnicodeBlock.IDEOGRAPHIC_DESCRIPTION_CHARACTERS.equals(block) || - Character.UnicodeBlock.HIRAGANA.equals(block) || - Character.UnicodeBlock.KATAKANA.equals(block) || - Character.UnicodeBlock.KATAKANA_PHONETIC_EXTENSIONS.equals(block) || - Character.UnicodeBlock.HANGUL_JAMO.equals(block) || - Character.UnicodeBlock.HANGUL_COMPATIBILITY_JAMO.equals(block) || - Character.UnicodeBlock.HANGUL_SYLLABLES.equals(block) || - Character.isIdeographic(codepoint); - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/contactshare/ContactRepository.java b/app/src/main/java/org/thoughtcrime/securesms/contactshare/ContactRepository.java deleted file mode 100644 index f606d3444..000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/contactshare/ContactRepository.java +++ /dev/null @@ -1,389 +0,0 @@ -package org.thoughtcrime.securesms.contactshare; - -import android.content.Context; -import android.database.Cursor; -import android.net.Uri; -import android.provider.ContactsContract; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.annotation.WorkerThread; -import android.text.TextUtils; - -import org.thoughtcrime.securesms.contacts.ContactsDatabase; -import org.thoughtcrime.securesms.contacts.avatars.ContactPhoto; -import org.thoughtcrime.securesms.contactshare.Contact.Email; -import org.thoughtcrime.securesms.contactshare.Contact.Name; -import org.thoughtcrime.securesms.contactshare.Contact.Phone; -import org.thoughtcrime.securesms.contactshare.Contact.PostalAddress; -import org.thoughtcrime.securesms.database.Address; -import org.thoughtcrime.securesms.logging.Log; -import org.thoughtcrime.securesms.mms.PartAuthority; -import org.thoughtcrime.securesms.providers.BlobProvider; -import org.thoughtcrime.securesms.recipients.Recipient; - -import java.io.IOException; -import java.io.InputStream; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.concurrent.Executor; - -import ezvcard.Ezvcard; -import ezvcard.VCard; - -import static org.thoughtcrime.securesms.contactshare.Contact.*; - -public class ContactRepository { - - private static final String TAG = ContactRepository.class.getSimpleName(); - - private final Context context; - private final Executor executor; - private final ContactsDatabase contactsDatabase; - - ContactRepository(@NonNull Context context, - @NonNull Executor executor, - @NonNull ContactsDatabase contactsDatabase) - { - this.context = context.getApplicationContext(); - this.executor = executor; - this.contactsDatabase = contactsDatabase; - } - - void getContacts(@NonNull List contactUris, @NonNull ValueCallback> callback) { - executor.execute(() -> { - List contacts = new ArrayList<>(contactUris.size()); - for (Uri contactUri : contactUris) { - Contact contact; - - if (ContactsContract.AUTHORITY.equals(contactUri.getAuthority())) { - contact = getContactFromSystemContacts(ContactUtil.getContactIdFromUri(contactUri)); - } else { - contact = getContactFromVcard(contactUri); - } - - if (contact != null) { - contacts.add(contact); - } - } - callback.onComplete(contacts); - }); - } - - @WorkerThread - private @Nullable Contact getContactFromSystemContacts(long contactId) { - Name name = getName(contactId); - if (name == null) { - Log.w(TAG, "Couldn't find a name associated with the provided contact ID."); - return null; - } - - List phoneNumbers = getPhoneNumbers(contactId); - AvatarInfo avatarInfo = getAvatarInfo(contactId, phoneNumbers); - Avatar avatar = avatarInfo != null ? new Avatar(avatarInfo.uri, avatarInfo.isProfile) : null; - - return new Contact(name, null, phoneNumbers, getEmails(contactId), getPostalAddresses(contactId), avatar); - } - - @WorkerThread - private @Nullable Contact getContactFromVcard(@NonNull Uri uri) { - Contact contact = null; - - try (InputStream stream = PartAuthority.getAttachmentStream(context, uri)) { - VCard vcard = Ezvcard.parse(stream).first(); - - ezvcard.property.StructuredName vName = vcard.getStructuredName(); - List vPhones = vcard.getTelephoneNumbers(); - List vEmails = vcard.getEmails(); - List vPostalAddresses = vcard.getAddresses(); - - String organization = vcard.getOrganization() != null && !vcard.getOrganization().getValues().isEmpty() ? vcard.getOrganization().getValues().get(0) : null; - String displayName = vcard.getFormattedName() != null ? vcard.getFormattedName().getValue() : null; - - if (displayName == null && vName != null) { - displayName = vName.getGiven(); - } - - if (displayName == null && vcard.getOrganization() != null) { - displayName = organization; - } - - if (displayName == null) { - throw new IOException("No valid name."); - } - - Name name = new Name(displayName, - vName != null ? vName.getGiven() : null, - vName != null ? vName.getFamily() : null, - vName != null && !vName.getPrefixes().isEmpty() ? vName.getPrefixes().get(0) : null, - vName != null && !vName.getSuffixes().isEmpty() ? vName.getSuffixes().get(0) : null, - null); - - - List phoneNumbers = new ArrayList<>(vPhones.size()); - for (ezvcard.property.Telephone vEmail : vPhones) { - String label = !vEmail.getTypes().isEmpty() ? getCleanedVcardType(vEmail.getTypes().get(0).getValue()) : null; - phoneNumbers.add(new Phone(vEmail.getText(), phoneTypeFromVcardType(label), label)); - } - - List emails = new ArrayList<>(vEmails.size()); - for (ezvcard.property.Email vEmail : vEmails) { - String label = !vEmail.getTypes().isEmpty() ? getCleanedVcardType(vEmail.getTypes().get(0).getValue()) : null; - emails.add(new Email(vEmail.getValue(), emailTypeFromVcardType(label), label)); - } - - List postalAddresses = new ArrayList<>(vPostalAddresses.size()); - for (ezvcard.property.Address vPostalAddress : vPostalAddresses) { - String label = !vPostalAddress.getTypes().isEmpty() ? getCleanedVcardType(vPostalAddress.getTypes().get(0).getValue()) : null; - postalAddresses.add(new PostalAddress(postalAddressTypeFromVcardType(label), - label, - vPostalAddress.getStreetAddress(), - vPostalAddress.getPoBox(), - null, - vPostalAddress.getLocality(), - vPostalAddress.getRegion(), - vPostalAddress.getPostalCode(), - vPostalAddress.getCountry())); - } - - contact = new Contact(name, organization, phoneNumbers, emails, postalAddresses, null); - } catch (IOException e) { - Log.w(TAG, "Failed to parse the vcard.", e); - } - - if (BlobProvider.AUTHORITY.equals(uri.getAuthority())) { - BlobProvider.getInstance().delete(context, uri); - } - - return contact; - } - - @WorkerThread - private @Nullable Name getName(long contactId) { - try (Cursor cursor = contactsDatabase.getNameDetails(contactId)) { - if (cursor != null && cursor.moveToFirst()) { - String cursorDisplayName = cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME)); - String cursorGivenName = cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME)); - String cursorFamilyName = cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME)); - String cursorPrefix = cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.StructuredName.PREFIX)); - String cursorSuffix = cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.StructuredName.SUFFIX)); - String cursorMiddleName = cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.StructuredName.MIDDLE_NAME)); - - Name name = new Name(cursorDisplayName, cursorGivenName, cursorFamilyName, cursorPrefix, cursorSuffix, cursorMiddleName); - if (!name.isEmpty()) { - return name; - } - } - } - - String org = contactsDatabase.getOrganizationName(contactId); - if (!TextUtils.isEmpty(org)) { - return new Name(org, org, null, null, null, null); - } - - return null; - } - - @WorkerThread - private @NonNull List getPhoneNumbers(long contactId) { - Map numberMap = new HashMap<>(); - try (Cursor cursor = contactsDatabase.getPhoneDetails(contactId)) { - while (cursor != null && cursor.moveToNext()) { - String cursorNumber = cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.Phone.NUMBER)); - int cursorType = cursor.getInt(cursor.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.Phone.TYPE)); - String cursorLabel = cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.Phone.LABEL)); - - String number = ContactUtil.getNormalizedPhoneNumber(context, cursorNumber); - Phone existing = numberMap.get(number); - Phone candidate = new Phone(number, phoneTypeFromContactType(cursorType), cursorLabel); - - if (existing == null || (existing.getType() == Phone.Type.CUSTOM && existing.getLabel() == null)) { - numberMap.put(number, candidate); - } - } - } - - List numbers = new ArrayList<>(numberMap.size()); - numbers.addAll(numberMap.values()); - return numbers; - } - - @WorkerThread - private @NonNull List getEmails(long contactId) { - List emails = new LinkedList<>(); - - try (Cursor cursor = contactsDatabase.getEmailDetails(contactId)) { - while (cursor != null && cursor.moveToNext()) { - String cursorEmail = cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.Email.ADDRESS)); - int cursorType = cursor.getInt(cursor.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.Email.TYPE)); - String cursorLabel = cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.Email.LABEL)); - - emails.add(new Email(cursorEmail, emailTypeFromContactType(cursorType), cursorLabel)); - } - } - - return emails; - } - - @WorkerThread - private @NonNull List getPostalAddresses(long contactId) { - List postalAddresses = new LinkedList<>(); - - try (Cursor cursor = contactsDatabase.getPostalAddressDetails(contactId)) { - while (cursor != null && cursor.moveToNext()) { - int cursorType = cursor.getInt(cursor.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.StructuredPostal.TYPE)); - String cursorLabel = cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.StructuredPostal.LABEL)); - String cursorStreet = cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.StructuredPostal.STREET)); - String cursorPoBox = cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.StructuredPostal.POBOX)); - String cursorNeighborhood = cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.StructuredPostal.NEIGHBORHOOD)); - String cursorCity = cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.StructuredPostal.CITY)); - String cursorRegion = cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.StructuredPostal.REGION)); - String cursorPostal = cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.StructuredPostal.POSTCODE)); - String cursorCountry = cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.StructuredPostal.COUNTRY)); - - postalAddresses.add(new PostalAddress(postalAddressTypeFromContactType(cursorType), - cursorLabel, - cursorStreet, - cursorPoBox, - cursorNeighborhood, - cursorCity, - cursorRegion, - cursorPostal, - cursorCountry)); - } - } - - return postalAddresses; - } - - @WorkerThread - private @Nullable AvatarInfo getAvatarInfo(long contactId, List phoneNumbers) { - AvatarInfo systemAvatar = getSystemAvatarInfo(contactId); - - if (systemAvatar != null) { - return systemAvatar; - } - - for (Phone phoneNumber : phoneNumbers) { - AvatarInfo recipientAvatar = getRecipientAvatarInfo(Address.fromExternal(context, phoneNumber.getNumber())); - if (recipientAvatar != null) { - return recipientAvatar; - } - } - return null; - } - - @WorkerThread - private @Nullable AvatarInfo getSystemAvatarInfo(long contactId) { - Uri uri = contactsDatabase.getAvatarUri(contactId); - if (uri != null) { - return new AvatarInfo(uri, false); - } - - return null; - } - - @WorkerThread - private @Nullable AvatarInfo getRecipientAvatarInfo(@NonNull Address address) { - Recipient recipient = Recipient.from(context, address, false); - ContactPhoto contactPhoto = recipient.getContactPhoto(); - - if (contactPhoto != null) { - Uri avatarUri = contactPhoto.getUri(context); - if (avatarUri != null) { - return new AvatarInfo(avatarUri, contactPhoto.isProfilePhoto()); - } - } - - return null; - } - - private Phone.Type phoneTypeFromContactType(int type) { - switch (type) { - case ContactsContract.CommonDataKinds.Phone.TYPE_HOME: - return Phone.Type.HOME; - case ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE: - return Phone.Type.MOBILE; - case ContactsContract.CommonDataKinds.Phone.TYPE_WORK: - return Phone.Type.WORK; - } - return Phone.Type.CUSTOM; - } - - private Phone.Type phoneTypeFromVcardType(@Nullable String type) { - if ("home".equalsIgnoreCase(type)) return Phone.Type.HOME; - else if ("cell".equalsIgnoreCase(type)) return Phone.Type.MOBILE; - else if ("work".equalsIgnoreCase(type)) return Phone.Type.WORK; - else return Phone.Type.CUSTOM; - } - - private Email.Type emailTypeFromContactType(int type) { - switch (type) { - case ContactsContract.CommonDataKinds.Email.TYPE_HOME: - return Email.Type.HOME; - case ContactsContract.CommonDataKinds.Email.TYPE_MOBILE: - return Email.Type.MOBILE; - case ContactsContract.CommonDataKinds.Email.TYPE_WORK: - return Email.Type.WORK; - } - return Email.Type.CUSTOM; - } - - private Email.Type emailTypeFromVcardType(@Nullable String type) { - if ("home".equalsIgnoreCase(type)) return Email.Type.HOME; - else if ("cell".equalsIgnoreCase(type)) return Email.Type.MOBILE; - else if ("work".equalsIgnoreCase(type)) return Email.Type.WORK; - else return Email.Type.CUSTOM; - } - - private PostalAddress.Type postalAddressTypeFromContactType(int type) { - switch (type) { - case ContactsContract.CommonDataKinds.StructuredPostal.TYPE_HOME: - return PostalAddress.Type.HOME; - case ContactsContract.CommonDataKinds.StructuredPostal.TYPE_WORK: - return PostalAddress.Type.WORK; - } - return PostalAddress.Type.CUSTOM; - } - - private PostalAddress.Type postalAddressTypeFromVcardType(@Nullable String type) { - if ("home".equalsIgnoreCase(type)) return PostalAddress.Type.HOME; - else if ("work".equalsIgnoreCase(type)) return PostalAddress.Type.WORK; - else return PostalAddress.Type.CUSTOM; - } - - private String getCleanedVcardType(@Nullable String type) { - if (TextUtils.isEmpty(type)) return ""; - - if (type.startsWith("x-") && type.length() > 2) { - return type.substring(2); - } - - return type; - } - - interface ValueCallback { - void onComplete(@NonNull T value); - } - - private static class AvatarInfo { - - private final Uri uri; - private final boolean isProfile; - - private AvatarInfo(Uri uri, boolean isProfile) { - this.uri = uri; - this.isProfile = isProfile; - } - - public Uri getUri() { - return uri; - } - - public boolean isProfile() { - return isProfile; - } - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/contactshare/ContactShareEditActivity.java b/app/src/main/java/org/thoughtcrime/securesms/contactshare/ContactShareEditActivity.java deleted file mode 100644 index 32b9dc80b..000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/contactshare/ContactShareEditActivity.java +++ /dev/null @@ -1,140 +0,0 @@ -package org.thoughtcrime.securesms.contactshare; - -import android.app.Activity; -import androidx.lifecycle.ViewModelProviders; -import android.content.Context; -import android.content.Intent; -import android.net.Uri; -import android.os.AsyncTask; -import android.os.Bundle; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.recyclerview.widget.LinearLayoutManager; -import androidx.recyclerview.widget.RecyclerView; -import android.view.View; -import android.widget.Toast; - -import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity; -import network.loki.messenger.R; -import org.thoughtcrime.securesms.database.DatabaseFactory; -import org.thoughtcrime.securesms.mms.GlideApp; -import org.thoughtcrime.securesms.util.DynamicLanguage; -import org.thoughtcrime.securesms.util.DynamicTheme; - -import java.util.ArrayList; -import java.util.List; - -import static org.thoughtcrime.securesms.contactshare.Contact.*; -import static org.thoughtcrime.securesms.contactshare.ContactShareEditViewModel.*; - -public class ContactShareEditActivity extends PassphraseRequiredActionBarActivity implements ContactShareEditAdapter.EventListener { - - public static final String KEY_CONTACTS = "contacts"; - private static final String KEY_CONTACT_URIS = "contact_uris"; - private static final int CODE_NAME_EDIT = 55; - - private final DynamicTheme dynamicTheme = new DynamicTheme(); - private final DynamicLanguage dynamicLanguage = new DynamicLanguage(); - - private ContactShareEditViewModel viewModel; - - public static Intent getIntent(@NonNull Context context, @NonNull List contactUris) { - ArrayList contactUriList = new ArrayList<>(contactUris); - - Intent intent = new Intent(context, ContactShareEditActivity.class); - intent.putParcelableArrayListExtra(KEY_CONTACT_URIS, contactUriList); - return intent; - } - - @Override - protected void onPreCreate() { - dynamicTheme.onCreate(this); - dynamicLanguage.onCreate(this); - } - - @Override - protected void onCreate(@Nullable Bundle savedInstanceState, boolean ready) { - setContentView(R.layout.activity_contact_share_edit); - - if (getIntent() == null) { - throw new IllegalStateException("You must supply extras to this activity. Please use the #getIntent() method."); - } - - List contactUris = getIntent().getParcelableArrayListExtra(KEY_CONTACT_URIS); - if (contactUris == null) { - throw new IllegalStateException("You must supply contact Uri's to this activity. Please use the #getIntent() method."); - } - - View sendButton = findViewById(R.id.contact_share_edit_send); - sendButton.setOnClickListener(v -> onSendClicked(viewModel.getFinalizedContacts())); - - RecyclerView contactList = findViewById(R.id.contact_share_edit_list); - contactList.setLayoutManager(new LinearLayoutManager(this)); - contactList.getLayoutManager().setAutoMeasureEnabled(true); - - ContactShareEditAdapter contactAdapter = new ContactShareEditAdapter(GlideApp.with(this), dynamicLanguage.getCurrentLocale(), this); - contactList.setAdapter(contactAdapter); - - ContactRepository contactRepository = new ContactRepository(this, - AsyncTask.THREAD_POOL_EXECUTOR, - DatabaseFactory.getContactsDatabase(this)); - - viewModel = ViewModelProviders.of(this, new Factory(contactUris, contactRepository)).get(ContactShareEditViewModel.class); - viewModel.getContacts().observe(this, contacts -> { - contactAdapter.setContacts(contacts); - contactList.post(() -> contactList.scrollToPosition(0)); - }); - viewModel.getEvents().observe(this, this::presentEvent); - } - - @Override - protected void onResume() { - super.onResume(); - dynamicTheme.onResume(this); - dynamicTheme.onResume(this); - } - - private void presentEvent(@Nullable Event event) { - if (event == null) { - return; - } - - if (event == Event.BAD_CONTACT) { - Toast.makeText(this, R.string.ContactShareEditActivity_invalid_contact, Toast.LENGTH_SHORT).show(); - finish(); - } - } - - private void onSendClicked(List contacts) { - Intent intent = new Intent(); - - ArrayList contactArrayList = new ArrayList<>(contacts.size()); - contactArrayList.addAll(contacts); - intent.putExtra(KEY_CONTACTS, contactArrayList); - - setResult(Activity.RESULT_OK, intent); - - finish(); - } - - @Override - public void onNameEditClicked(int position, @NonNull Name name) { - startActivityForResult(ContactNameEditActivity.getIntent(this, name, position), CODE_NAME_EDIT); - } - - @Override - protected void onActivityResult(int requestCode, int resultCode, Intent data) { - super.onActivityResult(requestCode, resultCode, data); - - if (requestCode != CODE_NAME_EDIT || resultCode != RESULT_OK || data == null) { - return; - } - - int position = data.getIntExtra(ContactNameEditActivity.KEY_CONTACT_INDEX, -1); - Name name = data.getParcelableExtra(ContactNameEditActivity.KEY_NAME); - - if (name != null) { - viewModel.updateContactName(position, name); - } - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/contactshare/ContactShareEditAdapter.java b/app/src/main/java/org/thoughtcrime/securesms/contactshare/ContactShareEditAdapter.java deleted file mode 100644 index 699f4b9ba..000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/contactshare/ContactShareEditAdapter.java +++ /dev/null @@ -1,95 +0,0 @@ -package org.thoughtcrime.securesms.contactshare; - -import android.content.Context; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.recyclerview.widget.LinearLayoutManager; -import androidx.recyclerview.widget.RecyclerView; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.TextView; - -import network.loki.messenger.R; - -import org.thoughtcrime.securesms.mms.GlideRequests; - -import java.util.ArrayList; -import java.util.List; -import java.util.Locale; - -import static org.thoughtcrime.securesms.contactshare.Contact.*; - -public class ContactShareEditAdapter extends RecyclerView.Adapter { - - private final GlideRequests glideRequests; - private final Locale locale; - private final EventListener eventListener; - private final List contacts; - - ContactShareEditAdapter(@NonNull GlideRequests glideRequests, @NonNull Locale locale, @NonNull EventListener eventListener) { - this.glideRequests = glideRequests; - this.locale = locale; - this.eventListener = eventListener; - this.contacts = new ArrayList<>(); - } - - @Override - public @NonNull ContactEditViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { - return new ContactEditViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_editable_contact, parent, false), - locale, - glideRequests); - } - - @Override - public void onBindViewHolder(@NonNull ContactEditViewHolder holder, int position) { - holder.bind(position, contacts.get(position), eventListener); - } - - @Override - public int getItemCount() { - return contacts.size(); - } - - void setContacts(@Nullable List contacts) { - this.contacts.clear(); - - if (contacts != null) { - this.contacts.addAll(contacts); - } - - notifyDataSetChanged(); - } - - static class ContactEditViewHolder extends RecyclerView.ViewHolder { - - private final TextView name; - private final View nameEditButton; - private final ContactFieldAdapter fieldAdapter; - - ContactEditViewHolder(View itemView, @NonNull Locale locale, @NonNull GlideRequests glideRequests) { - super(itemView); - - this.name = itemView.findViewById(R.id.editable_contact_name); - this.nameEditButton = itemView.findViewById(R.id.editable_contact_name_edit_button); - this.fieldAdapter = new ContactFieldAdapter(locale, glideRequests, true); - - RecyclerView fields = itemView.findViewById(R.id.editable_contact_fields); - fields.setLayoutManager(new LinearLayoutManager(itemView.getContext())); - fields.getLayoutManager().setAutoMeasureEnabled(true); - fields.setAdapter(fieldAdapter); - } - - void bind(int position, @NonNull Contact contact, @NonNull EventListener eventListener) { - Context context = itemView.getContext(); - - name.setText(ContactUtil.getDisplayName(contact)); - nameEditButton.setOnClickListener(v -> eventListener.onNameEditClicked(position, contact.getName())); - fieldAdapter.setFields(context, contact.getAvatar(), contact.getPhoneNumbers(), contact.getEmails(), contact.getPostalAddresses()); - } - } - - interface EventListener { - void onNameEditClicked(int position, @NonNull Name name); - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/contactshare/ContactShareEditViewModel.java b/app/src/main/java/org/thoughtcrime/securesms/contactshare/ContactShareEditViewModel.java deleted file mode 100644 index 860729cd4..000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/contactshare/ContactShareEditViewModel.java +++ /dev/null @@ -1,113 +0,0 @@ -package org.thoughtcrime.securesms.contactshare; - -import androidx.lifecycle.LiveData; -import androidx.lifecycle.MutableLiveData; -import androidx.lifecycle.ViewModel; -import androidx.lifecycle.ViewModelProvider; -import android.net.Uri; -import androidx.annotation.NonNull; - -import com.annimon.stream.Stream; - -import org.thoughtcrime.securesms.contactshare.Contact.Name; -import org.thoughtcrime.securesms.util.SingleLiveEvent; - -import java.util.ArrayList; -import java.util.List; - -class ContactShareEditViewModel extends ViewModel { - - private final MutableLiveData> contacts; - private final SingleLiveEvent events; - private final ContactRepository repo; - - ContactShareEditViewModel(@NonNull List contactUris, - @NonNull ContactRepository contactRepository) - { - contacts = new MutableLiveData<>(); - events = new SingleLiveEvent<>(); - repo = contactRepository; - - repo.getContacts(contactUris, retrieved -> { - if (retrieved.isEmpty()) { - events.postValue(Event.BAD_CONTACT); - } else { - contacts.postValue(retrieved); - } - }); - } - - @NonNull LiveData> getContacts() { - return contacts; - } - - @NonNull List getFinalizedContacts() { - List currentContacts = getCurrentContacts(); - List trimmedContacts = new ArrayList<>(currentContacts.size()); - - for (Contact contact : currentContacts) { - Contact trimmed = new Contact(contact.getName(), - contact.getOrganization(), - trimSelectables(contact.getPhoneNumbers()), - trimSelectables(contact.getEmails()), - trimSelectables(contact.getPostalAddresses()), - contact.getAvatar() != null && contact.getAvatar().isSelected() ? contact.getAvatar() : null); - trimmedContacts.add(trimmed); - } - - return trimmedContacts; - } - - @NonNull LiveData getEvents() { - return events; - } - - void updateContactName(int contactPosition, @NonNull Name name) { - if (name.isEmpty()) { - events.postValue(Event.BAD_CONTACT); - return; - } - - List currentContacts = getCurrentContacts(); - Contact original = currentContacts.remove(contactPosition); - - currentContacts.add(new Contact(name, - original.getOrganization(), - original.getPhoneNumbers(), - original.getEmails(), - original.getPostalAddresses(), - original.getAvatar())); - - contacts.postValue(currentContacts); - } - - private List trimSelectables(List selectables) { - return Stream.of(selectables).filter(Selectable::isSelected).toList(); - } - - @NonNull - private List getCurrentContacts() { - List currentContacts = contacts.getValue(); - return currentContacts != null ? currentContacts : new ArrayList<>(); - } - - enum Event { - BAD_CONTACT - } - - static class Factory extends ViewModelProvider.NewInstanceFactory { - - private final List contactUris; - private final ContactRepository contactRepository; - - Factory(@NonNull List contactUris, @NonNull ContactRepository contactRepository) { - this.contactUris = contactUris; - this.contactRepository = contactRepository; - } - - @Override - public @NonNull T create(@NonNull Class modelClass) { - return modelClass.cast(new ContactShareEditViewModel(contactUris, contactRepository)); - } - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/contactshare/ContactUtil.java b/app/src/main/java/org/thoughtcrime/securesms/contactshare/ContactUtil.java index b1db9417f..7be50b82a 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/contactshare/ContactUtil.java +++ b/app/src/main/java/org/thoughtcrime/securesms/contactshare/ContactUtil.java @@ -34,16 +34,6 @@ import network.loki.messenger.R; public final class ContactUtil { - private static final String TAG = ContactUtil.class.getSimpleName(); - - public static long getContactIdFromUri(@NonNull Uri uri) { - try { - return Long.parseLong(uri.getLastPathSegment()); - } catch (NumberFormatException e) { - return -1; - } - } - public static @NonNull CharSequence getStringSummary(@NonNull Context context, @NonNull Contact contact) { String contactName = ContactUtil.getDisplayName(contact); @@ -69,159 +59,4 @@ public final class ContactUtil { return ""; } - - public static @NonNull String getDisplayNumber(@NonNull Contact contact, @NonNull Locale locale) { - Phone displayNumber = getPrimaryNumber(contact); - - if (displayNumber != null) { - return ContactUtil.getPrettyPhoneNumber(displayNumber, locale); - } else if (contact.getEmails().size() > 0) { - return contact.getEmails().get(0).getEmail(); - } else { - return ""; - } - } - - private static @Nullable Phone getPrimaryNumber(@NonNull Contact contact) { - if (contact.getPhoneNumbers().size() == 0) { - return null; - } - - List mobileNumbers = Stream.of(contact.getPhoneNumbers()).filter(number -> number.getType() == Phone.Type.MOBILE).toList(); - if (mobileNumbers.size() > 0) { - return mobileNumbers.get(0); - } - - return contact.getPhoneNumbers().get(0); - } - - public static @NonNull String getPrettyPhoneNumber(@NonNull Phone phoneNumber, @NonNull Locale fallbackLocale) { - return getPrettyPhoneNumber(phoneNumber.getNumber(), fallbackLocale); - } - - private static @NonNull String getPrettyPhoneNumber(@NonNull String phoneNumber, @NonNull Locale fallbackLocale) { - return phoneNumber; - } - - public static @NonNull String getNormalizedPhoneNumber(@NonNull Context context, @NonNull String number) { - Address address = Address.fromExternal(context, number); - return address.serialize(); - } - - @MainThread - public static void selectRecipientThroughDialog(@NonNull Context context, @NonNull List choices, @NonNull Locale locale, @NonNull RecipientSelectedCallback callback) { - if (choices.size() > 1) { - CharSequence[] values = new CharSequence[choices.size()]; - - for (int i = 0; i < values.length; i++) { - values[i] = getPrettyPhoneNumber(choices.get(i).getAddress().toPhoneString(), locale); - } - - new AlertDialog.Builder(context) - .setItems(values, ((dialog, which) -> callback.onSelected(choices.get(which)))) - .create() - .show(); - } else { - callback.onSelected(choices.get(0)); - } - } - - public static List getRecipients(@NonNull Context context, @NonNull Contact contact) { - return Stream.of(contact.getPhoneNumbers()).map(phone -> Recipient.from(context, Address.fromExternal(context, phone.getNumber()), true)).toList(); - } - - @WorkerThread - public static @NonNull Intent buildAddToContactsIntent(@NonNull Context context, @NonNull Contact contact) { - Intent intent = new Intent(Intent.ACTION_INSERT_OR_EDIT); - intent.setType(ContactsContract.Contacts.CONTENT_ITEM_TYPE); - - if (!TextUtils.isEmpty(contact.getName().getDisplayName())) { - intent.putExtra(ContactsContract.Intents.Insert.NAME, contact.getName().getDisplayName()); - } - - if (!TextUtils.isEmpty(contact.getOrganization())) { - intent.putExtra(ContactsContract.Intents.Insert.COMPANY, contact.getOrganization()); - } - - if (contact.getPhoneNumbers().size() > 0) { - intent.putExtra(ContactsContract.Intents.Insert.PHONE, contact.getPhoneNumbers().get(0).getNumber()); - intent.putExtra(ContactsContract.Intents.Insert.PHONE_TYPE, getSystemType(contact.getPhoneNumbers().get(0).getType())); - } - - if (contact.getPhoneNumbers().size() > 1) { - intent.putExtra(ContactsContract.Intents.Insert.SECONDARY_PHONE, contact.getPhoneNumbers().get(1).getNumber()); - intent.putExtra(ContactsContract.Intents.Insert.SECONDARY_PHONE_TYPE, getSystemType(contact.getPhoneNumbers().get(1).getType())); - } - - if (contact.getPhoneNumbers().size() > 2) { - intent.putExtra(ContactsContract.Intents.Insert.TERTIARY_PHONE, contact.getPhoneNumbers().get(2).getNumber()); - intent.putExtra(ContactsContract.Intents.Insert.TERTIARY_PHONE_TYPE, getSystemType(contact.getPhoneNumbers().get(2).getType())); - } - - if (contact.getEmails().size() > 0) { - intent.putExtra(ContactsContract.Intents.Insert.EMAIL, contact.getEmails().get(0).getEmail()); - intent.putExtra(ContactsContract.Intents.Insert.EMAIL_TYPE, getSystemType(contact.getEmails().get(0).getType())); - } - - if (contact.getEmails().size() > 1) { - intent.putExtra(ContactsContract.Intents.Insert.SECONDARY_EMAIL, contact.getEmails().get(1).getEmail()); - intent.putExtra(ContactsContract.Intents.Insert.SECONDARY_EMAIL_TYPE, getSystemType(contact.getEmails().get(1).getType())); - } - - if (contact.getEmails().size() > 2) { - intent.putExtra(ContactsContract.Intents.Insert.TERTIARY_EMAIL, contact.getEmails().get(2).getEmail()); - intent.putExtra(ContactsContract.Intents.Insert.TERTIARY_EMAIL_TYPE, getSystemType(contact.getEmails().get(2).getType())); - } - - if (contact.getPostalAddresses().size() > 0) { - intent.putExtra(ContactsContract.Intents.Insert.POSTAL, contact.getPostalAddresses().get(0).toString()); - intent.putExtra(ContactsContract.Intents.Insert.POSTAL_TYPE, getSystemType(contact.getPostalAddresses().get(0).getType())); - } - - if (contact.getAvatarAttachment() != null && contact.getAvatarAttachment().getDataUri() != null) { - try { - ContentValues values = new ContentValues(); - values.put(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE); - values.put(ContactsContract.CommonDataKinds.Photo.PHOTO, Util.readFully(PartAuthority.getAttachmentStream(context, contact.getAvatarAttachment().getDataUri()))); - - ArrayList valuesArray = new ArrayList<>(1); - valuesArray.add(values); - - intent.putParcelableArrayListExtra(ContactsContract.Intents.Insert.DATA, valuesArray); - } catch (IOException e) { - Log.w(TAG, "Failed to read avatar into a byte array.", e); - } - } - return intent; - } - - private static int getSystemType(Phone.Type type) { - switch (type) { - case HOME: return ContactsContract.CommonDataKinds.Phone.TYPE_HOME; - case MOBILE: return ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE; - case WORK: return ContactsContract.CommonDataKinds.Phone.TYPE_WORK; - default: return ContactsContract.CommonDataKinds.Phone.TYPE_CUSTOM; - } - } - - private static int getSystemType(Email.Type type) { - switch (type) { - case HOME: return ContactsContract.CommonDataKinds.Email.TYPE_HOME; - case MOBILE: return ContactsContract.CommonDataKinds.Email.TYPE_MOBILE; - case WORK: return ContactsContract.CommonDataKinds.Email.TYPE_WORK; - default: return ContactsContract.CommonDataKinds.Email.TYPE_CUSTOM; - } - } - - private static int getSystemType(PostalAddress.Type type) { - switch (type) { - case HOME: return ContactsContract.CommonDataKinds.StructuredPostal.TYPE_HOME; - case WORK: return ContactsContract.CommonDataKinds.StructuredPostal.TYPE_WORK; - default: return ContactsContract.CommonDataKinds.StructuredPostal.TYPE_CUSTOM; - } - } - - public interface RecipientSelectedCallback { - void onSelected(@NonNull Recipient recipient); - } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationActivity.java b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationActivity.java index d9b22ced3..b80d811d0 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationActivity.java +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationActivity.java @@ -112,11 +112,9 @@ import org.thoughtcrime.securesms.components.identity.UntrustedSendDialog; import org.thoughtcrime.securesms.components.identity.UnverifiedBannerView; import org.thoughtcrime.securesms.components.identity.UnverifiedSendDialog; import org.thoughtcrime.securesms.components.location.SignalPlace; -import org.thoughtcrime.securesms.components.reminder.ReminderView; import org.thoughtcrime.securesms.contacts.ContactAccessor; import org.thoughtcrime.securesms.contacts.ContactAccessor.ContactData; import org.thoughtcrime.securesms.contactshare.Contact; -import org.thoughtcrime.securesms.contactshare.ContactShareEditActivity; import org.thoughtcrime.securesms.contactshare.ContactUtil; import org.thoughtcrime.securesms.contactshare.SimpleTextWatcher; import org.thoughtcrime.securesms.crypto.IdentityKeyParcelable; @@ -138,7 +136,6 @@ import org.thoughtcrime.securesms.database.identity.IdentityRecordList; import org.thoughtcrime.securesms.database.model.MessageRecord; import org.thoughtcrime.securesms.database.model.MmsMessageRecord; import org.thoughtcrime.securesms.database.model.StickerRecord; -import org.thoughtcrime.securesms.events.ReminderUpdateEvent; import org.thoughtcrime.securesms.giph.ui.GiphyActivity; import org.thoughtcrime.securesms.jobs.MultiDeviceBlockedUpdateJob; import org.thoughtcrime.securesms.linkpreview.LinkPreview; @@ -282,7 +279,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity private static final int PICK_DOCUMENT = 2; private static final int PICK_AUDIO = 3; private static final int PICK_CONTACT = 4; - private static final int GET_CONTACT_DETAILS = 5; +// private static final int GET_CONTACT_DETAILS = 5; // private static final int GROUP_EDIT = 6; private static final int TAKE_PHOTO = 7; private static final int ADD_CONTACT = 8; @@ -303,7 +300,6 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity private Button unblockButton; private Button makeDefaultSmsButton; private InputAwareLayout container; - protected Stub reminderView; private Stub unverifiedBannerView; private Stub groupShareProfileView; private TypingStatusTextWatcher typingTextWatcher; @@ -613,14 +609,11 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity break; case PICK_CONTACT: if (isSecureText && !isSmsForced()) { - openContactShareEditor(data.getData()); +// openContactShareEditor(data.getData()); } else { addAttachmentContactInfo(data.getData()); } break; - case GET_CONTACT_DETAILS: - sendSharedContact(data.getParcelableArrayListExtra(ContactShareEditActivity.KEY_CONTACTS)); - break; case TAKE_PHOTO: if (attachmentManager.getCaptureUri() != null) { setMedia(attachmentManager.getCaptureUri(), MediaType.IMAGE); @@ -887,11 +880,6 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity inputPanel.onKeyboardShown(); } - @Subscribe(threadMode = ThreadMode.MAIN) - public void onEvent(ReminderUpdateEvent event) { - updateReminders(recipient.hasSeenInviteReminder()); - } - @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); @@ -1487,14 +1475,6 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity } } - protected void updateReminders(boolean seenInvite) { - Log.i(TAG, "updateReminders(" + seenInvite + ")"); - - if (reminderView.resolved()) { - reminderView.get().hide(); - } - } - private void updateSessionRestoreBanner() { Set devices = DatabaseFactory.getLokiThreadDatabase(this).getSessionRestoreDevices(threadId); if (devices.size() > 0) { @@ -1592,7 +1572,6 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity unblockButton = ViewUtil.findById(this, R.id.unblock_button); makeDefaultSmsButton = ViewUtil.findById(this, R.id.make_default_sms_button); container = ViewUtil.findById(this, R.id.layout_container); - reminderView = ViewUtil.findStubById(this, R.id.reminder_stub); unverifiedBannerView = ViewUtil.findStubById(this, R.id.unverified_banner_stub); groupShareProfileView = ViewUtil.findStubById(this, R.id.group_share_profile_view_stub); quickAttachmentToggle = ViewUtil.findById(this, R.id.quick_attachment_toggle); @@ -1807,7 +1786,6 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity updateInputUI(recipient, isSecureText, isDefaultSms); setActionBarColor(recipient.getColor()); setGroupShareProfileReminder(recipient); - updateReminders(recipient.hasSeenInviteReminder()); updateDefaultSubscriptionId(recipient.getDefaultSubscriptionId()); initializeSecurity(isSecureText, isDefaultSms); @@ -1906,7 +1884,6 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity } if (MediaType.VCARD.equals(mediaType) && isSecureText) { - openContactShareEditor(uri); return new SettableFuture<>(false); } else if (MediaType.IMAGE.equals(mediaType) || MediaType.GIF.equals(mediaType) || MediaType.VIDEO.equals(mediaType)) { Media media = new Media(uri, MediaUtil.getMimeType(this, uri), 0, width, height, 0, Optional.absent(), Optional.absent()); @@ -1917,11 +1894,6 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity } } - private void openContactShareEditor(Uri contactUri) { - Intent intent = ContactShareEditActivity.getIntent(this, Collections.singletonList(contactUri)); - startActivityForResult(intent, GET_CONTACT_DETAILS); - } - private void addAttachmentContactInfo(Uri contactUri) { ContactAccessor contactDataList = ContactAccessor.getInstance(); ContactData contactData = contactDataList.getContactData(this, contactUri); diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationPopupActivity.java b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationPopupActivity.java index 44611d5f4..8b2747d83 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationPopupActivity.java +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationPopupActivity.java @@ -117,11 +117,4 @@ public class ConversationPopupActivity extends ConversationActivity { super.sendComplete(threadId); finish(); } - - @Override - protected void updateReminders(boolean seenInvite) { - if (reminderView.resolved()) { - reminderView.get().setVisibility(View.GONE); - } - } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationSearchViewModel.java b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationSearchViewModel.java index d83055071..11d2e2b90 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationSearchViewModel.java +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationSearchViewModel.java @@ -37,7 +37,6 @@ public class ConversationSearchViewModel extends AndroidViewModel { debouncer = new Debouncer(500); searchRepository = new SearchRepository(context, DatabaseFactory.getSearchDatabase(context), - DatabaseFactory.getContactsDatabase(context), DatabaseFactory.getThreadDatabase(context), ContactAccessor.getInstance(), SignalExecutors.SERIAL); diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationTitleView.java b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationTitleView.java deleted file mode 100644 index dd1394058..000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationTitleView.java +++ /dev/null @@ -1,154 +0,0 @@ -package org.thoughtcrime.securesms.conversation; - -import android.annotation.SuppressLint; -import android.content.Context; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import android.text.TextUtils; -import android.util.AttributeSet; -import android.view.View; -import android.widget.ImageView; -import android.widget.RelativeLayout; -import android.widget.TextView; - -import com.annimon.stream.Collectors; -import com.annimon.stream.Stream; - -import org.thoughtcrime.securesms.components.AvatarImageView; -import org.thoughtcrime.securesms.mms.GlideRequests; -import org.thoughtcrime.securesms.recipients.Recipient; -import org.thoughtcrime.securesms.util.TextSecurePreferences; -import org.thoughtcrime.securesms.util.ViewUtil; - -import network.loki.messenger.R; - -public class ConversationTitleView extends RelativeLayout { - - @SuppressWarnings("unused") - private static final String TAG = ConversationTitleView.class.getSimpleName(); - - private View content; - private AvatarImageView avatar; - private TextView title; - private TextView subtitle; - private ImageView verified; - private View subtitleContainer; - - public ConversationTitleView(Context context) { - this(context, null); - } - - public ConversationTitleView(Context context, AttributeSet attrs) { - super(context, attrs); - - } - - @Override - public void onFinishInflate() { - super.onFinishInflate(); - - this.content = ViewUtil.findById(this, R.id.content); - this.title = ViewUtil.findById(this, R.id.title); - this.subtitle = ViewUtil.findById(this, R.id.subtitle); - this.verified = ViewUtil.findById(this, R.id.verified_indicator); - this.subtitleContainer = ViewUtil.findById(this, R.id.subtitle_container); - this.avatar = ViewUtil.findById(this, R.id.contact_photo_image); - - this.avatar.setEnabled(false); - - ViewUtil.setTextViewGravityStart(this.title, getContext()); - ViewUtil.setTextViewGravityStart(this.subtitle, getContext()); - } - - public void setTitle(@NonNull GlideRequests glideRequests, @Nullable Recipient recipient) { - if (recipient == null) setComposeTitle(); - else setRecipientTitle(recipient); - - if (recipient != null && recipient.isBlocked()) { - title.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_block_white_18dp, 0, 0, 0); - } else if (recipient != null && recipient.isMuted()) { - title.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_volume_off_white_18dp, 0, 0, 0); - } else { - title.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0); - } - - if (recipient != null) { - this.avatar.setAvatar(glideRequests, recipient, false); - } - } - - public void setVerified(boolean verified) { - this.verified.setVisibility(verified ? View.VISIBLE : View.GONE); - } - - @Override - public void setOnClickListener(@Nullable OnClickListener listener) { - this.content.setOnClickListener(listener); - this.avatar.setOnClickListener(listener); - } - - @Override - public void setOnLongClickListener(@Nullable OnLongClickListener listener) { - this.content.setOnLongClickListener(listener); - this.avatar.setOnLongClickListener(listener); - } - - private void setComposeTitle() { - this.title.setText(R.string.ConversationActivity_compose_message); - this.subtitle.setText(null); - this.subtitle.setVisibility(View.GONE); - } - - private void setRecipientTitle(Recipient recipient) { - if (recipient.isGroupRecipient()) setGroupRecipientTitle(recipient); - else if (recipient.isLocalNumber()) setSelfTitle(); - else if (TextUtils.isEmpty(recipient.getName())) setNonContactRecipientTitle(recipient); - else setContactRecipientTitle(recipient); - } - - private void setGroupRecipientTitle(Recipient recipient) { - String localNumber = TextSecurePreferences.getLocalNumber(getContext()); - - this.title.setText(recipient.getName()); - this.subtitle.setText(Stream.of(recipient.getParticipants()) - .filter(r -> !r.getAddress().serialize().equals(localNumber)) - .map(Recipient::toShortString) - .collect(Collectors.joining(", "))); - - this.subtitle.setVisibility(View.GONE); - this.subtitleContainer.setVisibility(VISIBLE); - } - - private void setSelfTitle() { - this.title.setText(R.string.note_to_self); - this.subtitleContainer.setVisibility(View.GONE); - } - - @SuppressLint("SetTextI18n") - private void setNonContactRecipientTitle(Recipient recipient) { - this.title.setText(recipient.getAddress().serialize()); - this.subtitleContainer.setVisibility(VISIBLE); - - if (TextUtils.isEmpty(recipient.getProfileName())) { - this.subtitle.setText(null); - this.subtitle.setVisibility(View.GONE); - } else { - this.subtitle.setText("~" + recipient.getProfileName()); - this.subtitle.setVisibility(View.VISIBLE); - } - } - - private void setContactRecipientTitle(Recipient recipient) { - this.title.setText(recipient.getName()); - - if (TextUtils.isEmpty(recipient.getCustomLabel())) { - this.subtitle.setText(null); - this.subtitle.setVisibility(View.GONE); - this.subtitleContainer.setVisibility(View.GONE); - } else { - this.subtitle.setText(recipient.getCustomLabel()); - this.subtitle.setVisibility(View.VISIBLE); - this.subtitleContainer.setVisibility(View.VISIBLE); - } - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/DatabaseFactory.java b/app/src/main/java/org/thoughtcrime/securesms/database/DatabaseFactory.java index 3df26109b..8410017e9 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/DatabaseFactory.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/DatabaseFactory.java @@ -22,7 +22,6 @@ import androidx.annotation.NonNull; import net.sqlcipher.database.SQLiteDatabase; import org.thoughtcrime.securesms.DatabaseUpgradeActivity; -import org.thoughtcrime.securesms.contacts.ContactsDatabase; import org.thoughtcrime.securesms.crypto.AttachmentSecret; import org.thoughtcrime.securesms.crypto.AttachmentSecretProvider; import org.thoughtcrime.securesms.crypto.DatabaseSecret; @@ -59,7 +58,6 @@ public class DatabaseFactory { private final PushDatabase pushDatabase; private final GroupDatabase groupDatabase; private final RecipientDatabase recipientDatabase; - private final ContactsDatabase contactsDatabase; private final GroupReceiptDatabase groupReceiptDatabase; private final OneTimePreKeyDatabase preKeyDatabase; private final SignedPreKeyDatabase signedPreKeyDatabase; @@ -131,10 +129,6 @@ public class DatabaseFactory { return getInstance(context).recipientDatabase; } - public static ContactsDatabase getContactsDatabase(Context context) { - return getInstance(context).contactsDatabase; - } - public static GroupReceiptDatabase getGroupReceiptDatabase(Context context) { return getInstance(context).groupReceiptDatabase; } @@ -225,7 +219,6 @@ public class DatabaseFactory { this.groupDatabase = new GroupDatabase(context, databaseHelper); this.recipientDatabase = new RecipientDatabase(context, databaseHelper); this.groupReceiptDatabase = new GroupReceiptDatabase(context, databaseHelper); - this.contactsDatabase = new ContactsDatabase(context); this.preKeyDatabase = new OneTimePreKeyDatabase(context, databaseHelper); this.signedPreKeyDatabase = new SignedPreKeyDatabase(context, databaseHelper); this.sessionDatabase = new SessionDatabase(context, databaseHelper); diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/RecipientDatabase.java b/app/src/main/java/org/thoughtcrime/securesms/database/RecipientDatabase.java index cce572f5a..a5ceeb550 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/RecipientDatabase.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/RecipientDatabase.java @@ -199,7 +199,6 @@ public class RecipientDatabase extends Database { int callVibrateState = cursor.getInt(cursor.getColumnIndexOrThrow(CALL_VIBRATE)); long muteUntil = cursor.getLong(cursor.getColumnIndexOrThrow(MUTE_UNTIL)); String serializedColor = cursor.getString(cursor.getColumnIndexOrThrow(COLOR)); - boolean seenInviteReminder = cursor.getInt(cursor.getColumnIndexOrThrow(SEEN_INVITE_REMINDER)) == 1; int defaultSubscriptionId = cursor.getInt(cursor.getColumnIndexOrThrow(DEFAULT_SUBSCRIPTION_ID)); int expireMessages = cursor.getInt(cursor.getColumnIndexOrThrow(EXPIRE_MESSAGES)); int registeredState = cursor.getInt(cursor.getColumnIndexOrThrow(REGISTERED)); @@ -238,8 +237,8 @@ public class RecipientDatabase extends Database { VibrateState.fromId(messageVibrateState), VibrateState.fromId(callVibrateState), Util.uri(messageRingtone), Util.uri(callRingtone), - color, seenInviteReminder, - defaultSubscriptionId, expireMessages, + color, + defaultSubscriptionId, expireMessages, RegisteredState.fromId(registeredState), profileKey, systemDisplayName, systemContactPhoto, systemPhoneLabel, systemContactUri, @@ -326,13 +325,6 @@ public class RecipientDatabase extends Database { recipient.resolve().setMuted(until); } - public void setSeenInviteReminder(@NonNull Recipient recipient, @SuppressWarnings("SameParameterValue") boolean seen) { - ContentValues values = new ContentValues(1); - values.put(SEEN_INVITE_REMINDER, seen ? 1 : 0); - updateOrInsert(recipient.getAddress(), values); - recipient.resolve().setHasSeenInviteReminder(seen); - } - public void setExpireMessages(@NonNull Recipient recipient, int expiration) { recipient.setExpireMessages(expiration); @@ -553,7 +545,6 @@ public class RecipientDatabase extends Database { private final Uri messageRingtone; private final Uri callRingtone; private final MaterialColor color; - private final boolean seenInviteReminder; private final int defaultSubscriptionId; private final int expireMessages; private final RegisteredState registered; @@ -575,10 +566,9 @@ public class RecipientDatabase extends Database { @Nullable Uri messageRingtone, @Nullable Uri callRingtone, @Nullable MaterialColor color, - boolean seenInviteReminder, int defaultSubscriptionId, int expireMessages, - @NonNull RegisteredState registered, + @NonNull RegisteredState registered, @Nullable byte[] profileKey, @Nullable String systemDisplayName, @Nullable String systemContactPhoto, @@ -598,7 +588,6 @@ public class RecipientDatabase extends Database { this.messageRingtone = messageRingtone; this.callRingtone = callRingtone; this.color = color; - this.seenInviteReminder = seenInviteReminder; this.defaultSubscriptionId = defaultSubscriptionId; this.expireMessages = expireMessages; this.registered = registered; @@ -643,10 +632,6 @@ public class RecipientDatabase extends Database { return callRingtone; } - public boolean hasSeenInviteReminder() { - return seenInviteReminder; - } - public Optional getDefaultSubscriptionId() { return defaultSubscriptionId != -1 ? Optional.of(defaultSubscriptionId) : Optional.absent(); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/dependencies/SignalCommunicationModule.java b/app/src/main/java/org/thoughtcrime/securesms/dependencies/SignalCommunicationModule.java index b7137994e..d8d407066 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/dependencies/SignalCommunicationModule.java +++ b/app/src/main/java/org/thoughtcrime/securesms/dependencies/SignalCommunicationModule.java @@ -2,13 +2,19 @@ package org.thoughtcrime.securesms.dependencies; import android.content.Context; -import org.greenrobot.eventbus.EventBus; +import org.session.libsignal.libsignal.util.guava.Optional; +import org.session.libsignal.service.api.SignalServiceAccountManager; +import org.session.libsignal.service.api.SignalServiceMessageReceiver; +import org.session.libsignal.service.api.SignalServiceMessageSender; +import org.session.libsignal.service.api.util.CredentialsProvider; +import org.session.libsignal.service.api.util.SleepTimer; +import org.session.libsignal.service.api.util.UptimeSleepTimer; +import org.session.libsignal.service.api.websocket.ConnectivityListener; import org.thoughtcrime.securesms.ApplicationContext; import org.thoughtcrime.securesms.CreateProfileActivity; import org.thoughtcrime.securesms.DeviceListFragment; import org.thoughtcrime.securesms.crypto.storage.SignalProtocolStoreImpl; import org.thoughtcrime.securesms.database.DatabaseFactory; -import org.thoughtcrime.securesms.events.ReminderUpdateEvent; import org.thoughtcrime.securesms.jobs.AttachmentDownloadJob; import org.thoughtcrime.securesms.jobs.AttachmentUploadJob; import org.thoughtcrime.securesms.jobs.AvatarDownloadJob; @@ -55,14 +61,6 @@ import org.thoughtcrime.securesms.stickers.StickerPackPreviewRepository; import org.thoughtcrime.securesms.stickers.StickerRemoteUriLoader; import org.thoughtcrime.securesms.util.RealtimeSleepTimer; import org.thoughtcrime.securesms.util.TextSecurePreferences; -import org.session.libsignal.libsignal.util.guava.Optional; -import org.session.libsignal.service.api.SignalServiceAccountManager; -import org.session.libsignal.service.api.SignalServiceMessageReceiver; -import org.session.libsignal.service.api.SignalServiceMessageSender; -import org.session.libsignal.service.api.util.CredentialsProvider; -import org.session.libsignal.service.api.util.SleepTimer; -import org.session.libsignal.service.api.util.UptimeSleepTimer; -import org.session.libsignal.service.api.websocket.ConnectivityListener; import dagger.Module; import dagger.Provides; @@ -232,7 +230,6 @@ public class SignalCommunicationModule { public void onAuthenticationFailure() { Log.w(TAG, "onAuthenticationFailure()"); TextSecurePreferences.setUnauthorizedReceived(context, true); - EventBus.getDefault().post(new ReminderUpdateEvent()); } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/devicelist/DeviceNameProtos.java b/app/src/main/java/org/thoughtcrime/securesms/devicelist/DeviceNameProtos.java deleted file mode 100644 index 8700abbcf..000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/devicelist/DeviceNameProtos.java +++ /dev/null @@ -1,619 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// source: DeviceName.proto - -package org.thoughtcrime.securesms.devicelist; - -public final class DeviceNameProtos { - private DeviceNameProtos() {} - public static void registerAllExtensions( - com.google.protobuf.ExtensionRegistry registry) { - } - public interface DeviceNameOrBuilder - extends com.google.protobuf.MessageOrBuilder { - - // optional bytes ephemeralPublic = 1; - /** - * optional bytes ephemeralPublic = 1; - */ - boolean hasEphemeralPublic(); - /** - * optional bytes ephemeralPublic = 1; - */ - com.google.protobuf.ByteString getEphemeralPublic(); - - // optional bytes syntheticIv = 2; - /** - * optional bytes syntheticIv = 2; - */ - boolean hasSyntheticIv(); - /** - * optional bytes syntheticIv = 2; - */ - com.google.protobuf.ByteString getSyntheticIv(); - - // optional bytes ciphertext = 3; - /** - * optional bytes ciphertext = 3; - */ - boolean hasCiphertext(); - /** - * optional bytes ciphertext = 3; - */ - com.google.protobuf.ByteString getCiphertext(); - } - /** - * Protobuf type {@code signalservice.DeviceName} - */ - public static final class DeviceName extends - com.google.protobuf.GeneratedMessage - implements DeviceNameOrBuilder { - // Use DeviceName.newBuilder() to construct. - private DeviceName(com.google.protobuf.GeneratedMessage.Builder builder) { - super(builder); - this.unknownFields = builder.getUnknownFields(); - } - private DeviceName(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); } - - private static final DeviceName defaultInstance; - public static DeviceName getDefaultInstance() { - return defaultInstance; - } - - public DeviceName getDefaultInstanceForType() { - return defaultInstance; - } - - private final com.google.protobuf.UnknownFieldSet unknownFields; - @java.lang.Override - public final com.google.protobuf.UnknownFieldSet - getUnknownFields() { - return this.unknownFields; - } - private DeviceName( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - initFields(); - int mutable_bitField0_ = 0; - com.google.protobuf.UnknownFieldSet.Builder unknownFields = - com.google.protobuf.UnknownFieldSet.newBuilder(); - try { - boolean done = false; - while (!done) { - int tag = input.readTag(); - switch (tag) { - case 0: - done = true; - break; - default: { - if (!parseUnknownField(input, unknownFields, - extensionRegistry, tag)) { - done = true; - } - break; - } - case 10: { - bitField0_ |= 0x00000001; - ephemeralPublic_ = input.readBytes(); - break; - } - case 18: { - bitField0_ |= 0x00000002; - syntheticIv_ = input.readBytes(); - break; - } - case 26: { - bitField0_ |= 0x00000004; - ciphertext_ = input.readBytes(); - break; - } - } - } - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.setUnfinishedMessage(this); - } catch (java.io.IOException e) { - throw new com.google.protobuf.InvalidProtocolBufferException( - e.getMessage()).setUnfinishedMessage(this); - } finally { - this.unknownFields = unknownFields.build(); - makeExtensionsImmutable(); - } - } - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return org.thoughtcrime.securesms.devicelist.DeviceNameProtos.internal_static_signalservice_DeviceName_descriptor; - } - - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return org.thoughtcrime.securesms.devicelist.DeviceNameProtos.internal_static_signalservice_DeviceName_fieldAccessorTable - .ensureFieldAccessorsInitialized( - org.thoughtcrime.securesms.devicelist.DeviceNameProtos.DeviceName.class, org.thoughtcrime.securesms.devicelist.DeviceNameProtos.DeviceName.Builder.class); - } - - public static com.google.protobuf.Parser PARSER = - new com.google.protobuf.AbstractParser() { - public DeviceName parsePartialFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return new DeviceName(input, extensionRegistry); - } - }; - - @java.lang.Override - public com.google.protobuf.Parser getParserForType() { - return PARSER; - } - - private int bitField0_; - // optional bytes ephemeralPublic = 1; - public static final int EPHEMERALPUBLIC_FIELD_NUMBER = 1; - private com.google.protobuf.ByteString ephemeralPublic_; - /** - * optional bytes ephemeralPublic = 1; - */ - public boolean hasEphemeralPublic() { - return ((bitField0_ & 0x00000001) == 0x00000001); - } - /** - * optional bytes ephemeralPublic = 1; - */ - public com.google.protobuf.ByteString getEphemeralPublic() { - return ephemeralPublic_; - } - - // optional bytes syntheticIv = 2; - public static final int SYNTHETICIV_FIELD_NUMBER = 2; - private com.google.protobuf.ByteString syntheticIv_; - /** - * optional bytes syntheticIv = 2; - */ - public boolean hasSyntheticIv() { - return ((bitField0_ & 0x00000002) == 0x00000002); - } - /** - * optional bytes syntheticIv = 2; - */ - public com.google.protobuf.ByteString getSyntheticIv() { - return syntheticIv_; - } - - // optional bytes ciphertext = 3; - public static final int CIPHERTEXT_FIELD_NUMBER = 3; - private com.google.protobuf.ByteString ciphertext_; - /** - * optional bytes ciphertext = 3; - */ - public boolean hasCiphertext() { - return ((bitField0_ & 0x00000004) == 0x00000004); - } - /** - * optional bytes ciphertext = 3; - */ - public com.google.protobuf.ByteString getCiphertext() { - return ciphertext_; - } - - private void initFields() { - ephemeralPublic_ = com.google.protobuf.ByteString.EMPTY; - syntheticIv_ = com.google.protobuf.ByteString.EMPTY; - ciphertext_ = com.google.protobuf.ByteString.EMPTY; - } - private byte memoizedIsInitialized = -1; - public final boolean isInitialized() { - byte isInitialized = memoizedIsInitialized; - if (isInitialized != -1) return isInitialized == 1; - - memoizedIsInitialized = 1; - return true; - } - - public void writeTo(com.google.protobuf.CodedOutputStream output) - throws java.io.IOException { - getSerializedSize(); - if (((bitField0_ & 0x00000001) == 0x00000001)) { - output.writeBytes(1, ephemeralPublic_); - } - if (((bitField0_ & 0x00000002) == 0x00000002)) { - output.writeBytes(2, syntheticIv_); - } - if (((bitField0_ & 0x00000004) == 0x00000004)) { - output.writeBytes(3, ciphertext_); - } - getUnknownFields().writeTo(output); - } - - private int memoizedSerializedSize = -1; - public int getSerializedSize() { - int size = memoizedSerializedSize; - if (size != -1) return size; - - size = 0; - if (((bitField0_ & 0x00000001) == 0x00000001)) { - size += com.google.protobuf.CodedOutputStream - .computeBytesSize(1, ephemeralPublic_); - } - if (((bitField0_ & 0x00000002) == 0x00000002)) { - size += com.google.protobuf.CodedOutputStream - .computeBytesSize(2, syntheticIv_); - } - if (((bitField0_ & 0x00000004) == 0x00000004)) { - size += com.google.protobuf.CodedOutputStream - .computeBytesSize(3, ciphertext_); - } - size += getUnknownFields().getSerializedSize(); - memoizedSerializedSize = size; - return size; - } - - private static final long serialVersionUID = 0L; - @java.lang.Override - protected java.lang.Object writeReplace() - throws java.io.ObjectStreamException { - return super.writeReplace(); - } - - public static org.thoughtcrime.securesms.devicelist.DeviceNameProtos.DeviceName parseFrom( - com.google.protobuf.ByteString data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static org.thoughtcrime.securesms.devicelist.DeviceNameProtos.DeviceName parseFrom( - com.google.protobuf.ByteString data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static org.thoughtcrime.securesms.devicelist.DeviceNameProtos.DeviceName parseFrom(byte[] data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static org.thoughtcrime.securesms.devicelist.DeviceNameProtos.DeviceName parseFrom( - byte[] data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static org.thoughtcrime.securesms.devicelist.DeviceNameProtos.DeviceName parseFrom(java.io.InputStream input) - throws java.io.IOException { - return PARSER.parseFrom(input); - } - public static org.thoughtcrime.securesms.devicelist.DeviceNameProtos.DeviceName parseFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return PARSER.parseFrom(input, extensionRegistry); - } - public static org.thoughtcrime.securesms.devicelist.DeviceNameProtos.DeviceName parseDelimitedFrom(java.io.InputStream input) - throws java.io.IOException { - return PARSER.parseDelimitedFrom(input); - } - public static org.thoughtcrime.securesms.devicelist.DeviceNameProtos.DeviceName parseDelimitedFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return PARSER.parseDelimitedFrom(input, extensionRegistry); - } - public static org.thoughtcrime.securesms.devicelist.DeviceNameProtos.DeviceName parseFrom( - com.google.protobuf.CodedInputStream input) - throws java.io.IOException { - return PARSER.parseFrom(input); - } - public static org.thoughtcrime.securesms.devicelist.DeviceNameProtos.DeviceName parseFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return PARSER.parseFrom(input, extensionRegistry); - } - - public static Builder newBuilder() { return Builder.create(); } - public Builder newBuilderForType() { return newBuilder(); } - public static Builder newBuilder(org.thoughtcrime.securesms.devicelist.DeviceNameProtos.DeviceName prototype) { - return newBuilder().mergeFrom(prototype); - } - public Builder toBuilder() { return newBuilder(this); } - - @java.lang.Override - protected Builder newBuilderForType( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - Builder builder = new Builder(parent); - return builder; - } - /** - * Protobuf type {@code signalservice.DeviceName} - */ - public static final class Builder extends - com.google.protobuf.GeneratedMessage.Builder - implements org.thoughtcrime.securesms.devicelist.DeviceNameProtos.DeviceNameOrBuilder { - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return org.thoughtcrime.securesms.devicelist.DeviceNameProtos.internal_static_signalservice_DeviceName_descriptor; - } - - protected com.google.protobuf.GeneratedMessage.FieldAccessorTable - internalGetFieldAccessorTable() { - return org.thoughtcrime.securesms.devicelist.DeviceNameProtos.internal_static_signalservice_DeviceName_fieldAccessorTable - .ensureFieldAccessorsInitialized( - org.thoughtcrime.securesms.devicelist.DeviceNameProtos.DeviceName.class, org.thoughtcrime.securesms.devicelist.DeviceNameProtos.DeviceName.Builder.class); - } - - // Construct using org.thoughtcrime.securesms.devicelist.DeviceNameProtos.DeviceName.newBuilder() - private Builder() { - maybeForceBuilderInitialization(); - } - - private Builder( - com.google.protobuf.GeneratedMessage.BuilderParent parent) { - super(parent); - maybeForceBuilderInitialization(); - } - private void maybeForceBuilderInitialization() { - if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) { - } - } - private static Builder create() { - return new Builder(); - } - - public Builder clear() { - super.clear(); - ephemeralPublic_ = com.google.protobuf.ByteString.EMPTY; - bitField0_ = (bitField0_ & ~0x00000001); - syntheticIv_ = com.google.protobuf.ByteString.EMPTY; - bitField0_ = (bitField0_ & ~0x00000002); - ciphertext_ = com.google.protobuf.ByteString.EMPTY; - bitField0_ = (bitField0_ & ~0x00000004); - return this; - } - - public Builder clone() { - return create().mergeFrom(buildPartial()); - } - - public com.google.protobuf.Descriptors.Descriptor - getDescriptorForType() { - return org.thoughtcrime.securesms.devicelist.DeviceNameProtos.internal_static_signalservice_DeviceName_descriptor; - } - - public org.thoughtcrime.securesms.devicelist.DeviceNameProtos.DeviceName getDefaultInstanceForType() { - return org.thoughtcrime.securesms.devicelist.DeviceNameProtos.DeviceName.getDefaultInstance(); - } - - public org.thoughtcrime.securesms.devicelist.DeviceNameProtos.DeviceName build() { - org.thoughtcrime.securesms.devicelist.DeviceNameProtos.DeviceName result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException(result); - } - return result; - } - - public org.thoughtcrime.securesms.devicelist.DeviceNameProtos.DeviceName buildPartial() { - org.thoughtcrime.securesms.devicelist.DeviceNameProtos.DeviceName result = new org.thoughtcrime.securesms.devicelist.DeviceNameProtos.DeviceName(this); - int from_bitField0_ = bitField0_; - int to_bitField0_ = 0; - if (((from_bitField0_ & 0x00000001) == 0x00000001)) { - to_bitField0_ |= 0x00000001; - } - result.ephemeralPublic_ = ephemeralPublic_; - if (((from_bitField0_ & 0x00000002) == 0x00000002)) { - to_bitField0_ |= 0x00000002; - } - result.syntheticIv_ = syntheticIv_; - if (((from_bitField0_ & 0x00000004) == 0x00000004)) { - to_bitField0_ |= 0x00000004; - } - result.ciphertext_ = ciphertext_; - result.bitField0_ = to_bitField0_; - onBuilt(); - return result; - } - - public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof org.thoughtcrime.securesms.devicelist.DeviceNameProtos.DeviceName) { - return mergeFrom((org.thoughtcrime.securesms.devicelist.DeviceNameProtos.DeviceName)other); - } else { - super.mergeFrom(other); - return this; - } - } - - public Builder mergeFrom(org.thoughtcrime.securesms.devicelist.DeviceNameProtos.DeviceName other) { - if (other == org.thoughtcrime.securesms.devicelist.DeviceNameProtos.DeviceName.getDefaultInstance()) return this; - if (other.hasEphemeralPublic()) { - setEphemeralPublic(other.getEphemeralPublic()); - } - if (other.hasSyntheticIv()) { - setSyntheticIv(other.getSyntheticIv()); - } - if (other.hasCiphertext()) { - setCiphertext(other.getCiphertext()); - } - this.mergeUnknownFields(other.getUnknownFields()); - return this; - } - - public final boolean isInitialized() { - return true; - } - - public Builder mergeFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - org.thoughtcrime.securesms.devicelist.DeviceNameProtos.DeviceName parsedMessage = null; - try { - parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - parsedMessage = (org.thoughtcrime.securesms.devicelist.DeviceNameProtos.DeviceName) e.getUnfinishedMessage(); - throw e; - } finally { - if (parsedMessage != null) { - mergeFrom(parsedMessage); - } - } - return this; - } - private int bitField0_; - - // optional bytes ephemeralPublic = 1; - private com.google.protobuf.ByteString ephemeralPublic_ = com.google.protobuf.ByteString.EMPTY; - /** - * optional bytes ephemeralPublic = 1; - */ - public boolean hasEphemeralPublic() { - return ((bitField0_ & 0x00000001) == 0x00000001); - } - /** - * optional bytes ephemeralPublic = 1; - */ - public com.google.protobuf.ByteString getEphemeralPublic() { - return ephemeralPublic_; - } - /** - * optional bytes ephemeralPublic = 1; - */ - public Builder setEphemeralPublic(com.google.protobuf.ByteString value) { - if (value == null) { - throw new NullPointerException(); - } - bitField0_ |= 0x00000001; - ephemeralPublic_ = value; - onChanged(); - return this; - } - /** - * optional bytes ephemeralPublic = 1; - */ - public Builder clearEphemeralPublic() { - bitField0_ = (bitField0_ & ~0x00000001); - ephemeralPublic_ = getDefaultInstance().getEphemeralPublic(); - onChanged(); - return this; - } - - // optional bytes syntheticIv = 2; - private com.google.protobuf.ByteString syntheticIv_ = com.google.protobuf.ByteString.EMPTY; - /** - * optional bytes syntheticIv = 2; - */ - public boolean hasSyntheticIv() { - return ((bitField0_ & 0x00000002) == 0x00000002); - } - /** - * optional bytes syntheticIv = 2; - */ - public com.google.protobuf.ByteString getSyntheticIv() { - return syntheticIv_; - } - /** - * optional bytes syntheticIv = 2; - */ - public Builder setSyntheticIv(com.google.protobuf.ByteString value) { - if (value == null) { - throw new NullPointerException(); - } - bitField0_ |= 0x00000002; - syntheticIv_ = value; - onChanged(); - return this; - } - /** - * optional bytes syntheticIv = 2; - */ - public Builder clearSyntheticIv() { - bitField0_ = (bitField0_ & ~0x00000002); - syntheticIv_ = getDefaultInstance().getSyntheticIv(); - onChanged(); - return this; - } - - // optional bytes ciphertext = 3; - private com.google.protobuf.ByteString ciphertext_ = com.google.protobuf.ByteString.EMPTY; - /** - * optional bytes ciphertext = 3; - */ - public boolean hasCiphertext() { - return ((bitField0_ & 0x00000004) == 0x00000004); - } - /** - * optional bytes ciphertext = 3; - */ - public com.google.protobuf.ByteString getCiphertext() { - return ciphertext_; - } - /** - * optional bytes ciphertext = 3; - */ - public Builder setCiphertext(com.google.protobuf.ByteString value) { - if (value == null) { - throw new NullPointerException(); - } - bitField0_ |= 0x00000004; - ciphertext_ = value; - onChanged(); - return this; - } - /** - * optional bytes ciphertext = 3; - */ - public Builder clearCiphertext() { - bitField0_ = (bitField0_ & ~0x00000004); - ciphertext_ = getDefaultInstance().getCiphertext(); - onChanged(); - return this; - } - - // @@protoc_insertion_point(builder_scope:signalservice.DeviceName) - } - - static { - defaultInstance = new DeviceName(true); - defaultInstance.initFields(); - } - - // @@protoc_insertion_point(class_scope:signalservice.DeviceName) - } - - private static com.google.protobuf.Descriptors.Descriptor - internal_static_signalservice_DeviceName_descriptor; - private static - com.google.protobuf.GeneratedMessage.FieldAccessorTable - internal_static_signalservice_DeviceName_fieldAccessorTable; - - public static com.google.protobuf.Descriptors.FileDescriptor - getDescriptor() { - return descriptor; - } - private static com.google.protobuf.Descriptors.FileDescriptor - descriptor; - static { - java.lang.String[] descriptorData = { - "\n\020DeviceName.proto\022\rsignalservice\"N\n\nDev" + - "iceName\022\027\n\017ephemeralPublic\030\001 \001(\014\022\023\n\013synt" + - "heticIv\030\002 \001(\014\022\022\n\nciphertext\030\003 \001(\014B9\n%org" + - ".thoughtcrime.securesms.devicelistB\020Devi" + - "ceNameProtos" - }; - com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner = - new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() { - public com.google.protobuf.ExtensionRegistry assignDescriptors( - com.google.protobuf.Descriptors.FileDescriptor root) { - descriptor = root; - internal_static_signalservice_DeviceName_descriptor = - getDescriptor().getMessageTypes().get(0); - internal_static_signalservice_DeviceName_fieldAccessorTable = new - com.google.protobuf.GeneratedMessage.FieldAccessorTable( - internal_static_signalservice_DeviceName_descriptor, - new java.lang.String[] { "EphemeralPublic", "SyntheticIv", "Ciphertext", }); - return null; - } - }; - com.google.protobuf.Descriptors.FileDescriptor - .internalBuildGeneratedFileFrom(descriptorData, - new com.google.protobuf.Descriptors.FileDescriptor[] { - }, assigner); - } - - // @@protoc_insertion_point(outer_class_scope) -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/events/RedPhoneEvent.java b/app/src/main/java/org/thoughtcrime/securesms/events/RedPhoneEvent.java deleted file mode 100644 index 92f949aa3..000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/events/RedPhoneEvent.java +++ /dev/null @@ -1,51 +0,0 @@ -package org.thoughtcrime.securesms.events; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - -import org.thoughtcrime.securesms.recipients.Recipient; - -public class RedPhoneEvent { - - public enum Type { - CALL_CONNECTED, - WAITING_FOR_RESPONDER, - SERVER_FAILURE, - PERFORMING_HANDSHAKE, - HANDSHAKE_FAILED, - CONNECTING_TO_INITIATOR, - CALL_DISCONNECTED, - CALL_RINGING, - SERVER_MESSAGE, - RECIPIENT_UNAVAILABLE, - INCOMING_CALL, - OUTGOING_CALL, - CALL_BUSY, - LOGIN_FAILED, - CLIENT_FAILURE, - DEBUG_INFO, - NO_SUCH_USER - } - - private final @NonNull Type type; - private final @NonNull Recipient recipient; - private final @Nullable String extra; - - public RedPhoneEvent(@NonNull Type type, @NonNull Recipient recipient, @Nullable String extra) { - this.type = type; - this.recipient = recipient; - this.extra = extra; - } - - public @NonNull Type getType() { - return type; - } - - public @NonNull Recipient getRecipient() { - return recipient; - } - - public @Nullable String getExtra() { - return extra; - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/events/ReminderUpdateEvent.java b/app/src/main/java/org/thoughtcrime/securesms/events/ReminderUpdateEvent.java deleted file mode 100644 index 582143a1c..000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/events/ReminderUpdateEvent.java +++ /dev/null @@ -1,5 +0,0 @@ -package org.thoughtcrime.securesms.events; - - -public class ReminderUpdateEvent { -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/RefreshAttributesJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/RefreshAttributesJob.java index 63cd9f120..e2af735dd 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/RefreshAttributesJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/RefreshAttributesJob.java @@ -52,11 +52,10 @@ public class RefreshAttributesJob extends BaseJob implements InjectableType { public void onRun() throws IOException { int registrationId = TextSecurePreferences.getLocalRegistrationId(context); boolean fetchesMessages = TextSecurePreferences.isFcmDisabled(context); - String pin = TextSecurePreferences.getRegistrationLockPin(context); byte[] unidentifiedAccessKey = UnidentifiedAccessUtil.getSelfUnidentifiedAccessKey(context); boolean universalUnidentifiedAccess = TextSecurePreferences.isUniversalUnidentifiedAccess(context); - signalAccountManager.setAccountAttributes(null, registrationId, fetchesMessages, pin, + signalAccountManager.setAccountAttributes(null, registrationId, fetchesMessages, "", unidentifiedAccessKey, universalUnidentifiedAccess); ApplicationContext.getInstance(context) diff --git a/app/src/main/java/org/thoughtcrime/securesms/lock/RegistrationLockDialog.java b/app/src/main/java/org/thoughtcrime/securesms/lock/RegistrationLockDialog.java deleted file mode 100644 index ba5b8151f..000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/lock/RegistrationLockDialog.java +++ /dev/null @@ -1,236 +0,0 @@ -package org.thoughtcrime.securesms.lock; - - -import android.annotation.SuppressLint; -import android.content.Context; -import android.graphics.Typeface; -import android.os.AsyncTask; -import android.os.Build; -import androidx.annotation.NonNull; -import androidx.appcompat.app.AlertDialog; -import android.text.Editable; -import android.text.SpannableString; -import android.text.SpannableStringBuilder; -import android.text.Spanned; -import android.text.TextWatcher; -import android.text.method.LinkMovementMethod; -import android.text.style.ClickableSpan; -import android.text.style.StyleSpan; -import android.util.DisplayMetrics; -import org.thoughtcrime.securesms.logging.Log; -import android.view.Display; -import android.view.View; -import android.view.ViewGroup; -import android.view.WindowManager; -import android.widget.Button; -import android.widget.EditText; -import android.widget.ProgressBar; -import android.widget.TextView; -import android.widget.Toast; - -import network.loki.messenger.R; -import org.thoughtcrime.securesms.components.SwitchPreferenceCompat; -import org.thoughtcrime.securesms.util.ServiceUtil; -import org.thoughtcrime.securesms.util.TextSecurePreferences; -import org.session.libsignal.libsignal.util.guava.Optional; -import org.session.libsignal.service.api.SignalServiceAccountManager; - -import java.io.IOException; - -public class RegistrationLockDialog { - - private static final String TAG = RegistrationLockDialog.class.getSimpleName(); - - public static void showReminderIfNecessary(@NonNull Context context) { - if (!RegistrationLockReminders.needsReminder(context)) return; - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) return; - - AlertDialog dialog = new AlertDialog.Builder(context, R.style.Theme_TextSecure_Dialog_Rationale) - .setView(R.layout.registration_lock_reminder_view) - .setCancelable(true) - .setOnCancelListener(d -> RegistrationLockReminders.scheduleReminder(context, false)) - .create(); - - WindowManager windowManager = ServiceUtil.getWindowManager(context); - Display display = windowManager.getDefaultDisplay(); - DisplayMetrics metrics = new DisplayMetrics(); - display.getMetrics(metrics); - - dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE); - dialog.show(); - dialog.getWindow().setLayout((int)(metrics.widthPixels * .80), ViewGroup.LayoutParams.WRAP_CONTENT); - - EditText pinEditText = dialog.findViewById(R.id.pin); - TextView reminder = dialog.findViewById(R.id.reminder); - - assert pinEditText != null; - assert reminder != null; - - SpannableString reminderIntro = new SpannableString(context.getString(R.string.RegistrationLockDialog_reminder)); - SpannableString reminderText = new SpannableString(context.getString(R.string.RegistrationLockDialog_registration_lock_is_enabled_for_your_phone_number)); - SpannableString forgotText = new SpannableString(context.getString(R.string.RegistrationLockDialog_i_forgot_my_pin)); - - ClickableSpan clickableSpan = new ClickableSpan() { - @Override - public void onClick(@NonNull View widget) { - dialog.dismiss(); - new AlertDialog.Builder(context).setTitle(R.string.RegistrationLockDialog_forgotten_pin) - .setMessage(R.string.RegistrationLockDialog_registration_lock_helps_protect_your_phone_number_from_unauthorized_registration_attempts) - .setPositiveButton(android.R.string.ok, null) - .create() - .show(); - } - }; - - - reminderIntro.setSpan(new StyleSpan(Typeface.BOLD), 0, reminderIntro.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); - forgotText.setSpan(clickableSpan, 0, forgotText.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); - - reminder.setText(new SpannableStringBuilder(reminderIntro).append(" ").append(reminderText).append(" ").append(forgotText)); - reminder.setMovementMethod(LinkMovementMethod.getInstance()); - - pinEditText.addTextChangedListener(new TextWatcher() { - @Override - public void beforeTextChanged(CharSequence s, int start, int count, int after) {} - @Override - public void onTextChanged(CharSequence s, int start, int before, int count) {} - - @Override - public void afterTextChanged(Editable s) { - if (s != null && s.toString().replace(" ", "").equals(TextSecurePreferences.getRegistrationLockPin(context))) { - dialog.dismiss(); - RegistrationLockReminders.scheduleReminder(context, true); - } - } - }); - - } - - @SuppressLint("StaticFieldLeak") - public static void showRegistrationLockPrompt(@NonNull Context context, @NonNull SwitchPreferenceCompat preference, @NonNull SignalServiceAccountManager accountManager) { - AlertDialog dialog = new AlertDialog.Builder(context) - .setTitle(R.string.RegistrationLockDialog_registration_lock) - .setView(R.layout.registration_lock_dialog_view) - .setPositiveButton(R.string.RegistrationLockDialog_enable, null) - .setNegativeButton(android.R.string.cancel, null) - .create(); - - dialog.setOnShowListener(created -> { - Button button = ((AlertDialog) created).getButton(AlertDialog.BUTTON_POSITIVE); - button.setOnClickListener(v -> { - EditText pin = dialog.findViewById(R.id.pin); - EditText repeat = dialog.findViewById(R.id.repeat); - ProgressBar progressBar = dialog.findViewById(R.id.progress); - - assert pin != null; - assert repeat != null; - assert progressBar != null; - - String pinValue = pin.getText().toString().replace(" ", ""); - String repeatValue = repeat.getText().toString().replace(" ", ""); - - if (pinValue.length() < 4) { - Toast.makeText(context, R.string.RegistrationLockDialog_the_registration_lock_pin_must_be_at_least_four_digits, Toast.LENGTH_LONG).show(); - return; - } - - if (!pinValue.equals(repeatValue)) { - Toast.makeText(context, R.string.RegistrationLockDialog_the_two_pins_you_entered_do_not_match, Toast.LENGTH_LONG).show(); - return; - } - - new AsyncTask() { - @Override - protected void onPreExecute() { - progressBar.setVisibility(View.VISIBLE); - progressBar.setIndeterminate(true); - button.setEnabled(false); - } - - @Override - protected Boolean doInBackground(Void... voids) { - try { - accountManager.setPin(Optional.of(pinValue)); - TextSecurePreferences.setRegistrationLockPin(context, pinValue); - TextSecurePreferences.setRegistrationLockLastReminderTime(context, System.currentTimeMillis()); - TextSecurePreferences.setRegistrationLockNextReminderInterval(context, RegistrationLockReminders.INITIAL_INTERVAL); - return true; - } catch (IOException e) { - Log.w(TAG, e); - return false; - } - } - - @Override - protected void onPostExecute(@NonNull Boolean result) { - button.setEnabled(true); - progressBar.setVisibility(View.GONE); - - if (result) { - preference.setChecked(true); - created.dismiss(); - } else { - Toast.makeText(context, R.string.RegistrationLockDialog_error_connecting_to_the_service, Toast.LENGTH_LONG).show(); - } - } - }.execute(); - }); - }); - - dialog.show(); - } - - @SuppressLint("StaticFieldLeak") - public static void showRegistrationUnlockPrompt(@NonNull Context context, @NonNull SwitchPreferenceCompat preference, @NonNull SignalServiceAccountManager accountManager) { - AlertDialog dialog = new AlertDialog.Builder(context) - .setTitle(R.string.RegistrationLockDialog_disable_registration_lock_pin) - .setView(R.layout.registration_unlock_dialog_view) - .setPositiveButton(R.string.RegistrationLockDialog_disable, null) - .setNegativeButton(android.R.string.cancel, null) - .create(); - - dialog.setOnShowListener(created -> { - Button button = ((AlertDialog) created).getButton(AlertDialog.BUTTON_POSITIVE); - button.setOnClickListener(v -> { - ProgressBar progressBar = dialog.findViewById(R.id.progress); - assert progressBar != null; - - new AsyncTask() { - @Override - protected void onPreExecute() { - progressBar.setVisibility(View.VISIBLE); - progressBar.setIndeterminate(true); - button.setEnabled(false); - } - - @Override - protected Boolean doInBackground(Void... voids) { - try { - accountManager.setPin(Optional.absent()); - return true; - } catch (IOException e) { - Log.w(TAG, e); - return false; - } - } - - @Override - protected void onPostExecute(Boolean result) { - progressBar.setVisibility(View.GONE); - button.setEnabled(true); - - if (result) { - preference.setChecked(false); - created.dismiss(); - } else { - Toast.makeText(context, R.string.RegistrationLockDialog_error_connecting_to_the_service, Toast.LENGTH_LONG).show(); - } - } - }.execute(); - }); - }); - - dialog.show(); - } - -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/lock/RegistrationLockReminders.java b/app/src/main/java/org/thoughtcrime/securesms/lock/RegistrationLockReminders.java deleted file mode 100644 index d000870cd..000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/lock/RegistrationLockReminders.java +++ /dev/null @@ -1,51 +0,0 @@ -package org.thoughtcrime.securesms.lock; - - -import android.content.Context; -import androidx.annotation.NonNull; - -import org.thoughtcrime.securesms.util.TextSecurePreferences; - -import java.util.NavigableSet; -import java.util.TreeSet; -import java.util.concurrent.TimeUnit; - -public class RegistrationLockReminders { - - private static final NavigableSet INTERVALS = new TreeSet() {{ - add(TimeUnit.HOURS.toMillis(6)); - add(TimeUnit.HOURS.toMillis(12)); - add(TimeUnit.DAYS.toMillis(1)); - add(TimeUnit.DAYS.toMillis(3)); - add(TimeUnit.DAYS.toMillis(7)); - }}; - - public static final long INITIAL_INTERVAL = INTERVALS.first(); - - public static boolean needsReminder(@NonNull Context context) { - if (!TextSecurePreferences.isRegistrationtLockEnabled(context)) return false; - - long lastReminderTime = TextSecurePreferences.getRegistrationLockLastReminderTime(context); - long nextIntervalTime = TextSecurePreferences.getRegistrationLockNextReminderInterval(context); - - return System.currentTimeMillis() > lastReminderTime + nextIntervalTime; - } - - public static void scheduleReminder(@NonNull Context context, boolean success) { - Long nextReminderInterval; - - if (success) { - long timeSinceLastReminder = System.currentTimeMillis() - TextSecurePreferences.getRegistrationLockLastReminderTime(context); - nextReminderInterval = INTERVALS.higher(timeSinceLastReminder); - if (nextReminderInterval == null) nextReminderInterval = INTERVALS.last(); - } else { - long lastReminderInterval = TextSecurePreferences.getRegistrationLockNextReminderInterval(context); - nextReminderInterval = INTERVALS.lower(lastReminderInterval); - if (nextReminderInterval == null) nextReminderInterval = INTERVALS.first(); - } - - TextSecurePreferences.setRegistrationLockLastReminderTime(context, System.currentTimeMillis()); - TextSecurePreferences.setRegistrationLockNextReminderInterval(context, nextReminderInterval); - } - -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/preferences/AppProtectionPreferenceFragment.java b/app/src/main/java/org/thoughtcrime/securesms/preferences/AppProtectionPreferenceFragment.java index 5b10b50d8..4d64ccd29 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/preferences/AppProtectionPreferenceFragment.java +++ b/app/src/main/java/org/thoughtcrime/securesms/preferences/AppProtectionPreferenceFragment.java @@ -219,17 +219,17 @@ public class AppProtectionPreferenceFragment extends CorrectedPreferenceFragment final String offRes = context.getString(R.string.ApplicationPreferencesActivity_off); if (TextSecurePreferences.isPasswordDisabled(context) && !TextSecurePreferences.isScreenLockEnabled(context)) { - if (TextSecurePreferences.isRegistrationtLockEnabled(context)) { - return context.getString(privacySummaryResId, offRes, onRes); - } else { +// if (TextSecurePreferences.isRegistrationtLockEnabled(context)) { +// return context.getString(privacySummaryResId, offRes, onRes); +// } else { return context.getString(privacySummaryResId, offRes, offRes); - } +// } } else { - if (TextSecurePreferences.isRegistrationtLockEnabled(context)) { - return context.getString(privacySummaryResId, onRes, onRes); - } else { +// if (TextSecurePreferences.isRegistrationtLockEnabled(context)) { +// return context.getString(privacySummaryResId, onRes, onRes); +// } else { return context.getString(privacySummaryResId, onRes, offRes); - } +// } } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/recipients/Recipient.java b/app/src/main/java/org/thoughtcrime/securesms/recipients/Recipient.java index be7b7ce9a..4b1b653cc 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/recipients/Recipient.java +++ b/app/src/main/java/org/thoughtcrime/securesms/recipients/Recipient.java @@ -94,7 +94,6 @@ public class Recipient implements RecipientModifiedListener { private @NonNull RegisteredState registered = RegisteredState.UNKNOWN; private @Nullable MaterialColor color; - private boolean seenInviteReminder; private @Nullable byte[] profileKey; private @Nullable String profileName; private @Nullable String profileAvatar; @@ -151,7 +150,6 @@ public class Recipient implements RecipientModifiedListener { this.messageVibrate = stale.messageVibrate; this.callVibrate = stale.callVibrate; this.expireMessages = stale.expireMessages; - this.seenInviteReminder = stale.seenInviteReminder; this.defaultSubscriptionId = stale.defaultSubscriptionId; this.registered = stale.registered; this.notificationChannel = stale.notificationChannel; @@ -179,7 +177,6 @@ public class Recipient implements RecipientModifiedListener { this.messageVibrate = details.get().messageVibrateState; this.callVibrate = details.get().callVibrateState; this.expireMessages = details.get().expireMessages; - this.seenInviteReminder = details.get().seenInviteReminder; this.defaultSubscriptionId = details.get().defaultSubscriptionId; this.registered = details.get().registered; this.notificationChannel = details.get().notificationChannel; @@ -213,7 +210,6 @@ public class Recipient implements RecipientModifiedListener { Recipient.this.messageVibrate = result.messageVibrateState; Recipient.this.callVibrate = result.callVibrateState; Recipient.this.expireMessages = result.expireMessages; - Recipient.this.seenInviteReminder = result.seenInviteReminder; Recipient.this.defaultSubscriptionId = result.defaultSubscriptionId; Recipient.this.registered = result.registered; Recipient.this.notificationChannel = result.notificationChannel; @@ -263,7 +259,6 @@ public class Recipient implements RecipientModifiedListener { this.messageVibrate = details.messageVibrateState; this.callVibrate = details.callVibrateState; this.expireMessages = details.expireMessages; - this.seenInviteReminder = details.seenInviteReminder; this.defaultSubscriptionId = details.defaultSubscriptionId; this.registered = details.registered; this.notificationChannel = details.notificationChannel; @@ -615,18 +610,6 @@ public class Recipient implements RecipientModifiedListener { notifyListeners(); } - public synchronized boolean hasSeenInviteReminder() { - return seenInviteReminder; - } - - public void setHasSeenInviteReminder(boolean value) { - synchronized (this) { - this.seenInviteReminder = value; - } - - notifyListeners(); - } - public synchronized RegisteredState getRegistered() { if (isPushGroupRecipient()) return RegisteredState.REGISTERED; else if (isMmsGroupRecipient()) return RegisteredState.NOT_REGISTERED; diff --git a/app/src/main/java/org/thoughtcrime/securesms/recipients/RecipientProvider.java b/app/src/main/java/org/thoughtcrime/securesms/recipients/RecipientProvider.java index 19e2b77f0..e8740f78f 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/recipients/RecipientProvider.java +++ b/app/src/main/java/org/thoughtcrime/securesms/recipients/RecipientProvider.java @@ -175,7 +175,6 @@ class RecipientProvider { final int expireMessages; @NonNull final List participants; @Nullable final String profileName; - final boolean seenInviteReminder; final Optional defaultSubscriptionId; @NonNull final RegisteredState registered; @Nullable final byte[] profileKey; @@ -205,7 +204,6 @@ class RecipientProvider { this.expireMessages = settings != null ? settings.getExpireMessages() : 0; this.participants = participants == null ? new LinkedList<>() : participants; this.profileName = settings != null ? settings.getProfileName() : null; - this.seenInviteReminder = settings != null && settings.hasSeenInviteReminder(); this.defaultSubscriptionId = settings != null ? settings.getDefaultSubscriptionId() : Optional.absent(); this.registered = settings != null ? settings.getRegistered() : RegisteredState.UNKNOWN; this.profileKey = settings != null ? settings.getProfileKey() : null; diff --git a/app/src/main/java/org/thoughtcrime/securesms/search/SearchRepository.java b/app/src/main/java/org/thoughtcrime/securesms/search/SearchRepository.java index ab3f90a78..e7c614099 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/search/SearchRepository.java +++ b/app/src/main/java/org/thoughtcrime/securesms/search/SearchRepository.java @@ -9,7 +9,6 @@ import android.text.TextUtils; import com.annimon.stream.Stream; import org.thoughtcrime.securesms.contacts.ContactAccessor; -import org.thoughtcrime.securesms.contacts.ContactsDatabase; import org.thoughtcrime.securesms.database.Address; import org.thoughtcrime.securesms.database.CursorList; import org.thoughtcrime.securesms.database.MmsSmsColumns; @@ -53,21 +52,18 @@ public class SearchRepository { private final Context context; private final SearchDatabase searchDatabase; - private final ContactsDatabase contactsDatabase; private final ThreadDatabase threadDatabase; private final ContactAccessor contactAccessor; private final Executor executor; public SearchRepository(@NonNull Context context, @NonNull SearchDatabase searchDatabase, - @NonNull ContactsDatabase contactsDatabase, @NonNull ThreadDatabase threadDatabase, @NonNull ContactAccessor contactAccessor, @NonNull Executor executor) { this.context = context.getApplicationContext(); this.searchDatabase = searchDatabase; - this.contactsDatabase = contactsDatabase; this.threadDatabase = threadDatabase; this.contactAccessor = contactAccessor; this.executor = executor; diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/TextSecurePreferences.java b/app/src/main/java/org/thoughtcrime/securesms/util/TextSecurePreferences.java index 3cb9521d9..ff1834e22 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/util/TextSecurePreferences.java +++ b/app/src/main/java/org/thoughtcrime/securesms/util/TextSecurePreferences.java @@ -15,7 +15,6 @@ import androidx.core.app.NotificationCompat; import org.greenrobot.eventbus.EventBus; import org.thoughtcrime.securesms.backup.BackupProtos; import org.thoughtcrime.securesms.jobmanager.impl.SqlCipherMigrationConstraintObserver; -import org.thoughtcrime.securesms.lock.RegistrationLockReminders; import org.thoughtcrime.securesms.logging.Log; import org.thoughtcrime.securesms.preferences.widgets.NotificationPrivacyPreference; import org.session.libsignal.libsignal.util.Medium; @@ -153,11 +152,6 @@ public class TextSecurePreferences { public static final String SCREEN_LOCK = "pref_android_screen_lock"; public static final String SCREEN_LOCK_TIMEOUT = "pref_android_screen_lock_timeout"; - public static final String REGISTRATION_LOCK_PREF = "pref_registration_lock"; - private static final String REGISTRATION_LOCK_PIN_PREF = "pref_registration_lock_pin"; - private static final String REGISTRATION_LOCK_LAST_REMINDER_TIME = "pref_registration_lock_last_reminder_time"; - private static final String REGISTRATION_LOCK_NEXT_REMINDER_INTERVAL = "pref_registration_lock_next_reminder_interval"; - private static final String LAST_FULL_CONTACT_SYNC_TIME = "pref_last_full_contact_sync_time"; private static final String NEEDS_FULL_CONTACT_SYNC = "pref_needs_full_contact_sync"; @@ -232,38 +226,6 @@ public class TextSecurePreferences { setLongPreference(context, SCREEN_LOCK_TIMEOUT, value); } - public static boolean isRegistrationtLockEnabled(@NonNull Context context) { - return getBooleanPreference(context, REGISTRATION_LOCK_PREF, false); - } - - public static void setRegistrationtLockEnabled(@NonNull Context context, boolean value) { - setBooleanPreference(context, REGISTRATION_LOCK_PREF, value); - } - - public static @Nullable String getRegistrationLockPin(@NonNull Context context) { - return getStringPreference(context, REGISTRATION_LOCK_PIN_PREF, null); - } - - public static void setRegistrationLockPin(@NonNull Context context, String pin) { - setStringPreference(context, REGISTRATION_LOCK_PIN_PREF, pin); - } - - public static long getRegistrationLockLastReminderTime(@NonNull Context context) { - return getLongPreference(context, REGISTRATION_LOCK_LAST_REMINDER_TIME, 0); - } - - public static void setRegistrationLockLastReminderTime(@NonNull Context context, long time) { - setLongPreference(context, REGISTRATION_LOCK_LAST_REMINDER_TIME, time); - } - - public static long getRegistrationLockNextReminderInterval(@NonNull Context context) { - return getLongPreference(context, REGISTRATION_LOCK_NEXT_REMINDER_INTERVAL, RegistrationLockReminders.INITIAL_INTERVAL); - } - - public static void setRegistrationLockNextReminderInterval(@NonNull Context context, long value) { - setLongPreference(context, REGISTRATION_LOCK_NEXT_REMINDER_INTERVAL, value); - } - public static void setBackupPassphrase(@NonNull Context context, @Nullable String passphrase) { setStringPreference(context, BACKUP_PASSPHRASE, passphrase); } diff --git a/app/src/main/protobuf/DeviceName.proto b/app/src/main/protobuf/DeviceName.proto deleted file mode 100644 index c0b4b1135..000000000 --- a/app/src/main/protobuf/DeviceName.proto +++ /dev/null @@ -1,15 +0,0 @@ -/** - * Copyright (C) 2014-2016 Open Whisper Systems - * - * Licensed according to the LICENSE file in this repository. - */ -package signalservice; - -option java_package = "org.thoughtcrime.securesms.devicelist"; -option java_outer_classname = "DeviceNameProtos"; - -message DeviceName { - optional bytes ephemeralPublic = 1; - optional bytes syntheticIv = 2; - optional bytes ciphertext = 3; -} diff --git a/app/src/main/res/layout/activity_contact_name_edit.xml b/app/src/main/res/layout/activity_contact_name_edit.xml deleted file mode 100644 index 42785c8e4..000000000 --- a/app/src/main/res/layout/activity_contact_name_edit.xml +++ /dev/null @@ -1,71 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/conversation_activity.xml b/app/src/main/res/layout/conversation_activity.xml index 668daad1b..f42cdfd39 100644 --- a/app/src/main/res/layout/conversation_activity.xml +++ b/app/src/main/res/layout/conversation_activity.xml @@ -153,13 +153,6 @@ android:inflatedId="@+id/unverified_banner" android:layout="@layout/conversation_activity_unverified_banner_stub" /> - - - diff --git a/app/src/main/res/layout/conversation_item_received_shared_contact.xml b/app/src/main/res/layout/conversation_item_received_shared_contact.xml deleted file mode 100644 index 0fec8a5bf..000000000 --- a/app/src/main/res/layout/conversation_item_received_shared_contact.xml +++ /dev/null @@ -1,11 +0,0 @@ - - diff --git a/app/src/main/res/layout/conversation_item_sent_shared_contact.xml b/app/src/main/res/layout/conversation_item_sent_shared_contact.xml deleted file mode 100644 index e53e97f80..000000000 --- a/app/src/main/res/layout/conversation_item_sent_shared_contact.xml +++ /dev/null @@ -1,10 +0,0 @@ - - diff --git a/app/src/main/res/layout/conversation_title_view.xml b/app/src/main/res/layout/conversation_title_view.xml deleted file mode 100644 index b4abaf761..000000000 --- a/app/src/main/res/layout/conversation_title_view.xml +++ /dev/null @@ -1,83 +0,0 @@ - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/push_recipients_panel.xml b/app/src/main/res/layout/push_recipients_panel.xml deleted file mode 100644 index e3cc02857..000000000 --- a/app/src/main/res/layout/push_recipients_panel.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/registration_lock_reminder_view.xml b/app/src/main/res/layout/registration_lock_reminder_view.xml deleted file mode 100644 index 918527ab4..000000000 --- a/app/src/main/res/layout/registration_lock_reminder_view.xml +++ /dev/null @@ -1,53 +0,0 @@ - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/values/attrs.xml b/app/src/main/res/values/attrs.xml index 24810da3e..783fdaaa3 100644 --- a/app/src/main/res/values/attrs.xml +++ b/app/src/main/res/values/attrs.xml @@ -246,13 +246,6 @@ - - - - - - -