|
|
@ -11,7 +11,6 @@ import android.view.View
|
|
|
|
import android.view.ViewGroup
|
|
|
|
import android.view.ViewGroup
|
|
|
|
import android.view.inputmethod.InputMethodManager
|
|
|
|
import android.view.inputmethod.InputMethodManager
|
|
|
|
import android.widget.Toast
|
|
|
|
import android.widget.Toast
|
|
|
|
import androidx.activity.viewModels
|
|
|
|
|
|
|
|
import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory
|
|
|
|
import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory
|
|
|
|
import androidx.core.view.isVisible
|
|
|
|
import androidx.core.view.isVisible
|
|
|
|
import androidx.fragment.app.*
|
|
|
|
import androidx.fragment.app.*
|
|
|
@ -42,9 +41,6 @@ import org.thoughtcrime.securesms.loki.viewmodel.DefaultGroupsViewModel
|
|
|
|
import org.thoughtcrime.securesms.loki.viewmodel.State
|
|
|
|
import org.thoughtcrime.securesms.loki.viewmodel.State
|
|
|
|
|
|
|
|
|
|
|
|
class JoinPublicChatActivity : PassphraseRequiredActionBarActivity(), ScanQRCodeWrapperFragmentDelegate {
|
|
|
|
class JoinPublicChatActivity : PassphraseRequiredActionBarActivity(), ScanQRCodeWrapperFragmentDelegate {
|
|
|
|
|
|
|
|
|
|
|
|
private val viewModel by viewModels<DefaultGroupsViewModel>()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private val adapter = JoinPublicChatActivityAdapter(this)
|
|
|
|
private val adapter = JoinPublicChatActivityAdapter(this)
|
|
|
|
|
|
|
|
|
|
|
|
// region Lifecycle
|
|
|
|
// region Lifecycle
|
|
|
@ -83,23 +79,18 @@ class JoinPublicChatActivity : PassphraseRequiredActionBarActivity(), ScanQRCode
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fun joinPublicChatIfPossible(url: String) {
|
|
|
|
fun joinPublicChatIfPossible(url: String) {
|
|
|
|
// add http if just an IP style / host style URL is entered but leave it if scheme is included
|
|
|
|
// Add "http" if not entered explicitly
|
|
|
|
val properString = if (!url.startsWith("http")) "http://$url" else url
|
|
|
|
val stringWithExplicitScheme = if (!url.startsWith("http")) "http://$url" else url
|
|
|
|
val httpUrl = HttpUrl.parse(properString) ?: return Toast.makeText(this,R.string.invalid_url, Toast.LENGTH_SHORT).show()
|
|
|
|
val url = HttpUrl.parse(stringWithExplicitScheme) ?: return Toast.makeText(this,R.string.invalid_url, Toast.LENGTH_SHORT).show()
|
|
|
|
|
|
|
|
val room = url.pathSegments().firstOrNull()
|
|
|
|
val room = httpUrl.pathSegments().firstOrNull()
|
|
|
|
val publicKey = url.queryParameter("public_key")
|
|
|
|
val publicKey = httpUrl.queryParameter("public_key")
|
|
|
|
|
|
|
|
val isV2OpenGroup = !room.isNullOrEmpty()
|
|
|
|
val isV2OpenGroup = !room.isNullOrEmpty()
|
|
|
|
showLoader()
|
|
|
|
showLoader()
|
|
|
|
|
|
|
|
|
|
|
|
lifecycleScope.launch(Dispatchers.IO) {
|
|
|
|
lifecycleScope.launch(Dispatchers.IO) {
|
|
|
|
try {
|
|
|
|
try {
|
|
|
|
val (threadID, groupID) = if (isV2OpenGroup) {
|
|
|
|
val (threadID, groupID) = if (isV2OpenGroup) {
|
|
|
|
val server = HttpUrl.Builder().scheme(httpUrl.scheme()).host(httpUrl.host()).apply {
|
|
|
|
val server = HttpUrl.Builder().scheme(url.scheme()).host(url.host()).apply {
|
|
|
|
if (httpUrl.port() != 80 || httpUrl.port() != 443) {
|
|
|
|
if (url.port() != 80 || url.port() != 443) { this.port(url.port()) } // Non-standard port; add to server
|
|
|
|
// non-standard port, add to server
|
|
|
|
|
|
|
|
this.port(httpUrl.port())
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}.build()
|
|
|
|
}.build()
|
|
|
|
val group = OpenGroupUtilities.addGroup(this@JoinPublicChatActivity, server.toString().removeSuffix("/"), room!!, publicKey!!)
|
|
|
|
val group = OpenGroupUtilities.addGroup(this@JoinPublicChatActivity, server.toString().removeSuffix("/"), room!!, publicKey!!)
|
|
|
|
val threadID = GroupManager.getOpenGroupThreadID(group.id, this@JoinPublicChatActivity)
|
|
|
|
val threadID = GroupManager.getOpenGroupThreadID(group.id, this@JoinPublicChatActivity)
|
|
|
@ -107,21 +98,19 @@ class JoinPublicChatActivity : PassphraseRequiredActionBarActivity(), ScanQRCode
|
|
|
|
threadID to groupID
|
|
|
|
threadID to groupID
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
val channel: Long = 1
|
|
|
|
val channel: Long = 1
|
|
|
|
val group = OpenGroupUtilities.addGroup(this@JoinPublicChatActivity, properString, channel)
|
|
|
|
val group = OpenGroupUtilities.addGroup(this@JoinPublicChatActivity, stringWithExplicitScheme, channel)
|
|
|
|
val threadID = GroupManager.getOpenGroupThreadID(group.id, this@JoinPublicChatActivity)
|
|
|
|
val threadID = GroupManager.getOpenGroupThreadID(group.id, this@JoinPublicChatActivity)
|
|
|
|
val groupID = GroupUtil.getEncodedOpenGroupID(group.id.toByteArray())
|
|
|
|
val groupID = GroupUtil.getEncodedOpenGroupID(group.id.toByteArray())
|
|
|
|
threadID to groupID
|
|
|
|
threadID to groupID
|
|
|
|
}
|
|
|
|
}
|
|
|
|
MultiDeviceProtocol.forceSyncConfigurationNowIfNeeded(this@JoinPublicChatActivity)
|
|
|
|
MultiDeviceProtocol.forceSyncConfigurationNowIfNeeded(this@JoinPublicChatActivity)
|
|
|
|
|
|
|
|
|
|
|
|
withContext(Dispatchers.Main) {
|
|
|
|
withContext(Dispatchers.Main) {
|
|
|
|
// go to the new conversation and finish this one
|
|
|
|
val recipient = Recipient.from(this@JoinPublicChatActivity, Address.fromSerialized(groupID), false)
|
|
|
|
openConversationActivity(this@JoinPublicChatActivity, threadID, Recipient.from(this@JoinPublicChatActivity, Address.fromSerialized(groupID), false))
|
|
|
|
openConversationActivity(this@JoinPublicChatActivity, threadID, recipient)
|
|
|
|
finish()
|
|
|
|
finish()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
} catch (e: Exception) {
|
|
|
|
} catch (e: Exception) {
|
|
|
|
Log.e("JoinPublicChatActivity", "Fialed to join open group.", e)
|
|
|
|
Log.e("Loki", "Couldn't join open group.", e)
|
|
|
|
withContext(Dispatchers.Main) {
|
|
|
|
withContext(Dispatchers.Main) {
|
|
|
|
hideLoader()
|
|
|
|
hideLoader()
|
|
|
|
Toast.makeText(this@JoinPublicChatActivity, R.string.activity_join_public_chat_error, Toast.LENGTH_SHORT).show()
|
|
|
|
Toast.makeText(this@JoinPublicChatActivity, R.string.activity_join_public_chat_error, Toast.LENGTH_SHORT).show()
|
|
|
@ -175,13 +164,33 @@ private class JoinPublicChatActivityAdapter(val activity: JoinPublicChatActivity
|
|
|
|
|
|
|
|
|
|
|
|
// region Enter Chat URL Fragment
|
|
|
|
// region Enter Chat URL Fragment
|
|
|
|
class EnterChatURLFragment : Fragment() {
|
|
|
|
class EnterChatURLFragment : Fragment() {
|
|
|
|
|
|
|
|
|
|
|
|
private val viewModel by activityViewModels<DefaultGroupsViewModel>()
|
|
|
|
private val viewModel by activityViewModels<DefaultGroupsViewModel>()
|
|
|
|
|
|
|
|
|
|
|
|
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
|
|
|
|
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
|
|
|
|
return inflater.inflate(R.layout.fragment_enter_chat_url, container, false)
|
|
|
|
return inflater.inflate(R.layout.fragment_enter_chat_url, container, false)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
|
|
|
|
|
|
|
super.onViewCreated(view, savedInstanceState)
|
|
|
|
|
|
|
|
chatURLEditText.imeOptions = chatURLEditText.imeOptions or 16777216 // Always use incognito keyboard
|
|
|
|
|
|
|
|
joinPublicChatButton.setOnClickListener { joinPublicChatIfPossible() }
|
|
|
|
|
|
|
|
viewModel.defaultRooms.observe(viewLifecycleOwner) { state ->
|
|
|
|
|
|
|
|
defaultRoomsContainer.isVisible = state is State.Success
|
|
|
|
|
|
|
|
defaultRoomsLoader.isVisible = state is State.Loading
|
|
|
|
|
|
|
|
when (state) {
|
|
|
|
|
|
|
|
State.Loading -> {
|
|
|
|
|
|
|
|
// TODO: Show a loader
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
is State.Error -> {
|
|
|
|
|
|
|
|
// TODO: Hide the loader
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
is State.Success -> {
|
|
|
|
|
|
|
|
populateDefaultGroups(state.value)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private fun populateDefaultGroups(groups: List<DefaultGroup>) {
|
|
|
|
private fun populateDefaultGroups(groups: List<DefaultGroup>) {
|
|
|
|
defaultRoomsGridLayout.removeAllViews()
|
|
|
|
defaultRoomsGridLayout.removeAllViews()
|
|
|
|
groups.forEach { defaultGroup ->
|
|
|
|
groups.forEach { defaultGroup ->
|
|
|
@ -200,32 +209,10 @@ class EnterChatURLFragment : Fragment() {
|
|
|
|
defaultRoomsGridLayout.addView(chip)
|
|
|
|
defaultRoomsGridLayout.addView(chip)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (groups.size and 1 != 0) {
|
|
|
|
if (groups.size and 1 != 0) {
|
|
|
|
// add a filler weight 1 view
|
|
|
|
|
|
|
|
layoutInflater.inflate(R.layout.grid_layout_filler, defaultRoomsGridLayout)
|
|
|
|
layoutInflater.inflate(R.layout.grid_layout_filler, defaultRoomsGridLayout)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
|
|
|
|
|
|
|
super.onViewCreated(view, savedInstanceState)
|
|
|
|
|
|
|
|
chatURLEditText.imeOptions = chatURLEditText.imeOptions or 16777216 // Always use incognito keyboard
|
|
|
|
|
|
|
|
joinPublicChatButton.setOnClickListener { joinPublicChatIfPossible() }
|
|
|
|
|
|
|
|
viewModel.defaultRooms.observe(viewLifecycleOwner) { state ->
|
|
|
|
|
|
|
|
defaultRoomsParent.isVisible = state is State.Success
|
|
|
|
|
|
|
|
defaultRoomsLoader.isVisible = state is State.Loading
|
|
|
|
|
|
|
|
when (state) {
|
|
|
|
|
|
|
|
State.Loading -> {
|
|
|
|
|
|
|
|
// show a loader here probs
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
is State.Error -> {
|
|
|
|
|
|
|
|
// hide the loader and the
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
is State.Success -> {
|
|
|
|
|
|
|
|
populateDefaultGroups(state.value)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// region Convenience
|
|
|
|
// region Convenience
|
|
|
|
private fun joinPublicChatIfPossible() {
|
|
|
|
private fun joinPublicChatIfPossible() {
|
|
|
|
val inputMethodManager = requireContext().getSystemService(BaseActionBarActivity.INPUT_METHOD_SERVICE) as InputMethodManager
|
|
|
|
val inputMethodManager = requireContext().getSystemService(BaseActionBarActivity.INPUT_METHOD_SERVICE) as InputMethodManager
|
|
|
|