Implement join public chat screen redesign

This commit is contained in:
Niels Andriesse 2019-12-18 15:25:23 +01:00
parent 6dbe9b0ca9
commit 95dc4e6590
12 changed files with 281 additions and 66 deletions

View File

@ -143,8 +143,12 @@
android:name="org.thoughtcrime.securesms.loki.redesign.activities.HomeActivity"
android:launchMode="singleTask" />
<activity
android:name="org.thoughtcrime.securesms.loki.redesign.activities.NewPrivateChatActivity"
android:name="org.thoughtcrime.securesms.loki.redesign.activities.CreatePrivateChatActivity"
android:launchMode="singleTask" />
<activity
android:name="org.thoughtcrime.securesms.loki.redesign.activities.JoinPublicChatActivity"
android:launchMode="singleTask"
android:windowSoftInputMode="adjustResize" />
<!-- Session -->
<activity android:name="org.thoughtcrime.securesms.loki.LinkedDevicesActivity" />
<activity

View File

@ -0,0 +1,4 @@
<vector android:height="24dp" android:viewportHeight="25"
android:viewportWidth="25" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FFFFFF" android:pathData="M12.5,0.61C5.94,0.61 0.61,5.94 0.61,12.5S5.94,24.39 12.5,24.39s11.89,-5.34 11.89,-11.89S19.06,0.61 12.5,0.61zM2.35,13.35h3.41c0.05,1.35 0.22,2.64 0.5,3.82H3.45C2.85,16.01 2.46,14.72 2.35,13.35zM13.35,6.13V2.47c1.22,0.44 2.3,1.78 3.07,3.66H13.35zM16.98,7.83c0.31,1.17 0.51,2.46 0.57,3.82h-4.19V7.83H16.98zM11.65,2.47v3.66H8.58C9.35,4.24 10.43,2.9 11.65,2.47zM11.65,7.83v3.82H7.46C7.52,10.29 7.72,9 8.02,7.83H11.65zM5.76,11.65H2.35c0.11,-1.37 0.5,-2.66 1.1,-3.82h2.81C5.98,9.01 5.81,10.3 5.76,11.65zM7.46,13.35h4.19v3.82H8.02C7.72,16 7.52,14.71 7.46,13.35zM11.65,18.87v3.66c-1.22,-0.44 -2.3,-1.78 -3.07,-3.66H11.65zM13.35,22.53v-3.66h3.07C15.65,20.76 14.57,22.1 13.35,22.53zM13.35,17.17v-3.82h4.19c-0.06,1.36 -0.26,2.65 -0.57,3.82H13.35zM19.24,13.35h3.41c-0.11,1.37 -0.5,2.66 -1.1,3.82h-2.81C19.02,15.99 19.19,14.7 19.24,13.35zM19.24,11.65c-0.05,-1.35 -0.22,-2.64 -0.5,-3.82h2.81c0.6,1.16 0.99,2.45 1.1,3.82H19.24zM20.45,6.13h-2.21c-0.38,-1.08 -0.86,-2.05 -1.42,-2.85C18.23,3.94 19.47,4.92 20.45,6.13zM8.18,3.28c-0.56,0.8 -1.03,1.77 -1.42,2.85H4.56C5.53,4.92 6.77,3.94 8.18,3.28zM4.55,18.87h2.21c0.38,1.08 0.86,2.05 1.42,2.85C6.77,21.06 5.53,20.08 4.55,18.87zM16.82,21.72c0.56,-0.8 1.03,-1.77 1.42,-2.85h2.21C19.47,20.08 18.23,21.06 16.82,21.72z"/>
</vector>

View 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>

View File

@ -0,0 +1,47 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/contentView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/default_session_background"
android:orientation="vertical">
<EditText
style="@style/SessionEditText"
android:id="@+id/chatURLEditText"
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:hint="https://chat.lokinet.org" />
<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/small_font_size"
android:textColor="@color/text"
android:alpha="0.6"
android:textAlignment="center"
android:text="Enter the URL of the public chat you'd like to join" />
<View
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_weight="1" />
<Button
style="@style/MediumProminentOutlineButton"
android:id="@+id/joinPublicChatButton"
android:layout_width="match_parent"
android:layout_height="@dimen/medium_button_height"
android:layout_marginLeft="90dp"
android:layout_marginRight="90dp"
android:layout_marginBottom="@dimen/medium_spacing"
android:text="Next" />
</LinearLayout>

View File

@ -24,7 +24,7 @@
android:layout_height="0dp"/>
<TextView
android:id="@+id/descriptionTextView"
android:id="@+id/messageTextView"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"

12
res/menu/menu_home.xml Normal file
View File

@ -0,0 +1,12 @@
<?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/joinPublicChatItem"
android:title="Join Public Chat"
android:icon="@drawable/ic_globe"
app:showAsAction="always" />
</menu>

View File

@ -1,22 +1,17 @@
package org.thoughtcrime.securesms.loki.redesign.activities
import android.Manifest
import android.content.ClipData
import android.content.ClipboardManager
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.os.Bundle
import android.support.v4.app.Fragment
import android.support.v4.app.FragmentManager
import android.support.v4.app.FragmentPagerAdapter
import android.support.v4.content.ContextCompat
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import com.tbruyelle.rxpermissions2.RxPermissions
import kotlinx.android.synthetic.main.activity_new_private_chat.*
import kotlinx.android.synthetic.main.activity_create_private_chat.*
import kotlinx.android.synthetic.main.fragment_enter_public_key.*
import network.loki.messenger.R
import org.thoughtcrime.securesms.BaseActionBarActivity
@ -24,22 +19,20 @@ 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.ScanQRCodeFragmentV2
import org.thoughtcrime.securesms.loki.redesign.fragments.ScanQRCodePlaceholderFragment
import org.thoughtcrime.securesms.loki.redesign.fragments.ScanQRCodePlaceholderFragmentDelegate
import org.thoughtcrime.securesms.qr.ScanListener
import org.thoughtcrime.securesms.loki.redesign.fragments.ScanQRCodeWrapperFragment
import org.thoughtcrime.securesms.loki.redesign.fragments.ScanQRCodeWrapperFragmentDelegate
import org.thoughtcrime.securesms.recipients.Recipient
import org.thoughtcrime.securesms.util.TextSecurePreferences
import org.whispersystems.signalservice.loki.utilities.PublicKeyValidation
class NewPrivateChatActivity : BaseActionBarActivity() {
private val adapter = Adapter(supportFragmentManager)
class CreatePrivateChatActivity : BaseActionBarActivity(), ScanQRCodeWrapperFragmentDelegate {
private val adapter = CreatePrivateChatActivityAdapter(this)
// region Lifecycle
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Set content view
setContentView(R.layout.activity_new_private_chat)
setContentView(R.layout.activity_create_private_chat)
// Set title
supportActionBar!!.title = "New Conversation"
// Set up view pager
@ -49,6 +42,10 @@ class NewPrivateChatActivity : BaseActionBarActivity() {
// 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)
@ -69,7 +66,7 @@ class NewPrivateChatActivity : BaseActionBarActivity() {
}
// region Adapter
private class Adapter(manager: FragmentManager) : FragmentPagerAdapter(manager) {
private class CreatePrivateChatActivityAdapter(val activity: CreatePrivateChatActivity) : FragmentPagerAdapter(activity.supportFragmentManager) {
override fun getCount(): Int {
return 2
@ -78,7 +75,12 @@ private class Adapter(manager: FragmentManager) : FragmentPagerAdapter(manager)
override fun getItem(index: Int): Fragment {
return when (index) {
0 -> EnterPublicKeyFragment()
1 -> ScanQRCodeWrapperFragment()
1 -> {
val result = ScanQRCodeWrapperFragment()
result.delegate = activity
result.message = "Users can share their QR code by going into their account settings and tapping &quot;Share QR Code&quot;"
result
}
else -> throw IllegalStateException()
}
}
@ -95,6 +97,7 @@ private class Adapter(manager: FragmentManager) : FragmentPagerAdapter(manager)
// region Enter Public Key Fragment
class EnterPublicKeyFragment : Fragment() {
private val hexEncodedPublicKey: String
get() {
val masterHexEncodedPublicKey = TextSecurePreferences.getMasterHexEncodedPublicKey(context!!)
@ -131,51 +134,7 @@ class EnterPublicKeyFragment : Fragment() {
private fun createPrivateChatIfPossible() {
val hexEncodedPublicKey = publicKeyEditText.text.trim().toString()
(activity!! as NewPrivateChatActivity).createPrivateChatIfPossible(hexEncodedPublicKey)
(activity!! as CreatePrivateChatActivity).createPrivateChatIfPossible(hexEncodedPublicKey)
}
}
// endregion
// region Scan QR Code Wrapper Fragment
class ScanQRCodeWrapperFragment : Fragment(), ScanQRCodePlaceholderFragmentDelegate, ScanListener {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_scan_qr_code_wrapper, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
update()
}
private fun update() {
val fragment: Fragment
if (ContextCompat.checkSelfPermission(activity!!, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) {
val scanQRCodeFragment = ScanQRCodeFragmentV2()
scanQRCodeFragment.scanListener = this
fragment = scanQRCodeFragment
} else {
val scanQRCodePlaceholderFragment = ScanQRCodePlaceholderFragment()
scanQRCodePlaceholderFragment.delegate = this
fragment = scanQRCodePlaceholderFragment
}
val transaction = childFragmentManager.beginTransaction()
transaction.replace(R.id.fragmentContainer, fragment)
transaction.commit()
}
override fun requestCameraAccess() {
@SuppressWarnings("unused")
val unused = RxPermissions(this).request(Manifest.permission.CAMERA).subscribe { isGranted ->
if (isGranted) {
update()
}
}
}
override fun onQrDataFound(hexEncodedPublicKey: String) {
val activity = activity!! as NewPrivateChatActivity
activity.createPrivateChatIfPossible(hexEncodedPublicKey)
}
}
// endregion

View File

@ -3,6 +3,8 @@ package org.thoughtcrime.securesms.loki.redesign.activities
import android.content.Intent
import android.os.Bundle
import android.support.v7.widget.LinearLayoutManager
import android.view.Menu
import android.view.MenuItem
import kotlinx.android.synthetic.main.activity_home.*
import network.loki.messenger.R
import org.thoughtcrime.securesms.ApplicationContext
@ -42,8 +44,23 @@ class HomeActivity : PassphraseRequiredActionBarActivity, ConversationClickListe
application.startRSSFeedPollersIfNeeded()
}
}
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
menuInflater.inflate(R.menu.menu_home, menu)
return true
}
// endregion
// region Interaction
override fun onOptionsItemSelected(item: MenuItem): Boolean {
val id = item.getItemId()
when (id) {
R.id.joinPublicChatItem -> joinPublicChat()
else -> { /* Do nothing */ }
}
return super.onOptionsItemSelected(item)
}
override fun onConversationClick(view: ConversationView) {
val thread = view.thread ?: return
openConversation(thread)
@ -65,7 +82,13 @@ class HomeActivity : PassphraseRequiredActionBarActivity, ConversationClickListe
}
private fun createPrivateChat() {
val intent = Intent(this, NewPrivateChatActivity::class.java)
val intent = Intent(this, CreatePrivateChatActivity::class.java)
startActivity(intent)
}
private fun joinPublicChat() {
val intent = Intent(this, JoinPublicChatActivity::class.java)
startActivity(intent)
}
// endregion
}

View File

@ -0,0 +1,90 @@
package org.thoughtcrime.securesms.loki.redesign.activities
import android.os.Bundle
import android.support.v4.app.Fragment
import android.support.v4.app.FragmentPagerAdapter
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import kotlinx.android.synthetic.main.activity_join_public_chat.*
import kotlinx.android.synthetic.main.fragment_enter_chat_url.*
import network.loki.messenger.R
import org.thoughtcrime.securesms.BaseActionBarActivity
import org.thoughtcrime.securesms.loki.redesign.fragments.ScanQRCodeWrapperFragment
import org.thoughtcrime.securesms.loki.redesign.fragments.ScanQRCodeWrapperFragmentDelegate
class JoinPublicChatActivity : BaseActionBarActivity(), ScanQRCodeWrapperFragmentDelegate {
private val adapter = JoinPublicChatActivityAdapter(this)
// region Lifecycle
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Set content view
setContentView(R.layout.activity_join_public_chat)
// Set title
supportActionBar!!.title = "Join Public Chat"
// Set up view pager
viewPager.adapter = adapter
tabLayout.setupWithViewPager(viewPager)
}
// endregion
// region Interaction
override fun handleQRCodeScanned(url: String) {
joinPublicChatIfPossible(url)
}
fun joinPublicChatIfPossible(url: String) {
// TODO: Implement
}
// endregion
}
// region Adapter
private class JoinPublicChatActivityAdapter(val activity: JoinPublicChatActivity) : FragmentPagerAdapter(activity.supportFragmentManager) {
override fun getCount(): Int {
return 2
}
override fun getItem(index: Int): Fragment {
return when (index) {
0 -> EnterChatURLFragment()
1 -> {
val result = ScanQRCodeWrapperFragment()
result.delegate = activity
result.message = "Scan the QR code of the public chat you'd like to join"
result
}
else -> throw IllegalStateException()
}
}
override fun getPageTitle(index: Int): CharSequence? {
return when (index) {
0 -> "Enter Chat URL"
1 -> "Scan QR Code"
else -> throw IllegalStateException()
}
}
}
// endregion
// region Enter Public Key Fragment
class EnterChatURLFragment : Fragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
return inflater.inflate(R.layout.fragment_enter_chat_url, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
joinPublicChatButton.setOnClickListener { joinPublicChatIfPossible() }
}
private fun joinPublicChatIfPossible() {
val chatURL = chatURLEditText.text.trim().toString()
(activity!! as JoinPublicChatActivity).joinPublicChatIfPossible(chatURL)
}
}
// endregion

View File

@ -7,16 +7,16 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.LinearLayout
import kotlinx.android.synthetic.main.fragment_scan_qr_code.*
import kotlinx.android.synthetic.main.fragment_scan_qr_code_v2.*
import network.loki.messenger.R
import org.thoughtcrime.securesms.qr.ScanListener
import org.thoughtcrime.securesms.qr.ScanningThread
class ScanQRCodeFragmentV2 : Fragment() {
private val scanningThread = ScanningThread()
private var viewCreated = false
var scanListener: ScanListener? = null
set(value) { field = value; scanningThread.setScanListener(scanListener) }
var message: CharSequence = ""
override fun onCreateView(layoutInflater: LayoutInflater, viewGroup: ViewGroup?, bundle: Bundle?): View? {
return layoutInflater.inflate(R.layout.fragment_scan_qr_code_v2, viewGroup, false)
@ -24,11 +24,11 @@ class ScanQRCodeFragmentV2 : Fragment() {
override fun onViewCreated(view: View, bundle: Bundle?) {
super.onViewCreated(view, bundle)
viewCreated = true
when (resources.configuration.orientation) {
Configuration.ORIENTATION_LANDSCAPE -> overlayView.orientation = LinearLayout.HORIZONTAL
else -> overlayView.orientation = LinearLayout.VERTICAL
}
messageTextView.text = message
}
override fun onResume() {

View File

@ -0,0 +1,62 @@
package org.thoughtcrime.securesms.loki.redesign.fragments
import android.Manifest
import android.content.pm.PackageManager
import android.os.Bundle
import android.support.v4.app.Fragment
import android.support.v4.content.ContextCompat
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.tbruyelle.rxpermissions2.RxPermissions
import network.loki.messenger.R
import org.thoughtcrime.securesms.qr.ScanListener
class ScanQRCodeWrapperFragment : Fragment(), ScanQRCodePlaceholderFragmentDelegate, ScanListener {
var delegate: ScanQRCodeWrapperFragmentDelegate? = null
var message: CharSequence = ""
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_scan_qr_code_wrapper, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
update()
}
private fun update() {
val fragment: Fragment
if (ContextCompat.checkSelfPermission(activity!!, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) {
val scanQRCodeFragment = ScanQRCodeFragmentV2()
scanQRCodeFragment.scanListener = this
scanQRCodeFragment.message = message
fragment = scanQRCodeFragment
} else {
val scanQRCodePlaceholderFragment = ScanQRCodePlaceholderFragment()
scanQRCodePlaceholderFragment.delegate = this
fragment = scanQRCodePlaceholderFragment
}
val transaction = childFragmentManager.beginTransaction()
transaction.replace(R.id.fragmentContainer, fragment)
transaction.commit()
}
override fun requestCameraAccess() {
@SuppressWarnings("unused")
val unused = RxPermissions(this).request(Manifest.permission.CAMERA).subscribe { isGranted ->
if (isGranted) {
update()
}
}
}
override fun onQrDataFound(string: String) {
delegate?.handleQRCodeScanned(string)
}
}
interface ScanQRCodeWrapperFragmentDelegate {
fun handleQRCodeScanned(string: String)
}