mirror of
https://github.com/oxen-io/session-android.git
synced 2025-12-03 09:22:23 +00:00
Merge branch 'dev' into editgroup
This commit is contained in:
@@ -7,9 +7,12 @@ import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.support.v4.app.Fragment
|
||||
import android.support.v4.app.FragmentPagerAdapter
|
||||
import android.text.InputType
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.inputmethod.EditorInfo
|
||||
import android.view.inputmethod.InputMethodManager
|
||||
import android.widget.Toast
|
||||
import kotlinx.android.synthetic.main.activity_create_private_chat.*
|
||||
import kotlinx.android.synthetic.main.fragment_enter_public_key.*
|
||||
@@ -25,6 +28,7 @@ import org.thoughtcrime.securesms.recipients.Recipient
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||
import org.whispersystems.signalservice.loki.utilities.PublicKeyValidation
|
||||
|
||||
|
||||
class CreatePrivateChatActivity : PassphraseRequiredActionBarActivity(), ScanQRCodeWrapperFragmentDelegate {
|
||||
private val adapter = CreatePrivateChatActivityAdapter(this)
|
||||
|
||||
@@ -111,7 +115,18 @@ class EnterPublicKeyFragment : Fragment() {
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
publicKeyTextView.imeOptions = publicKeyTextView.imeOptions or 16777216 // Always use incognito keyboard
|
||||
publicKeyEditText.imeOptions = EditorInfo.IME_ACTION_DONE or 16777216 // Always use incognito keyboard
|
||||
publicKeyEditText.setRawInputType(InputType.TYPE_CLASS_TEXT)
|
||||
publicKeyEditText.setOnEditorActionListener { v, actionID, _ ->
|
||||
if (actionID == EditorInfo.IME_ACTION_DONE) {
|
||||
val imm = v.context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
|
||||
imm.hideSoftInputFromWindow(v.windowToken, 0)
|
||||
createPrivateChatIfPossible()
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
publicKeyTextView.text = hexEncodedPublicKey
|
||||
copyButton.setOnClickListener { copyPublicKey() }
|
||||
shareButton.setOnClickListener { sharePublicKey() }
|
||||
|
||||
@@ -41,9 +41,6 @@ class DisplayNameActivity : BaseActionBarActivity() {
|
||||
if (displayName.isEmpty()) {
|
||||
return Toast.makeText(this, R.string.activity_display_name_display_name_missing_error, Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
if (!displayName.matches(Regex("[a-zA-Z0-9_]+"))) {
|
||||
return Toast.makeText(this, R.string.activity_display_name_display_name_invalid_error, Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
if (displayName.toByteArray().size > ProfileCipher.NAME_PADDED_LENGTH) {
|
||||
return Toast.makeText(this, R.string.activity_display_name_display_name_too_long_error, Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
|
||||
@@ -1,21 +1,20 @@
|
||||
package org.thoughtcrime.securesms.loki.activities
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.AlertDialog
|
||||
import android.arch.lifecycle.Observer
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.IntentFilter
|
||||
import android.database.Cursor
|
||||
import android.graphics.BitmapFactory
|
||||
import android.graphics.Canvas
|
||||
import android.graphics.Paint
|
||||
import android.net.Uri
|
||||
import android.os.AsyncTask
|
||||
import android.os.Bundle
|
||||
import android.os.Handler
|
||||
import android.support.v4.app.LoaderManager
|
||||
import android.support.v4.content.Loader
|
||||
import android.support.v4.content.LocalBroadcastManager
|
||||
import android.support.v7.widget.LinearLayoutManager
|
||||
import android.support.v7.widget.RecyclerView
|
||||
import android.support.v7.widget.helper.ItemTouchHelper
|
||||
import android.text.Spannable
|
||||
import android.text.SpannableString
|
||||
import android.text.style.ForegroundColorSpan
|
||||
@@ -31,35 +30,36 @@ import org.thoughtcrime.securesms.conversation.ConversationActivity
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory
|
||||
import org.thoughtcrime.securesms.database.ThreadDatabase
|
||||
import org.thoughtcrime.securesms.database.model.ThreadRecord
|
||||
import org.thoughtcrime.securesms.loki.dialogs.PNModeBottomSheet
|
||||
import org.thoughtcrime.securesms.jobs.MultiDeviceBlockedUpdateJob
|
||||
import org.thoughtcrime.securesms.loki.database.LokiAPIDatabase
|
||||
import org.thoughtcrime.securesms.loki.dialogs.ConversationOptionsBottomSheet
|
||||
import org.thoughtcrime.securesms.loki.dialogs.MultiDeviceRemovalBottomSheet
|
||||
import org.thoughtcrime.securesms.loki.protocol.ClosedGroupsProtocol
|
||||
import org.thoughtcrime.securesms.loki.protocol.LokiSessionResetImplementation
|
||||
import org.thoughtcrime.securesms.loki.protocol.SessionResetImplementation
|
||||
import org.thoughtcrime.securesms.loki.utilities.*
|
||||
import org.thoughtcrime.securesms.loki.views.ConversationView
|
||||
import org.thoughtcrime.securesms.loki.views.NewConversationButtonSetViewDelegate
|
||||
import org.thoughtcrime.securesms.loki.views.SeedReminderViewDelegate
|
||||
import org.thoughtcrime.securesms.mms.GlideApp
|
||||
import org.thoughtcrime.securesms.mms.GlideRequests
|
||||
import org.thoughtcrime.securesms.notifications.MessageNotifier
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||
import org.whispersystems.signalservice.loki.protocol.friendrequests.FriendRequestProtocol
|
||||
import org.thoughtcrime.securesms.util.Util
|
||||
import org.whispersystems.signalservice.loki.api.fileserver.FileServerAPI
|
||||
import org.whispersystems.signalservice.loki.protocol.mentions.MentionsManager
|
||||
import org.whispersystems.signalservice.loki.protocol.meta.SessionMetaProtocol
|
||||
import org.whispersystems.signalservice.loki.protocol.multidevice.MultiDeviceProtocol
|
||||
import org.whispersystems.signalservice.loki.protocol.shelved.multidevice.MultiDeviceProtocol
|
||||
import org.whispersystems.signalservice.loki.protocol.sessionmanagement.SessionManagementProtocol
|
||||
import org.whispersystems.signalservice.loki.protocol.syncmessages.SyncMessagesProtocol
|
||||
import org.whispersystems.signalservice.loki.protocol.todo.LokiMessageFriendRequestStatus
|
||||
import org.whispersystems.signalservice.loki.protocol.todo.LokiThreadFriendRequestStatus
|
||||
import kotlin.math.abs
|
||||
import org.whispersystems.signalservice.loki.protocol.shelved.syncmessages.SyncMessagesProtocol
|
||||
|
||||
class HomeActivity : PassphraseRequiredActionBarActivity, ConversationClickListener, SeedReminderViewDelegate, NewConversationButtonSetViewDelegate {
|
||||
private lateinit var glide: GlideRequests
|
||||
private var broadcastReceiver: BroadcastReceiver? = null
|
||||
|
||||
private val hexEncodedPublicKey: String
|
||||
private val publicKey: String
|
||||
get() {
|
||||
val masterHexEncodedPublicKey = TextSecurePreferences.getMasterHexEncodedPublicKey(this)
|
||||
val userHexEncodedPublicKey = TextSecurePreferences.getLocalNumber(this)
|
||||
return masterHexEncodedPublicKey ?: userHexEncodedPublicKey
|
||||
val masterPublicKey = TextSecurePreferences.getMasterHexEncodedPublicKey(this)
|
||||
val userPublicKey = TextSecurePreferences.getLocalNumber(this)
|
||||
return masterPublicKey ?: userPublicKey
|
||||
}
|
||||
|
||||
// region Lifecycle
|
||||
@@ -77,7 +77,7 @@ class HomeActivity : PassphraseRequiredActionBarActivity, ConversationClickListe
|
||||
val threadID = archivedConversations.getLong(archivedConversations.getColumnIndex(ThreadDatabase.ID))
|
||||
AsyncTask.execute {
|
||||
threadDatabase.deleteConversation(threadID)
|
||||
MessageNotifier.updateNotification(this)
|
||||
(applicationContext as ApplicationContext).messageNotifier.updateNotification(this)
|
||||
}
|
||||
}
|
||||
deleteThreadAtCurrentPosition()
|
||||
@@ -95,7 +95,7 @@ class HomeActivity : PassphraseRequiredActionBarActivity, ConversationClickListe
|
||||
glide = GlideApp.with(this)
|
||||
// Set up toolbar buttons
|
||||
profileButton.glide = glide
|
||||
profileButton.hexEncodedPublicKey = hexEncodedPublicKey
|
||||
profileButton.publicKey = publicKey
|
||||
profileButton.update()
|
||||
profileButton.setOnClickListener { openSettings() }
|
||||
pathStatusViewContainer.setOnClickListener { showPath() }
|
||||
@@ -119,7 +119,6 @@ class HomeActivity : PassphraseRequiredActionBarActivity, ConversationClickListe
|
||||
homeAdapter.conversationClickListener = this
|
||||
recyclerView.adapter = homeAdapter
|
||||
recyclerView.layoutManager = LinearLayoutManager(this)
|
||||
ItemTouchHelper(SwipeCallback(this)).attachToRecyclerView(recyclerView)
|
||||
// Set up empty state view
|
||||
createNewPrivateChatButton.setOnClickListener { createNewPrivateChat() }
|
||||
// This is a workaround for the fact that CursorRecyclerViewAdapter doesn't actually auto-update (even though it says it will)
|
||||
@@ -157,62 +156,66 @@ class HomeActivity : PassphraseRequiredActionBarActivity, ConversationClickListe
|
||||
val threadDB = DatabaseFactory.getLokiThreadDatabase(this)
|
||||
val userDB = DatabaseFactory.getLokiUserDatabase(this)
|
||||
val userPublicKey = TextSecurePreferences.getLocalNumber(this)
|
||||
val sessionResetImpl = LokiSessionResetImplementation(this)
|
||||
val sessionResetImpl = SessionResetImplementation(this)
|
||||
if (userPublicKey != null) {
|
||||
FriendRequestProtocol.configureIfNeeded(apiDB, userPublicKey)
|
||||
MentionsManager.configureIfNeeded(userPublicKey, threadDB, userDB)
|
||||
SessionMetaProtocol.configureIfNeeded(apiDB, userPublicKey)
|
||||
SyncMessagesProtocol.configureIfNeeded(apiDB, userPublicKey)
|
||||
application.lokiPublicChatManager.startPollersIfNeeded()
|
||||
application.publicChatManager.startPollersIfNeeded()
|
||||
}
|
||||
SessionManagementProtocol.configureIfNeeded(sessionResetImpl, threadDB, application)
|
||||
MultiDeviceProtocol.configureIfNeeded(apiDB)
|
||||
IP2Country.configureIfNeeded(this)
|
||||
// TODO: Temporary hack to unbork existing clients
|
||||
val allContacts = DatabaseFactory.getRecipientDatabase(this).allAddresses.map {
|
||||
MultiDeviceProtocol.shared.getMasterDevice(it.serialize()) ?: it.serialize()
|
||||
// Preload device links to make message sending quicker
|
||||
val publicKeys = ContactUtilities.getAllContacts(this).filter { contact ->
|
||||
!contact.recipient.isGroupRecipient && !contact.isOurDevice && !contact.isSlave
|
||||
}.map {
|
||||
it.recipient.address.toPhoneString()
|
||||
}.toSet()
|
||||
val lokiMessageDB = DatabaseFactory.getLokiMessageDatabase(this)
|
||||
for (contact in allContacts) {
|
||||
val slaveDeviceHasPendingFR = MultiDeviceProtocol.shared.getSlaveDevices(contact).any {
|
||||
val slaveDeviceThreadID = DatabaseFactory.getThreadDatabase(this).getThreadIdFor(recipient(this, it))
|
||||
DatabaseFactory.getLokiThreadDatabase(this).getFriendRequestStatus(slaveDeviceThreadID) == LokiThreadFriendRequestStatus.REQUEST_RECEIVED
|
||||
}
|
||||
val masterDeviceThreadID = DatabaseFactory.getThreadDatabase(this).getThreadIdFor(recipient(this, contact))
|
||||
val masterDeviceHasNoPendingFR = (DatabaseFactory.getLokiThreadDatabase(this).getFriendRequestStatus(masterDeviceThreadID) == LokiThreadFriendRequestStatus.NONE)
|
||||
if (slaveDeviceHasPendingFR && masterDeviceHasNoPendingFR) {
|
||||
val lastMessageID = org.thoughtcrime.securesms.loki.protocol.FriendRequestProtocol.getLastMessageID(this, masterDeviceThreadID)
|
||||
if (lastMessageID != null) {
|
||||
val lastMessageFRStatus = lokiMessageDB.getFriendRequestStatus(lastMessageID)
|
||||
if (lastMessageFRStatus != LokiMessageFriendRequestStatus.REQUEST_PENDING) {
|
||||
lokiMessageDB.setFriendRequestStatus(lastMessageID, LokiMessageFriendRequestStatus.REQUEST_PENDING)
|
||||
}
|
||||
}
|
||||
FileServerAPI.shared.getDeviceLinks(publicKeys)
|
||||
// Observe blocked contacts changed events
|
||||
val broadcastReceiver = object : BroadcastReceiver() {
|
||||
|
||||
override fun onReceive(context: Context, intent: Intent) {
|
||||
recyclerView.adapter!!.notifyDataSetChanged()
|
||||
}
|
||||
}
|
||||
this.broadcastReceiver = broadcastReceiver
|
||||
LocalBroadcastManager.getInstance(this).registerReceiver(broadcastReceiver, IntentFilter("blockedContactsChanged"))
|
||||
// Clear all data if this is a secondary device
|
||||
if (TextSecurePreferences.getMasterHexEncodedPublicKey(this) != null) {
|
||||
TextSecurePreferences.setWasUnlinked(this, true)
|
||||
ApplicationContext.getInstance(this).clearData()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
if (TextSecurePreferences.getLocalNumber(this) == null) { return; } // This can be the case after a secondary device is auto-cleared
|
||||
profileButton.update()
|
||||
val isMasterDevice = (TextSecurePreferences.getMasterHexEncodedPublicKey(this) == null)
|
||||
val hasViewedSeed = TextSecurePreferences.getHasViewedSeed(this)
|
||||
if (hasViewedSeed || !isMasterDevice) {
|
||||
seedReminderView.visibility = View.GONE
|
||||
}
|
||||
if (!TextSecurePreferences.hasSeenPNModeSheet(this)) {
|
||||
val bottomSheet = PNModeBottomSheet()
|
||||
bottomSheet.onConfirmTapped = { isUsingFCM ->
|
||||
TextSecurePreferences.setHasSeenPNModeSheet(this, true)
|
||||
TextSecurePreferences.setIsUsingFCM(this, isUsingFCM)
|
||||
ApplicationContext.getInstance(this).registerForFCMIfNeeded(true)
|
||||
bottomSheet.dismiss()
|
||||
val hasSeenMultiDeviceRemovalSheet = TextSecurePreferences.getHasSeenMultiDeviceRemovalSheet(this)
|
||||
if (!hasSeenMultiDeviceRemovalSheet) {
|
||||
TextSecurePreferences.setHasSeenMultiDeviceRemovalSheet(this)
|
||||
val userPublicKey = TextSecurePreferences.getLocalNumber(this)
|
||||
val deviceLinks = DatabaseFactory.getLokiAPIDatabase(this).getDeviceLinks(userPublicKey)
|
||||
if (deviceLinks.isNotEmpty()) {
|
||||
val bottomSheet = MultiDeviceRemovalBottomSheet()
|
||||
bottomSheet.onOKTapped = {
|
||||
bottomSheet.dismiss()
|
||||
}
|
||||
bottomSheet.onLinkTapped = {
|
||||
bottomSheet.dismiss()
|
||||
val url = "https://getsession.org/faq"
|
||||
val intent = Intent(Intent.ACTION_VIEW, Uri.parse(url))
|
||||
startActivity(intent)
|
||||
}
|
||||
bottomSheet.show(supportFragmentManager, bottomSheet.tag)
|
||||
}
|
||||
bottomSheet.onSkipTapped = {
|
||||
TextSecurePreferences.setHasSeenPNModeSheet(this, true)
|
||||
bottomSheet.dismiss()
|
||||
}
|
||||
bottomSheet.show(supportFragmentManager, bottomSheet.tag)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -222,6 +225,14 @@ class HomeActivity : PassphraseRequiredActionBarActivity, ConversationClickListe
|
||||
createNewPrivateChat()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
val broadcastReceiver = this.broadcastReceiver
|
||||
if (broadcastReceiver != null) {
|
||||
LocalBroadcastManager.getInstance(this).unregisterReceiver(broadcastReceiver)
|
||||
}
|
||||
super.onDestroy()
|
||||
}
|
||||
// endregion
|
||||
|
||||
// region Updating
|
||||
@@ -243,7 +254,104 @@ class HomeActivity : PassphraseRequiredActionBarActivity, ConversationClickListe
|
||||
}
|
||||
|
||||
override fun onLongConversationClick(view: ConversationView) {
|
||||
// Do nothing
|
||||
val thread = view.thread ?: return
|
||||
val bottomSheet = ConversationOptionsBottomSheet()
|
||||
bottomSheet.recipient = thread.recipient
|
||||
bottomSheet.onBlockOrUnblockTapped = {
|
||||
bottomSheet.dismiss()
|
||||
if (thread.recipient.isBlocked) {
|
||||
unblockConversation(thread)
|
||||
} else {
|
||||
blockConversation(thread)
|
||||
}
|
||||
}
|
||||
bottomSheet.onDeleteTapped = {
|
||||
bottomSheet.dismiss()
|
||||
deleteConversation(thread)
|
||||
}
|
||||
bottomSheet.show(supportFragmentManager, bottomSheet.tag)
|
||||
}
|
||||
|
||||
private fun blockConversation(thread: ThreadRecord) {
|
||||
AlertDialog.Builder(this)
|
||||
.setTitle(R.string.RecipientPreferenceActivity_block_this_contact_question)
|
||||
.setMessage(R.string.RecipientPreferenceActivity_you_will_no_longer_receive_messages_and_calls_from_this_contact)
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.setPositiveButton(R.string.RecipientPreferenceActivity_block) { dialog, _ ->
|
||||
Thread {
|
||||
DatabaseFactory.getRecipientDatabase(this).setBlocked(thread.recipient, true)
|
||||
ApplicationContext.getInstance(this).jobManager.add(MultiDeviceBlockedUpdateJob())
|
||||
Util.runOnMain {
|
||||
recyclerView.adapter!!.notifyDataSetChanged()
|
||||
dialog.dismiss()
|
||||
}
|
||||
}.start()
|
||||
}.show()
|
||||
}
|
||||
|
||||
private fun unblockConversation(thread: ThreadRecord) {
|
||||
AlertDialog.Builder(this)
|
||||
.setTitle(R.string.RecipientPreferenceActivity_unblock_this_contact_question)
|
||||
.setMessage(R.string.RecipientPreferenceActivity_you_will_once_again_be_able_to_receive_messages_and_calls_from_this_contact)
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.setPositiveButton(R.string.RecipientPreferenceActivity_unblock) { dialog, _ ->
|
||||
Thread {
|
||||
DatabaseFactory.getRecipientDatabase(this).setBlocked(thread.recipient, false)
|
||||
ApplicationContext.getInstance(this).jobManager.add(MultiDeviceBlockedUpdateJob())
|
||||
Util.runOnMain {
|
||||
recyclerView.adapter!!.notifyDataSetChanged()
|
||||
dialog.dismiss()
|
||||
}
|
||||
}.start()
|
||||
}.show()
|
||||
}
|
||||
|
||||
private fun deleteConversation(thread: ThreadRecord) {
|
||||
val threadID = thread.threadId
|
||||
val recipient = thread.recipient
|
||||
val threadDB = DatabaseFactory.getThreadDatabase(this)
|
||||
val deleteThread = object : Runnable {
|
||||
|
||||
override fun run() {
|
||||
AsyncTask.execute {
|
||||
val publicChat = DatabaseFactory.getLokiThreadDatabase(this@HomeActivity).getPublicChat(threadID)
|
||||
if (publicChat != null) {
|
||||
val apiDB = DatabaseFactory.getLokiAPIDatabase(this@HomeActivity)
|
||||
apiDB.removeLastMessageServerID(publicChat.channel, publicChat.server)
|
||||
apiDB.removeLastDeletionServerID(publicChat.channel, publicChat.server)
|
||||
ApplicationContext.getInstance(this@HomeActivity).publicChatAPI!!.leave(publicChat.channel, publicChat.server)
|
||||
}
|
||||
threadDB.deleteConversation(threadID)
|
||||
ApplicationContext.getInstance(this@HomeActivity).messageNotifier.updateNotification(this@HomeActivity)
|
||||
}
|
||||
}
|
||||
}
|
||||
val dialogMessage = if (recipient.isGroupRecipient) R.string.activity_home_leave_group_dialog_message else R.string.activity_home_delete_conversation_dialog_message
|
||||
val dialog = AlertDialog.Builder(this)
|
||||
dialog.setMessage(dialogMessage)
|
||||
dialog.setPositiveButton(R.string.yes) { _, _ ->
|
||||
val isClosedGroup = recipient.address.isClosedGroup
|
||||
// Send a leave group message if this is an active closed group
|
||||
if (isClosedGroup && DatabaseFactory.getGroupDatabase(this).isActive(recipient.address.toGroupString())) {
|
||||
if (!ClosedGroupsProtocol.leaveGroup(this, recipient)) {
|
||||
Toast.makeText(this, R.string.activity_home_leaving_group_failed_message, Toast.LENGTH_LONG).show()
|
||||
return@setPositiveButton
|
||||
}
|
||||
}
|
||||
// Archive the conversation and then delete it after 10 seconds (the case where the
|
||||
// app was closed before the conversation could be deleted is handled in onCreate)
|
||||
threadDB.archiveConversation(threadID)
|
||||
val delay = if (isClosedGroup) 10000L else 1000L
|
||||
val handler = Handler()
|
||||
handler.postDelayed(deleteThread, delay)
|
||||
// Notify the user
|
||||
val toastMessage = if (recipient.isGroupRecipient) R.string.MessageRecord_left_group else R.string.activity_home_conversation_deleted_message
|
||||
Toast.makeText(this, toastMessage, Toast.LENGTH_LONG).show()
|
||||
}
|
||||
dialog.setNegativeButton(R.string.no) { _, _ ->
|
||||
// Do nothing
|
||||
}
|
||||
dialog.create().show()
|
||||
}
|
||||
|
||||
private fun openConversation(thread: ThreadRecord) {
|
||||
@@ -281,92 +389,5 @@ class HomeActivity : PassphraseRequiredActionBarActivity, ConversationClickListe
|
||||
val intent = Intent(this, JoinPublicChatActivity::class.java)
|
||||
show(intent)
|
||||
}
|
||||
|
||||
private class SwipeCallback(val activity: HomeActivity) : ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT) {
|
||||
|
||||
override fun onMove(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder, target: RecyclerView.ViewHolder): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
@SuppressLint("StaticFieldLeak")
|
||||
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
|
||||
viewHolder as HomeAdapter.ViewHolder
|
||||
val threadID = viewHolder.view.thread!!.threadId
|
||||
val recipient = viewHolder.view.thread!!.recipient
|
||||
val threadDatabase = DatabaseFactory.getThreadDatabase(activity)
|
||||
val deleteThread = object : Runnable {
|
||||
|
||||
override fun run() {
|
||||
AsyncTask.execute {
|
||||
val publicChat = DatabaseFactory.getLokiThreadDatabase(activity).getPublicChat(threadID)
|
||||
if (publicChat != null) {
|
||||
val apiDatabase = DatabaseFactory.getLokiAPIDatabase(activity)
|
||||
apiDatabase.removeLastMessageServerID(publicChat.channel, publicChat.server)
|
||||
apiDatabase.removeLastDeletionServerID(publicChat.channel, publicChat.server)
|
||||
ApplicationContext.getInstance(activity).lokiPublicChatAPI!!.leave(publicChat.channel, publicChat.server)
|
||||
}
|
||||
threadDatabase.deleteConversation(threadID)
|
||||
MessageNotifier.updateNotification(activity)
|
||||
}
|
||||
}
|
||||
}
|
||||
val dialogMessage = if (recipient.isGroupRecipient) R.string.activity_home_leave_group_dialog_message else R.string.activity_home_delete_conversation_dialog_message
|
||||
val dialog = AlertDialog.Builder(activity)
|
||||
dialog.setMessage(dialogMessage)
|
||||
dialog.setPositiveButton(R.string.yes) { _, _ ->
|
||||
val isClosedGroup = recipient.address.isClosedGroup
|
||||
// Send a leave group message if this is an active closed group
|
||||
if (isClosedGroup && DatabaseFactory.getGroupDatabase(activity).isActive(recipient.address.toGroupString())) {
|
||||
if (!ClosedGroupsProtocol.leaveGroup(activity, recipient)) {
|
||||
Toast.makeText(activity, R.string.activity_home_leaving_group_failed_message, Toast.LENGTH_LONG).show()
|
||||
clearView(activity.recyclerView, viewHolder)
|
||||
return@setPositiveButton
|
||||
}
|
||||
}
|
||||
// Archive the conversation and then delete it after 10 seconds (the case where the
|
||||
// app was closed before the conversation could be deleted is handled in onCreate)
|
||||
threadDatabase.archiveConversation(threadID)
|
||||
val delay = if (isClosedGroup) 10000L else 1000L
|
||||
val handler = Handler()
|
||||
handler.postDelayed(deleteThread, delay)
|
||||
// Notify the user
|
||||
val toastMessage = if (recipient.isGroupRecipient) R.string.MessageRecord_left_group else R.string.activity_home_conversation_deleted_message
|
||||
Toast.makeText(activity, toastMessage, Toast.LENGTH_LONG).show()
|
||||
}
|
||||
dialog.setNegativeButton(R.string.no) { _, _ ->
|
||||
clearView(activity.recyclerView, viewHolder)
|
||||
}
|
||||
dialog.create().show()
|
||||
}
|
||||
|
||||
override fun onChildDraw(c: Canvas, recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder, dx: Float, dy: Float, actionState: Int, isCurrentlyActive: Boolean) {
|
||||
if (actionState == ItemTouchHelper.ACTION_STATE_SWIPE && dx < 0) {
|
||||
val itemView = viewHolder.itemView
|
||||
animate(viewHolder, dx)
|
||||
val backgroundPaint = Paint()
|
||||
backgroundPaint.color = activity.resources.getColorWithID(R.color.destructive, activity.theme)
|
||||
c.drawRect(itemView.right.toFloat() - abs(dx), itemView.top.toFloat(), itemView.right.toFloat(), itemView.bottom.toFloat(), backgroundPaint)
|
||||
val icon = BitmapFactory.decodeResource(activity.resources, R.drawable.ic_trash_filled_32)
|
||||
val iconPaint = Paint()
|
||||
val left = itemView.right.toFloat() - abs(dx) + activity.resources.getDimension(R.dimen.medium_spacing)
|
||||
val top = itemView.top.toFloat() + (itemView.bottom.toFloat() - itemView.top.toFloat() - icon.height) / 2
|
||||
c.drawBitmap(icon, left, top, iconPaint)
|
||||
} else {
|
||||
super.onChildDraw(c, recyclerView, viewHolder, dx, dy, actionState, isCurrentlyActive)
|
||||
}
|
||||
}
|
||||
|
||||
private fun animate(viewHolder: RecyclerView.ViewHolder, dx: Float) {
|
||||
val alpha = 1.0f - abs(dx) / viewHolder.itemView.width.toFloat()
|
||||
viewHolder.itemView.alpha = alpha
|
||||
viewHolder.itemView.translationX = dx
|
||||
}
|
||||
|
||||
override fun clearView(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder) {
|
||||
super.clearView(recyclerView, viewHolder)
|
||||
viewHolder.itemView.alpha = 1.0f
|
||||
viewHolder.itemView.translationX = 0.0f
|
||||
}
|
||||
}
|
||||
// endregion
|
||||
}
|
||||
@@ -15,7 +15,7 @@ import org.thoughtcrime.securesms.database.IdentityDatabase
|
||||
import org.thoughtcrime.securesms.logging.Log
|
||||
import org.thoughtcrime.securesms.loki.dialogs.LinkDeviceSlaveModeDialog
|
||||
import org.thoughtcrime.securesms.loki.dialogs.LinkDeviceSlaveModeDialogDelegate
|
||||
import org.thoughtcrime.securesms.loki.protocol.LokiSessionResetImplementation
|
||||
import org.thoughtcrime.securesms.loki.protocol.SessionResetImplementation
|
||||
import org.thoughtcrime.securesms.loki.protocol.MultiDeviceProtocol
|
||||
import org.thoughtcrime.securesms.loki.utilities.push
|
||||
import org.thoughtcrime.securesms.loki.utilities.setUpActionBarSessionLogo
|
||||
@@ -27,12 +27,11 @@ import org.whispersystems.curve25519.Curve25519
|
||||
import org.whispersystems.libsignal.ecc.Curve
|
||||
import org.whispersystems.libsignal.ecc.ECKeyPair
|
||||
import org.whispersystems.libsignal.util.KeyHelper
|
||||
import org.whispersystems.signalservice.loki.protocol.friendrequests.FriendRequestProtocol
|
||||
import org.whispersystems.signalservice.loki.protocol.mentions.MentionsManager
|
||||
import org.whispersystems.signalservice.loki.protocol.meta.SessionMetaProtocol
|
||||
import org.whispersystems.signalservice.loki.protocol.multidevice.DeviceLink
|
||||
import org.whispersystems.signalservice.loki.protocol.shelved.multidevice.DeviceLink
|
||||
import org.whispersystems.signalservice.loki.protocol.sessionmanagement.SessionManagementProtocol
|
||||
import org.whispersystems.signalservice.loki.protocol.syncmessages.SyncMessagesProtocol
|
||||
import org.whispersystems.signalservice.loki.protocol.shelved.syncmessages.SyncMessagesProtocol
|
||||
import org.whispersystems.signalservice.loki.utilities.hexEncodedPublicKey
|
||||
import org.whispersystems.signalservice.loki.utilities.retryIfNeeded
|
||||
|
||||
@@ -45,7 +44,7 @@ class LandingActivity : BaseActionBarActivity(), LinkDeviceSlaveModeDialogDelega
|
||||
fakeChatView.startAnimating()
|
||||
registerButton.setOnClickListener { register() }
|
||||
restoreButton.setOnClickListener { restore() }
|
||||
linkButton.setOnClickListener { linkDevice() }
|
||||
// linkButton.setOnClickListener { linkDevice() }
|
||||
if (TextSecurePreferences.getWasUnlinked(this)) {
|
||||
Toast.makeText(this, R.string.activity_landing_device_unlinked_dialog_title, Toast.LENGTH_LONG).show()
|
||||
}
|
||||
@@ -110,11 +109,10 @@ class LandingActivity : BaseActionBarActivity(), LinkDeviceSlaveModeDialogDelega
|
||||
val threadDB = DatabaseFactory.getLokiThreadDatabase(this)
|
||||
val userDB = DatabaseFactory.getLokiUserDatabase(this)
|
||||
val userPublicKey = TextSecurePreferences.getLocalNumber(this)
|
||||
val sessionResetImpl = LokiSessionResetImplementation(this)
|
||||
FriendRequestProtocol.configureIfNeeded(apiDB, userPublicKey)
|
||||
val sessionResetImpl = SessionResetImplementation(this)
|
||||
MentionsManager.configureIfNeeded(userPublicKey, threadDB, userDB)
|
||||
SessionMetaProtocol.configureIfNeeded(apiDB, userPublicKey)
|
||||
org.whispersystems.signalservice.loki.protocol.multidevice.MultiDeviceProtocol.configureIfNeeded(apiDB)
|
||||
org.whispersystems.signalservice.loki.protocol.shelved.multidevice.MultiDeviceProtocol.configureIfNeeded(apiDB)
|
||||
SessionManagementProtocol.configureIfNeeded(sessionResetImpl, threadDB, application)
|
||||
SyncMessagesProtocol.configureIfNeeded(apiDB, userPublicKey)
|
||||
application.setUpP2PAPIIfNeeded()
|
||||
@@ -124,13 +122,13 @@ class LandingActivity : BaseActionBarActivity(), LinkDeviceSlaveModeDialogDelega
|
||||
linkDeviceDialog.show(supportFragmentManager, "Link Device Dialog")
|
||||
AsyncTask.execute {
|
||||
retryIfNeeded(8) {
|
||||
MultiDeviceProtocol.sendDeviceLinkMessage(this@LandingActivity, deviceLink.masterHexEncodedPublicKey, deviceLink)
|
||||
MultiDeviceProtocol.sendDeviceLinkMessage(this@LandingActivity, deviceLink.masterPublicKey, deviceLink)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDeviceLinkRequestAuthorized(deviceLink: DeviceLink) {
|
||||
TextSecurePreferences.setMasterHexEncodedPublicKey(this, deviceLink.masterHexEncodedPublicKey)
|
||||
TextSecurePreferences.setMasterHexEncodedPublicKey(this, deviceLink.masterPublicKey)
|
||||
val intent = Intent(this, HomeActivity::class.java)
|
||||
show(intent)
|
||||
finish()
|
||||
@@ -145,5 +143,7 @@ class LandingActivity : BaseActionBarActivity(), LinkDeviceSlaveModeDialogDelega
|
||||
TextSecurePreferences.removeLocalNumber(this)
|
||||
TextSecurePreferences.setHasSeenWelcomeScreen(this, false)
|
||||
TextSecurePreferences.setPromptedPushRegistration(this, false)
|
||||
val application = ApplicationContext.getInstance(this)
|
||||
application.stopPolling()
|
||||
}
|
||||
}
|
||||
@@ -26,7 +26,7 @@ import org.thoughtcrime.securesms.loki.utilities.recipient
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||
import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage
|
||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress
|
||||
import org.whispersystems.signalservice.loki.api.fileserver.LokiFileServerAPI
|
||||
import org.whispersystems.signalservice.loki.api.fileserver.FileServerAPI
|
||||
import java.util.*
|
||||
import kotlin.concurrent.schedule
|
||||
|
||||
@@ -126,30 +126,30 @@ class LinkedDevicesActivity : PassphraseRequiredActionBarActivity, LoaderManager
|
||||
val userPublicKey = TextSecurePreferences.getLocalNumber(this)
|
||||
val apiDB = DatabaseFactory.getLokiAPIDatabase(this)
|
||||
val deviceLinks = apiDB.getDeviceLinks(userPublicKey)
|
||||
val deviceLink = deviceLinks.find { it.masterHexEncodedPublicKey == userPublicKey && it.slaveHexEncodedPublicKey == slaveDevicePublicKey }
|
||||
val deviceLink = deviceLinks.find { it.masterPublicKey == userPublicKey && it.slavePublicKey == slaveDevicePublicKey }
|
||||
if (deviceLink == null) {
|
||||
return Toast.makeText(this, R.string.activity_linked_devices_unlinking_failed_message, Toast.LENGTH_LONG).show()
|
||||
}
|
||||
LokiFileServerAPI.shared.setDeviceLinks(setOf()).successUi {
|
||||
FileServerAPI.shared.setDeviceLinks(setOf()).successUi {
|
||||
DatabaseFactory.getLokiAPIDatabase(this).clearDeviceLinks(userPublicKey)
|
||||
deviceLinks.forEach { deviceLink ->
|
||||
// We don't use PushEphemeralMessageJob because want these messages to send before the pre key and
|
||||
// session associated with the slave device have been deleted
|
||||
val unlinkingRequest = SignalServiceDataMessage.newBuilder()
|
||||
.withTimestamp(System.currentTimeMillis())
|
||||
.asUnlinkingRequest(true)
|
||||
.asDeviceUnlinkingRequest(true)
|
||||
val messageSender = ApplicationContext.getInstance(this@LinkedDevicesActivity).communicationModule.provideSignalMessageSender()
|
||||
val address = SignalServiceAddress(deviceLink.slaveHexEncodedPublicKey)
|
||||
val address = SignalServiceAddress(deviceLink.slavePublicKey)
|
||||
try {
|
||||
val udAccess = UnidentifiedAccessUtil.getAccessFor(this@LinkedDevicesActivity, recipient(this@LinkedDevicesActivity, deviceLink.slaveHexEncodedPublicKey))
|
||||
val udAccess = UnidentifiedAccessUtil.getAccessFor(this@LinkedDevicesActivity, recipient(this@LinkedDevicesActivity, deviceLink.slavePublicKey))
|
||||
messageSender.sendMessage(0, address, udAccess, unlinkingRequest.build()) // The message ID doesn't matter
|
||||
} catch (e: Exception) {
|
||||
Log.d("Loki", "Failed to send unlinking request due to error: $e.")
|
||||
throw e
|
||||
}
|
||||
DatabaseFactory.getLokiPreKeyBundleDatabase(this).removePreKeyBundle(deviceLink.slaveHexEncodedPublicKey)
|
||||
DatabaseFactory.getLokiPreKeyBundleDatabase(this).removePreKeyBundle(deviceLink.slavePublicKey)
|
||||
val sessionStore = TextSecureSessionStore(this@LinkedDevicesActivity)
|
||||
sessionStore.deleteAllSessions(deviceLink.slaveHexEncodedPublicKey)
|
||||
sessionStore.deleteAllSessions(deviceLink.slavePublicKey)
|
||||
}
|
||||
LoaderManager.getInstance(this).restartLoader(0, null, this)
|
||||
Toast.makeText(this, R.string.activity_linked_devices_unlinking_successful_message, Toast.LENGTH_LONG).show()
|
||||
|
||||
@@ -7,7 +7,7 @@ import org.thoughtcrime.securesms.loki.utilities.MnemonicUtilities
|
||||
import org.thoughtcrime.securesms.util.AsyncLoader
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||
import org.whispersystems.signalservice.loki.crypto.MnemonicCodec
|
||||
import org.whispersystems.signalservice.loki.protocol.multidevice.MultiDeviceProtocol
|
||||
import org.whispersystems.signalservice.loki.protocol.shelved.multidevice.MultiDeviceProtocol
|
||||
import java.io.File
|
||||
|
||||
class LinkedDevicesLoader(context: Context) : AsyncLoader<List<Device>>(context) {
|
||||
|
||||
@@ -3,10 +3,14 @@ package org.thoughtcrime.securesms.loki.activities
|
||||
import android.app.AlertDialog
|
||||
import android.content.Intent
|
||||
import android.graphics.drawable.TransitionDrawable
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.support.annotation.DrawableRes
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.Toast
|
||||
import kotlinx.android.synthetic.main.activity_display_name.registerButton
|
||||
import kotlinx.android.synthetic.main.activity_pn_mode.*
|
||||
import network.loki.messenger.R
|
||||
@@ -28,6 +32,11 @@ class PNModeActivity : BaseActionBarActivity() {
|
||||
backgroundPollingOptionView.setOnClickListener { toggleBackgroundPolling() }
|
||||
registerButton.setOnClickListener { register() }
|
||||
}
|
||||
|
||||
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
|
||||
menuInflater.inflate(R.menu.menu_pn_mode, menu)
|
||||
return true
|
||||
}
|
||||
// endregion
|
||||
|
||||
// region Animation
|
||||
@@ -39,6 +48,25 @@ class PNModeActivity : BaseActionBarActivity() {
|
||||
// endregion
|
||||
|
||||
// region Interaction
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
val id = item.itemId
|
||||
when(id) {
|
||||
R.id.learnMoreButton -> learnMore()
|
||||
else -> { /* Do nothing */ }
|
||||
}
|
||||
return super.onOptionsItemSelected(item)
|
||||
}
|
||||
|
||||
private fun learnMore() {
|
||||
try {
|
||||
val url = "https://getsession.org/faq/#privacy"
|
||||
val intent = Intent(Intent.ACTION_VIEW, Uri.parse(url))
|
||||
startActivity(intent)
|
||||
} catch (e: Exception) {
|
||||
Toast.makeText(this, R.string.invalid_url, Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
|
||||
private fun toggleFCM() {
|
||||
when (selectedOptionView) {
|
||||
null -> {
|
||||
@@ -87,7 +115,7 @@ class PNModeActivity : BaseActionBarActivity() {
|
||||
TextSecurePreferences.setHasSeenWelcomeScreen(this, true)
|
||||
TextSecurePreferences.setPromptedPushRegistration(this, true)
|
||||
TextSecurePreferences.setIsUsingFCM(this, (selectedOptionView == fcmOptionView))
|
||||
TextSecurePreferences.setHasSeenPNModeSheet(this, true) // Shouldn't be shown to users who've done the new onboarding
|
||||
TextSecurePreferences.setHasSeenMultiDeviceRemovalSheet(this)
|
||||
val application = ApplicationContext.getInstance(this)
|
||||
application.setUpStorageAPIIfNeeded()
|
||||
application.setUpP2PAPIIfNeeded()
|
||||
|
||||
@@ -121,6 +121,7 @@ class PathActivity : PassphraseRequiredActionBarActivity() {
|
||||
titleTextView.setTextColor(resources.getColorWithID(R.color.text, theme))
|
||||
titleTextView.setTextSize(TypedValue.COMPLEX_UNIT_PX, resources.getDimension(R.dimen.medium_font_size))
|
||||
titleTextView.text = title
|
||||
titleTextView.textAlignment = TextView.TEXT_ALIGNMENT_VIEW_START
|
||||
val titleContainer = LinearLayout(this)
|
||||
titleContainer.orientation = LinearLayout.VERTICAL
|
||||
titleContainer.addView(titleTextView)
|
||||
@@ -133,6 +134,7 @@ class PathActivity : PassphraseRequiredActionBarActivity() {
|
||||
subtitleTextView.setTextColor(resources.getColorWithID(R.color.text, theme))
|
||||
subtitleTextView.setTextSize(TypedValue.COMPLEX_UNIT_PX, resources.getDimension(R.dimen.small_font_size))
|
||||
subtitleTextView.text = subtitle
|
||||
subtitleTextView.textAlignment = TextView.TEXT_ALIGNMENT_VIEW_START
|
||||
titleContainer.addView(subtitleTextView)
|
||||
}
|
||||
return mainContainer
|
||||
|
||||
@@ -8,9 +8,8 @@ class SelectContactsLoader(context: Context) : AsyncLoader<List<String>>(context
|
||||
|
||||
override fun loadInBackground(): List<String> {
|
||||
val contacts = ContactUtilities.getAllContacts(context)
|
||||
// Only show the master devices of the users we are friends with
|
||||
return contacts.filter { contact ->
|
||||
!contact.recipient.isGroupRecipient && contact.isFriend && !contact.isOurDevice && !contact.isSlave
|
||||
!contact.recipient.isGroupRecipient && !contact.isOurDevice && !contact.isSlave
|
||||
}.map {
|
||||
it.recipient.address.toPhoneString()
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ import org.thoughtcrime.securesms.util.BitmapUtil
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||
import org.whispersystems.signalservice.api.crypto.ProfileCipher
|
||||
import org.whispersystems.signalservice.api.util.StreamDetails
|
||||
import org.whispersystems.signalservice.loki.api.fileserver.LokiFileServerAPI
|
||||
import org.whispersystems.signalservice.loki.api.fileserver.FileServerAPI
|
||||
import java.io.ByteArrayInputStream
|
||||
import java.io.File
|
||||
import java.security.SecureRandom
|
||||
@@ -73,7 +73,7 @@ class SettingsActivity : PassphraseRequiredActionBarActivity() {
|
||||
showQRCodeButton.setOnClickListener { showQRCode() }
|
||||
glide = GlideApp.with(this)
|
||||
profilePictureView.glide = glide
|
||||
profilePictureView.hexEncodedPublicKey = hexEncodedPublicKey
|
||||
profilePictureView.publicKey = hexEncodedPublicKey
|
||||
profilePictureView.isLarge = true
|
||||
profilePictureView.update()
|
||||
profilePictureView.setOnClickListener { showEditProfilePictureUI() }
|
||||
@@ -83,16 +83,16 @@ class SettingsActivity : PassphraseRequiredActionBarActivity() {
|
||||
copyButton.setOnClickListener { copyPublicKey() }
|
||||
shareButton.setOnClickListener { sharePublicKey() }
|
||||
val isMasterDevice = (TextSecurePreferences.getMasterHexEncodedPublicKey(this) == null)
|
||||
linkedDevicesButtonTopSeparator.visibility = View.GONE
|
||||
linkedDevicesButton.visibility = View.GONE
|
||||
if (!isMasterDevice) {
|
||||
linkedDevicesButtonTopSeparator.visibility = View.GONE
|
||||
linkedDevicesButton.visibility = View.GONE
|
||||
seedButtonTopSeparator.visibility = View.GONE
|
||||
seedButton.visibility = View.GONE
|
||||
}
|
||||
privacyButton.setOnClickListener { showPrivacySettings() }
|
||||
notificationsButton.setOnClickListener { showNotificationSettings() }
|
||||
chatsButton.setOnClickListener { showChatSettings() }
|
||||
linkedDevicesButton.setOnClickListener { showLinkedDevices() }
|
||||
// linkedDevicesButton.setOnClickListener { showLinkedDevices() }
|
||||
seedButton.setOnClickListener { showSeed() }
|
||||
clearAllDataButton.setOnClickListener { clearAllData() }
|
||||
versionTextView.text = String.format(getString(R.string.version_s), BuildConfig.VERSION_NAME)
|
||||
@@ -151,7 +151,7 @@ class SettingsActivity : PassphraseRequiredActionBarActivity() {
|
||||
val promises = mutableListOf<Promise<*, Exception>>()
|
||||
val displayName = displayNameToBeUploaded
|
||||
if (displayName != null) {
|
||||
val publicChatAPI = ApplicationContext.getInstance(this).lokiPublicChatAPI
|
||||
val publicChatAPI = ApplicationContext.getInstance(this).publicChatAPI
|
||||
if (publicChatAPI != null) {
|
||||
val servers = DatabaseFactory.getLokiThreadDatabase(this).getAllPublicChatServers()
|
||||
promises.addAll(servers.map { publicChatAPI.setDisplayName(displayName, it) })
|
||||
@@ -162,7 +162,7 @@ class SettingsActivity : PassphraseRequiredActionBarActivity() {
|
||||
val encodedProfileKey = ProfileKeyUtil.generateEncodedProfileKey(this)
|
||||
val profileKey = ProfileKeyUtil.getProfileKeyFromEncodedString(encodedProfileKey)
|
||||
if (isUpdatingProfilePicture && profilePicture != null) {
|
||||
val storageAPI = LokiFileServerAPI.shared
|
||||
val storageAPI = FileServerAPI.shared
|
||||
val deferred = deferred<Unit, Exception>()
|
||||
AsyncTask.execute {
|
||||
val stream = StreamDetails(ByteArrayInputStream(profilePicture), "image/jpeg", profilePicture.size.toLong())
|
||||
@@ -202,9 +202,6 @@ class SettingsActivity : PassphraseRequiredActionBarActivity() {
|
||||
if (displayName.isEmpty()) {
|
||||
return Toast.makeText(this, R.string.activity_settings_display_name_missing_error, Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
if (!displayName.matches(Regex("[a-zA-Z0-9_]+"))) {
|
||||
return Toast.makeText(this, R.string.activity_settings_invalid_display_name_error, Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
if (displayName.toByteArray().size > ProfileCipher.NAME_PADDED_LENGTH) {
|
||||
return Toast.makeText(this, R.string.activity_settings_display_name_too_long_error, Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user