Use actual path data, clean and fix incorrect copy

This commit is contained in:
nielsandriesse 2020-05-29 09:43:03 +10:00
parent c7adf9f232
commit 326b5a9475
6 changed files with 108 additions and 60 deletions

View File

@ -0,0 +1,12 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="496dp"
android:height="496dp"
android:viewportWidth="496"
android:viewportHeight="496">
<path
android:pathData="M248,0C111.043,0 0,111.083 0,248C0,384.997 111.043,496 248,496C384.957,496 496,384.997 496,248C496,111.083 384.957,0 248,0ZM248.5,467C127.744,467 30,369.297 30,248.5C30,127.784 127.748,30 248.5,30C369.211,30 467,127.747 467,248.5C467,369.254 369.297,467 248.5,467ZM270.703,285.663L270.703,292C270.703,298.627 268.33,304 261.703,304L238.056,304C231.429,304 226.056,298.627 226.056,292L226.056,283.341C226.056,247.596 250.224,244.566 270.703,233.084C288.264,223.239 314.235,222.608 314.235,185.76C314.235,164.861 286.202,147.355 253.674,147.355C230.485,147.355 204.281,169.53 189.233,188.522C185.176,193.642 177.773,194.593 172.567,190.646L155.743,185.548C150.636,181.676 149.492,174.482 153.099,169.185C176.726,134.491 206.82,104 253.674,104C302.745,104 355.124,142.304 355.124,192.8C355.124,267.221 270.703,260.884 270.703,285.663ZM282,373C282,388.991 268.991,402 253,402C237.009,402 224,388.991 224,373C224,357.009 237.009,344 253,344C268.991,344 282,357.009 282,373Z"
android:strokeWidth="1"
android:fillColor="@color/text"
android:fillType="nonZero"
android:strokeColor="@color/text"/>
</vector>

10
res/menu/menu_path.xml Normal file
View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/learnMoreButton"
android:icon="@drawable/ic_question_mark"
app:showAsAction="always" />
</menu>

View File

@ -1699,7 +1699,7 @@
<string name="fragment_enter_session_id_edit_text_hint">Enter your Session ID</string>
<string name="activity_display_name_title_2">Pick your display name</string>
<string name="activity_display_name_explanation">This will be your name when you use Session.</string>
<string name="activity_display_name_explanation">This will be your name when you use Session. It can be your real name, an alias, or anything else you like.</string>
<string name="activity_display_name_edit_text_hint">Enter a display name</string>
<string name="activity_display_name_display_name_missing_error">Please pick a display name</string>
<string name="activity_display_name_display_name_invalid_error">Please pick a display name that consists of only a-z, A-Z, 0-9 and _ characters</string>
@ -1708,9 +1708,9 @@
<string name="activity_pn_mode_title">Push Notifications</string>
<string name="activity_pn_mode_explanation">There are two ways Session can handle push notifications. Make sure to read the descriptions carefully before you choose.</string>
<string name="activity_pn_mode_fcm_option_title">Firebase Cloud Messaging</string>
<string name="activity_pn_mode_fcm_option_explanation">Session will use the Firebase Cloud Messaging service to receive push notifications. You\ll be notified of new messages reliably and immediately. Using FCM means that this device will communicate directly with Google\s servers to retrieve push notifications, which will expose your IP address to Google. Your messages will still be onion-routed and end-to-end encrypted, so the contents of your messages will remain completely private.</string>
<string name="activity_pn_mode_fcm_option_explanation">Session will use the Firebase Cloud Messaging service to receive push notifications. You\'ll be notified of new messages reliably and immediately. Using FCM means that your IP address and device token will be exposed to Google. If you use push notifications for other apps, this will already be the case. Your IP address and device token will also be exposed to Loki, but your messages will still be onion-routed and end-to-end encrypted, so the contents of your messages will remain completely private.</string>
<string name="activity_pn_mode_background_polling_option_title">Background Polling</string>
<string name="activity_pn_mode_background_polling_option_explanation">Session will occasionally check for new messages in the background. This guarantees full privacy protection, but message notifications may be significantly delayed.</string>
<string name="activity_pn_mode_background_polling_option_explanation">Session will occasionally check for new messages in the background. This guarantees full metadata protection, but message notifications may be significantly delayed.</string>
<string name="activity_pn_mode_recommended_option_tag">Recommended</string>
<string name="activity_pn_mode_no_option_picked_dialog_title">Please Pick an Option</string>
@ -1724,9 +1724,9 @@
<string name="sheet_pn_mode_title">Push Notifications</string>
<string name="sheet_pn_mode_explanation">Session now features two ways to handle push notifications. Make sure to read the descriptions carefully before you choose.</string>
<string name="sheet_pn_mode_fcm_option_title">Firebase Cloud Messaging</string>
<string name="sheet_pn_mode_fcm_option_explanation">Session will use the Firebase Cloud Messaging service to receive push notifications. You\ll be notified of new messages reliably and immediately. Using FCM means that this device will communicate directly with Google\s servers to retrieve push notifications, which will expose your IP address to Google. Your messages will still be onion-routed and end-to-end encrypted, so the contents of your messages will remain completely private.</string>
<string name="sheet_pn_mode_fcm_option_explanation">Session will use the Firebase Cloud Messaging service to receive push notifications. You\'ll be notified of new messages reliably and immediately. Using FCM means that your IP address and device token will be exposed to Google. If you use push notifications for other apps, this will already be the case. Your IP address and device token will also be exposed to Loki, but your messages will still be onion-routed and end-to-end encrypted, so the contents of your messages will remain completely private.</string>
<string name="sheet_pn_mode_background_polling_option_title">Background Polling</string>
<string name="sheet_pn_mode_background_polling_option_explanation">Session will occasionally check for new messages in the background. This guarantees full privacy protection, but message notifications may be significantly delayed.</string>
<string name="sheet_pn_mode_background_polling_option_explanation">Session will occasionally check for new messages in the background. This guarantees full metadata protection, but message notifications may be significantly delayed.</string>
<string name="sheet_pn_mode_recommended_option_tag">Recommended</string>
<string name="sheet_pn_mode_no_option_picked_dialog_title">Please Pick an Option</string>
<string name="sheet_pn_mode_confirm_button_title">Confirm</string>
@ -1734,7 +1734,7 @@
<string name="activity_seed_title">Your Recovery Phrase</string>
<string name="activity_seed_title_2">Meet your recovery phrase</string>
<string name="activity_seed_explanation">Your recovery phrase is the master key to your Session ID — you can use it to restore your Session ID if you lose access to your device. Store your recovery phrase in a safe place, and don\t give it to anyone. To restore your Session ID, launch Session and tap Continue your Session.</string>
<string name="activity_seed_explanation">Your recovery phrase is the master key to your Session ID — you can use it to restore your Session ID if you lose access to your device. Store your recovery phrase in a safe place, and don\t give it to anyone.</string>
<string name="activity_seed_reveal_button_title">Hold to reveal</string>
<string name="view_seed_reminder_subtitle_1">Secure your account by saving your recovery phrase</string>
@ -1804,7 +1804,7 @@
<string name="preferences_notifications_strategy_category_title">Notification Strategy</string>
<string name="preferences_notifications_use_fcm_option_title">Use FCM</string>
<string name="preferences_notifications_use_fcm_option_explanation">Using Firebase Cloud Messaging allows for more reliable push notifications, but exposes your IP to Google.</string>
<string name="preferences_notifications_use_fcm_option_explanation">Using Firebase Cloud Messaging allows for more reliable push notifications, but exposes your IP and device token to Google and Loki.</string>
<string name="dialog_link_device_slave_mode_title_1">Waiting for Authorization</string>
<string name="dialog_link_device_slave_mode_title_2">Device Link Authorized</string>
@ -1828,7 +1828,7 @@
<string name="dialog_seed_explanation">This is your recovery phrase. With it, you can restore or migrate your Session ID to a new device.</string>
<string name="dialog_clear_all_data_title">Clear All Data</string>
<string name="dialog_clear_all_data_explanation">This will permanently delete your Session ID, including all messages, sessions, and contacts.</string>
<string name="dialog_clear_all_data_explanation">This will permanently delete your messages, sessions, and contacts.</string>
<string name="activity_qr_code_title">QR Code</string>
<string name="activity_qr_code_view_my_qr_code_tab_title">View My QR Code</string>

View File

@ -1,23 +1,27 @@
package org.thoughtcrime.securesms.loki.activities
import android.animation.FloatEvaluator
import android.animation.ValueAnimator
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.os.Handler
import android.support.annotation.DimenRes
import android.util.AttributeSet
import android.util.TypedValue
import android.view.Gravity
import android.view.Menu
import android.view.MenuItem
import android.view.View
import android.widget.LinearLayout
import android.widget.RelativeLayout
import android.widget.TextView
import android.widget.Toast
import kotlinx.android.synthetic.main.activity_path.*
import network.loki.messenger.R
import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity
import org.thoughtcrime.securesms.loki.utilities.animateSizeChange
import org.thoughtcrime.securesms.loki.utilities.getColorWithID
import org.thoughtcrime.securesms.loki.views.NewConversationButtonSetView
import org.whispersystems.signalservice.loki.api.onionrequests.OnionRequestAPI
import org.whispersystems.signalservice.loki.api.onionrequests.Snode
class PathActivity : PassphraseRequiredActionBarActivity() {
@ -27,23 +31,36 @@ class PathActivity : PassphraseRequiredActionBarActivity() {
setContentView(R.layout.activity_path)
supportActionBar!!.title = resources.getString(R.string.activity_path_title)
val youRow = getPathRow("You", null, LineView.Location.Top, 1000, 4000)
val row1 = getPathRow("Guard Node", "0.0.0.0", LineView.Location.Middle, 2000, 4000)
val row2 = getPathRow("Service Node", "0.0.0.0", LineView.Location.Middle, 3000, 4000)
val row3 = getPathRow("Service Node", "0.0.0.0", LineView.Location.Middle, 4000, 4000)
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)
}
val destinationRow = getPathRow("Destination", null, LineView.Location.Bottom, 5000, 4000)
pathRowsContainer.addView(youRow)
pathRowsContainer.addView(row1)
pathRowsContainer.addView(row2)
pathRowsContainer.addView(row3)
for (pathRow in pathRows) {
pathRowsContainer.addView(pathRow)
}
pathRowsContainer.addView(destinationRow)
}
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
menuInflater.inflate(R.menu.menu_path, menu)
return true
}
// endregion
// region General
private fun getPathRow(title: String, subtitle: String?, location: LineView.Location, dotAnimationStartDelay: Long, dotAnimationRepeatInterval: Long): LinearLayout {
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
val lineView = LineView(this, location, dotAnimationStartDelay, dotAnimationRepeatInterval)
val lineViewLayoutParams = LinearLayout.LayoutParams(resources.getDimensionPixelSize(R.dimen.path_row_expanded_dot_size), resources.getDimensionPixelSize(R.dimen.path_row_height))
lineView.layoutParams = lineViewLayoutParams
mainContainer.addView(lineView)
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))
@ -54,6 +71,7 @@ class PathActivity : PassphraseRequiredActionBarActivity() {
val titleContainerLayoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT)
titleContainerLayoutParams.marginStart = resources.getDimensionPixelSize(R.dimen.large_spacing)
titleContainer.layoutParams = titleContainerLayoutParams
mainContainer.addView(titleContainer)
if (subtitle != null) {
val subtitleTextView = TextView(this)
subtitleTextView.setTextColor(resources.getColorWithID(R.color.text, theme))
@ -61,15 +79,35 @@ class PathActivity : PassphraseRequiredActionBarActivity() {
subtitleTextView.text = subtitle
titleContainer.addView(subtitleTextView)
}
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
mainContainer.addView(lineView)
mainContainer.addView(titleContainer)
return mainContainer
}
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()
}
}
// endregion
// region Line View
@ -147,26 +185,11 @@ class PathActivity : PassphraseRequiredActionBarActivity() {
}
private fun expand() {
animateDotViewSizeChange(R.dimen.path_row_dot_size, R.dimen.path_row_expanded_dot_size)
dotView.animateSizeChange(R.dimen.path_row_dot_size, R.dimen.path_row_expanded_dot_size)
}
private fun collapse() {
animateDotViewSizeChange(R.dimen.path_row_expanded_dot_size, R.dimen.path_row_dot_size)
}
private fun animateDotViewSizeChange(@DimenRes startSizeID: Int, @DimenRes endSizeID: Int) {
val layoutParams = dotView.layoutParams
val startSize = resources.getDimension(startSizeID)
val endSize = resources.getDimension(endSizeID)
val animation = ValueAnimator.ofObject(FloatEvaluator(), startSize, endSize)
animation.duration = NewConversationButtonSetView.Button.animationDuration
animation.addUpdateListener { animator ->
val size = animator.animatedValue as Float
layoutParams.width = size.toInt()
layoutParams.height = size.toInt()
dotView.layoutParams = layoutParams
}
animation.start()
dotView.animateSizeChange(R.dimen.path_row_expanded_dot_size, R.dimen.path_row_dot_size)
}
}
// endregion

