Finish friend request view & add message friend request status

This commit is contained in:
Niels Andriesse 2019-06-24 11:22:53 +10:00
parent 5c4ef59c0b
commit d99a996d0e
12 changed files with 184 additions and 129 deletions

View File

@ -1540,5 +1540,15 @@
<string name="activity_contact_selection_search_bar_placeholder">Search by name or public key</string> <string name="activity_contact_selection_search_bar_placeholder">Search by name or public key</string>
<!-- New conversation activity --> <!-- New conversation activity -->
<string name="activity_new_conversation_invalid_public_key_message">Invalid Public Key</string> <string name="activity_new_conversation_invalid_public_key_message">Invalid Public Key</string>
<!-- Friend request view -->
<string name="view_friend_request_accept_button_title">Accept</string>
<string name="view_friend_request_reject_button_title">Reject</string>
<string name="view_friend_request_incoming_pending_message">%1$s sent you a friend request</string>
<string name="view_friend_request_incoming_accepted_message">You\'ve accepted %1$s\'s friend request</string>
<string name="view_friend_request_incoming_declined_message">You\'ve declined %1$s\'s friend request</string>
<string name="view_friend_request_incoming_expired_message">%1$s\'s friend request has expired</string>
<string name="view_friend_request_outgoing_pending_message">You\'ve sent %1$s a friend request</string>
<string name="view_friend_request_outgoing_accepted_message">%1$s accepted your friend request</string>
<string name="view_friend_request_outgoing_expired_message">Your friend request to %1$s has expired</string>
</resources> </resources>

View File

@ -146,7 +146,7 @@ import org.thoughtcrime.securesms.giph.ui.GiphyActivity;
import org.thoughtcrime.securesms.linkpreview.LinkPreview; import org.thoughtcrime.securesms.linkpreview.LinkPreview;
import org.thoughtcrime.securesms.linkpreview.LinkPreviewRepository; import org.thoughtcrime.securesms.linkpreview.LinkPreviewRepository;
import org.thoughtcrime.securesms.linkpreview.LinkPreviewViewModel; import org.thoughtcrime.securesms.linkpreview.LinkPreviewViewModel;
import org.thoughtcrime.securesms.loki.LokiFriendRequestStatus; import org.thoughtcrime.securesms.loki.LokiThreadFriendRequestStatus;
import org.thoughtcrime.securesms.mediasend.MediaSendActivity; import org.thoughtcrime.securesms.mediasend.MediaSendActivity;
import org.thoughtcrime.securesms.mediasend.Media; import org.thoughtcrime.securesms.mediasend.Media;
import org.thoughtcrime.securesms.jobs.MultiDeviceBlockedUpdateJob; import org.thoughtcrime.securesms.jobs.MultiDeviceBlockedUpdateJob;
@ -2155,8 +2155,8 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
} }
// Loki - Always send friend requests if we're not friends with the user // Loki - Always send friend requests if we're not friends with the user
LokiFriendRequestStatus friendRequestStatus = DatabaseFactory.getLokiThreadFriendRequestDatabase(context).getFriendRequestStatus(threadId); LokiThreadFriendRequestStatus friendRequestStatus = DatabaseFactory.getLokiThreadFriendRequestDatabase(context).friendRequestStatus(threadId);
message.isFriendRequest = (friendRequestStatus != LokiFriendRequestStatus.FRIENDS); message.isFriendRequest = (friendRequestStatus != LokiThreadFriendRequestStatus.FRIENDS);
Permissions.with(this) Permissions.with(this)
.request(Manifest.permission.SEND_SMS) .request(Manifest.permission.SEND_SMS)

View File

@ -169,7 +169,7 @@ public class DatabaseFactory {
return getInstance(context).lokiPreKeyBundleDatabase; return getInstance(context).lokiPreKeyBundleDatabase;
} }
public static LokiMessageFriendRequestDatabase getLokiSmsFriendRequestDatabase(Context context) { public static LokiMessageFriendRequestDatabase getLokiMessageFriendRequestDatabase(Context context) {
return getInstance(context).lokiMessageFriendRequestDatabase; return getInstance(context).lokiMessageFriendRequestDatabase;
} }

View File

@ -37,6 +37,7 @@ import org.thoughtcrime.securesms.database.model.MessageRecord;
import org.thoughtcrime.securesms.database.model.SmsMessageRecord; import org.thoughtcrime.securesms.database.model.SmsMessageRecord;
import org.thoughtcrime.securesms.jobs.TrimThreadJob; import org.thoughtcrime.securesms.jobs.TrimThreadJob;
import org.thoughtcrime.securesms.logging.Log; import org.thoughtcrime.securesms.logging.Log;
import org.thoughtcrime.securesms.loki.LokiMessageFriendRequestStatus;
import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.sms.IncomingGroupMessage; import org.thoughtcrime.securesms.sms.IncomingGroupMessage;
import org.thoughtcrime.securesms.sms.IncomingTextMessage; import org.thoughtcrime.securesms.sms.IncomingTextMessage;
@ -661,9 +662,9 @@ public class SmsDatabase extends MessagingDatabase {
ApplicationContext.getInstance(context).getJobManager().add(new TrimThreadJob(threadId)); ApplicationContext.getInstance(context).getJobManager().add(new TrimThreadJob(threadId));
} }
// Loki - Save friend request state on sms // Loki - Set message friend request status
if (message.isFriendRequest) { if (message.isFriendRequest) {
DatabaseFactory.getLokiSmsFriendRequestDatabase(context).setIsFriendRequest(messageId, message.isFriendRequest); DatabaseFactory.getLokiMessageFriendRequestDatabase(context).setFriendRequestStatus(messageId, LokiMessageFriendRequestStatus.REQUEST_SENDING_OR_FAILED);
} }
return messageId; return messageId;
@ -880,7 +881,7 @@ public class SmsDatabase extends MessagingDatabase {
Recipient recipient = Recipient.from(context, address, true); Recipient recipient = Recipient.from(context, address, true);
// Loki - Check to see if this message was a friend request // Loki - Check to see if this message was a friend request
boolean isFriendRequest = DatabaseFactory.getLokiSmsFriendRequestDatabase(context).getIsFriendRequest(messageId); boolean isFriendRequest = DatabaseFactory.getLokiMessageFriendRequestDatabase(context).isFriendRequest(messageId);
return new SmsMessageRecord(messageId, body, recipient, return new SmsMessageRecord(messageId, body, recipient,
recipient, recipient,

View File

@ -62,7 +62,7 @@ import org.thoughtcrime.securesms.linkpreview.Link;
import org.thoughtcrime.securesms.linkpreview.LinkPreview; import org.thoughtcrime.securesms.linkpreview.LinkPreview;
import org.thoughtcrime.securesms.linkpreview.LinkPreviewUtil; import org.thoughtcrime.securesms.linkpreview.LinkPreviewUtil;
import org.thoughtcrime.securesms.logging.Log; import org.thoughtcrime.securesms.logging.Log;
import org.thoughtcrime.securesms.loki.LokiFriendRequestStatus; import org.thoughtcrime.securesms.loki.LokiThreadFriendRequestStatus;
import org.thoughtcrime.securesms.loki.LokiPreKeyBundleDatabase; import org.thoughtcrime.securesms.loki.LokiPreKeyBundleDatabase;
import org.thoughtcrime.securesms.loki.LokiThreadFriendRequestDatabase; import org.thoughtcrime.securesms.loki.LokiThreadFriendRequestDatabase;
import org.thoughtcrime.securesms.mms.IncomingMediaMessage; import org.thoughtcrime.securesms.mms.IncomingMediaMessage;
@ -827,9 +827,9 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
Recipient recipient = getMessageDestination(content, message); Recipient recipient = getMessageDestination(content, message);
long threadID = DatabaseFactory.getThreadDatabase(context).getThreadIdIfExistsFor(recipient); long threadID = DatabaseFactory.getThreadDatabase(context).getThreadIdIfExistsFor(recipient);
LokiThreadFriendRequestDatabase database = DatabaseFactory.getLokiThreadFriendRequestDatabase(context); LokiThreadFriendRequestDatabase database = DatabaseFactory.getLokiThreadFriendRequestDatabase(context);
LokiFriendRequestStatus friendRequestStatus = database.getFriendRequestStatus(threadID); LokiThreadFriendRequestStatus friendRequestStatus = database.friendRequestStatus(threadID);
if (envelope.isFriendRequest()) { if (envelope.isFriendRequest()) {
if (friendRequestStatus == LokiFriendRequestStatus.REQUEST_SENT) { if (friendRequestStatus == LokiThreadFriendRequestStatus.REQUEST_SENT) {
// This can happen if Alice sent Bob a friend request, Bob declined, but then Bob changed his // This can happen if Alice sent Bob a friend request, Bob declined, but then Bob changed his
// mind and sent a friend request to Alice. In this case we want Alice to auto-accept the request // mind and sent a friend request to Alice. In this case we want Alice to auto-accept the request
// and send a friend request accepted message back to Bob. We don't check that sending the // and send a friend request accepted message back to Bob. We don't check that sending the
@ -840,21 +840,21 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
// before updating Alice's thread's friend request status to `FRIENDS`, // before updating Alice's thread's friend request status to `FRIENDS`,
// we can end up in a deadlock where both users' threads' friend request statuses are // we can end up in a deadlock where both users' threads' friend request statuses are
// `REQUEST_SENT`. // `REQUEST_SENT`.
database.setFriendRequestStatus(threadID, LokiFriendRequestStatus.FRIENDS); database.setFriendRequestStatus(threadID, LokiThreadFriendRequestStatus.FRIENDS);
// Accept the friend request // Accept the friend request
sendEmptyMessage(envelope.getSource()); sendEmptyMessage(envelope.getSource());
} else if (friendRequestStatus != LokiFriendRequestStatus.FRIENDS) { } else if (friendRequestStatus != LokiThreadFriendRequestStatus.FRIENDS) {
// Checking that the sender of the message isn't already a friend is necessary because otherwise // Checking that the sender of the message isn't already a friend is necessary because otherwise
// the following situation can occur: Alice and Bob are friends. Bob loses his database and his // the following situation can occur: Alice and Bob are friends. Bob loses his database and his
// friend request status is reset to `NONE`. Bob now sends Alice a friend // friend request status is reset to `NONE`. Bob now sends Alice a friend
// request. Alice's thread's friend request status is reset to // request. Alice's thread's friend request status is reset to
// `REQUEST_RECEIVED`. // `REQUEST_RECEIVED`.
database.setFriendRequestStatus(threadID, LokiFriendRequestStatus.REQUEST_RECEIVED); database.setFriendRequestStatus(threadID, LokiThreadFriendRequestStatus.REQUEST_RECEIVED);
} }
} else if (friendRequestStatus != LokiFriendRequestStatus.FRIENDS) { } else if (friendRequestStatus != LokiThreadFriendRequestStatus.FRIENDS) {
// If the thread's friend request status is not `FRIENDS`, but we're receiving a message, // If the thread's friend request status is not `FRIENDS`, but we're receiving a message,
// it must be a friend request accepted message. Declining a friend request doesn't send a message. // it must be a friend request accepted message. Declining a friend request doesn't send a message.
database.setFriendRequestStatus(threadID, LokiFriendRequestStatus.FRIENDS); database.setFriendRequestStatus(threadID, LokiThreadFriendRequestStatus.FRIENDS);
// TODO: Send p2p details here // TODO: Send p2p details here
} }
} }

View File

@ -8,32 +8,26 @@ import android.widget.Button
import android.widget.LinearLayout import android.widget.LinearLayout
import android.widget.TextView import android.widget.TextView
import org.thoughtcrime.securesms.R import org.thoughtcrime.securesms.R
import org.thoughtcrime.securesms.database.DatabaseFactory
import org.thoughtcrime.securesms.sms.IncomingTextMessage import org.thoughtcrime.securesms.sms.IncomingTextMessage
import org.thoughtcrime.securesms.sms.OutgoingTextMessage
class FriendRequestView(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : LinearLayout(context, attrs, defStyleAttr) { class FriendRequestView(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : LinearLayout(context, attrs, defStyleAttr) {
private var isUISetUp = false
var message: Any? = null var message: Any? = null
set(newValue) { set(newValue) { field = newValue; handleMessageChanged() }
field = newValue
kind = if (message is IncomingTextMessage) Kind.Incoming else Kind.Outgoing
}
var kind: Kind? = null
var delegate: FriendRequestViewDelegate? = null var delegate: FriendRequestViewDelegate? = null
// region Types
enum class Kind { Incoming, Outgoing }
// endregion
// region Components // region Components
private val topSpacer by lazy { private val topSpacer by lazy {
val result = View(context) val result = View(context)
result.layoutParams = LayoutParams(LayoutParams.MATCH_PARENT, 12) result.layoutParams = LayoutParams(LayoutParams.MATCH_PARENT, toPx(12, resources))
result result
} }
private val label by lazy { private val label by lazy {
val result = TextView(context) val result = TextView(context)
result.setTextColor(resources.getColorWithID(R.color.core_grey_90, context.theme)) result.setTextColor(resources.getColorWithID(R.color.core_grey_90, context.theme))
// TODO: Typeface
result.textAlignment = TextView.TEXT_ALIGNMENT_CENTER result.textAlignment = TextView.TEXT_ALIGNMENT_CENTER
result result
} }
@ -48,86 +42,100 @@ class FriendRequestView(context: Context, attrs: AttributeSet?, defStyleAttr: In
// region Initialization // region Initialization
constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0) constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)
constructor(context: Context) : this(context, null) constructor(context: Context) : this(context, null)
init {
orientation = VERTICAL
addView(topSpacer)
addView(label)
// if (kind == Kind.Incoming) {
// Accept button
val acceptButton = Button(context)
acceptButton.text = "Accept"
acceptButton.setTextColor(resources.getColorWithID(R.color.signal_primary, context.theme))
acceptButton.setBackgroundColor(resources.getColorWithID(R.color.transparent, context.theme))
// TODO: Typeface
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
acceptButton.elevation = 0f
acceptButton.stateListAnimator = null
}
acceptButton.setOnClickListener { accept() }
val acceptButtonLayoutParams = LayoutParams(0, convertToPixels(50, resources))
acceptButtonLayoutParams.weight = 1f
acceptButton.layoutParams = acceptButtonLayoutParams
buttonLinearLayout.addView(acceptButton)
// Reject button
val rejectButton = Button(context)
rejectButton.text = "Reject"
rejectButton.setTextColor(resources.getColorWithID(R.color.red, context.theme))
rejectButton.setBackgroundColor(resources.getColorWithID(R.color.transparent, context.theme))
// TODO: Typeface
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
rejectButton.elevation = 0f
rejectButton.stateListAnimator = null
}
rejectButton.setOnClickListener { reject() }
val rejectButtonLayoutParams = LayoutParams(0, convertToPixels(50, resources))
rejectButtonLayoutParams.weight = 1f
rejectButton.layoutParams = rejectButtonLayoutParams
buttonLinearLayout.addView(rejectButton)
//
buttonLinearLayout.layoutParams = LayoutParams(LayoutParams.MATCH_PARENT, convertToPixels(50, resources))
addView(buttonLinearLayout)
// }
kind = Kind.Incoming // TODO: For debugging purposes
updateUI()
// TODO: Observe friend request status changes
}
// endregion // endregion
// region Updating // region Updating
private fun handleMessageChanged() {
setUpUIIfNeeded()
updateUI()
}
private fun setUpUIIfNeeded() {
if (isUISetUp) { return }
isUISetUp = true
orientation = VERTICAL
addView(topSpacer)
addView(label)
if (message is IncomingTextMessage) {
fun button(): Button {
val result = Button(context)
result.setBackgroundColor(resources.getColorWithID(R.color.transparent, context.theme))
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
result.elevation = 0f
result.stateListAnimator = null
}
val layoutParams = LayoutParams(0, toPx(50, resources))
layoutParams.weight = 1f
result.layoutParams = layoutParams
return result
}
val acceptButton = button()
acceptButton.text = resources.getString(R.string.view_friend_request_accept_button_title)
acceptButton.setTextColor(resources.getColorWithID(R.color.signal_primary, context.theme))
acceptButton.setOnClickListener { accept() }
buttonLinearLayout.addView(acceptButton)
val rejectButton = button()
rejectButton.text = resources.getString(R.string.view_friend_request_reject_button_title)
rejectButton.setTextColor(resources.getColorWithID(R.color.red, context.theme))
rejectButton.setOnClickListener { reject() }
buttonLinearLayout.addView(rejectButton)
buttonLinearLayout.layoutParams = LayoutParams(LayoutParams.MATCH_PARENT, toPx(50, resources))
addView(buttonLinearLayout)
}
// TODO: Observe friend request status changes
}
private fun updateUI() { private fun updateUI() {
when (kind) { val database = DatabaseFactory.getLokiMessageFriendRequestDatabase(context)
Kind.Incoming -> { if (message is IncomingTextMessage) {
// val message = this.message as IncomingTextMessage val message = this.message as IncomingTextMessage
// buttonLinearLayout.visibility = View.GONE // TODO: Base on friend request status val friendRequestStatus = database.friendRequestStatus(0) // TODO: Message ID
val text = { // TODO: Base on friend request status buttonLinearLayout.visibility = if (friendRequestStatus != LokiMessageFriendRequestStatus.REQUEST_PENDING) View.GONE else View.VISIBLE
"You've received a friend request" val formatID = when (friendRequestStatus) {
}() LokiMessageFriendRequestStatus.NONE, LokiMessageFriendRequestStatus.REQUEST_SENDING_OR_FAILED -> throw IllegalStateException()
label.text = text LokiMessageFriendRequestStatus.REQUEST_PENDING -> R.string.view_friend_request_incoming_pending_message
LokiMessageFriendRequestStatus.REQUEST_ACCEPTED -> R.string.view_friend_request_incoming_accepted_message
LokiMessageFriendRequestStatus.REQUEST_REJECTED -> R.string.view_friend_request_incoming_declined_message
LokiMessageFriendRequestStatus.REQUEST_EXPIRED -> R.string.view_friend_request_incoming_expired_message
} }
Kind.Outgoing -> { val contactID = message.sender.toString()
// val message = this.message as OutgoingTextMessage label.text = resources.getString(formatID, contactID)
// buttonLinearLayout.visibility = View.GONE } else {
val text = { val message = this.message as OutgoingTextMessage
"You've sent a friend request" val friendRequestStatus = database.friendRequestStatus(0) // TODO: Message ID
}() buttonLinearLayout.visibility = View.GONE
label.text = text val formatID = when (friendRequestStatus) {
LokiMessageFriendRequestStatus.NONE -> throw IllegalStateException()
LokiMessageFriendRequestStatus.REQUEST_SENDING_OR_FAILED -> null
LokiMessageFriendRequestStatus.REQUEST_PENDING -> R.string.view_friend_request_outgoing_pending_message
LokiMessageFriendRequestStatus.REQUEST_ACCEPTED -> R.string.view_friend_request_outgoing_accepted_message
LokiMessageFriendRequestStatus.REQUEST_REJECTED -> throw IllegalStateException()
LokiMessageFriendRequestStatus.REQUEST_EXPIRED -> R.string.view_friend_request_outgoing_expired_message
} }
if (formatID != null) {
val threadID = DatabaseFactory.getSmsDatabase(context).getThreadIdForMessage(0)
val contactID = DatabaseFactory.getThreadDatabase(context).getRecipientForThreadId(threadID)!!.address.toString()
label.text = resources.getString(formatID, contactID)
}
label.visibility = if (formatID != null) View.VISIBLE else View.GONE
topSpacer.visibility = label.visibility
} }
} }
// endregion // endregion
// region Interaction // region Interaction
private fun accept() { private fun accept() {
// val message = this.message as IncomingTextMessage val message = this.message as IncomingTextMessage
// TODO: Update message friend request status val database = DatabaseFactory.getLokiMessageFriendRequestDatabase(context)
// delegate?.acceptFriendRequest(message) database.setFriendRequestStatus(0, LokiMessageFriendRequestStatus.REQUEST_ACCEPTED)
delegate?.acceptFriendRequest(message)
} }
private fun reject() { private fun reject() {
// val message = this.message as IncomingTextMessage val message = this.message as IncomingTextMessage
// TODO: Update message friend request status val database = DatabaseFactory.getLokiMessageFriendRequestDatabase(context)
// delegate?.rejectFriendRequest(message) database.setFriendRequestStatus(0, LokiMessageFriendRequestStatus.REQUEST_REJECTED)
delegate?.rejectFriendRequest(message)
} }
// endregion // endregion
} }

View File

@ -13,7 +13,7 @@ fun Resources.getColorWithID(@ColorRes id: Int, theme: Resources.Theme?): Int {
} }
} }
fun convertToPixels(points: Int, resources: Resources): Int { fun toPx(dp: Int, resources: Resources): Int {
val scale = resources.displayMetrics.density val scale = resources.displayMetrics.density
return (points * scale).roundToInt() return (dp * scale).roundToInt()
} }

View File

@ -1,16 +0,0 @@
package org.thoughtcrime.securesms.loki
enum class LokiFriendRequestStatus(val rawValue: Int) {
// New conversation; no messages sent or received.
NONE(0),
// This state is used to lock the input early while sending.
REQUEST_SENDING(1),
// Friend request sent; awaiting response.
REQUEST_SENT(2),
// Friend request received; awaiting user input.
REQUEST_RECEIVED(3),
// We are friends with the user in this thread.
FRIENDS(4),
// A friend request was sent, but it timed out (i.e other user didn't accept within the allocated time)
REQUEST_EXPIRED(5)
}

View File

@ -8,26 +8,37 @@ import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper
class LokiMessageFriendRequestDatabase(context: Context, helper: SQLCipherOpenHelper) : Database(context, helper) { class LokiMessageFriendRequestDatabase(context: Context, helper: SQLCipherOpenHelper) : Database(context, helper) {
companion object { companion object {
private val tableName = "loki_sms_friend_request_database" private val tableName = "loki_message_friend_request_database"
private val messageID = "message_id" private val messageID = "message_id"
private val isFriendRequest = "is_friend_request" private val friendRequestStatus = "friend_request_status"
@JvmStatic val createTableCommand = "CREATE TABLE $tableName ($messageID INTEGER PRIMARY KEY, $isFriendRequest INTEGER DEFAULT 0);" @JvmStatic val createTableCommand = "CREATE TABLE $tableName ($messageID INTEGER PRIMARY KEY, $friendRequestStatus INTEGER DEFAULT 0);"
} }
fun getIsFriendRequest(messageID: Long): Boolean { fun friendRequestStatus(messageID: Long): LokiMessageFriendRequestStatus {
val database = databaseHelper.readableDatabase val database = databaseHelper.readableDatabase
return database.get(tableName, "${Companion.messageID} = ?", arrayOf( messageID.toString() )) { cursor -> val result = database.get(tableName, "${Companion.messageID} = ?", arrayOf( messageID.toString() )) { cursor ->
val rawIsFriendRequest = cursor.getInt(isFriendRequest) cursor.getInt(friendRequestStatus)
rawIsFriendRequest == 1 }
} ?: false return if (result != null) {
LokiMessageFriendRequestStatus.values().first { it.rawValue == result }
} else {
LokiMessageFriendRequestStatus.NONE
}
} }
fun setIsFriendRequest(messageID: Long, isFriendRequest: Boolean) { fun setFriendRequestStatus(messageID: Long, friendRequestStatus: LokiMessageFriendRequestStatus) {
val database = databaseHelper.writableDatabase val database = databaseHelper.writableDatabase
val rawIsFriendRequest = if (isFriendRequest) 1 else 0 val contentValues = ContentValues(2)
val contentValues = ContentValues()
contentValues.put(Companion.messageID, messageID) contentValues.put(Companion.messageID, messageID)
contentValues.put(Companion.isFriendRequest, rawIsFriendRequest) contentValues.put(Companion.friendRequestStatus, friendRequestStatus.rawValue)
database.insertOrUpdate(tableName, contentValues, "${Companion.messageID} = ?", arrayOf( messageID.toString() )) database.insertOrUpdate(tableName, contentValues, "${Companion.messageID} = ?", arrayOf( messageID.toString() ))
} }
fun isFriendRequest(messageID: Long): Boolean {
return friendRequestStatus(messageID) != LokiMessageFriendRequestStatus.NONE
}
fun hasFriendRequestStatusMessage(messageID: Long): Boolean {
return isFriendRequest(messageID) && friendRequestStatus(messageID) != LokiMessageFriendRequestStatus.REQUEST_SENDING_OR_FAILED
}
} }

View File

@ -0,0 +1,13 @@
package org.thoughtcrime.securesms.loki
enum class LokiMessageFriendRequestStatus(val rawValue: Int) {
NONE(0),
REQUEST_SENDING_OR_FAILED(1),
/**
* Either sent or received.
*/
REQUEST_PENDING(2),
REQUEST_ACCEPTED(3),
REQUEST_REJECTED(4),
REQUEST_EXPIRED(5)
}

View File

@ -14,23 +14,23 @@ class LokiThreadFriendRequestDatabase(context: Context, helper: SQLCipherOpenHel
@JvmStatic val createTableCommand = "CREATE TABLE $tableName ($threadID INTEGER PRIMARY KEY, $friendRequestStatus INTEGER DEFAULT 0);" @JvmStatic val createTableCommand = "CREATE TABLE $tableName ($threadID INTEGER PRIMARY KEY, $friendRequestStatus INTEGER DEFAULT 0);"
} }
fun getFriendRequestStatus(threadID: Long): LokiFriendRequestStatus { fun friendRequestStatus(threadID: Long): LokiThreadFriendRequestStatus {
val db = databaseHelper.readableDatabase val database = databaseHelper.readableDatabase
val result = db.get(tableName, "${Companion.threadID} = ?", arrayOf( threadID.toString() )) { cursor -> val result = database.get(tableName, "${Companion.threadID} = ?", arrayOf( threadID.toString() )) { cursor ->
cursor.getInt(friendRequestStatus) cursor.getInt(friendRequestStatus)
} }
return if (result != null) { return if (result != null) {
LokiFriendRequestStatus.values().first { it.rawValue == result } LokiThreadFriendRequestStatus.values().first { it.rawValue == result }
} else { } else {
LokiFriendRequestStatus.NONE LokiThreadFriendRequestStatus.NONE
} }
} }
fun setFriendRequestStatus(threadID: Long, status: LokiFriendRequestStatus) { fun setFriendRequestStatus(threadID: Long, friendRequestStatus: LokiThreadFriendRequestStatus) {
val database = databaseHelper.writableDatabase val database = databaseHelper.writableDatabase
val contentValues = ContentValues(1) val contentValues = ContentValues(2)
contentValues.put(Companion.threadID, threadID) contentValues.put(Companion.threadID, threadID)
contentValues.put(friendRequestStatus, status.rawValue) contentValues.put(Companion.friendRequestStatus, friendRequestStatus.rawValue)
database.insertOrUpdate(tableName, contentValues, "${Companion.threadID} = ?", arrayOf( threadID.toString() )) database.insertOrUpdate(tableName, contentValues, "${Companion.threadID} = ?", arrayOf( threadID.toString() ))
notifyConversationListListeners() notifyConversationListListeners()
} }

View File

@ -0,0 +1,28 @@
package org.thoughtcrime.securesms.loki
enum class LokiThreadFriendRequestStatus(val rawValue: Int) {
/**
* New conversation; no messages sent or received.
*/
NONE(0),
/**
* Used to lock the input early while sending.
*/
REQUEST_SENDING(1),
/**
* Friend request sent; awaiting response.
*/
REQUEST_SENT(2),
/**
* Friend request received; awaiting user input.
*/
REQUEST_RECEIVED(3),
/**
* The user is friends with the other user in this thread.
*/
FRIENDS(4),
/**
* A friend request was sent, but it timed out (i.e the other user didn't accept within the allocated time).
*/
REQUEST_EXPIRED(5)
}