Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
A
Android
Project overview
Project overview
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
3
Issues
3
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Pattle
Android
Commits
5257d66b
Commit
5257d66b
authored
Mar 17, 2019
by
Wilko Manger
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add ability to scroll up and view history
parent
39de2eeb
Pipeline
#268
passed with stages
in 3 minutes and 6 seconds
Changes
12
Pipelines
1
Show whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
159 additions
and
9 deletions
+159
-9
app/src/main/kotlin/im/pattle/app/data/chat/event/ChatEventRemoteSource.kt
...in/im/pattle/app/data/chat/event/ChatEventRemoteSource.kt
+54
-5
app/src/main/kotlin/im/pattle/app/data/chat/event/ChatEventRepository.kt
...tlin/im/pattle/app/data/chat/event/ChatEventRepository.kt
+3
-0
app/src/main/kotlin/im/pattle/app/data/chat/event/ChatEventSource.kt
...n/kotlin/im/pattle/app/data/chat/event/ChatEventSource.kt
+2
-0
app/src/main/kotlin/im/pattle/app/data/chat/event/model/ChatEvent.kt
...n/kotlin/im/pattle/app/data/chat/event/model/ChatEvent.kt
+11
-1
app/src/main/kotlin/im/pattle/app/data/chat/event/model/ChatMessage.kt
...kotlin/im/pattle/app/data/chat/event/model/ChatMessage.kt
+5
-1
app/src/main/kotlin/im/pattle/app/data/chat/event/model/ChatNotice.kt
.../kotlin/im/pattle/app/data/chat/event/model/ChatNotice.kt
+3
-1
app/src/main/kotlin/im/pattle/app/data/chat/event/model/MemberChangeEvent.kt
.../im/pattle/app/data/chat/event/model/MemberChangeEvent.kt
+2
-0
app/src/main/kotlin/im/pattle/app/data/chat/event/model/TypingEvent.kt
...kotlin/im/pattle/app/data/chat/event/model/TypingEvent.kt
+6
-0
app/src/main/kotlin/im/pattle/app/ui/main/chat/ChatFragment.kt
...rc/main/kotlin/im/pattle/app/ui/main/chat/ChatFragment.kt
+22
-1
app/src/main/kotlin/im/pattle/app/ui/main/chat/ChatViewModel.kt
...c/main/kotlin/im/pattle/app/ui/main/chat/ChatViewModel.kt
+3
-0
app/src/main/kotlin/im/pattle/app/ui/util/PaginatingScrollListener.kt
.../kotlin/im/pattle/app/ui/util/PaginatingScrollListener.kt
+32
-0
app/src/main/res/layout/fragment_chat.xml
app/src/main/res/layout/fragment_chat.xml
+16
-0
No files found.
app/src/main/kotlin/im/pattle/app/data/chat/event/ChatEventRemoteSource.kt
View file @
5257d66b
...
...
@@ -19,6 +19,7 @@
*/
package
im.pattle.app.data.chat.event
import
android.util.Log
import
im.pattle.app.data.chat.event.model.*
import
im.pattle.app.data.sync.SyncManager
import
im.pattle.app.sdk.Matrix
...
...
@@ -27,6 +28,7 @@ import io.reactivex.Flowable
import
org.matrix.androidsdk.data.RoomState
import
org.matrix.androidsdk.data.timeline.EventTimeline
import
org.matrix.androidsdk.listeners.MXEventListener
import
org.matrix.androidsdk.rest.callback.ApiCallback
import
org.matrix.androidsdk.rest.callback.SimpleApiCallback
import
org.matrix.androidsdk.rest.model.Event
import
org.matrix.androidsdk.rest.model.TokensChunkEvents
...
...
@@ -37,7 +39,17 @@ class ChatEventRemoteSource(private val matrix: Matrix,
private
val
syncManager
:
SyncManager
)
:
ChatEventSource
{
/**
* Unsorted collection of alle events that are in memory right now.
*/
private
val
roomEvents
=
mutableMapOf
<
String
,
MutableList
<
ChatEvent
>>()
private
fun
eventsForRoom
(
chatId
:
String
):
MutableList
<
ChatEvent
>
{
if
(
roomEvents
[
chatId
]
==
null
)
{
roomEvents
[
chatId
]
=
mutableListOf
()
}
return
roomEvents
[
chatId
]
!!
}
fun
send
(
chatId
:
String
,
message
:
Message
)
{
...
...
@@ -54,11 +66,7 @@ class ChatEventRemoteSource(private val matrix: Matrix,
@Suppress
(
"UNCHECKED_CAST"
)
override
fun
getChatEvents
(
chatId
:
String
):
Flowable
<
List
<
ChatEvent
>>
{
val
dataHandler
=
matrix
.
dataHandler
if
(
roomEvents
[
chatId
]
==
null
)
{
roomEvents
[
chatId
]
=
mutableListOf
()
}
val
events
=
roomEvents
[
chatId
]
!!
val
events
=
eventsForRoom
(
chatId
)
return
matrix
.
waitForInitialSync
().
andThen
(
Flowable
.
create
({
...
...
@@ -123,4 +131,45 @@ class ChatEventRemoteSource(private val matrix: Matrix,
},
BackpressureStrategy
.
BUFFER
)
)
}
override
fun
getHistoricChatEvents
(
chatId
:
String
,
from
:
ChatEvent
):
Flowable
<
List
<
ChatEvent
>>
{
return
Flowable
.
create
({
val
room
=
matrix
.
dataHandler
.
getRoom
(
chatId
)
val
token
=
from
.
original
.
mToken
if
(
token
!=
null
)
{
val
events
=
eventsForRoom
(
chatId
)
room
.
requestServerRoomHistory
(
token
,
20
,
object
:
SimpleApiCallback
<
TokensChunkEvents
>()
{
override
fun
onSuccess
(
response
:
TokensChunkEvents
?)
{
if
(
response
!=
null
)
{
for
(
event
in
response
.
chunk
)
{
// TODO: Reuse code
val
chatEvent
=
event
.
toChatEvent
(
room
)
if
(
chatEvent
!=
null
)
{
val
old
=
events
.
find
{
it
.
id
==
chatEvent
.
id
}
if
(
old
!=
null
)
{
events
.
remove
(
old
)
}
events
.
add
(
chatEvent
)
}
}
it
.
onNext
(
events
)
}
}
})
}
else
{
Log
.
e
(
"ChatEventRemoteSource"
,
"token is null"
)
}
},
BackpressureStrategy
.
BUFFER
)
}
}
app/src/main/kotlin/im/pattle/app/data/chat/event/ChatEventRepository.kt
View file @
5257d66b
...
...
@@ -28,4 +28,7 @@ class ChatEventRepository(
fun
send
(
chatId
:
String
,
message
:
Message
)
=
remoteSource
.
send
(
chatId
,
message
)
fun
getHistoricChatEvents
(
chatId
:
String
,
from
:
ChatEvent
)
=
remoteSource
.
getHistoricChatEvents
(
chatId
,
from
)
}
\ No newline at end of file
app/src/main/kotlin/im/pattle/app/data/chat/event/ChatEventSource.kt
View file @
5257d66b
...
...
@@ -25,4 +25,6 @@ import io.reactivex.Flowable
interface
ChatEventSource
{
fun
getChatEvents
(
chatId
:
String
):
Flowable
<
List
<
ChatEvent
>>
fun
getHistoricChatEvents
(
chatId
:
String
,
from
:
ChatEvent
):
Flowable
<
List
<
ChatEvent
>>
}
\ No newline at end of file
app/src/main/kotlin/im/pattle/app/data/chat/event/model/ChatEvent.kt
View file @
5257d66b
...
...
@@ -29,6 +29,10 @@ abstract class ChatEvent {
abstract
val
id
:
String
abstract
val
sentAt
:
Date
abstract
val
sender
:
User
?
/**
* Underlying Matrix SDK event.
*/
abstract
val
original
:
Event
override
fun
equals
(
other
:
Any
?):
Boolean
{
return
when
(
other
)
{
...
...
@@ -66,6 +70,7 @@ fun Event.toChatEvent(room: Room): ChatEvent? {
id
=
id
,
sentAt
=
sentAt
,
sender
=
sender
,
original
=
this
,
text
=
text
)
}
...
...
@@ -74,6 +79,7 @@ fun Event.toChatEvent(room: Room): ChatEvent? {
id
=
id
,
sentAt
=
sentAt
,
sender
=
sender
,
original
=
this
,
text
=
text
)
}
...
...
@@ -83,6 +89,7 @@ fun Event.toChatEvent(room: Room): ChatEvent? {
id
=
id
,
sentAt
=
sentAt
,
sender
=
sender
,
original
=
this
,
text
=
text
)
}
...
...
@@ -108,6 +115,7 @@ fun Event.toChatEvent(room: Room): ChatEvent? {
sentAt
=
sentAt
,
sender
=
sender
,
subject
=
subject
,
original
=
this
,
type
=
type
)
}
...
...
@@ -136,7 +144,8 @@ fun Event.toChatEvent(room: Room): ChatEvent? {
EncryptedChatMessage
(
id
=
eventId
,
sentAt
=
sentAt
,
sender
=
sender
sender
=
sender
,
original
=
this
)
}
else
->
{
...
...
@@ -144,6 +153,7 @@ fun Event.toChatEvent(room: Room): ChatEvent? {
override
val
id
=
eventId
override
val
sentAt
=
sentAt
override
val
sender
=
sender
override
val
original
=
this
@
toChatEvent
}
}
}
...
...
app/src/main/kotlin/im/pattle/app/data/chat/event/model/ChatMessage.kt
View file @
5257d66b
...
...
@@ -19,6 +19,7 @@
package
im.pattle.app.data.chat.event.model
import
im.pattle.app.data.user.User
import
org.matrix.androidsdk.rest.model.Event
import
java.util.*
enum
class
MessageType
{
...
...
@@ -34,6 +35,7 @@ interface Message {
open
class
ChatMessage
(
override
val
id
:
String
,
override
val
sentAt
:
Date
,
override
val
sender
:
User
,
override
val
original
:
Event
,
override
val
text
:
String
)
:
ChatEvent
(),
Message
{
override
val
type
=
MessageType
.
MESSAGE
}
...
...
@@ -41,4 +43,6 @@ open class ChatMessage(override val id: String,
data class
EncryptedChatMessage
(
override
val
id
:
String
,
override
val
sentAt
:
Date
,
override
val
sender
:
User
,
override
val
text
:
String
=
""
)
:
ChatMessage
(
id
,
sentAt
,
sender
,
text
)
\ No newline at end of file
override
val
original
:
Event
,
override
val
text
:
String
=
""
)
:
ChatMessage
(
id
,
sentAt
,
sender
,
original
,
text
)
\ No newline at end of file
app/src/main/kotlin/im/pattle/app/data/chat/event/model/ChatNotice.kt
View file @
5257d66b
...
...
@@ -19,12 +19,14 @@
package
im.pattle.app.data.chat.event.model
import
im.pattle.app.data.user.User
import
org.matrix.androidsdk.rest.model.Event
import
java.util.*
data class
ChatNotice
(
override
val
id
:
String
,
override
val
sentAt
:
Date
,
override
val
sender
:
User
,
override
val
original
:
Event
,
override
val
text
:
String
)
:
ChatMessage
(
id
,
sentAt
,
sender
,
text
)
{
:
ChatMessage
(
id
,
sentAt
,
sender
,
original
,
text
)
{
override
val
type
=
MessageType
.
NOTICE
}
\ No newline at end of file
app/src/main/kotlin/im/pattle/app/data/chat/event/model/MemberChangeEvent.kt
View file @
5257d66b
...
...
@@ -19,6 +19,7 @@
package
im.pattle.app.data.chat.event.model
import
im.pattle.app.data.user.User
import
org.matrix.androidsdk.rest.model.Event
import
java.util.*
enum
class
MemberChangeType
{
...
...
@@ -32,6 +33,7 @@ enum class MemberChangeType {
data class
MemberChangeEvent
(
override
val
id
:
String
,
override
val
sentAt
:
Date
,
override
val
sender
:
User
,
override
val
original
:
Event
,
val
subject
:
User
,
val
type
:
MemberChangeType
)
:
ChatEvent
()
\ No newline at end of file
app/src/main/kotlin/im/pattle/app/data/chat/event/model/TypingEvent.kt
View file @
5257d66b
package
im.pattle.app.data.chat.event.model
import
im.pattle.app.data.user.User
import
org.matrix.androidsdk.rest.model.Event
import
java.util.*
/**
...
...
@@ -20,4 +21,9 @@ data class TypingEvent(val users: List<User>) : ChatEvent() {
override
lateinit
var
sentAt
:
Date
override
val
sender
:
User
?
=
null
/**
* Should be ignored.
*/
override
lateinit
var
original
:
Event
}
\ No newline at end of file
app/src/main/kotlin/im/pattle/app/ui/main/chat/ChatFragment.kt
View file @
5257d66b
...
...
@@ -23,6 +23,8 @@ import android.os.Bundle
import
android.util.Log
import
android.view.LayoutInflater
import
android.view.View
import
android.view.View.GONE
import
android.view.View.VISIBLE
import
android.view.ViewGroup
import
android.view.WindowManager
import
androidx.appcompat.app.ActionBar
...
...
@@ -30,11 +32,13 @@ import androidx.appcompat.app.AppCompatActivity
import
androidx.navigation.fragment.findNavController
import
androidx.recyclerview.widget.LinearLayoutManager
import
im.pattle.app.R
import
im.pattle.app.data.chat.event.model.ChatEvent
import
im.pattle.app.data.chat.event.model.ChatMessage
import
im.pattle.app.data.chat.event.model.Message
import
im.pattle.app.data.chat.event.model.MessageType
import
im.pattle.app.ui.base.BaseFragment
import
im.pattle.app.ui.util.ImageLoader
import
im.pattle.app.ui.util.PaginatingScrollListener
import
im.pattle.app.ui.util.toPx
import
io.reactivex.rxkotlin.addTo
import
io.reactivex.rxkotlin.subscribeBy
...
...
@@ -67,6 +71,22 @@ class ChatFragment : BaseFragment<ChatViewModel>() {
Unit
}
private
val
onShouldPaginate
=
{
val
from
=
adapter
.
items
.
filterIsInstance
<
ChatEvent
>().
first
()
progressBar
.
visibility
=
VISIBLE
model
.
getHistoricChatEvents
(
from
)
.
subscribe
{
runOnUiThread
{
adapter
.
submitList
(
it
)
progressBar
.
visibility
=
GONE
}
}
.
addTo
(
compDisposable
)
Unit
}
override
fun
onAttach
(
context
:
Context
?)
{
super
.
onAttach
(
context
)
...
...
@@ -95,6 +115,7 @@ class ChatFragment : BaseFragment<ChatViewModel>() {
view
.
chatEventsView
.
layoutManager
=
layoutManager
view
.
chatEventsView
.
adapter
=
adapter
view
.
chatEventsView
.
addOnScrollListener
(
PaginatingScrollListener
(
onShouldPaginate
))
view
.
toolbar
.
title
=
model
.
chatName
...
...
@@ -113,7 +134,7 @@ class ChatFragment : BaseFragment<ChatViewModel>() {
onNext
=
{
runOnUiThread
{
adapter
.
submitList
(
it
)
view
.
chatEventsView
.
smoothScrollToPosition
(
adapter
.
itemCount
-
1
)
//
view.chatEventsView.smoothScrollToPosition(adapter.itemCount - 1)
}
}
)
...
...
app/src/main/kotlin/im/pattle/app/ui/main/chat/ChatViewModel.kt
View file @
5257d66b
...
...
@@ -35,5 +35,8 @@ class ChatViewModel(private val eventRepo: ChatEventRepository,
fun
getChatEvents
()
=
eventRepo
.
getChatEvents
(
chatId
)
fun
getHistoricChatEvents
(
from
:
ChatEvent
)
=
eventRepo
.
getHistoricChatEvents
(
chatId
,
from
)
fun
send
(
message
:
Message
)
=
eventRepo
.
send
(
chatId
,
message
)
}
\ No newline at end of file
app/src/main/kotlin/im/pattle/app/ui/util/PaginatingScrollListener.kt
0 → 100644
View file @
5257d66b
package
im.pattle.app.ui.util
import
android.util.Log
import
androidx.recyclerview.widget.LinearLayoutManager
import
androidx.recyclerview.widget.RecyclerView
import
androidx.recyclerview.widget.RecyclerView.SCROLL_STATE_DRAGGING
import
androidx.recyclerview.widget.RecyclerView.SCROLL_STATE_SETTLING
class
PaginatingScrollListener
(
val
onShouldPaginate
:
()
->
Unit
)
:
RecyclerView
.
OnScrollListener
()
{
private
var
scrollingUp
=
false
override
fun
onScrolled
(
recyclerView
:
RecyclerView
,
dx
:
Int
,
dy
:
Int
)
{
super
.
onScrolled
(
recyclerView
,
dx
,
dy
)
scrollingUp
=
dy
<
0
}
override
fun
onScrollStateChanged
(
recyclerView
:
RecyclerView
,
newState
:
Int
)
{
super
.
onScrollStateChanged
(
recyclerView
,
newState
)
val
layoutManager
=
recyclerView
.
layoutManager
as
LinearLayoutManager
if
(
layoutManager
.
findFirstCompletelyVisibleItemPosition
()
==
0
&&
(
newState
==
SCROLL_STATE_DRAGGING
||
newState
==
SCROLL_STATE_SETTLING
)
&&
scrollingUp
)
{
onShouldPaginate
()
Log
.
d
(
"PAGINATE!"
,
"please"
)
}
}
}
\ No newline at end of file
app/src/main/res/layout/fragment_chat.xml
View file @
5257d66b
...
...
@@ -79,4 +79,20 @@ along with Pattle. If not, see <https://www.gnu.org/licenses/>.
android:inputType=
"textAutoComplete"
/>
</com.google.android.material.textfield.TextInputLayout>
<ProgressBar
android:id=
"@+id/progressBar"
style=
"?android:attr/progressBarStyle"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_marginStart=
"8dp"
android:layout_marginLeft=
"8dp"
android:layout_marginTop=
"16dp"
android:layout_marginEnd=
"8dp"
android:layout_marginRight=
"8dp"
android:indeterminate=
"true"
android:visibility=
"gone"
app:layout_constraintEnd_toEndOf=
"parent"
app:layout_constraintStart_toStartOf=
"parent"
app:layout_constraintTop_toTopOf=
"@+id/chatEventsView"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment