Hook up home screen logic

This commit is contained in:
Niels Andriesse 2019-12-19 11:15:58 +01:00
parent 95dc4e6590
commit ded709a58b
10 changed files with 111 additions and 17 deletions

View File

@ -27,6 +27,7 @@ apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-android'
apply plugin: 'witness'
apply plugin: 'io.fabric'
apply plugin: 'kotlin-kapt'
repositories {
mavenLocal()
@ -112,6 +113,7 @@ dependencies {
implementation 'com.github.chrisbanes:PhotoView:2.1.3'
implementation 'com.github.bumptech.glide:glide:4.5.0'
annotationProcessor 'com.github.bumptech.glide:compiler:4.5.0'
kapt 'com.github.bumptech.glide:compiler:4.5.0'
implementation 'com.makeramen:roundedimageview:2.1.0'
implementation 'com.pnikosis:materialish-progress:1.5'
implementation 'org.greenrobot:eventbus:3.0.0'

View File

@ -0,0 +1,7 @@
<vector android:height="24dp" android:viewportHeight="15"
android:viewportWidth="15" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#00000000"
android:pathData="M7.5,7.5m-6.5,0a6.5,6.5 0,1 1,13 0a6.5,6.5 0,1 1,-13 0"
android:strokeColor="#FFFFFF" android:strokeWidth="1"/>
<path android:fillColor="#FFFFFF" android:pathData="M4.77,7.61c-0.15,-0.15 -0.38,-0.15 -0.53,0c-0.15,0.15 -0.15,0.38 0,0.53l1.88,1.88c0.15,0.15 0.38,0.15 0.53,0l4.13,-4.12c0.15,-0.15 0.15,-0.38 0,-0.53c-0.15,-0.15 -0.38,-0.15 -0.53,0L6.38,9.22L4.77,7.61z"/>
</vector>

View File

@ -0,0 +1,7 @@
<vector android:height="24dp" android:viewportHeight="15"
android:viewportWidth="15" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#00000000"
android:pathData="M7.5,7.5m-6.5,0a6.5,6.5 0,1 1,13 0a6.5,6.5 0,1 1,-13 0"
android:strokeColor="#FFFFFF" android:strokeWidth="1"/>
<path android:fillColor="#FFFFFF" android:pathData="M4.76,7.47c0,-0.32 0.26,-0.57 0.57,-0.57c0.32,0 0.57,0.25 0.57,0.57c0,0.31 -0.25,0.57 -0.57,0.57C5.02,8.04 4.76,7.78 4.76,7.47zM7.04,7.47c0,-0.32 0.26,-0.57 0.57,-0.57c0.32,0 0.57,0.25 0.57,0.57c0,0.31 -0.25,0.57 -0.57,0.57C7.3,8.04 7.04,7.78 7.04,7.47zM9.32,7.47c0,-0.32 0.26,-0.57 0.57,-0.57c0.32,0 0.57,0.25 0.57,0.57c0,0.31 -0.25,0.57 -0.57,0.57C9.58,8.04 9.32,7.78 9.32,7.47z"/>
</vector>

View File

@ -0,0 +1,5 @@
<vector android:height="24dp" android:viewportHeight="13"
android:viewportWidth="13" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FFFFFF" android:pathData="M6.5,6.5m-6.5,0a6.5,6.5 0,1 1,13 0a6.5,6.5 0,1 1,-13 0"/>
<path android:fillColor="#231F20" android:pathData="M3.77,6.61c-0.15,-0.15 -0.38,-0.15 -0.53,0c-0.15,0.15 -0.15,0.38 0,0.53l1.88,1.88c0.15,0.15 0.38,0.15 0.53,0L9.78,4.9c0.15,-0.15 0.15,-0.38 0,-0.53c-0.15,-0.15 -0.38,-0.15 -0.53,0L5.38,8.22L3.77,6.61z"/>
</vector>

View File

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:background="@drawable/conversation_view_background"
android:orientation="horizontal"
android:gravity="center_vertical">
@ -70,22 +70,35 @@
android:orientation="horizontal"
android:gravity="center_vertical">
<TextView
android:id="@+id/snippetTextView"
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxLines="1"
android:ellipsize="end"
android:textSize="@dimen/medium_font_size"
android:textColor="@color/text"
android:text="Sorry, gotta go fight crime again" />
android:layout_height="wrap_content">
<TextView
android:id="@+id/snippetTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxLines="1"
android:ellipsize="end"
android:textSize="@dimen/medium_font_size"
android:textColor="@color/text"
android:text="Sorry, gotta go fight crime again" />
<org.thoughtcrime.securesms.components.TypingIndicatorView
android:id="@+id/typingIndicatorView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
app:typingIndicator_tint="@color/text" />
</RelativeLayout>
<View
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_weight="1" />
<View
<ImageView
android:id="@+id/statusIndicatorImageView"
android:layout_width="@dimen/conversation_view_status_indicator_size"
android:layout_height="@dimen/conversation_view_status_indicator_size"

View File

@ -78,7 +78,7 @@ private class CreatePrivateChatActivityAdapter(val activity: CreatePrivateChatAc
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.message = "Users can share their QR code by going into their account settings and tapping \"Share QR Code\""
result
}
else -> throw IllegalStateException()

View File

@ -1,5 +1,6 @@
package org.thoughtcrime.securesms.loki.redesign.activities
import android.arch.lifecycle.Observer
import android.content.Intent
import android.os.Bundle
import android.support.v7.widget.LinearLayoutManager
@ -14,9 +15,12 @@ import org.thoughtcrime.securesms.database.DatabaseFactory
import org.thoughtcrime.securesms.database.model.ThreadRecord
import org.thoughtcrime.securesms.loki.redesign.utilities.push
import org.thoughtcrime.securesms.loki.redesign.views.ConversationView
import org.thoughtcrime.securesms.mms.GlideApp
import org.thoughtcrime.securesms.mms.GlideRequests
import org.thoughtcrime.securesms.util.TextSecurePreferences
class HomeActivity : PassphraseRequiredActionBarActivity, ConversationClickListener {
private lateinit var glide: GlideRequests
// region Lifecycle
constructor() : super()
@ -27,14 +31,25 @@ class HomeActivity : PassphraseRequiredActionBarActivity, ConversationClickListe
setContentView(R.layout.activity_home)
// Set title
supportActionBar!!.title = "Messages"
// Set up Glide
glide = GlideApp.with(this)
// Set up recycler view
val cursor = DatabaseFactory.getThreadDatabase(this).conversationList
val conversationAdapter = HomeAdapter(this, cursor)
conversationAdapter.conversationClickListener = this
recyclerView.adapter = conversationAdapter
val homeAdapter = HomeAdapter(this, cursor)
homeAdapter.glide = glide
homeAdapter.conversationClickListener = this
recyclerView.adapter = homeAdapter
recyclerView.layoutManager = LinearLayoutManager(this)
// Set up new conversation button
newConversationButton.setOnClickListener { createPrivateChat() }
// Set up typing observer
ApplicationContext.getInstance(this).typingStatusRepository.typingThreads.observe(this, object : Observer<Set<Long>> {
override fun onChanged(threadIDs: Set<Long>?) {
val adapter = recyclerView.adapter as HomeAdapter
adapter.typingThreadIDs = threadIDs ?: setOf()
}
})
// Set up public chats and RSS feeds if needed
if (TextSecurePreferences.getLocalNumber(this) != null) {
val application = ApplicationContext.getInstance(this)

View File

@ -8,9 +8,13 @@ import org.thoughtcrime.securesms.database.CursorRecyclerViewAdapter
import org.thoughtcrime.securesms.database.DatabaseFactory
import org.thoughtcrime.securesms.database.model.ThreadRecord
import org.thoughtcrime.securesms.loki.redesign.views.ConversationView
import org.thoughtcrime.securesms.mms.GlideRequests
class HomeAdapter(context: Context, cursor: Cursor) : CursorRecyclerViewAdapter<HomeAdapter.ViewHolder>(context, cursor) {
private val threadDatabase = DatabaseFactory.getThreadDatabase(context)
lateinit var glide: GlideRequests
var typingThreadIDs = setOf<Long>()
set(value) { field = value; notifyDataSetChanged() }
var conversationClickListener: ConversationClickListener? = null
class ViewHolder(val view: ConversationView) : RecyclerView.ViewHolder(view)
@ -26,7 +30,9 @@ class HomeAdapter(context: Context, cursor: Cursor) : CursorRecyclerViewAdapter<
}
override fun onBindItemViewHolder(viewHolder: ViewHolder, cursor: Cursor) {
viewHolder.view.bind(getThread(cursor)!!)
val thread = getThread(cursor)!!
val isTyping = typingThreadIDs.contains(thread.threadId)
viewHolder.view.bind(thread, isTyping, glide)
}
private fun getThread(cursor: Cursor): ThreadRecord? {

View File

@ -11,6 +11,7 @@ import network.loki.messenger.R
import org.thoughtcrime.securesms.database.model.ThreadRecord
import org.thoughtcrime.securesms.loki.LokiAPIUtilities.populateUserHexEncodedPublicKeyCacheIfNeeded
import org.thoughtcrime.securesms.loki.MentionUtilities.highlightMentions
import org.thoughtcrime.securesms.mms.GlideRequests
import org.thoughtcrime.securesms.util.DateUtils
import org.whispersystems.signalservice.loki.api.LokiAPI
import java.util.*
@ -43,7 +44,7 @@ class ConversationView : LinearLayout {
// endregion
// region Updating
fun bind(thread: ThreadRecord) {
fun bind(thread: ThreadRecord, isTyping: Boolean, glide: GlideRequests) {
this.thread = thread
populateUserHexEncodedPublicKeyCacheIfNeeded(thread.threadId, context) // FIXME: This is a terrible place to do this
unreadMessagesIndicatorView.visibility = if (thread.unreadCount > 0) View.VISIBLE else View.INVISIBLE
@ -58,6 +59,7 @@ class ConversationView : LinearLayout {
profilePictureView.additionalHexEncodedPublicKey = null
profilePictureView.isRSSFeed = false
}
profilePictureView.glide = glide
profilePictureView.update()
val senderDisplayName = if (thread.recipient.isLocalNumber) context.getString(R.string.note_to_self) else thread.recipient.name
displayNameTextView.text = senderDisplayName
@ -66,6 +68,21 @@ class ConversationView : LinearLayout {
val snippet = highlightMentions(rawSnippet, thread.threadId, context)
snippetTextView.text = snippet
snippetTextView.typeface = if (thread.unreadCount > 0) Typeface.DEFAULT_BOLD else Typeface.DEFAULT
snippetTextView.visibility = if (isTyping) View.GONE else View.VISIBLE
if (isTyping) {
typingIndicatorView.startAnimation()
} else {
typingIndicatorView.stopAnimation()
}
typingIndicatorView.visibility = if (isTyping) View.VISIBLE else View.GONE
statusIndicatorImageView.visibility = View.VISIBLE
when {
!thread.isOutgoing || thread.isVerificationStatusChange -> statusIndicatorImageView.visibility = View.GONE
thread.isFailed -> statusIndicatorImageView.setImageResource(R.drawable.ic_error)
thread.isPending -> statusIndicatorImageView.setImageResource(R.drawable.ic_circle_dot_dot_dot)
thread.isRemoteRead -> statusIndicatorImageView.setImageResource(R.drawable.ic_filled_circle_check)
else -> statusIndicatorImageView.setImageResource(R.drawable.ic_circle_check)
}
}
// endregion
}

View File

@ -4,11 +4,17 @@ import android.content.Context
import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.View
import android.widget.ImageView
import android.widget.RelativeLayout
import com.bumptech.glide.load.engine.DiskCacheStrategy
import kotlinx.android.synthetic.main.view_profile_picture.view.*
import network.loki.messenger.R
import org.thoughtcrime.securesms.database.Address
import org.thoughtcrime.securesms.mms.GlideRequests
import org.thoughtcrime.securesms.recipients.Recipient
class ProfilePictureView : RelativeLayout {
lateinit var glide: GlideRequests
var hexEncodedPublicKey: String? = null
var additionalHexEncodedPublicKey: String? = null
var isRSSFeed = false
@ -44,6 +50,22 @@ class ProfilePictureView : RelativeLayout {
doubleModeImageViewContainer.visibility = if (additionalHexEncodedPublicKey != null && !isRSSFeed) View.VISIBLE else View.INVISIBLE
singleModeImageView.visibility = if (additionalHexEncodedPublicKey == null && !isRSSFeed) View.VISIBLE else View.INVISIBLE
rssTextView.visibility = if (isRSSFeed) View.VISIBLE else View.INVISIBLE
fun setProfilePictureIfNeeded(imageView: ImageView, hexEncodedPublicKey: String) {
glide.clear(imageView)
if (hexEncodedPublicKey.isNotEmpty()) {
val signalProfilePicture = Recipient.from(context, Address.fromSerialized(hexEncodedPublicKey), false).contactPhoto
if (signalProfilePicture != null) {
glide.load(signalProfilePicture).diskCacheStrategy(DiskCacheStrategy.ALL).circleCrop().into(imageView)
} else {
imageView.setImageDrawable(null)
}
} else {
imageView.setImageDrawable(null)
}
}
setProfilePictureIfNeeded(singleModeImageView, hexEncodedPublicKey)
setProfilePictureIfNeeded(doubleModeImageView1, hexEncodedPublicKey)
setProfilePictureIfNeeded(doubleModeImageView2, additionalHexEncodedPublicKey ?: "")
}
// endregion
}