View File

@ -1,7 +1,10 @@
package org.thoughtcrime.securesms.loki.utilities
import android.animation.FloatEvaluator
import android.animation.ValueAnimator
import android.graphics.PointF
import android.graphics.Rect
import android.support.annotation.DimenRes
import android.view.View
fun View.contains(point: PointF): Boolean {
@ -13,4 +16,19 @@ val View.hitRect: Rect
val rect = Rect()
getHitRect(rect)
return rect
}
}
fun View.animateSizeChange(@DimenRes startSizeID: Int, @DimenRes endSizeID: Int, animationDuration: Long = 250) {
val layoutParams = this.layoutParams
val startSize = resources.getDimension(startSizeID)
val endSize = resources.getDimension(endSizeID)
val animation = ValueAnimator.ofObject(FloatEvaluator(), startSize, endSize)
animation.duration = animationDuration
animation.addUpdateListener { animator ->
val size = animator.animatedValue as Float
layoutParams.width = size.toInt()
layoutParams.height = size.toInt()
this.layoutParams = layoutParams
}
animation.start()
}

View File

@ -96,13 +96,13 @@ class NewConversationButtonSetView : RelativeLayout {
fun expand() {
animateImageViewColorChange(R.color.new_conversation_button_collapsed_background, R.color.accent)
animateImageViewSizeChange(R.dimen.new_conversation_button_collapsed_size, R.dimen.new_conversation_button_expanded_size)
imageView.animateSizeChange(R.dimen.new_conversation_button_collapsed_size, R.dimen.new_conversation_button_expanded_size, animationDuration)
animateImageViewPositionChange(collapsedImageViewPosition, expandedImageViewPosition)
}
fun collapse() {
animateImageViewColorChange(R.color.accent, R.color.new_conversation_button_collapsed_background)
animateImageViewSizeChange(R.dimen.new_conversation_button_expanded_size, R.dimen.new_conversation_button_collapsed_size)
imageView.animateSizeChange(R.dimen.new_conversation_button_expanded_size, R.dimen.new_conversation_button_collapsed_size, animationDuration)
animateImageViewPositionChange(expandedImageViewPosition, collapsedImageViewPosition)
}
@ -119,21 +119,6 @@ class NewConversationButtonSetView : RelativeLayout {
animation.start()
}
private fun animateImageViewSizeChange(@DimenRes startSizeID: Int, @DimenRes endSizeID: Int) {
val layoutParams = imageView.layoutParams
val startSize = resources.getDimension(startSizeID)
val endSize = resources.getDimension(endSizeID)
val animation = ValueAnimator.ofObject(FloatEvaluator(), startSize, endSize)
animation.duration = animationDuration
animation.addUpdateListener { animator ->
val size = animator.animatedValue as Float
layoutParams.width = size.toInt()
layoutParams.height = size.toInt()
imageView.layoutParams = layoutParams
}
animation.start()
}
private fun animateImageViewPositionChange(startPosition: PointF, endPosition: PointF) {
val animation = ValueAnimator.ofObject(PointFEvaluator(), startPosition, endPosition)
animation.duration = animationDuration