mirror of
https://github.com/oxen-io/session-android.git
synced 2025-02-22 08:08:26 +00:00
Implement QR code screen redesign
This commit is contained in:
parent
c76335150c
commit
b56d19e865
@ -153,6 +153,9 @@
|
|||||||
<activity
|
<activity
|
||||||
android:name="org.thoughtcrime.securesms.loki.redesign.activities.SettingsActivity"
|
android:name="org.thoughtcrime.securesms.loki.redesign.activities.SettingsActivity"
|
||||||
android:launchMode="singleTask" />
|
android:launchMode="singleTask" />
|
||||||
|
<activity
|
||||||
|
android:name="org.thoughtcrime.securesms.loki.redesign.activities.QRCodeActivity"
|
||||||
|
android:launchMode="singleTask" />
|
||||||
<!-- Session -->
|
<!-- Session -->
|
||||||
<activity android:name="org.thoughtcrime.securesms.loki.LinkedDevicesActivity" />
|
<activity android:name="org.thoughtcrime.securesms.loki.LinkedDevicesActivity" />
|
||||||
<activity
|
<activity
|
||||||
|
14
res/layout/activity_qr_code.xml
Normal file
14
res/layout/activity_qr_code.xml
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<android.support.v4.view.ViewPager
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:id="@+id/viewPager"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent" >
|
||||||
|
|
||||||
|
<android.support.design.widget.TabLayout
|
||||||
|
style="@style/Session.DarkTabLayout"
|
||||||
|
android:id="@+id/tabLayout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="@dimen/tab_bar_height" />
|
||||||
|
|
||||||
|
</android.support.v4.view.ViewPager>
|
@ -115,6 +115,22 @@
|
|||||||
android:layout_height="1px"
|
android:layout_height="1px"
|
||||||
android:background="@color/separator" />
|
android:background="@color/separator" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/chatsButton"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="@dimen/setting_button_height"
|
||||||
|
android:background="@drawable/setting_button_background"
|
||||||
|
android:textColor="@color/text"
|
||||||
|
android:textSize="@dimen/medium_font_size"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:gravity="center"
|
||||||
|
android:text="Chats" />
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="1px"
|
||||||
|
android:background="@color/separator" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/linkedDevicesButton"
|
android:id="@+id/linkedDevicesButton"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
74
res/layout/fragment_view_my_qr_code.xml
Normal file
74
res/layout/fragment_view_my_qr_code.xml
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<RelativeLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:background="@drawable/default_session_background" >
|
||||||
|
|
||||||
|
<ScrollView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:scrollbars="none">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/contentView"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginLeft="@dimen/very_large_spacing"
|
||||||
|
android:layout_marginTop="@dimen/medium_spacing"
|
||||||
|
android:layout_marginRight="@dimen/very_large_spacing"
|
||||||
|
android:textSize="@dimen/massive_font_size"
|
||||||
|
android:textColor="@color/text"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:textAlignment="center"
|
||||||
|
android:text="Scan Me" />
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginLeft="@dimen/very_large_spacing"
|
||||||
|
android:layout_marginTop="@dimen/small_spacing"
|
||||||
|
android:layout_marginRight="@dimen/very_large_spacing"
|
||||||
|
android:gravity="center">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/qrCodeImageView"
|
||||||
|
android:layout_width="320dp"
|
||||||
|
android:layout_height="320dp" />
|
||||||
|
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/explanationTextView"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginLeft="@dimen/very_large_spacing"
|
||||||
|
android:layout_marginTop="20dp"
|
||||||
|
android:layout_marginRight="@dimen/very_large_spacing"
|
||||||
|
android:textSize="@dimen/medium_font_size"
|
||||||
|
android:textColor="@color/text"
|
||||||
|
android:fontFamily="@font/space_mono_regular"
|
||||||
|
android:textAlignment="center"
|
||||||
|
android:text="This is your unique public QR code. Other users may scan this in order to begin a conversation with you." />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
style="@style/MediumUnimportantOutlineButton"
|
||||||
|
android:id="@+id/shareButton"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="@dimen/medium_button_height"
|
||||||
|
android:layout_marginLeft="90dp"
|
||||||
|
android:layout_marginTop="28dp"
|
||||||
|
android:layout_marginRight="90dp"
|
||||||
|
android:layout_marginBottom="@dimen/medium_spacing"
|
||||||
|
android:text="Share" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</ScrollView>
|
||||||
|
|
||||||
|
</RelativeLayout>
|
@ -0,0 +1,131 @@
|
|||||||
|
package org.thoughtcrime.securesms.loki.redesign.activities
|
||||||
|
|
||||||
|
import android.content.Intent
|
||||||
|
import android.graphics.Typeface
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.support.v4.app.Fragment
|
||||||
|
import android.support.v4.app.FragmentPagerAdapter
|
||||||
|
import android.text.Spannable
|
||||||
|
import android.text.SpannableStringBuilder
|
||||||
|
import android.text.style.StyleSpan
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import android.widget.Toast
|
||||||
|
import kotlinx.android.synthetic.main.activity_qr_code.*
|
||||||
|
import kotlinx.android.synthetic.main.fragment_view_my_qr_code.*
|
||||||
|
import network.loki.messenger.R
|
||||||
|
import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity
|
||||||
|
import org.thoughtcrime.securesms.conversation.ConversationActivity
|
||||||
|
import org.thoughtcrime.securesms.database.Address
|
||||||
|
import org.thoughtcrime.securesms.database.DatabaseFactory
|
||||||
|
import org.thoughtcrime.securesms.database.ThreadDatabase
|
||||||
|
import org.thoughtcrime.securesms.loki.redesign.fragments.ScanQRCodeWrapperFragment
|
||||||
|
import org.thoughtcrime.securesms.loki.redesign.fragments.ScanQRCodeWrapperFragmentDelegate
|
||||||
|
import org.thoughtcrime.securesms.loki.redesign.utilities.QRCodeUtilities
|
||||||
|
import org.thoughtcrime.securesms.loki.toPx
|
||||||
|
import org.thoughtcrime.securesms.recipients.Recipient
|
||||||
|
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||||
|
import org.whispersystems.signalservice.loki.utilities.PublicKeyValidation
|
||||||
|
|
||||||
|
|
||||||
|
class QRCodeActivity : PassphraseRequiredActionBarActivity(), ScanQRCodeWrapperFragmentDelegate {
|
||||||
|
private val adapter = QRCodeActivityAdapter(this)
|
||||||
|
|
||||||
|
// region Lifecycle
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?, isReady: Boolean) {
|
||||||
|
super.onCreate(savedInstanceState, isReady)
|
||||||
|
// Set content view
|
||||||
|
setContentView(R.layout.activity_qr_code)
|
||||||
|
// Set title
|
||||||
|
supportActionBar!!.title = "QR Code"
|
||||||
|
// Set up view pager
|
||||||
|
viewPager.adapter = adapter
|
||||||
|
tabLayout.setupWithViewPager(viewPager)
|
||||||
|
}
|
||||||
|
// endregion
|
||||||
|
|
||||||
|
// region Interaction
|
||||||
|
override fun handleQRCodeScanned(hexEncodedPublicKey: String) {
|
||||||
|
createPrivateChatIfPossible(hexEncodedPublicKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun createPrivateChatIfPossible(hexEncodedPublicKey: String) {
|
||||||
|
if (!PublicKeyValidation.isValid(hexEncodedPublicKey)) { return Toast.makeText(this, "Invalid Session ID", Toast.LENGTH_SHORT).show() }
|
||||||
|
val masterHexEncodedPublicKey = TextSecurePreferences.getMasterHexEncodedPublicKey(this)
|
||||||
|
val userHexEncodedPublicKey = TextSecurePreferences.getLocalNumber(this)
|
||||||
|
val targetHexEncodedPublicKey = if (hexEncodedPublicKey == masterHexEncodedPublicKey) userHexEncodedPublicKey else hexEncodedPublicKey
|
||||||
|
val recipient = Recipient.from(this, Address.fromSerialized(targetHexEncodedPublicKey), true)
|
||||||
|
val intent = Intent(this, ConversationActivity::class.java)
|
||||||
|
intent.putExtra(ConversationActivity.ADDRESS_EXTRA, recipient.address)
|
||||||
|
intent.putExtra(ConversationActivity.TEXT_EXTRA, getIntent().getStringExtra(ConversationActivity.TEXT_EXTRA))
|
||||||
|
intent.setDataAndType(getIntent().data, getIntent().type)
|
||||||
|
val existingThread = DatabaseFactory.getThreadDatabase(this).getThreadIdIfExistsFor(recipient)
|
||||||
|
intent.putExtra(ConversationActivity.THREAD_ID_EXTRA, existingThread)
|
||||||
|
intent.putExtra(ConversationActivity.DISTRIBUTION_TYPE_EXTRA, ThreadDatabase.DistributionTypes.DEFAULT)
|
||||||
|
startActivity(intent)
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
// endregion
|
||||||
|
}
|
||||||
|
|
||||||
|
// region Adapter
|
||||||
|
private class QRCodeActivityAdapter(val activity: QRCodeActivity) : FragmentPagerAdapter(activity.supportFragmentManager) {
|
||||||
|
|
||||||
|
override fun getCount(): Int {
|
||||||
|
return 2
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getItem(index: Int): Fragment {
|
||||||
|
return when (index) {
|
||||||
|
0 -> ViewMyQRCodeFragment()
|
||||||
|
1 -> {
|
||||||
|
val result = ScanQRCodeWrapperFragment()
|
||||||
|
result.delegate = activity
|
||||||
|
result.message = "Scan someone\'s QR code to start a conversation with them"
|
||||||
|
result
|
||||||
|
}
|
||||||
|
else -> throw IllegalStateException()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getPageTitle(index: Int): CharSequence? {
|
||||||
|
return when (index) {
|
||||||
|
0 -> "View My QR Code"
|
||||||
|
1 -> "Scan QR Code"
|
||||||
|
else -> throw IllegalStateException()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// endregion
|
||||||
|
|
||||||
|
// region View My QR Code Fragment
|
||||||
|
class ViewMyQRCodeFragment : Fragment() {
|
||||||
|
|
||||||
|
private val hexEncodedPublicKey: String
|
||||||
|
get() {
|
||||||
|
val masterHexEncodedPublicKey = TextSecurePreferences.getMasterHexEncodedPublicKey(context!!)
|
||||||
|
val userHexEncodedPublicKey = TextSecurePreferences.getLocalNumber(context!!)
|
||||||
|
return masterHexEncodedPublicKey ?: userHexEncodedPublicKey
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
|
||||||
|
return inflater.inflate(R.layout.fragment_view_my_qr_code, container, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
val size = toPx(240, resources)
|
||||||
|
val qrCode = QRCodeUtilities.encode(hexEncodedPublicKey, size)
|
||||||
|
qrCodeImageView.setImageBitmap(qrCode)
|
||||||
|
val explanation = SpannableStringBuilder("This is your unique public QR code. Other users may scan this in order to begin a conversation with you.")
|
||||||
|
explanation.setSpan(StyleSpan(Typeface.BOLD), 8, 34, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||||
|
explanationTextView.text = explanation
|
||||||
|
shareButton.setOnClickListener { shareQRCode() }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun shareQRCode() {
|
||||||
|
// TODO: Implement
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// endregion
|
@ -12,6 +12,7 @@ import kotlinx.android.synthetic.main.activity_settings.*
|
|||||||
import network.loki.messenger.R
|
import network.loki.messenger.R
|
||||||
import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity
|
import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity
|
||||||
import org.thoughtcrime.securesms.database.DatabaseFactory
|
import org.thoughtcrime.securesms.database.DatabaseFactory
|
||||||
|
import org.thoughtcrime.securesms.loki.redesign.utilities.push
|
||||||
import org.thoughtcrime.securesms.mms.GlideApp
|
import org.thoughtcrime.securesms.mms.GlideApp
|
||||||
import org.thoughtcrime.securesms.mms.GlideRequests
|
import org.thoughtcrime.securesms.mms.GlideRequests
|
||||||
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
import org.thoughtcrime.securesms.util.TextSecurePreferences
|
||||||
@ -67,7 +68,8 @@ class SettingsActivity : PassphraseRequiredActionBarActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun showQRCode() {
|
private fun showQRCode() {
|
||||||
// TODO: Implement
|
val intent = Intent(this, QRCodeActivity::class.java)
|
||||||
|
push(intent)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun copyPublicKey() {
|
private fun copyPublicKey() {
|
||||||
|
@ -35,7 +35,11 @@ class ScanQRCodeFragmentV2 : Fragment() {
|
|||||||
super.onResume()
|
super.onResume()
|
||||||
cameraView.onResume()
|
cameraView.onResume()
|
||||||
cameraView.setPreviewCallback(scanningThread)
|
cameraView.setPreviewCallback(scanningThread)
|
||||||
scanningThread.start()
|
try {
|
||||||
|
scanningThread.start()
|
||||||
|
} catch (exception: Exception) {
|
||||||
|
// Do nothing
|
||||||
|
}
|
||||||
scanningThread.setScanListener(scanListener)
|
scanningThread.setScanListener(scanListener)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,31 @@
|
|||||||
|
package org.thoughtcrime.securesms.loki.redesign.utilities
|
||||||
|
|
||||||
|
import android.graphics.Bitmap
|
||||||
|
import android.graphics.Color
|
||||||
|
import com.google.zxing.BarcodeFormat
|
||||||
|
import com.google.zxing.EncodeHintType
|
||||||
|
import com.google.zxing.WriterException
|
||||||
|
import com.google.zxing.qrcode.QRCodeWriter
|
||||||
|
|
||||||
|
object QRCodeUtilities {
|
||||||
|
|
||||||
|
fun encode(data: String, size: Int, hasTransparentBackground: Boolean = true): Bitmap {
|
||||||
|
try {
|
||||||
|
val hints = hashMapOf( EncodeHintType.MARGIN to 1 )
|
||||||
|
val result = QRCodeWriter().encode(data, BarcodeFormat.QR_CODE, size, size, hints)
|
||||||
|
val bitmap = Bitmap.createBitmap(result.width, result.height, Bitmap.Config.ARGB_8888)
|
||||||
|
for (y in 0 until result.height) {
|
||||||
|
for (x in 0 until result.width) {
|
||||||
|
if (result.get(x, y)) {
|
||||||
|
bitmap.setPixel(x, y, Color.WHITE)
|
||||||
|
} else if (!hasTransparentBackground) {
|
||||||
|
bitmap.setPixel(x, y, Color.BLACK)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return bitmap
|
||||||
|
} catch (e: WriterException) {
|
||||||
|
return Bitmap.createBitmap(512, 512, Bitmap.Config.ARGB_8888)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -15,7 +15,7 @@ import org.thoughtcrime.securesms.loki.JazzIdenticonDrawable
|
|||||||
import org.thoughtcrime.securesms.mms.GlideRequests
|
import org.thoughtcrime.securesms.mms.GlideRequests
|
||||||
import org.thoughtcrime.securesms.recipients.Recipient
|
import org.thoughtcrime.securesms.recipients.Recipient
|
||||||
|
|
||||||
// TODO: Look into a better way of handling different sizes
|
// TODO: Look into a better way of handling different sizes. Maybe an enum (with associated values) encapsulating the different modes?
|
||||||
|
|
||||||
class ProfilePictureView : RelativeLayout {
|
class ProfilePictureView : RelativeLayout {
|
||||||
lateinit var glide: GlideRequests
|
lateinit var glide: GlideRequests
|
||||||
|
Loading…
x
Reference in New Issue
Block a user