2020-05-28 08:43:37 +02:00
|
|
|
package org.thoughtcrime.securesms.loki.activities
|
|
|
|
|
|
|
|
import android.content.Context
|
2020-05-29 01:43:03 +02:00
|
|
|
import android.content.Intent
|
|
|
|
import android.net.Uri
|
2020-05-28 08:43:37 +02:00
|
|
|
import android.os.Bundle
|
2020-05-28 10:16:53 +02:00
|
|
|
import android.os.Handler
|
2020-05-28 08:43:37 +02:00
|
|
|
import android.util.AttributeSet
|
|
|
|
import android.util.TypedValue
|
|
|
|
import android.view.Gravity
|
2020-05-29 01:43:03 +02:00
|
|
|
import android.view.Menu
|
|
|
|
import android.view.MenuItem
|
2020-05-28 08:43:37 +02:00
|
|
|
import android.view.View
|
|
|
|
import android.widget.LinearLayout
|
|
|
|
import android.widget.RelativeLayout
|
|
|
|
import android.widget.TextView
|
2020-05-29 01:43:03 +02:00
|
|
|
import android.widget.Toast
|
2020-05-28 08:43:37 +02:00
|
|
|
import kotlinx.android.synthetic.main.activity_path.*
|
|
|
|
import network.loki.messenger.R
|
|
|
|
import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity
|
2020-05-29 01:43:03 +02:00
|
|
|
import org.thoughtcrime.securesms.loki.utilities.animateSizeChange
|
2020-05-28 08:43:37 +02:00
|
|
|
import org.thoughtcrime.securesms.loki.utilities.getColorWithID
|
2020-05-29 01:43:03 +02:00
|
|
|
import org.whispersystems.signalservice.loki.api.onionrequests.OnionRequestAPI
|
|
|
|
import org.whispersystems.signalservice.loki.api.onionrequests.Snode
|
2020-05-28 08:43:37 +02:00
|
|
|
|
|
|
|
class PathActivity : PassphraseRequiredActionBarActivity() {
|
|
|
|
|
|
|
|
// region Lifecycle
|
|
|
|
override fun onCreate(savedInstanceState: Bundle?, isReady: Boolean) {
|
|
|
|
super.onCreate(savedInstanceState, isReady)
|
|
|
|
setContentView(R.layout.activity_path)
|
|
|
|
supportActionBar!!.title = resources.getString(R.string.activity_path_title)
|
2020-05-28 10:16:53 +02:00
|
|
|
val youRow = getPathRow("You", null, LineView.Location.Top, 1000, 4000)
|
2020-05-29 01:43:03 +02:00
|
|
|
val path = OnionRequestAPI.paths.firstOrNull() ?: return finish()
|
|
|
|
val pathRows = path.mapIndexed { index, snode ->
|
|
|
|
val isGuardSnode = (OnionRequestAPI.guardSnodes.contains(snode))
|
|
|
|
getPathRow(snode, LineView.Location.Middle, index.toLong() * 1000 + 2000, 4000, isGuardSnode)
|
|
|
|
}
|
2020-05-28 10:16:53 +02:00
|
|
|
val destinationRow = getPathRow("Destination", null, LineView.Location.Bottom, 5000, 4000)
|
2020-05-28 08:43:37 +02:00
|
|
|
pathRowsContainer.addView(youRow)
|
2020-05-29 01:43:03 +02:00
|
|
|
for (pathRow in pathRows) {
|
|
|
|
pathRowsContainer.addView(pathRow)
|
|
|
|
}
|
2020-05-28 08:43:37 +02:00
|
|
|
pathRowsContainer.addView(destinationRow)
|
|
|
|
}
|
2020-05-29 01:43:03 +02:00
|
|
|
|
|
|
|
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
|
|
|
|
menuInflater.inflate(R.menu.menu_path, menu)
|
|
|
|
return true
|
|
|
|
}
|
2020-05-28 08:43:37 +02:00
|
|
|
// endregion
|
|
|
|
|
|
|
|
// region General
|
2020-05-28 10:16:53 +02:00
|
|
|
private fun getPathRow(title: String, subtitle: String?, location: LineView.Location, dotAnimationStartDelay: Long, dotAnimationRepeatInterval: Long): LinearLayout {
|
2020-05-29 01:43:03 +02:00
|
|
|
val mainContainer = LinearLayout(this)
|
|
|
|
mainContainer.orientation = LinearLayout.HORIZONTAL
|
|
|
|
mainContainer.gravity = Gravity.CENTER_VERTICAL
|
|
|
|
val mainContainerLayoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT)
|
|
|
|
mainContainer.layoutParams = mainContainerLayoutParams
|
2020-05-28 08:43:37 +02:00
|
|
|
val lineView = LineView(this, location, dotAnimationStartDelay, dotAnimationRepeatInterval)
|
2020-05-28 10:16:53 +02:00
|
|
|
val lineViewLayoutParams = LinearLayout.LayoutParams(resources.getDimensionPixelSize(R.dimen.path_row_expanded_dot_size), resources.getDimensionPixelSize(R.dimen.path_row_height))
|
2020-05-28 08:43:37 +02:00
|
|
|
lineView.layoutParams = lineViewLayoutParams
|
2020-05-29 01:43:03 +02:00
|
|
|
mainContainer.addView(lineView)
|
2020-05-28 08:43:37 +02:00
|
|
|
val titleTextView = TextView(this)
|
|
|
|
titleTextView.setTextColor(resources.getColorWithID(R.color.text, theme))
|
|
|
|
titleTextView.setTextSize(TypedValue.COMPLEX_UNIT_PX, resources.getDimension(R.dimen.medium_font_size))
|
|
|
|
titleTextView.text = title
|
|
|
|
val titleContainer = LinearLayout(this)
|
|
|
|
titleContainer.orientation = LinearLayout.VERTICAL
|
|
|
|
titleContainer.addView(titleTextView)
|
|
|
|
val titleContainerLayoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT)
|
|
|
|
titleContainerLayoutParams.marginStart = resources.getDimensionPixelSize(R.dimen.large_spacing)
|
|
|
|
titleContainer.layoutParams = titleContainerLayoutParams
|
2020-05-29 01:43:03 +02:00
|
|
|
mainContainer.addView(titleContainer)
|
2020-05-28 08:43:37 +02:00
|
|
|
if (subtitle != null) {
|
|
|
|
val subtitleTextView = TextView(this)
|
|
|
|
subtitleTextView.setTextColor(resources.getColorWithID(R.color.text, theme))
|
|
|
|
subtitleTextView.setTextSize(TypedValue.COMPLEX_UNIT_PX, resources.getDimension(R.dimen.small_font_size))
|
|
|
|
subtitleTextView.text = subtitle
|
|
|
|
titleContainer.addView(subtitleTextView)
|
|
|
|
}
|
|
|
|
return mainContainer
|
|
|
|
}
|
2020-05-29 01:43:03 +02:00
|
|
|
|
|
|
|
private fun getPathRow(snode: Snode, location: LineView.Location, dotAnimationStartDelay: Long, dotAnimationRepeatInterval: Long, isGuardSnode: Boolean): LinearLayout {
|
|
|
|
val title = if (isGuardSnode) resources.getString(R.string.activity_path_guard_node_row_title) else resources.getString(R.string.activity_path_service_node_row_title)
|
|
|
|
val subtitle = snode.toString().removePrefix("https://").substringBefore(":")
|
|
|
|
return getPathRow(title, subtitle, location, dotAnimationStartDelay, dotAnimationRepeatInterval)
|
|
|
|
}
|
|
|
|
// 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/#onion-routing"
|
|
|
|
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()
|
|
|
|
}
|
|
|
|
}
|
2020-05-28 08:43:37 +02:00
|
|
|
// endregion
|
|
|
|
|
|
|
|
// region Line View
|
|
|
|
private class LineView : RelativeLayout {
|
|
|
|
private lateinit var location: Location
|
2020-05-28 10:16:53 +02:00
|
|
|
private var dotAnimationStartDelay: Long = 0
|
|
|
|
private var dotAnimationRepeatInterval: Long = 0
|
|
|
|
|
|
|
|
private val dotView by lazy {
|
|
|
|
val result = View(context)
|
|
|
|
result.setBackgroundResource(R.drawable.accent_dot)
|
|
|
|
result
|
|
|
|
}
|
2020-05-28 08:43:37 +02:00
|
|
|
|
|
|
|
enum class Location {
|
|
|
|
Top, Middle, Bottom
|
|
|
|
}
|
|
|
|
|
2020-05-28 10:16:53 +02:00
|
|
|
constructor(context: Context, location: Location, dotAnimationStartDelay: Long, dotAnimationRepeatInterval: Long) : super(context) {
|
2020-05-28 08:43:37 +02:00
|
|
|
this.location = location
|
|
|
|
this.dotAnimationStartDelay = dotAnimationStartDelay
|
|
|
|
this.dotAnimationRepeatInterval = dotAnimationRepeatInterval
|
|
|
|
setUpViewHierarchy()
|
|
|
|
}
|
|
|
|
|
|
|
|
constructor(context: Context) : super(context) {
|
|
|
|
throw Exception("Use LineView(context:location:dotAnimationStartDelay:dotAnimationRepeatInterval:) instead.")
|
|
|
|
}
|
|
|
|
|
|
|
|
constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {
|
|
|
|
throw Exception("Use LineView(context:location:dotAnimationStartDelay:dotAnimationRepeatInterval:) instead.")
|
|
|
|
}
|
|
|
|
|
|
|
|
constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {
|
|
|
|
throw Exception("Use LineView(context:location:dotAnimationStartDelay:dotAnimationRepeatInterval:) instead.")
|
|
|
|
}
|
|
|
|
|
|
|
|
constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int, defStyleRes: Int) : super(context, attrs, defStyleAttr, defStyleRes) {
|
|
|
|
throw Exception("Use LineView(context:location:dotAnimationStartDelay:dotAnimationRepeatInterval:) instead.")
|
|
|
|
}
|
|
|
|
|
|
|
|
private fun setUpViewHierarchy() {
|
|
|
|
val lineView = View(context)
|
|
|
|
lineView.setBackgroundColor(resources.getColorWithID(R.color.text, context.theme))
|
|
|
|
val lineViewHeight = when (location) {
|
|
|
|
Location.Top, Location.Bottom -> resources.getDimensionPixelSize(R.dimen.path_row_height) / 2
|
|
|
|
Location.Middle -> resources.getDimensionPixelSize(R.dimen.path_row_height)
|
|
|
|
}
|
|
|
|
val lineViewLayoutParams = LayoutParams(1, lineViewHeight)
|
|
|
|
when (location) {
|
|
|
|
Location.Top -> lineViewLayoutParams.addRule(ALIGN_PARENT_BOTTOM)
|
|
|
|
Location.Middle, Location.Bottom -> lineViewLayoutParams.addRule(ALIGN_PARENT_TOP)
|
|
|
|
}
|
|
|
|
lineViewLayoutParams.addRule(CENTER_HORIZONTAL)
|
|
|
|
lineView.layoutParams = lineViewLayoutParams
|
|
|
|
addView(lineView)
|
|
|
|
val dotViewSize = resources.getDimensionPixelSize(R.dimen.path_row_dot_size)
|
|
|
|
val dotViewLayoutParams = LayoutParams(dotViewSize, dotViewSize)
|
|
|
|
dotViewLayoutParams.addRule(CENTER_IN_PARENT)
|
|
|
|
dotView.layoutParams = dotViewLayoutParams
|
|
|
|
addView(dotView)
|
2020-05-28 10:16:53 +02:00
|
|
|
Handler().postDelayed({
|
|
|
|
performAnimation()
|
|
|
|
}, dotAnimationStartDelay)
|
|
|
|
}
|
|
|
|
|
|
|
|
private fun performAnimation() {
|
|
|
|
expand()
|
|
|
|
Handler().postDelayed({
|
|
|
|
collapse()
|
|
|
|
Handler().postDelayed({
|
|
|
|
performAnimation()
|
|
|
|
}, dotAnimationRepeatInterval)
|
|
|
|
}, 1000)
|
|
|
|
}
|
|
|
|
|
|
|
|
private fun expand() {
|
2020-05-29 01:43:03 +02:00
|
|
|
dotView.animateSizeChange(R.dimen.path_row_dot_size, R.dimen.path_row_expanded_dot_size)
|
2020-05-28 10:16:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
private fun collapse() {
|
2020-05-29 01:43:03 +02:00
|
|
|
dotView.animateSizeChange(R.dimen.path_row_expanded_dot_size, R.dimen.path_row_dot_size)
|
2020-05-28 08:43:37 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
// endregion
|
|
|
|
}
|