mirror of
https://github.com/oxen-io/session-android.git
synced 2025-10-25 11:58:34 +00:00
Display unknown sender footer for unknown senders
// FREEBIE
This commit is contained in:
@@ -61,6 +61,7 @@ import org.thoughtcrime.securesms.database.model.MediaMmsMessageRecord;
|
||||
import org.thoughtcrime.securesms.database.model.MessageRecord;
|
||||
import org.thoughtcrime.securesms.mms.OutgoingMediaMessage;
|
||||
import org.thoughtcrime.securesms.mms.Slide;
|
||||
import org.thoughtcrime.securesms.profiles.UnknownSenderView;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientFactory;
|
||||
import org.thoughtcrime.securesms.sms.MessageSender;
|
||||
@@ -100,6 +101,7 @@ public class ConversationFragment extends Fragment
|
||||
private RecyclerView list;
|
||||
private RecyclerView.ItemDecoration lastSeenDecoration;
|
||||
private View loadMoreView;
|
||||
private UnknownSenderView unknownSenderView;
|
||||
private View composeDivider;
|
||||
private View scrollToBottomButton;
|
||||
private TextView scrollDateHeader;
|
||||
@@ -132,14 +134,12 @@ public class ConversationFragment extends Fragment
|
||||
list.setItemAnimator(null);
|
||||
|
||||
loadMoreView = inflater.inflate(R.layout.load_more_header, container, false);
|
||||
loadMoreView.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
Bundle args = new Bundle();
|
||||
args.putLong("limit", 0);
|
||||
getLoaderManager().restartLoader(0, args, ConversationFragment.this);
|
||||
}
|
||||
loadMoreView.setOnClickListener(v -> {
|
||||
Bundle args = new Bundle();
|
||||
args.putLong("limit", 0);
|
||||
getLoaderManager().restartLoader(0, args, ConversationFragment.this);
|
||||
});
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
@@ -184,10 +184,11 @@ public class ConversationFragment extends Fragment
|
||||
}
|
||||
|
||||
private void initializeResources() {
|
||||
this.recipient = RecipientFactory.getRecipientFor(getActivity(), (Address)getActivity().getIntent().getParcelableExtra(ConversationActivity.ADDRESS_EXTRA), true);
|
||||
this.threadId = this.getActivity().getIntent().getLongExtra(ConversationActivity.THREAD_ID_EXTRA, -1);
|
||||
this.lastSeen = this.getActivity().getIntent().getLongExtra(ConversationActivity.LAST_SEEN_EXTRA, -1);
|
||||
this.firstLoad = true;
|
||||
this.recipient = RecipientFactory.getRecipientFor(getActivity(), (Address) getActivity().getIntent().getParcelableExtra(ConversationActivity.ADDRESS_EXTRA), true);
|
||||
this.threadId = this.getActivity().getIntent().getLongExtra(ConversationActivity.THREAD_ID_EXTRA, -1);
|
||||
this.lastSeen = this.getActivity().getIntent().getLongExtra(ConversationActivity.LAST_SEEN_EXTRA, -1);
|
||||
this.firstLoad = true;
|
||||
this.unknownSenderView = new UnknownSenderView(getActivity(), recipient, threadId);
|
||||
|
||||
OnScrollListener scrollListener = new ConversationScrollListener(getActivity());
|
||||
list.addOnScrollListener(scrollListener);
|
||||
@@ -430,6 +431,12 @@ public class ConversationFragment extends Fragment
|
||||
setLastSeen(loader.getLastSeen());
|
||||
}
|
||||
|
||||
if (!loader.hasSent() && recipient.getName() == null) {
|
||||
getListAdapter().setHeaderView(unknownSenderView);
|
||||
} else {
|
||||
getListAdapter().setHeaderView(null);
|
||||
}
|
||||
|
||||
getListAdapter().changeCursor(cursor);
|
||||
|
||||
int lastSeenPosition = getListAdapter().findLastSeenPosition(lastSeen);
|
||||
@@ -456,6 +463,8 @@ public class ConversationFragment extends Fragment
|
||||
MessageRecord messageRecord = DatabaseFactory.getMmsDatabase(getContext()).readerFor(message, threadId).getCurrent();
|
||||
|
||||
if (getListAdapter() != null) {
|
||||
getListAdapter().setHeaderView(null);
|
||||
setLastSeen(0);
|
||||
getListAdapter().addFastRecord(messageRecord);
|
||||
}
|
||||
|
||||
@@ -466,6 +475,8 @@ public class ConversationFragment extends Fragment
|
||||
MessageRecord messageRecord = DatabaseFactory.getSmsDatabase(getContext()).readerFor(message, threadId).getCurrent();
|
||||
|
||||
if (getListAdapter() != null) {
|
||||
getListAdapter().setHeaderView(null);
|
||||
setLastSeen(0);
|
||||
getListAdapter().addFastRecord(messageRecord);
|
||||
}
|
||||
|
||||
|
||||
@@ -105,7 +105,8 @@ public class DatabaseFactory {
|
||||
private static final int INTERNAL_SYSTEM_DISPLAY_NAME = 40;
|
||||
private static final int PROFILES = 41;
|
||||
private static final int PROFILE_SHARING_APPROVAL = 42;
|
||||
private static final int DATABASE_VERSION = 42;
|
||||
private static final int UNSEEN_NUMBER_OFFER = 43;
|
||||
private static final int DATABASE_VERSION = 43;
|
||||
|
||||
private static final String DATABASE_NAME = "messages.db";
|
||||
private static final Object lock = new Object();
|
||||
@@ -1312,6 +1313,10 @@ public class DatabaseFactory {
|
||||
db.execSQL("ALTER TABLE recipient_preferences ADD COLUMN profile_sharing_approval INTEGER DEFAULT 0");
|
||||
}
|
||||
|
||||
if (oldVersion < UNSEEN_NUMBER_OFFER) {
|
||||
db.execSQL("ALTER TABLE thread ADD COLUMN has_sent INTEGER DEFAULT 0");
|
||||
}
|
||||
|
||||
db.setTransactionSuccessful();
|
||||
db.endTransaction();
|
||||
}
|
||||
|
||||
@@ -808,6 +808,7 @@ public class MmsDatabase extends MessagingDatabase {
|
||||
long messageId = insertMediaMessage(masterSecret, message.getBody(), message.getAttachments(), contentValues, insertListener);
|
||||
|
||||
DatabaseFactory.getThreadDatabase(context).setLastSeen(threadId);
|
||||
DatabaseFactory.getThreadDatabase(context).setHasSent(threadId, true);
|
||||
jobManager.add(new TrimThreadJob(context, threadId));
|
||||
|
||||
return messageId;
|
||||
|
||||
@@ -615,6 +615,8 @@ public class SmsDatabase extends MessagingDatabase {
|
||||
DatabaseFactory.getThreadDatabase(context).setLastSeen(threadId);
|
||||
}
|
||||
|
||||
DatabaseFactory.getThreadDatabase(context).setHasSent(threadId, true);
|
||||
|
||||
notifyConversationListeners(threadId);
|
||||
|
||||
if (!message.isIdentityVerified() && !message.isIdentityDefault()) {
|
||||
|
||||
@@ -46,6 +46,7 @@ import org.thoughtcrime.securesms.recipients.RecipientFactory;
|
||||
import org.thoughtcrime.securesms.util.DelimiterUtil;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
import org.whispersystems.libsignal.InvalidMessageException;
|
||||
import org.whispersystems.libsignal.util.Pair;
|
||||
import org.whispersystems.libsignal.util.guava.Optional;
|
||||
|
||||
import java.util.LinkedList;
|
||||
@@ -73,6 +74,7 @@ public class ThreadDatabase extends Database {
|
||||
public static final String RECEIPT_COUNT = "delivery_receipt_count";
|
||||
public static final String EXPIRES_IN = "expires_in";
|
||||
public static final String LAST_SEEN = "last_seen";
|
||||
private static final String HAS_SENT = "has_sent";
|
||||
|
||||
public static final String CREATE_TABLE = "CREATE TABLE " + TABLE_NAME + " (" +
|
||||
ID + " INTEGER PRIMARY KEY, " + DATE + " INTEGER DEFAULT 0, " +
|
||||
@@ -82,7 +84,7 @@ public class ThreadDatabase extends Database {
|
||||
SNIPPET_TYPE + " INTEGER DEFAULT 0, " + SNIPPET_URI + " TEXT DEFAULT NULL, " +
|
||||
ARCHIVED + " INTEGER DEFAULT 0, " + STATUS + " INTEGER DEFAULT 0, " +
|
||||
RECEIPT_COUNT + " INTEGER DEFAULT 0, " + EXPIRES_IN + " INTEGER DEFAULT 0, " +
|
||||
LAST_SEEN + " INTEGER DEFAULT 0);";
|
||||
LAST_SEEN + " INTEGER DEFAULT 0, " + HAS_SENT + " INTEGER DEFAULT 0);";
|
||||
|
||||
public static final String[] CREATE_INDEXS = {
|
||||
"CREATE INDEX IF NOT EXISTS thread_recipient_ids_index ON " + TABLE_NAME + " (" + ADDRESS + ");",
|
||||
@@ -417,20 +419,19 @@ public class ThreadDatabase extends Database {
|
||||
notifyConversationListListeners();
|
||||
}
|
||||
|
||||
public long getLastSeen(long threadId) {
|
||||
public Pair<Long, Boolean> getLastSeenAndHasSent(long threadId) {
|
||||
SQLiteDatabase db = databaseHelper.getReadableDatabase();
|
||||
Cursor cursor = db.query(TABLE_NAME, new String[]{LAST_SEEN}, ID_WHERE, new String[]{String.valueOf(threadId)}, null, null, null);
|
||||
Cursor cursor = db.query(TABLE_NAME, new String[]{LAST_SEEN, HAS_SENT}, ID_WHERE, new String[]{String.valueOf(threadId)}, null, null, null);
|
||||
|
||||
try {
|
||||
if (cursor != null && cursor.moveToFirst()) {
|
||||
return cursor.getLong(0);
|
||||
return new Pair<>(cursor.getLong(0), cursor.getLong(1) == 1);
|
||||
}
|
||||
|
||||
return -1;
|
||||
return new Pair<>(-1L, false);
|
||||
} finally {
|
||||
if (cursor != null) cursor.close();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void deleteConversation(long threadId) {
|
||||
@@ -520,6 +521,16 @@ public class ThreadDatabase extends Database {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void setHasSent(long threadId, boolean hasSent) {
|
||||
ContentValues contentValues = new ContentValues(1);
|
||||
contentValues.put(HAS_SENT, hasSent ? 1 : 0);
|
||||
|
||||
databaseHelper.getWritableDatabase().update(TABLE_NAME, contentValues, ID_WHERE,
|
||||
new String[] {String.valueOf(threadId)});
|
||||
|
||||
notifyConversationListeners(threadId);
|
||||
}
|
||||
|
||||
public void updateReadState(long threadId) {
|
||||
int unreadCount = DatabaseFactory.getMmsSmsDatabase(context).getUnreadCount(threadId);
|
||||
|
||||
|
||||
@@ -5,17 +5,20 @@ import android.database.Cursor;
|
||||
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.util.AbstractCursorLoader;
|
||||
import org.whispersystems.libsignal.util.Pair;
|
||||
|
||||
public class ConversationLoader extends AbstractCursorLoader {
|
||||
private final long threadId;
|
||||
private long limit;
|
||||
private long lastSeen;
|
||||
private final long threadId;
|
||||
private long limit;
|
||||
private long lastSeen;
|
||||
private boolean hasSent;
|
||||
|
||||
public ConversationLoader(Context context, long threadId, long limit, long lastSeen) {
|
||||
super(context);
|
||||
this.threadId = threadId;
|
||||
this.limit = limit;
|
||||
this.lastSeen = lastSeen;
|
||||
this.hasSent = true;
|
||||
}
|
||||
|
||||
public boolean hasLimit() {
|
||||
@@ -26,10 +29,18 @@ public class ConversationLoader extends AbstractCursorLoader {
|
||||
return lastSeen;
|
||||
}
|
||||
|
||||
public boolean hasSent() {
|
||||
return hasSent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Cursor getCursor() {
|
||||
Pair<Long, Boolean> lastSeenAndHasSent = DatabaseFactory.getThreadDatabase(context).getLastSeenAndHasSent(threadId);
|
||||
|
||||
this.hasSent = lastSeenAndHasSent.second();
|
||||
|
||||
if (lastSeen == -1) {
|
||||
this.lastSeen = DatabaseFactory.getThreadDatabase(context).getLastSeen(threadId);
|
||||
this.lastSeen = lastSeenAndHasSent.first();
|
||||
}
|
||||
|
||||
return DatabaseFactory.getMmsSmsDatabase(context).getConversation(threadId, limit);
|
||||
|
||||
106
src/org/thoughtcrime/securesms/profiles/UnknownSenderView.java
Normal file
106
src/org/thoughtcrime/securesms/profiles/UnknownSenderView.java
Normal file
@@ -0,0 +1,106 @@
|
||||
package org.thoughtcrime.securesms.profiles;
|
||||
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.AsyncTask;
|
||||
import android.provider.ContactsContract;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v7.app.AlertDialog;
|
||||
import android.text.TextUtils;
|
||||
import android.view.View;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.util.ViewUtil;
|
||||
|
||||
public class UnknownSenderView extends FrameLayout {
|
||||
|
||||
private final @NonNull Recipient recipient;
|
||||
private final long threadId;
|
||||
|
||||
public UnknownSenderView(@NonNull Context context, @NonNull Recipient recipient, long threadId) {
|
||||
super(context);
|
||||
this.recipient = recipient;
|
||||
this.threadId = threadId;
|
||||
|
||||
inflate(context, R.layout.unknown_sender_view, this);
|
||||
|
||||
View block = ViewUtil.findById(this, R.id.block);
|
||||
View add = ViewUtil.findById(this, R.id.add_to_contacts);
|
||||
View profileAccess = ViewUtil.findById(this, R.id.share_profile);
|
||||
|
||||
block.setOnClickListener(v -> handleBlock());
|
||||
add.setOnClickListener(v -> handleAdd());
|
||||
profileAccess.setOnClickListener(v -> handleProfileAccess());
|
||||
}
|
||||
|
||||
private void handleBlock() {
|
||||
final Context context = getContext();
|
||||
|
||||
new AlertDialog.Builder(getContext())
|
||||
.setIconAttribute(R.attr.dialog_alert_icon)
|
||||
.setTitle(getContext().getString(R.string.UnknownSenderView_block_s, recipient.toShortString()))
|
||||
.setMessage(R.string.UnknownSenderView_blocked_contacts_will_no_longer_be_able_to_send_you_messages_or_call_you)
|
||||
.setPositiveButton(R.string.UnknownSenderView_block, (dialog, which) -> {
|
||||
new AsyncTask<Void, Void, Void>() {
|
||||
@Override
|
||||
protected Void doInBackground(Void... params) {
|
||||
DatabaseFactory.getRecipientPreferenceDatabase(context).setBlocked(recipient, true);
|
||||
if (threadId != -1) DatabaseFactory.getThreadDatabase(context).setHasSent(threadId, true);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Void result) {
|
||||
recipient.setBlocked(true);
|
||||
}
|
||||
}.execute();
|
||||
})
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.show();
|
||||
}
|
||||
|
||||
private void handleAdd() {
|
||||
Intent intent = new Intent(Intent.ACTION_INSERT_OR_EDIT);
|
||||
intent.setType(ContactsContract.Contacts.CONTENT_ITEM_TYPE);
|
||||
|
||||
if (!TextUtils.isEmpty(recipient.getProfileName())) {
|
||||
intent.putExtra(ContactsContract.Intents.Insert.NAME, recipient.getProfileName());
|
||||
}
|
||||
|
||||
if (recipient.getAddress().isEmail()) {
|
||||
intent.putExtra(ContactsContract.Intents.Insert.EMAIL, recipient.getAddress().toEmailString());
|
||||
}
|
||||
|
||||
if (recipient.getAddress().isPhone()) {
|
||||
intent.putExtra(ContactsContract.Intents.Insert.PHONE, recipient.getAddress().toPhoneString());
|
||||
}
|
||||
|
||||
getContext().startActivity(intent);
|
||||
if (threadId != -1) DatabaseFactory.getThreadDatabase(getContext()).setHasSent(threadId, true);
|
||||
}
|
||||
|
||||
private void handleProfileAccess() {
|
||||
final Context context = getContext();
|
||||
|
||||
new AlertDialog.Builder(getContext())
|
||||
.setIconAttribute(R.attr.dialog_info_icon)
|
||||
.setTitle(getContext().getString(R.string.UnknownSenderView_share_profile_with_s, recipient.toShortString()))
|
||||
.setMessage(R.string.UnknownSenderView_the_easiest_way_to_share_your_profile_information_is_to_add_the_sender_to_your_contacts)
|
||||
.setPositiveButton(R.string.UnknownSenderView_share_profile, (dialog, which) -> {
|
||||
new AsyncTask<Void, Void, Void>() {
|
||||
@Override
|
||||
protected Void doInBackground(Void... params) {
|
||||
DatabaseFactory.getRecipientPreferenceDatabase(context).setProfileSharing(recipient.getAddress(), true);
|
||||
if (threadId != -1) DatabaseFactory.getThreadDatabase(context).setHasSent(threadId, true);
|
||||
return null;
|
||||
}
|
||||
}.execute();
|
||||
})
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.show();
|
||||
}
|
||||
}
|
||||
@@ -132,7 +132,7 @@ public class StickyHeaderDecoration extends RecyclerView.ItemDecoration {
|
||||
{
|
||||
int headerHeight = getHeaderHeightForLayout(header);
|
||||
int top = getChildY(parent, child) - headerHeight;
|
||||
if (layoutPos == 0) {
|
||||
if (sticky && layoutPos == 0) {
|
||||
final int count = parent.getChildCount();
|
||||
final long currentId = adapter.getHeaderId(adapterPos);
|
||||
// find next view with header and compute the offscreen push if needed
|
||||
|
||||
Reference in New Issue
Block a user