Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
A
AloqaIM-Android
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Administrator
AloqaIM-Android
Commits
8685b5dd
Commit
8685b5dd
authored
Mar 30, 2018
by
Filipe de Lima Brito
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'develop-2.x' of github.com:RocketChat/Rocket.Chat.Android into fix/login-with-oauth
parents
29355692
2176c0ce
Changes
38
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
38 changed files
with
538 additions
and
379 deletions
+538
-379
RocketChatApplication.kt
...ain/java/chat/rocket/android/app/RocketChatApplication.kt
+0
-1
ChatRoomAdapter.kt
...a/chat/rocket/android/chatroom/adapter/ChatRoomAdapter.kt
+16
-8
CommandSuggestionsAdapter.kt
...ket/android/chatroom/adapter/CommandSuggestionsAdapter.kt
+1
-1
MessageAttachmentViewHolder.kt
...t/android/chatroom/adapter/MessageAttachmentViewHolder.kt
+29
-0
PeopleSuggestionsAdapter.kt
...cket/android/chatroom/adapter/PeopleSuggestionsAdapter.kt
+33
-6
ChatRoomPresenter.kt
...rocket/android/chatroom/presentation/ChatRoomPresenter.kt
+1
-2
ActionSnackbar.kt
...in/java/chat/rocket/android/chatroom/ui/ActionSnackbar.kt
+8
-12
ChatRoomFragment.kt
.../java/chat/rocket/android/chatroom/ui/ChatRoomFragment.kt
+49
-7
AudioAttachmentViewModel.kt
...et/android/chatroom/viewmodel/AudioAttachmentViewModel.kt
+3
-2
BaseViewModel.kt
...a/chat/rocket/android/chatroom/viewmodel/BaseViewModel.kt
+1
-0
ImageAttachmentViewModel.kt
...et/android/chatroom/viewmodel/ImageAttachmentViewModel.kt
+2
-1
MessageAttachmentViewModel.kt
.../android/chatroom/viewmodel/MessageAttachmentViewModel.kt
+24
-0
MessageViewModel.kt
...hat/rocket/android/chatroom/viewmodel/MessageViewModel.kt
+1
-0
UrlPreviewViewModel.kt
.../rocket/android/chatroom/viewmodel/UrlPreviewViewModel.kt
+2
-1
VideoAttachmentViewModel.kt
...et/android/chatroom/viewmodel/VideoAttachmentViewModel.kt
+2
-1
ViewModelMapper.kt
...chat/rocket/android/chatroom/viewmodel/ViewModelMapper.kt
+50
-108
PeopleSuggestionViewModel.kt
...hatroom/viewmodel/suggestion/PeopleSuggestionViewModel.kt
+1
-1
ChatRoomsPresenter.kt
...cket/android/chatrooms/presentation/ChatRoomsPresenter.kt
+21
-6
ChatRoomsAdapter.kt
...java/chat/rocket/android/chatrooms/ui/ChatRoomsAdapter.kt
+23
-9
ChatRoomsFragment.kt
...ava/chat/rocket/android/chatrooms/ui/ChatRoomsFragment.kt
+12
-5
MessageParser.kt
...src/main/java/chat/rocket/android/helper/MessageParser.kt
+58
-159
LocalRepository.kt
...ava/chat/rocket/android/infrastructure/LocalRepository.kt
+3
-1
ProfileFragment.kt
...in/java/chat/rocket/android/profile/ui/ProfileFragment.kt
+5
-3
CompletionStrategy.kt
...roid/widget/autocompletion/strategy/CompletionStrategy.kt
+1
-0
StringMatchingCompletionStrategy.kt
...letion/strategy/regex/StringMatchingCompletionStrategy.kt
+19
-4
TrieCompletionStrategy.kt
...et/autocompletion/strategy/trie/TrieCompletionStrategy.kt
+4
-0
SuggestionsAdapter.kt
...et/android/widget/autocompletion/ui/SuggestionsAdapter.kt
+14
-3
SuggestionsView.kt
...ocket/android/widget/autocompletion/ui/SuggestionsView.kt
+17
-16
EmojiParser.kt
...main/java/chat/rocket/android/widget/emoji/EmojiParser.kt
+19
-6
EmojiRepository.kt
.../java/chat/rocket/android/widget/emoji/EmojiRepository.kt
+6
-7
EmojiTypefaceSpan.kt
...ava/chat/rocket/android/widget/emoji/EmojiTypefaceSpan.kt
+5
-5
quote_vertical_bar.xml
app/src/main/res/drawable/quote_vertical_bar.xml
+3
-1
item_message_attachment.xml
app/src/main/res/layout/item_message_attachment.xml
+70
-0
message_action_bar.xml
app/src/main/res/layout/message_action_bar.xml
+11
-0
suggestion_member_item.xml
app/src/main/res/layout/suggestion_member_item.xml
+4
-3
strings.xml
app/src/main/res/values-pt-rBR/strings.xml
+8
-0
strings.xml
app/src/main/res/values/strings.xml
+8
-0
styles.xml
app/src/main/res/values/styles.xml
+4
-0
No files found.
app/src/main/java/chat/rocket/android/app/RocketChatApplication.kt
View file @
8685b5dd
...
@@ -24,7 +24,6 @@ import chat.rocket.android.server.domain.*
...
@@ -24,7 +24,6 @@ import chat.rocket.android.server.domain.*
import
chat.rocket.android.server.domain.model.Account
import
chat.rocket.android.server.domain.model.Account
import
chat.rocket.android.widget.emoji.EmojiRepository
import
chat.rocket.android.widget.emoji.EmojiRepository
import
chat.rocket.common.model.Token
import
chat.rocket.common.model.Token
import
chat.rocket.common.util.ifNull
import
chat.rocket.core.model.Value
import
chat.rocket.core.model.Value
import
com.crashlytics.android.Crashlytics
import
com.crashlytics.android.Crashlytics
import
com.crashlytics.android.core.CrashlyticsCore
import
com.crashlytics.android.core.CrashlyticsCore
...
...
app/src/main/java/chat/rocket/android/chatroom/adapter/ChatRoomAdapter.kt
View file @
8685b5dd
...
@@ -49,6 +49,10 @@ class ChatRoomAdapter(
...
@@ -49,6 +49,10 @@ class ChatRoomAdapter(
val
view
=
parent
.
inflate
(
R
.
layout
.
message_url_preview
)
val
view
=
parent
.
inflate
(
R
.
layout
.
message_url_preview
)
UrlPreviewViewHolder
(
view
,
actionsListener
,
reactionListener
)
UrlPreviewViewHolder
(
view
,
actionsListener
,
reactionListener
)
}
}
BaseViewModel
.
ViewType
.
MESSAGE_ATTACHMENT
->
{
val
view
=
parent
.
inflate
(
R
.
layout
.
item_message_attachment
)
MessageAttachmentViewHolder
(
view
,
actionsListener
,
reactionListener
)
}
else
->
{
else
->
{
throw
InvalidParameterException
(
"TODO - implement for ${viewType.toViewType()}"
)
throw
InvalidParameterException
(
"TODO - implement for ${viewType.toViewType()}"
)
}
}
...
@@ -87,6 +91,7 @@ class ChatRoomAdapter(
...
@@ -87,6 +91,7 @@ class ChatRoomAdapter(
is
AudioAttachmentViewHolder
->
holder
.
bind
(
dataSet
[
position
]
as
AudioAttachmentViewModel
)
is
AudioAttachmentViewHolder
->
holder
.
bind
(
dataSet
[
position
]
as
AudioAttachmentViewModel
)
is
VideoAttachmentViewHolder
->
holder
.
bind
(
dataSet
[
position
]
as
VideoAttachmentViewModel
)
is
VideoAttachmentViewHolder
->
holder
.
bind
(
dataSet
[
position
]
as
VideoAttachmentViewModel
)
is
UrlPreviewViewHolder
->
holder
.
bind
(
dataSet
[
position
]
as
UrlPreviewViewModel
)
is
UrlPreviewViewHolder
->
holder
.
bind
(
dataSet
[
position
]
as
UrlPreviewViewModel
)
is
MessageAttachmentViewHolder
->
holder
.
bind
(
dataSet
[
position
]
as
MessageAttachmentViewModel
)
}
}
}
}
...
@@ -117,19 +122,22 @@ class ChatRoomAdapter(
...
@@ -117,19 +122,22 @@ class ChatRoomAdapter(
fun
updateItem
(
message
:
BaseViewModel
<
*
>)
{
fun
updateItem
(
message
:
BaseViewModel
<
*
>)
{
var
index
=
dataSet
.
indexOfLast
{
it
.
messageId
==
message
.
messageId
}
var
index
=
dataSet
.
indexOfLast
{
it
.
messageId
==
message
.
messageId
}
val
indexOf
Firs
t
=
dataSet
.
indexOfFirst
{
it
.
messageId
==
message
.
messageId
}
val
indexOf
Nex
t
=
dataSet
.
indexOfFirst
{
it
.
messageId
==
message
.
messageId
}
Timber
.
d
(
"index: $index"
)
Timber
.
d
(
"index: $index"
)
if
(
index
>
-
1
)
{
if
(
index
>
-
1
)
{
dataSet
[
index
]
=
message
dataSet
[
index
]
=
message
notifyItemChanged
(
index
)
dataSet
.
forEachIndexed
{
index
,
viewModel
->
while
(
dataSet
[
index
].
nextDownStreamMessage
!=
null
)
{
if
(
viewModel
.
messageId
==
message
.
messageId
)
{
dataSet
[
index
].
nextDownStreamMessage
!!
.
reactions
=
message
.
reactions
if
(
viewModel
.
nextDownStreamMessage
==
null
)
{
notifyItemChanged
(--
index
)
viewModel
.
reactions
=
message
.
reactions
}
notifyItemChanged
(
index
)
}
}
}
// Delete message only if current is a system message update, i.e.: Message Removed
// Delete message only if current is a system message update, i.e.: Message Removed
if
(
message
.
message
.
isSystemMessage
()
&&
indexOf
First
>
-
1
&&
indexOfFirs
t
!=
index
)
{
if
(
message
.
message
.
isSystemMessage
()
&&
indexOf
Next
>
-
1
&&
indexOfNex
t
!=
index
)
{
dataSet
.
removeAt
(
indexOf
Firs
t
)
dataSet
.
removeAt
(
indexOf
Nex
t
)
notifyItemRemoved
(
indexOf
Firs
t
)
notifyItemRemoved
(
indexOf
Nex
t
)
}
}
}
}
}
}
...
...
app/src/main/java/chat/rocket/android/chatroom/adapter/CommandSuggestionsAdapter.kt
View file @
8685b5dd
...
@@ -12,7 +12,7 @@ import chat.rocket.android.widget.autocompletion.ui.BaseSuggestionViewHolder
...
@@ -12,7 +12,7 @@ import chat.rocket.android.widget.autocompletion.ui.BaseSuggestionViewHolder
import
chat.rocket.android.widget.autocompletion.ui.SuggestionsAdapter
import
chat.rocket.android.widget.autocompletion.ui.SuggestionsAdapter
class
CommandSuggestionsAdapter
:
SuggestionsAdapter
<
CommandSuggestionsViewHolder
>(
token
=
"/"
,
class
CommandSuggestionsAdapter
:
SuggestionsAdapter
<
CommandSuggestionsViewHolder
>(
token
=
"/"
,
constraint
=
CONSTRAINT_BOUND_TO_START
,
threshold
=
UNLIMITED_RESULT_COUNT
)
{
constraint
=
CONSTRAINT_BOUND_TO_START
,
threshold
=
RESULT_COUNT_UNLIMITED
)
{
override
fun
onCreateViewHolder
(
parent
:
ViewGroup
,
viewType
:
Int
):
CommandSuggestionsViewHolder
{
override
fun
onCreateViewHolder
(
parent
:
ViewGroup
,
viewType
:
Int
):
CommandSuggestionsViewHolder
{
val
view
=
LayoutInflater
.
from
(
parent
.
context
).
inflate
(
R
.
layout
.
suggestion_command_item
,
parent
,
val
view
=
LayoutInflater
.
from
(
parent
.
context
).
inflate
(
R
.
layout
.
suggestion_command_item
,
parent
,
...
...
app/src/main/java/chat/rocket/android/chatroom/adapter/MessageAttachmentViewHolder.kt
0 → 100644
View file @
8685b5dd
package
chat.rocket.android.chatroom.adapter
import
android.text.method.LinkMovementMethod
import
android.view.View
import
chat.rocket.android.chatroom.viewmodel.MessageAttachmentViewModel
import
chat.rocket.android.widget.emoji.EmojiReactionListener
import
kotlinx.android.synthetic.main.item_message.view.*
class
MessageAttachmentViewHolder
(
itemView
:
View
,
listener
:
ActionsListener
,
reactionListener
:
EmojiReactionListener
?
=
null
)
:
BaseViewHolder
<
MessageAttachmentViewModel
>(
itemView
,
listener
,
reactionListener
)
{
init
{
with
(
itemView
)
{
text_content
.
movementMethod
=
LinkMovementMethod
()
setupActionMenu
(
text_content
)
}
}
override
fun
bindViews
(
data
:
MessageAttachmentViewModel
)
{
with
(
itemView
)
{
text_message_time
.
text
=
data
.
time
text_sender
.
text
=
data
.
senderName
text_content
.
text
=
data
.
content
}
}
}
\ No newline at end of file
app/src/main/java/chat/rocket/android/chatroom/adapter/PeopleSuggestionsAdapter.kt
View file @
8685b5dd
package
chat.rocket.android.chatroom.adapter
package
chat.rocket.android.chatroom.adapter
import
DrawableHelper
import
DrawableHelper
import
android.content.Context
import
android.view.LayoutInflater
import
android.view.LayoutInflater
import
android.view.View
import
android.view.View
import
android.view.ViewGroup
import
android.view.ViewGroup
...
@@ -13,10 +14,32 @@ import chat.rocket.android.util.extensions.setVisible
...
@@ -13,10 +14,32 @@ import chat.rocket.android.util.extensions.setVisible
import
chat.rocket.android.widget.autocompletion.model.SuggestionModel
import
chat.rocket.android.widget.autocompletion.model.SuggestionModel
import
chat.rocket.android.widget.autocompletion.ui.BaseSuggestionViewHolder
import
chat.rocket.android.widget.autocompletion.ui.BaseSuggestionViewHolder
import
chat.rocket.android.widget.autocompletion.ui.SuggestionsAdapter
import
chat.rocket.android.widget.autocompletion.ui.SuggestionsAdapter
import
chat.rocket.common.model.UserStatus
import
com.facebook.drawee.view.SimpleDraweeView
import
com.facebook.drawee.view.SimpleDraweeView
class
PeopleSuggestionsAdapter
:
SuggestionsAdapter
<
PeopleSuggestionViewHolder
>(
"@"
)
{
class
PeopleSuggestionsAdapter
(
context
:
Context
)
:
SuggestionsAdapter
<
PeopleSuggestionViewHolder
>(
"@"
)
{
init
{
val
allDescription
=
context
.
getString
(
R
.
string
.
suggest_all_description
)
val
hereDescription
=
context
.
getString
(
R
.
string
.
suggest_here_description
)
val
pinnedList
=
listOf
(
PeopleSuggestionViewModel
(
imageUri
=
null
,
text
=
"all"
,
username
=
"all"
,
name
=
allDescription
,
status
=
null
,
pinned
=
false
,
searchList
=
listOf
(
"all"
)),
PeopleSuggestionViewModel
(
imageUri
=
null
,
text
=
"here"
,
username
=
"here"
,
name
=
hereDescription
,
status
=
null
,
pinned
=
false
,
searchList
=
listOf
(
"here"
))
)
setPinnedSuggestions
(
pinnedList
)
}
override
fun
onCreateViewHolder
(
parent
:
ViewGroup
,
viewType
:
Int
):
PeopleSuggestionViewHolder
{
override
fun
onCreateViewHolder
(
parent
:
ViewGroup
,
viewType
:
Int
):
PeopleSuggestionViewHolder
{
val
view
=
LayoutInflater
.
from
(
parent
.
context
).
inflate
(
R
.
layout
.
suggestion_member_item
,
parent
,
val
view
=
LayoutInflater
.
from
(
parent
.
context
).
inflate
(
R
.
layout
.
suggestion_member_item
,
parent
,
false
)
false
)
...
@@ -34,15 +57,19 @@ class PeopleSuggestionsAdapter : SuggestionsAdapter<PeopleSuggestionViewHolder>(
...
@@ -34,15 +57,19 @@ class PeopleSuggestionsAdapter : SuggestionsAdapter<PeopleSuggestionViewHolder>(
val
statusView
=
itemView
.
findViewById
<
ImageView
>(
R
.
id
.
image_status
)
val
statusView
=
itemView
.
findViewById
<
ImageView
>(
R
.
id
.
image_status
)
username
.
text
=
item
.
username
username
.
text
=
item
.
username
name
.
text
=
item
.
name
name
.
text
=
item
.
name
if
(
item
.
imageUri
.
isEmpty
()
)
{
if
(
item
.
imageUri
?.
isEmpty
()
!=
false
)
{
avatar
.
setVisible
(
false
)
avatar
.
setVisible
(
false
)
}
else
{
}
else
{
avatar
.
setVisible
(
true
)
avatar
.
setVisible
(
true
)
avatar
.
setImageURI
(
item
.
imageUri
)
avatar
.
setImageURI
(
item
.
imageUri
)
}
}
val
status
=
item
.
status
?:
UserStatus
.
Offline
()
val
status
=
item
.
status
val
statusDrawable
=
DrawableHelper
.
getUserStatusDrawable
(
status
,
itemView
.
context
)
if
(
status
!=
null
)
{
statusView
.
setImageDrawable
(
statusDrawable
)
val
statusDrawable
=
DrawableHelper
.
getUserStatusDrawable
(
status
,
itemView
.
context
)
statusView
.
setImageDrawable
(
statusDrawable
)
}
else
{
statusView
.
setVisible
(
false
)
}
setOnClickListener
{
setOnClickListener
{
itemClickListener
?.
onClick
(
item
)
itemClickListener
?.
onClick
(
item
)
}
}
...
...
app/src/main/java/chat/rocket/android/chatroom/presentation/ChatRoomPresenter.kt
View file @
8685b5dd
...
@@ -291,7 +291,7 @@ class ChatRoomPresenter @Inject constructor(private val view: ChatRoomView,
...
@@ -291,7 +291,7 @@ class ChatRoomPresenter @Inject constructor(private val view: ChatRoomView,
view
.
showReplyingAction
(
view
.
showReplyingAction
(
username
=
user
,
username
=
user
,
replyMarkdown
=
"[ ]($serverUrl/$room/$roomName?msg=$id) $mention "
,
replyMarkdown
=
"[ ]($serverUrl/$room/$roomName?msg=$id) $mention "
,
quotedMessage
=
m
.
message
quotedMessage
=
m
apper
.
map
(
message
).
last
().
preview
?.
message
?:
""
)
)
}
}
}
}
...
@@ -499,7 +499,6 @@ class ChatRoomPresenter @Inject constructor(private val view: ChatRoomView,
...
@@ -499,7 +499,6 @@ class ChatRoomPresenter @Inject constructor(private val view: ChatRoomView,
//TODO: cache the commands
//TODO: cache the commands
val
commands
=
client
.
commands
(
0
,
100
).
result
val
commands
=
client
.
commands
(
0
,
100
).
result
view
.
populateCommandSuggestions
(
commands
.
map
{
view
.
populateCommandSuggestions
(
commands
.
map
{
println
(
"${it.command} - ${it.description}"
)
CommandSuggestionViewModel
(
it
.
command
,
it
.
description
?:
""
,
listOf
(
it
.
command
))
CommandSuggestionViewModel
(
it
.
command
,
it
.
description
?:
""
,
listOf
(
it
.
command
))
})
})
}
catch
(
ex
:
RocketChatException
)
{
}
catch
(
ex
:
RocketChatException
)
{
...
...
app/src/main/java/chat/rocket/android/chatroom/ui/ActionSnackbar.kt
View file @
8685b5dd
package
chat.rocket.android.chatroom.ui
package
chat.rocket.android.chatroom.ui
import
android.graphics.drawable.Drawable
import
android.support.design.widget.BaseTransientBottomBar
import
android.support.design.widget.BaseTransientBottomBar
import
android.support.v4.view.ViewCompat
import
android.support.v4.view.ViewCompat
import
android.text.Spannable
import
android.text.Spannable
import
android.text.SpannableStringBuilder
import
android.view.LayoutInflater
import
android.view.LayoutInflater
import
android.view.View
import
android.view.View
import
android.view.ViewGroup
import
android.view.ViewGroup
...
@@ -27,7 +27,6 @@ class ActionSnackbar : BaseTransientBottomBar<ActionSnackbar> {
...
@@ -27,7 +27,6 @@ class ActionSnackbar : BaseTransientBottomBar<ActionSnackbar> {
actionSnackbar
.
cancelView
=
view
.
findViewById
(
R
.
id
.
image_view_action_cancel_quote
)
as
ImageView
actionSnackbar
.
cancelView
=
view
.
findViewById
(
R
.
id
.
image_view_action_cancel_quote
)
as
ImageView
actionSnackbar
.
duration
=
BaseTransientBottomBar
.
LENGTH_INDEFINITE
actionSnackbar
.
duration
=
BaseTransientBottomBar
.
LENGTH_INDEFINITE
val
spannable
=
Markwon
.
markdown
(
context
,
content
).
trim
()
val
spannable
=
Markwon
.
markdown
(
context
,
content
).
trim
()
actionSnackbar
.
marginDrawable
=
context
.
getDrawable
(
R
.
drawable
.
quote
)
actionSnackbar
.
messageTextView
.
content
=
spannable
actionSnackbar
.
messageTextView
.
content
=
spannable
return
actionSnackbar
return
actionSnackbar
}
}
...
@@ -37,19 +36,16 @@ class ActionSnackbar : BaseTransientBottomBar<ActionSnackbar> {
...
@@ -37,19 +36,16 @@ class ActionSnackbar : BaseTransientBottomBar<ActionSnackbar> {
lateinit
var
cancelView
:
View
lateinit
var
cancelView
:
View
private
lateinit
var
messageTextView
:
TextView
private
lateinit
var
messageTextView
:
TextView
private
lateinit
var
titleTextView
:
TextView
private
lateinit
var
titleTextView
:
TextView
private
lateinit
var
marginDrawable
:
Drawable
var
text
:
String
=
""
var
text
:
String
=
""
set
(
value
)
{
set
(
value
)
{
val
spannable
=
parser
.
renderMarkdown
(
value
)
as
Spannable
val
spannable
=
SpannableStringBuilder
.
valueOf
(
value
)
spannable
.
setSpan
(
MessageParser
.
QuoteMarginSpan
(
marginDrawable
,
10
),
0
,
spannable
.
length
,
0
)
messageTextView
.
content
=
spannable
messageTextView
.
content
=
spannable
}
}
var
title
:
String
=
""
var
title
:
String
=
""
set
(
value
)
{
set
(
value
)
{
val
spannable
=
Markwon
.
markdown
(
this
.
context
,
value
)
as
Spannable
val
spannable
=
Markwon
.
markdown
(
this
.
context
,
value
)
as
Spannable
spannable
.
setSpan
(
MessageParser
.
QuoteMarginSpan
(
marginDrawable
,
10
),
0
,
spannable
.
length
,
0
)
titleTextView
.
content
=
spannable
titleTextView
.
content
=
spannable
}
}
...
@@ -68,17 +64,17 @@ class ActionSnackbar : BaseTransientBottomBar<ActionSnackbar> {
...
@@ -68,17 +64,17 @@ class ActionSnackbar : BaseTransientBottomBar<ActionSnackbar> {
override
fun
animateContentOut
(
delay
:
Int
,
duration
:
Int
)
{
override
fun
animateContentOut
(
delay
:
Int
,
duration
:
Int
)
{
ViewCompat
.
setScaleY
(
content
,
1f
)
ViewCompat
.
setScaleY
(
content
,
1f
)
ViewCompat
.
animate
(
content
)
ViewCompat
.
animate
(
content
)
.
scaleY
(
0f
)
.
scaleY
(
0f
)
.
setDuration
(
duration
.
toLong
())
.
setDuration
(
duration
.
toLong
())
.
startDelay
=
delay
.
toLong
()
.
startDelay
=
delay
.
toLong
()
}
}
override
fun
animateContentIn
(
delay
:
Int
,
duration
:
Int
)
{
override
fun
animateContentIn
(
delay
:
Int
,
duration
:
Int
)
{
ViewCompat
.
setScaleY
(
content
,
0f
)
ViewCompat
.
setScaleY
(
content
,
0f
)
ViewCompat
.
animate
(
content
)
ViewCompat
.
animate
(
content
)
.
scaleY
(
1f
)
.
scaleY
(
1f
)
.
setDuration
(
duration
.
toLong
())
.
setDuration
(
duration
.
toLong
())
.
startDelay
=
delay
.
toLong
()
.
startDelay
=
delay
.
toLong
()
}
}
}
}
}
}
\ No newline at end of file
app/src/main/java/chat/rocket/android/chatroom/ui/ChatRoomFragment.kt
View file @
8685b5dd
...
@@ -36,7 +36,9 @@ import kotlinx.android.synthetic.main.message_attachment_options.*
...
@@ -36,7 +36,9 @@ import kotlinx.android.synthetic.main.message_attachment_options.*
import
kotlinx.android.synthetic.main.message_composer.*
import
kotlinx.android.synthetic.main.message_composer.*
import
kotlinx.android.synthetic.main.message_list.*
import
kotlinx.android.synthetic.main.message_list.*
import
timber.log.Timber
import
timber.log.Timber
import
java.util.concurrent.atomic.AtomicInteger
import
javax.inject.Inject
import
javax.inject.Inject
import
kotlin.math.absoluteValue
fun
newInstance
(
chatRoomId
:
String
,
fun
newInstance
(
chatRoomId
:
String
,
chatRoomName
:
String
,
chatRoomName
:
String
,
...
@@ -88,6 +90,7 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
...
@@ -88,6 +90,7 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
private
val
centerX
by
lazy
{
recycler_view
.
right
}
private
val
centerX
by
lazy
{
recycler_view
.
right
}
private
val
centerY
by
lazy
{
recycler_view
.
bottom
}
private
val
centerY
by
lazy
{
recycler_view
.
bottom
}
private
val
handler
=
Handler
()
private
val
handler
=
Handler
()
private
var
verticalScrollOffset
=
AtomicInteger
(
0
)
override
fun
onCreate
(
savedInstanceState
:
Bundle
?)
{
override
fun
onCreate
(
savedInstanceState
:
Bundle
?)
{
super
.
onCreate
(
savedInstanceState
)
super
.
onCreate
(
savedInstanceState
)
...
@@ -207,13 +210,54 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
...
@@ -207,13 +210,54 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
}
}
})
})
}
}
recycler_view
.
addOnLayoutChangeListener
{
_
,
_
,
_
,
_
,
bottom
,
_
,
_
,
_
,
oldBottom
->
val
y
=
oldBottom
-
bottom
if
(
y
.
absoluteValue
>
0
)
{
// if y is positive the keyboard is up else it's down
recycler_view
.
post
{
if
(
y
>
0
||
verticalScrollOffset
.
get
().
absoluteValue
>=
y
.
absoluteValue
)
{
recycler_view
.
scrollBy
(
0
,
y
)
}
else
{
recycler_view
.
scrollBy
(
0
,
verticalScrollOffset
.
get
())
}
}
}
}
recycler_view
.
addOnScrollListener
(
object
:
RecyclerView
.
OnScrollListener
()
{
var
state
=
AtomicInteger
(
RecyclerView
.
SCROLL_STATE_IDLE
)
override
fun
onScrollStateChanged
(
recyclerView
:
RecyclerView
,
newState
:
Int
)
{
state
.
compareAndSet
(
RecyclerView
.
SCROLL_STATE_IDLE
,
newState
)
when
(
newState
)
{
RecyclerView
.
SCROLL_STATE_IDLE
->
{
if
(!
state
.
compareAndSet
(
RecyclerView
.
SCROLL_STATE_SETTLING
,
newState
))
{
state
.
compareAndSet
(
RecyclerView
.
SCROLL_STATE_DRAGGING
,
newState
)
}
}
RecyclerView
.
SCROLL_STATE_DRAGGING
->
{
state
.
compareAndSet
(
RecyclerView
.
SCROLL_STATE_IDLE
,
newState
)
}
RecyclerView
.
SCROLL_STATE_SETTLING
->
{
state
.
compareAndSet
(
RecyclerView
.
SCROLL_STATE_DRAGGING
,
newState
)
}
}
}
override
fun
onScrolled
(
recyclerView
:
RecyclerView
,
dx
:
Int
,
dy
:
Int
)
{
if
(
state
.
get
()
!=
RecyclerView
.
SCROLL_STATE_IDLE
)
{
verticalScrollOffset
.
getAndAdd
(
dy
)
}
}
})
}
}
val
oldMessagesCount
=
adapter
.
itemCount
val
oldMessagesCount
=
adapter
.
itemCount
adapter
.
appendData
(
dataSet
)
adapter
.
appendData
(
dataSet
)
recycler_view
.
scrollToPosition
(
92
)
if
(
oldMessagesCount
==
0
&&
dataSet
.
isNotEmpty
())
{
if
(
oldMessagesCount
==
0
&&
dataSet
.
isNotEmpty
())
{
recycler_view
.
scrollToPosition
(
0
)
recycler_view
.
scrollToPosition
(
0
)
verticalScrollOffset
.
set
(
0
)
}
}
presenter
.
loadActiveMembers
(
chatRoomId
,
chatRoomType
,
filterSelfOut
=
true
)
presenter
.
loadActiveMembers
(
chatRoomId
,
chatRoomType
,
filterSelfOut
=
true
)
}
}
...
@@ -241,6 +285,7 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
...
@@ -241,6 +285,7 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
override
fun
showNewMessage
(
message
:
List
<
BaseViewModel
<*
>>)
{
override
fun
showNewMessage
(
message
:
List
<
BaseViewModel
<*
>>)
{
adapter
.
prependData
(
message
)
adapter
.
prependData
(
message
)
recycler_view
.
scrollToPosition
(
0
)
recycler_view
.
scrollToPosition
(
0
)
verticalScrollOffset
.
set
(
0
)
}
}
override
fun
disableSendMessageButton
()
{
override
fun
disableSendMessageButton
()
{
...
@@ -281,6 +326,7 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
...
@@ -281,6 +326,7 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
if
(!
recycler_view
.
isAtBottom
())
{
if
(!
recycler_view
.
isAtBottom
())
{
if
(
adapter
.
itemCount
>
0
)
{
if
(
adapter
.
itemCount
>
0
)
{
recycler_view
.
scrollToPosition
(
0
)
recycler_view
.
scrollToPosition
(
0
)
verticalScrollOffset
.
set
(
0
)
}
}
}
}
}
}
...
@@ -430,6 +476,7 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
...
@@ -430,6 +476,7 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
private
fun
setupFab
()
{
private
fun
setupFab
()
{
button_fab
.
setOnClickListener
{
button_fab
.
setOnClickListener
{
recycler_view
.
scrollToPosition
(
0
)
recycler_view
.
scrollToPosition
(
0
)
verticalScrollOffset
.
set
(
0
)
button_fab
.
hide
()
button_fab
.
hide
()
}
}
}
}
...
@@ -453,11 +500,6 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
...
@@ -453,11 +500,6 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
emojiKeyboardPopup
.
listener
=
this
emojiKeyboardPopup
.
listener
=
this
text_message
.
listener
=
object
:
ComposerEditText
.
ComposerEditTextListener
{
text_message
.
listener
=
object
:
ComposerEditText
.
ComposerEditTextListener
{
override
fun
onKeyboardOpened
()
{
override
fun
onKeyboardOpened
()
{
if
(
recycler_view
.
isAtBottom
())
{
if
(
adapter
.
itemCount
>
0
)
{
recycler_view
.
scrollToPosition
(
0
)
}
}
}
}
override
fun
onKeyboardClosed
()
{
override
fun
onKeyboardClosed
()
{
...
@@ -511,7 +553,7 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
...
@@ -511,7 +553,7 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
private
fun
setupSuggestionsView
()
{
private
fun
setupSuggestionsView
()
{
suggestions_view
.
anchorTo
(
text_message
)
suggestions_view
.
anchorTo
(
text_message
)
.
setMaximumHeight
(
resources
.
getDimensionPixelSize
(
R
.
dimen
.
suggestions_box_max_height
))
.
setMaximumHeight
(
resources
.
getDimensionPixelSize
(
R
.
dimen
.
suggestions_box_max_height
))
.
addTokenAdapter
(
PeopleSuggestionsAdapter
())
.
addTokenAdapter
(
PeopleSuggestionsAdapter
(
context
!!
))
.
addTokenAdapter
(
CommandSuggestionsAdapter
())
.
addTokenAdapter
(
CommandSuggestionsAdapter
())
.
addTokenAdapter
(
RoomSuggestionsAdapter
())
.
addTokenAdapter
(
RoomSuggestionsAdapter
())
.
addSuggestionProviderAction
(
"@"
)
{
query
->
.
addSuggestionProviderAction
(
"@"
)
{
query
->
...
...
app/src/main/java/chat/rocket/android/chatroom/viewmodel/AudioAttachmentViewModel.kt
View file @
8685b5dd
...
@@ -12,8 +12,9 @@ data class AudioAttachmentViewModel(
...
@@ -12,8 +12,9 @@ data class AudioAttachmentViewModel(
override
val
attachmentTitle
:
CharSequence
,
override
val
attachmentTitle
:
CharSequence
,
override
val
id
:
Long
,
override
val
id
:
Long
,
override
var
reactions
:
List
<
ReactionViewModel
>,
override
var
reactions
:
List
<
ReactionViewModel
>,
override
var
nextDownStreamMessage
:
BaseViewModel
<*>?
=
null
override
var
nextDownStreamMessage
:
BaseViewModel
<*>?
=
null
,
)
:
BaseFileAttachmentViewModel
<
AudioAttachment
>
{
override
var
preview
:
Message
?
=
null
)
:
BaseFileAttachmentViewModel
<
AudioAttachment
>
{
override
val
viewType
:
Int
override
val
viewType
:
Int
get
()
=
BaseViewModel
.
ViewType
.
AUDIO_ATTACHMENT
.
viewType
get
()
=
BaseViewModel
.
ViewType
.
AUDIO_ATTACHMENT
.
viewType
override
val
layoutId
:
Int
override
val
layoutId
:
Int
...
...
app/src/main/java/chat/rocket/android/chatroom/viewmodel/BaseViewModel.kt
View file @
8685b5dd
...
@@ -11,6 +11,7 @@ interface BaseViewModel<out T> {
...
@@ -11,6 +11,7 @@ interface BaseViewModel<out T> {
val
layoutId
:
Int
val
layoutId
:
Int
var
reactions
:
List
<
ReactionViewModel
>
var
reactions
:
List
<
ReactionViewModel
>
var
nextDownStreamMessage
:
BaseViewModel
<*>?
var
nextDownStreamMessage
:
BaseViewModel
<*>?
var
preview
:
Message
?
enum
class
ViewType
(
val
viewType
:
Int
)
{
enum
class
ViewType
(
val
viewType
:
Int
)
{
MESSAGE
(
0
),
MESSAGE
(
0
),
...
...
app/src/main/java/chat/rocket/android/chatroom/viewmodel/ImageAttachmentViewModel.kt
View file @
8685b5dd
...
@@ -12,7 +12,8 @@ data class ImageAttachmentViewModel(
...
@@ -12,7 +12,8 @@ data class ImageAttachmentViewModel(
override
val
attachmentTitle
:
CharSequence
,
override
val
attachmentTitle
:
CharSequence
,
override
val
id
:
Long
,
override
val
id
:
Long
,
override
var
reactions
:
List
<
ReactionViewModel
>,
override
var
reactions
:
List
<
ReactionViewModel
>,
override
var
nextDownStreamMessage
:
BaseViewModel
<*>?
=
null
override
var
nextDownStreamMessage
:
BaseViewModel
<*>?
=
null
,
override
var
preview
:
Message
?
=
null
)
:
BaseFileAttachmentViewModel
<
ImageAttachment
>
{
)
:
BaseFileAttachmentViewModel
<
ImageAttachment
>
{
override
val
viewType
:
Int
override
val
viewType
:
Int
get
()
=
BaseViewModel
.
ViewType
.
IMAGE_ATTACHMENT
.
viewType
get
()
=
BaseViewModel
.
ViewType
.
IMAGE_ATTACHMENT
.
viewType
...
...
app/src/main/java/chat/rocket/android/chatroom/viewmodel/MessageAttachmentViewModel.kt
0 → 100644
View file @
8685b5dd
package
chat.rocket.android.chatroom.viewmodel
import
chat.rocket.android.R
import
chat.rocket.core.model.Message
data class
MessageAttachmentViewModel
(
override
val
message
:
Message
,
override
val
rawData
:
Message
,
override
val
messageId
:
String
,
var
senderName
:
String
,
val
time
:
CharSequence
,
val
content
:
CharSequence
,
val
isPinned
:
Boolean
,
override
var
reactions
:
List
<
ReactionViewModel
>,
override
var
nextDownStreamMessage
:
BaseViewModel
<*>?
=
null
,
var
messageLink
:
String
?
=
null
,
override
var
preview
:
Message
?
=
null
)
:
BaseViewModel
<
Message
>
{
override
val
viewType
:
Int
get
()
=
BaseViewModel
.
ViewType
.
MESSAGE_ATTACHMENT
.
viewType
override
val
layoutId
:
Int
get
()
=
R
.
layout
.
item_message_attachment
}
\ No newline at end of file
app/src/main/java/chat/rocket/android/chatroom/viewmodel/MessageViewModel.kt
View file @
8685b5dd
...
@@ -14,6 +14,7 @@ data class MessageViewModel(
...
@@ -14,6 +14,7 @@ data class MessageViewModel(
override
val
isPinned
:
Boolean
,
override
val
isPinned
:
Boolean
,
override
var
reactions
:
List
<
ReactionViewModel
>,
override
var
reactions
:
List
<
ReactionViewModel
>,
override
var
nextDownStreamMessage
:
BaseViewModel
<*>?
=
null
,
override
var
nextDownStreamMessage
:
BaseViewModel
<*>?
=
null
,
override
var
preview
:
Message
?
=
null
,
var
isFirstUnread
:
Boolean
var
isFirstUnread
:
Boolean
)
:
BaseMessageViewModel
<
Message
>
{
)
:
BaseMessageViewModel
<
Message
>
{
override
val
viewType
:
Int
override
val
viewType
:
Int
...
...
app/src/main/java/chat/rocket/android/chatroom/viewmodel/UrlPreviewViewModel.kt
View file @
8685b5dd
...
@@ -13,7 +13,8 @@ data class UrlPreviewViewModel(
...
@@ -13,7 +13,8 @@ data class UrlPreviewViewModel(
val
description
:
CharSequence
?,
val
description
:
CharSequence
?,
val
thumbUrl
:
String
?,
val
thumbUrl
:
String
?,
override
var
reactions
:
List
<
ReactionViewModel
>,
override
var
reactions
:
List
<
ReactionViewModel
>,
override
var
nextDownStreamMessage
:
BaseViewModel
<*>?
=
null
override
var
nextDownStreamMessage
:
BaseViewModel
<*>?
=
null
,
override
var
preview
:
Message
?
=
null
)
:
BaseViewModel
<
Url
>
{
)
:
BaseViewModel
<
Url
>
{
override
val
viewType
:
Int
override
val
viewType
:
Int
get
()
=
BaseViewModel
.
ViewType
.
URL_PREVIEW
.
viewType
get
()
=
BaseViewModel
.
ViewType
.
URL_PREVIEW
.
viewType
...
...
app/src/main/java/chat/rocket/android/chatroom/viewmodel/VideoAttachmentViewModel.kt
View file @
8685b5dd
...
@@ -12,7 +12,8 @@ data class VideoAttachmentViewModel(
...
@@ -12,7 +12,8 @@ data class VideoAttachmentViewModel(
override
val
attachmentTitle
:
CharSequence
,
override
val
attachmentTitle
:
CharSequence
,
override
val
id
:
Long
,
override
val
id
:
Long
,
override
var
reactions
:
List
<
ReactionViewModel
>,
override
var
reactions
:
List
<
ReactionViewModel
>,
override
var
nextDownStreamMessage
:
BaseViewModel
<*>?
=
null
override
var
nextDownStreamMessage
:
BaseViewModel
<*>?
=
null
,
override
var
preview
:
Message
?
=
null
)
:
BaseFileAttachmentViewModel
<
VideoAttachment
>
{
)
:
BaseFileAttachmentViewModel
<
VideoAttachment
>
{
override
val
viewType
:
Int
override
val
viewType
:
Int
get
()
=
BaseViewModel
.
ViewType
.
VIDEO_ATTACHMENT
.
viewType
get
()
=
BaseViewModel
.
ViewType
.
VIDEO_ATTACHMENT
.
viewType
...
...
app/src/main/java/chat/rocket/android/chatroom/viewmodel/ViewModelMapper.kt
View file @
8685b5dd
This diff is collapsed.
Click to expand it.
app/src/main/java/chat/rocket/android/chatroom/viewmodel/suggestion/PeopleSuggestionViewModel.kt
View file @
8685b5dd
...
@@ -3,7 +3,7 @@ package chat.rocket.android.chatroom.viewmodel.suggestion
...
@@ -3,7 +3,7 @@ package chat.rocket.android.chatroom.viewmodel.suggestion
import
chat.rocket.android.widget.autocompletion.model.SuggestionModel
import
chat.rocket.android.widget.autocompletion.model.SuggestionModel
import
chat.rocket.common.model.UserStatus
import
chat.rocket.common.model.UserStatus
class
PeopleSuggestionViewModel
(
val
imageUri
:
String
,
class
PeopleSuggestionViewModel
(
val
imageUri
:
String
?
,
text
:
String
,
text
:
String
,
val
username
:
String
,
val
username
:
String
,
val
name
:
String
,
val
name
:
String
,
...
...
app/src/main/java/chat/rocket/android/chatrooms/presentation/ChatRoomsPresenter.kt
View file @
8685b5dd
package
chat.rocket.android.chatrooms.presentation
package
chat.rocket.android.chatrooms.presentation
import
chat.rocket.android.chatroom.viewmodel.ViewModelMapper
import
chat.rocket.android.core.lifecycle.CancelStrategy
import
chat.rocket.android.core.lifecycle.CancelStrategy
import
chat.rocket.android.main.presentation.MainNavigator
import
chat.rocket.android.main.presentation.MainNavigator
import
chat.rocket.android.server.domain.*
import
chat.rocket.android.server.domain.*
...
@@ -9,7 +10,10 @@ import chat.rocket.android.server.infraestructure.chatRooms
...
@@ -9,7 +10,10 @@ import chat.rocket.android.server.infraestructure.chatRooms
import
chat.rocket.android.server.infraestructure.state
import
chat.rocket.android.server.infraestructure.state
import
chat.rocket.android.util.extensions.launchUI
import
chat.rocket.android.util.extensions.launchUI
import
chat.rocket.common.RocketChatException
import
chat.rocket.common.RocketChatException
import
chat.rocket.common.model.*
import
chat.rocket.common.model.BaseRoom
import
chat.rocket.common.model.RoomType
import
chat.rocket.common.model.SimpleUser
import
chat.rocket.common.model.User
import
chat.rocket.core.internal.model.Subscription
import
chat.rocket.core.internal.model.Subscription
import
chat.rocket.core.internal.realtime.State
import
chat.rocket.core.internal.realtime.State
import
chat.rocket.core.internal.realtime.StreamMessage
import
chat.rocket.core.internal.realtime.StreamMessage
...
@@ -30,6 +34,7 @@ class ChatRoomsPresenter @Inject constructor(private val view: ChatRoomsView,
...
@@ -30,6 +34,7 @@ class ChatRoomsPresenter @Inject constructor(private val view: ChatRoomsView,
private
val
getChatRoomsInteractor
:
GetChatRoomsInteractor
,
private
val
getChatRoomsInteractor
:
GetChatRoomsInteractor
,
private
val
saveChatRoomsInteractor
:
SaveChatRoomsInteractor
,
private
val
saveChatRoomsInteractor
:
SaveChatRoomsInteractor
,
private
val
refreshSettingsInteractor
:
RefreshSettingsInteractor
,
private
val
refreshSettingsInteractor
:
RefreshSettingsInteractor
,
private
val
viewModelMapper
:
ViewModelMapper
,
settingsRepository
:
SettingsRepository
,
settingsRepository
:
SettingsRepository
,
factory
:
ConnectionManagerFactory
)
{
factory
:
ConnectionManagerFactory
)
{
private
val
manager
:
ConnectionManager
=
factory
.
create
(
serverInteractor
.
get
()
!!
)
private
val
manager
:
ConnectionManager
=
factory
.
create
(
serverInteractor
.
get
()
!!
)
...
@@ -89,9 +94,9 @@ class ChatRoomsPresenter @Inject constructor(private val view: ChatRoomsView,
...
@@ -89,9 +94,9 @@ class ChatRoomsPresenter @Inject constructor(private val view: ChatRoomsView,
val
chatRoomsCombined
=
mutableListOf
<
ChatRoom
>()
val
chatRoomsCombined
=
mutableListOf
<
ChatRoom
>()
chatRoomsCombined
.
addAll
(
usersToChatRooms
(
users
))
chatRoomsCombined
.
addAll
(
usersToChatRooms
(
users
))
chatRoomsCombined
.
addAll
(
roomsToChatRooms
(
rooms
))
chatRoomsCombined
.
addAll
(
roomsToChatRooms
(
rooms
))
view
.
updateChatRooms
(
chatRoomsCombined
)
view
.
updateChatRooms
(
getChatRoomsWithPreviews
(
chatRoomsCombined
.
toList
())
)
}
else
{
}
else
{
view
.
updateChatRooms
(
roomList
)
view
.
updateChatRooms
(
getChatRoomsWithPreviews
(
roomList
)
)
}
}
}
catch
(
ex
:
RocketChatException
)
{
}
catch
(
ex
:
RocketChatException
)
{
Timber
.
e
(
ex
)
Timber
.
e
(
ex
)
...
@@ -156,7 +161,7 @@ class ChatRoomsPresenter @Inject constructor(private val view: ChatRoomsView,
...
@@ -156,7 +161,7 @@ class ChatRoomsPresenter @Inject constructor(private val view: ChatRoomsView,
val
sortedRooms
=
sortRooms
(
chatRooms
)
val
sortedRooms
=
sortRooms
(
chatRooms
)
Timber
.
d
(
"Loaded rooms: ${sortedRooms.size}"
)
Timber
.
d
(
"Loaded rooms: ${sortedRooms.size}"
)
saveChatRoomsInteractor
.
save
(
currentServer
,
sortedRooms
)
saveChatRoomsInteractor
.
save
(
currentServer
,
sortedRooms
)
return
sortedRooms
return
getChatRoomsWithPreviews
(
sortedRooms
)
}
}
private
fun
sortRooms
(
chatRooms
:
List
<
ChatRoom
>):
List
<
ChatRoom
>
{
private
fun
sortRooms
(
chatRooms
:
List
<
ChatRoom
>):
List
<
ChatRoom
>
{
...
@@ -167,7 +172,17 @@ class ChatRoomsPresenter @Inject constructor(private val view: ChatRoomsView,
...
@@ -167,7 +172,17 @@ class ChatRoomsPresenter @Inject constructor(private val view: ChatRoomsView,
private
fun
updateRooms
()
{
private
fun
updateRooms
()
{
Timber
.
d
(
"Updating Rooms"
)
Timber
.
d
(
"Updating Rooms"
)
launch
(
strategy
.
jobs
)
{
launch
(
strategy
.
jobs
)
{
view
.
updateChatRooms
(
getChatRoomsInteractor
.
get
(
currentServer
))
view
.
updateChatRooms
(
getChatRoomsWithPreviews
(
getChatRoomsInteractor
.
get
(
currentServer
)))
}
}
private
suspend
fun
getChatRoomsWithPreviews
(
chatRooms
:
List
<
ChatRoom
>):
List
<
ChatRoom
>
{
return
chatRooms
.
map
{
if
(
it
.
lastMessage
!=
null
)
{
it
.
copy
(
lastMessage
=
viewModelMapper
.
map
(
it
.
lastMessage
!!
).
last
().
preview
)
}
else
{
it
}
}
}
}
}
...
@@ -304,7 +319,7 @@ class ChatRoomsPresenter @Inject constructor(private val view: ChatRoomsView,
...
@@ -304,7 +319,7 @@ class ChatRoomsPresenter @Inject constructor(private val view: ChatRoomsView,
// Update a ChatRoom with a Subscription information
// Update a ChatRoom with a Subscription information
private
fun
updateSubscription
(
subscription
:
Subscription
)
{
private
fun
updateSubscription
(
subscription
:
Subscription
)
{
Timber
.
d
(
"Updating subscrition: ${subscription.id} - ${subscription.name}"
)
Timber
.
d
(
"Updating subscri
p
tion: ${subscription.id} - ${subscription.name}"
)
val
chatRooms
=
getChatRoomsInteractor
.
get
(
currentServer
).
toMutableList
()
val
chatRooms
=
getChatRoomsInteractor
.
get
(
currentServer
).
toMutableList
()
val
chatRoom
=
chatRooms
.
find
{
chatRoom
->
chatRoom
.
id
==
subscription
.
roomId
}
val
chatRoom
=
chatRooms
.
find
{
chatRoom
->
chatRoom
.
id
==
subscription
.
roomId
}
chatRoom
?.
apply
{
chatRoom
?.
apply
{
...
...
app/src/main/java/chat/rocket/android/chatrooms/ui/ChatRoomsAdapter.kt
View file @
8685b5dd
...
@@ -3,14 +3,18 @@ package chat.rocket.android.chatrooms.ui
...
@@ -3,14 +3,18 @@ package chat.rocket.android.chatrooms.ui
import
DateTimeHelper
import
DateTimeHelper
import
DrawableHelper
import
DrawableHelper
import
android.content.Context
import
android.content.Context
import
android.graphics.
drawable.Drawable
import
android.graphics.
Color
import
android.support.v4.content.ContextCompat
import
android.support.v4.content.ContextCompat
import
android.support.v7.widget.RecyclerView
import
android.support.v7.widget.RecyclerView
import
android.text.SpannableStringBuilder
import
android.text.style.ForegroundColorSpan
import
android.view.View
import
android.view.View
import
android.view.ViewGroup
import
android.view.ViewGroup
import
android.widget.TextView
import
android.widget.TextView
import
chat.rocket.android.R
import
chat.rocket.android.R
import
chat.rocket.android.helper.UrlHelper
import
chat.rocket.android.helper.UrlHelper
import
chat.rocket.android.infrastructure.LocalRepository
import
chat.rocket.android.infrastructure.checkIfMyself
import
chat.rocket.android.server.domain.PublicSettings
import
chat.rocket.android.server.domain.PublicSettings
import
chat.rocket.android.server.domain.useRealName
import
chat.rocket.android.server.domain.useRealName
import
chat.rocket.android.util.extensions.content
import
chat.rocket.android.util.extensions.content
...
@@ -26,6 +30,7 @@ import kotlinx.android.synthetic.main.unread_messages_badge.view.*
...
@@ -26,6 +30,7 @@ import kotlinx.android.synthetic.main.unread_messages_badge.view.*
class
ChatRoomsAdapter
(
private
val
context
:
Context
,
class
ChatRoomsAdapter
(
private
val
context
:
Context
,
private
val
settings
:
PublicSettings
,
private
val
settings
:
PublicSettings
,
private
val
localRepository
:
LocalRepository
,
private
val
listener
:
(
ChatRoom
)
->
Unit
)
:
RecyclerView
.
Adapter
<
ChatRoomsAdapter
.
ViewHolder
>()
{
private
val
listener
:
(
ChatRoom
)
->
Unit
)
:
RecyclerView
.
Adapter
<
ChatRoomsAdapter
.
ViewHolder
>()
{
var
dataSet
:
MutableList
<
ChatRoom
>
=
ArrayList
()
var
dataSet
:
MutableList
<
ChatRoom
>
=
ArrayList
()
...
@@ -35,7 +40,7 @@ class ChatRoomsAdapter(private val context: Context,
...
@@ -35,7 +40,7 @@ class ChatRoomsAdapter(private val context: Context,
override
fun
getItemCount
():
Int
=
dataSet
.
size
override
fun
getItemCount
():
Int
=
dataSet
.
size
fun
updateRooms
(
newRooms
:
List
<
ChatRoom
>)
{
fun
updateRooms
(
newRooms
:
List
<
ChatRoom
>)
{
dataSet
.
clear
()
dataSet
.
clear
()
dataSet
.
addAll
(
newRooms
)
dataSet
.
addAll
(
newRooms
)
}
}
...
@@ -116,21 +121,30 @@ class ChatRoomsAdapter(private val context: Context,
...
@@ -116,21 +121,30 @@ class ChatRoomsAdapter(private val context: Context,
val
lastMessageSender
=
lastMessage
?.
sender
val
lastMessageSender
=
lastMessage
?.
sender
if
(
lastMessage
!=
null
&&
lastMessageSender
!=
null
)
{
if
(
lastMessage
!=
null
&&
lastMessageSender
!=
null
)
{
val
message
=
lastMessage
.
message
val
message
=
lastMessage
.
message
val
senderUsername
=
lastMessageSender
.
username
val
senderUsername
=
if
(
settings
.
useRealName
())
{
lastMessageSender
.
name
?:
lastMessageSender
.
username
}
else
{
lastMessageSender
.
username
}
when
(
senderUsername
)
{
when
(
senderUsername
)
{
chatRoom
.
name
->
{
chatRoom
.
name
->
{
textView
.
content
=
message
textView
.
content
=
message
}
}
// TODO Change to MySelf
// chatRoom.user?.username -> {
// holder.lastMessage.textContent = context.getString(R.string.msg_you) + ": $message"
// }
else
->
{
else
->
{
textView
.
content
=
"@$senderUsername: $message"
val
user
=
if
(
localRepository
.
checkIfMyself
(
lastMessageSender
.
username
!!
))
{
"${context.getString(R.string.msg_you)}: "
}
else
{
"$senderUsername: "
}
val
spannable
=
SpannableStringBuilder
(
user
)
val
len
=
spannable
.
length
spannable
.
setSpan
(
ForegroundColorSpan
(
Color
.
BLACK
),
0
,
len
-
1
,
0
)
spannable
.
append
(
message
)
textView
.
content
=
spannable
}
}
}
}
}
else
{
}
else
{
textView
.
content
=
""
textView
.
content
=
context
.
getText
(
R
.
string
.
msg_no_messages_yet
)
}
}
}
}
...
...
app/src/main/java/chat/rocket/android/chatrooms/ui/ChatRoomsFragment.kt
View file @
8685b5dd
...
@@ -12,6 +12,7 @@ import android.view.*
...
@@ -12,6 +12,7 @@ import android.view.*
import
chat.rocket.android.R
import
chat.rocket.android.R
import
chat.rocket.android.chatrooms.presentation.ChatRoomsPresenter
import
chat.rocket.android.chatrooms.presentation.ChatRoomsPresenter
import
chat.rocket.android.chatrooms.presentation.ChatRoomsView
import
chat.rocket.android.chatrooms.presentation.ChatRoomsView
import
chat.rocket.android.infrastructure.LocalRepository
import
chat.rocket.android.server.domain.GetCurrentServerInteractor
import
chat.rocket.android.server.domain.GetCurrentServerInteractor
import
chat.rocket.android.server.domain.SettingsRepository
import
chat.rocket.android.server.domain.SettingsRepository
import
chat.rocket.android.util.extensions.*
import
chat.rocket.android.util.extensions.*
...
@@ -31,6 +32,7 @@ class ChatRoomsFragment : Fragment(), ChatRoomsView {
...
@@ -31,6 +32,7 @@ class ChatRoomsFragment : Fragment(), ChatRoomsView {
@Inject
lateinit
var
presenter
:
ChatRoomsPresenter
@Inject
lateinit
var
presenter
:
ChatRoomsPresenter
@Inject
lateinit
var
serverInteractor
:
GetCurrentServerInteractor
@Inject
lateinit
var
serverInteractor
:
GetCurrentServerInteractor
@Inject
lateinit
var
settingsRepository
:
SettingsRepository
@Inject
lateinit
var
settingsRepository
:
SettingsRepository
@Inject
lateinit
var
localRepository
:
LocalRepository
private
var
searchView
:
SearchView
?
=
null
private
var
searchView
:
SearchView
?
=
null
private
val
handler
=
Handler
()
private
val
handler
=
Handler
()
...
@@ -108,7 +110,11 @@ class ChatRoomsFragment : Fragment(), ChatRoomsView {
...
@@ -108,7 +110,11 @@ class ChatRoomsFragment : Fragment(), ChatRoomsView {
override
fun
showLoading
()
=
view_loading
.
setVisible
(
true
)
override
fun
showLoading
()
=
view_loading
.
setVisible
(
true
)
override
fun
hideLoading
()
=
view_loading
.
setVisible
(
false
)
override
fun
hideLoading
()
{
if
(
view_loading
!=
null
)
{
view_loading
.
setVisible
(
false
)
}
}
override
fun
showMessage
(
resId
:
Int
)
{
override
fun
showMessage
(
resId
:
Int
)
{
showToast
(
resId
)
showToast
(
resId
)
...
@@ -152,12 +158,13 @@ class ChatRoomsFragment : Fragment(), ChatRoomsView {
...
@@ -152,12 +158,13 @@ class ChatRoomsFragment : Fragment(), ChatRoomsView {
activity
?.
apply
{
activity
?.
apply
{
recycler_view
.
layoutManager
=
LinearLayoutManager
(
this
,
LinearLayoutManager
.
VERTICAL
,
false
)
recycler_view
.
layoutManager
=
LinearLayoutManager
(
this
,
LinearLayoutManager
.
VERTICAL
,
false
)
recycler_view
.
addItemDecoration
(
DividerItemDecoration
(
this
,
recycler_view
.
addItemDecoration
(
DividerItemDecoration
(
this
,
resources
.
getDimensionPixelSize
(
R
.
dimen
.
divider_item_decorator_bound_start
),
resources
.
getDimensionPixelSize
(
R
.
dimen
.
divider_item_decorator_bound_start
),
resources
.
getDimensionPixelSize
(
R
.
dimen
.
divider_item_decorator_bound_end
)))
resources
.
getDimensionPixelSize
(
R
.
dimen
.
divider_item_decorator_bound_end
)))
recycler_view
.
itemAnimator
=
DefaultItemAnimator
()
recycler_view
.
itemAnimator
=
DefaultItemAnimator
()
// TODO - use a ViewModel Mapper instead of using settings on the adapter
// TODO - use a ViewModel Mapper instead of using settings on the adapter
recycler_view
.
adapter
=
ChatRoomsAdapter
(
this
,
recycler_view
.
adapter
=
ChatRoomsAdapter
(
settingsRepository
.
get
(
serverInteractor
.
get
()
!!
))
{
chatRoom
->
this
,
settingsRepository
.
get
(
serverInteractor
.
get
()
!!
),
localRepository
)
{
chatRoom
->
presenter
.
loadChatRoom
(
chatRoom
)
presenter
.
loadChatRoom
(
chatRoom
)
}
}
}
}
...
...
app/src/main/java/chat/rocket/android/helper/MessageParser.kt
View file @
8685b5dd
This diff is collapsed.
Click to expand it.
app/src/main/java/chat/rocket/android/infrastructure/LocalRepository.kt
View file @
8685b5dd
...
@@ -22,4 +22,6 @@ interface LocalRepository {
...
@@ -22,4 +22,6 @@ interface LocalRepository {
const
val
SETTINGS_KEY
=
"settings_"
const
val
SETTINGS_KEY
=
"settings_"
const
val
CURRENT_USERNAME_KEY
=
"username_"
const
val
CURRENT_USERNAME_KEY
=
"username_"
}
}
}
}
\ No newline at end of file
fun
LocalRepository
.
checkIfMyself
(
username
:
String
)
=
get
(
LocalRepository
.
CURRENT_USERNAME_KEY
)
==
username
\ No newline at end of file
app/src/main/java/chat/rocket/android/profile/ui/ProfileFragment.kt
View file @
8685b5dd
...
@@ -56,8 +56,8 @@ class ProfileFragment : Fragment(), ProfileView, ActionMode.Callback {
...
@@ -56,8 +56,8 @@ class ProfileFragment : Fragment(), ProfileView, ActionMode.Callback {
text_email
.
textContent
=
email
text_email
.
textContent
=
email
text_avatar_url
.
textContent
=
""
text_avatar_url
.
textContent
=
""
currentName
=
user
name
currentName
=
name
currentUsername
=
name
currentUsername
=
user
name
currentEmail
=
email
currentEmail
=
email
currentAvatar
=
avatarUrl
currentAvatar
=
avatarUrl
...
@@ -76,7 +76,9 @@ class ProfileFragment : Fragment(), ProfileView, ActionMode.Callback {
...
@@ -76,7 +76,9 @@ class ProfileFragment : Fragment(), ProfileView, ActionMode.Callback {
}
}
override
fun
hideLoading
()
{
override
fun
hideLoading
()
{
view_loading
.
setVisible
(
false
)
if
(
view_loading
!=
null
)
{
view_loading
.
setVisible
(
false
)
}
enableUserInput
(
true
)
enableUserInput
(
true
)
}
}
...
...
app/src/main/java/chat/rocket/android/widget/autocompletion/strategy/CompletionStrategy.kt
View file @
8685b5dd
...
@@ -6,5 +6,6 @@ interface CompletionStrategy {
...
@@ -6,5 +6,6 @@ interface CompletionStrategy {
fun
getItem
(
prefix
:
String
,
position
:
Int
):
SuggestionModel
fun
getItem
(
prefix
:
String
,
position
:
Int
):
SuggestionModel
fun
autocompleteItems
(
prefix
:
String
):
List
<
SuggestionModel
>
fun
autocompleteItems
(
prefix
:
String
):
List
<
SuggestionModel
>
fun
addAll
(
list
:
List
<
SuggestionModel
>)
fun
addAll
(
list
:
List
<
SuggestionModel
>)
fun
addPinned
(
list
:
List
<
SuggestionModel
>)
fun
size
():
Int
fun
size
():
Int
}
}
\ No newline at end of file
app/src/main/java/chat/rocket/android/widget/autocompletion/strategy/regex/StringMatchingCompletionStrategy.kt
View file @
8685b5dd
...
@@ -2,14 +2,19 @@ package chat.rocket.android.widget.autocompletion.strategy.regex
...
@@ -2,14 +2,19 @@ package chat.rocket.android.widget.autocompletion.strategy.regex
import
chat.rocket.android.widget.autocompletion.model.SuggestionModel
import
chat.rocket.android.widget.autocompletion.model.SuggestionModel
import
chat.rocket.android.widget.autocompletion.strategy.CompletionStrategy
import
chat.rocket.android.widget.autocompletion.strategy.CompletionStrategy
import
chat.rocket.android.widget.autocompletion.ui.SuggestionsAdapter
import
chat.rocket.android.widget.autocompletion.ui.SuggestionsAdapter
.Companion.RESULT_COUNT_UNLIMITED
import
java.util.concurrent.CopyOnWriteArrayList
import
java.util.concurrent.CopyOnWriteArrayList
internal
class
StringMatchingCompletionStrategy
(
private
val
threshold
:
Int
=
-
1
)
:
CompletionStrategy
{
internal
class
StringMatchingCompletionStrategy
(
private
val
threshold
:
Int
=
RESULT_COUNT_UNLIMITED
)
:
CompletionStrategy
{
private
val
list
=
CopyOnWriteArrayList
<
SuggestionModel
>()
private
val
list
=
CopyOnWriteArrayList
<
SuggestionModel
>()
private
val
pinnedList
=
mutableListOf
<
SuggestionModel
>()
init
{
check
(
threshold
>=
RESULT_COUNT_UNLIMITED
)
}
override
fun
autocompleteItems
(
prefix
:
String
):
List
<
SuggestionModel
>
{
override
fun
autocompleteItems
(
prefix
:
String
):
List
<
SuggestionModel
>
{
val
r
esult
=
list
.
filter
{
val
partialR
esult
=
list
.
filter
{
it
.
searchList
.
forEach
{
word
->
it
.
searchList
.
forEach
{
word
->
if
(
word
.
contains
(
prefix
,
ignoreCase
=
true
))
{
if
(
word
.
contains
(
prefix
,
ignoreCase
=
true
))
{
return
@filter
true
return
@filter
true
...
@@ -17,13 +22,23 @@ internal class StringMatchingCompletionStrategy(private val threshold: Int = -1)
...
@@ -17,13 +22,23 @@ internal class StringMatchingCompletionStrategy(private val threshold: Int = -1)
}
}
false
false
}.
sortedByDescending
{
it
.
pinned
}
}.
sortedByDescending
{
it
.
pinned
}
return
if
(
threshold
==
SuggestionsAdapter
.
UNLIMITED_RESULT_COUNT
)
result
else
result
.
take
(
threshold
)
return
if
(
threshold
==
RESULT_COUNT_UNLIMITED
)
partialResult
.
toList
()
else
{
val
result
=
partialResult
.
take
(
threshold
).
toMutableList
()
result
.
addAll
(
pinnedList
)
result
.
toList
()
}
}
}
override
fun
addAll
(
list
:
List
<
SuggestionModel
>)
{
override
fun
addAll
(
list
:
List
<
SuggestionModel
>)
{
this
.
list
.
addAllAbsent
(
list
)
this
.
list
.
addAllAbsent
(
list
)
}
}
override
fun
addPinned
(
list
:
List
<
SuggestionModel
>)
{
this
.
pinnedList
.
addAll
(
list
)
}
override
fun
getItem
(
prefix
:
String
,
position
:
Int
):
SuggestionModel
{
override
fun
getItem
(
prefix
:
String
,
position
:
Int
):
SuggestionModel
{
return
list
[
position
]
return
list
[
position
]
}
}
...
...
app/src/main/java/chat/rocket/android/widget/autocompletion/strategy/trie/TrieCompletionStrategy.kt
View file @
8685b5dd
...
@@ -27,5 +27,9 @@ class TrieCompletionStrategy : CompletionStrategy {
...
@@ -27,5 +27,9 @@ class TrieCompletionStrategy : CompletionStrategy {
}
}
}
}
override
fun
addPinned
(
list
:
List
<
SuggestionModel
>)
{
}
override
fun
size
()
=
items
.
size
override
fun
size
()
=
items
.
size
}
}
\ No newline at end of file
app/src/main/java/chat/rocket/android/widget/autocompletion/ui/SuggestionsAdapter.kt
View file @
8685b5dd
...
@@ -10,10 +10,10 @@ import kotlin.properties.Delegates
...
@@ -10,10 +10,10 @@ import kotlin.properties.Delegates
abstract
class
SuggestionsAdapter
<
VH
:
BaseSuggestionViewHolder
>(
abstract
class
SuggestionsAdapter
<
VH
:
BaseSuggestionViewHolder
>(
val
token
:
String
,
val
token
:
String
,
val
constraint
:
Int
=
CONSTRAINT_UNBOUND
,
val
constraint
:
Int
=
CONSTRAINT_UNBOUND
,
threshold
:
Int
=
MAX_RESULT_COUNT
)
:
RecyclerView
.
Adapter
<
VH
>()
{
threshold
:
Int
=
MAX_RESULT_COUNT
)
:
RecyclerView
.
Adapter
<
VH
>()
{
companion
object
{
companion
object
{
// Any number of results.
// Any number of results.
const
val
UNLIMITED_RESULT_COUNT
=
-
1
const
val
RESULT_COUNT_UNLIMITED
=
-
1
// Trigger suggestions only if on the line start.
// Trigger suggestions only if on the line start.
const
val
CONSTRAINT_BOUND_TO_START
=
0
const
val
CONSTRAINT_BOUND_TO_START
=
0
// Trigger suggestions from anywhere.
// Trigger suggestions from anywhere.
...
@@ -21,12 +21,14 @@ abstract class SuggestionsAdapter<VH : BaseSuggestionViewHolder>(
...
@@ -21,12 +21,14 @@ abstract class SuggestionsAdapter<VH : BaseSuggestionViewHolder>(
// Maximum number of results to display by default.
// Maximum number of results to display by default.
private
const
val
MAX_RESULT_COUNT
=
5
private
const
val
MAX_RESULT_COUNT
=
5
}
}
private
var
itemType
:
Type
?
=
null
private
var
itemType
:
Type
?
=
null
private
var
itemClickListener
:
ItemClickListener
?
=
null
private
var
itemClickListener
:
ItemClickListener
?
=
null
// Called to gather results when no results have previously matched.
// Called to gather results when no results have previously matched.
private
var
providerExternal
:
((
query
:
String
)
->
Unit
)?
=
null
private
var
providerExternal
:
((
query
:
String
)
->
Unit
)?
=
null
private
var
pinnedSuggestions
:
List
<
SuggestionModel
>?
=
null
// Maximum number of results/suggestions to display.
// Maximum number of results/suggestions to display.
private
var
resultsThreshold
:
Int
=
if
(
threshold
>
0
)
threshold
else
UNLIMITED_RESULT_COUNT
private
var
resultsThreshold
:
Int
=
if
(
threshold
>
0
)
threshold
else
RESULT_COUNT_UNLIMITED
// The strategy used for suggesting completions.
// The strategy used for suggesting completions.
private
val
strategy
:
CompletionStrategy
=
StringMatchingCompletionStrategy
(
resultsThreshold
)
private
val
strategy
:
CompletionStrategy
=
StringMatchingCompletionStrategy
(
resultsThreshold
)
// Current input term to look up for suggestions.
// Current input term to look up for suggestions.
...
@@ -53,6 +55,15 @@ abstract class SuggestionsAdapter<VH : BaseSuggestionViewHolder>(
...
@@ -53,6 +55,15 @@ abstract class SuggestionsAdapter<VH : BaseSuggestionViewHolder>(
return
strategy
.
autocompleteItems
(
currentTerm
)[
position
]
return
strategy
.
autocompleteItems
(
currentTerm
)[
position
]
}
}
/**
* Set suggestions that should always appear when prompted.
*
* @param suggestions The list of suggestions that will be pinned.
*/
fun
setPinnedSuggestions
(
suggestions
:
List
<
SuggestionModel
>)
{
this
.
strategy
.
addPinned
(
suggestions
)
}
fun
autocomplete
(
newTerm
:
String
)
{
fun
autocomplete
(
newTerm
:
String
)
{
this
.
currentTerm
=
newTerm
.
toLowerCase
().
trim
()
this
.
currentTerm
=
newTerm
.
toLowerCase
().
trim
()
}
}
...
...
app/src/main/java/chat/rocket/android/widget/autocompletion/ui/SuggestionsView.kt
View file @
8685b5dd
...
@@ -23,23 +23,19 @@ import chat.rocket.android.R
...
@@ -23,23 +23,19 @@ import chat.rocket.android.R
import
chat.rocket.android.widget.autocompletion.model.SuggestionModel
import
chat.rocket.android.widget.autocompletion.model.SuggestionModel
import
chat.rocket.android.widget.autocompletion.ui.SuggestionsAdapter.Companion.CONSTRAINT_BOUND_TO_START
import
chat.rocket.android.widget.autocompletion.ui.SuggestionsAdapter.Companion.CONSTRAINT_BOUND_TO_START
import
java.lang.ref.WeakReference
import
java.lang.ref.WeakReference
import
java.util.concurrent.CopyOnWriteArrayList
import
java.util.concurrent.atomic.AtomicInteger
import
java.util.concurrent.atomic.AtomicInteger
/**
// This is a special index that means we're not at an autocompleting state.
* This is a special index that means we're not at an autocompleting state.
*/
private
const
val
NO_STATE_INDEX
=
0
private
const
val
NO_STATE_INDEX
=
0
class
SuggestionsView
:
FrameLayout
,
TextWatcher
{
class
SuggestionsView
:
FrameLayout
,
TextWatcher
{
private
val
recyclerView
:
RecyclerView
private
val
recyclerView
:
RecyclerView
private
val
registeredTokens
=
CopyOnWriteArrayList
<
String
>()
// Maps tokens to their respective adapters.
// Maps tokens to their respective adapters.
private
val
adaptersByToken
=
hashMapOf
<
String
,
SuggestionsAdapter
<
out
BaseSuggestionViewHolder
>>()
private
val
adaptersByToken
=
hashMapOf
<
String
,
SuggestionsAdapter
<
out
BaseSuggestionViewHolder
>>()
private
val
externalProvidersByToken
=
hashMapOf
<
String
,
((
query
:
String
)
->
Unit
)>()
private
val
externalProvidersByToken
=
hashMapOf
<
String
,
((
query
:
String
)
->
Unit
)>()
private
val
localProvidersByToken
=
hashMapOf
<
String
,
HashMap
<
String
,
List
<
SuggestionModel
>>>()
private
val
localProvidersByToken
=
hashMapOf
<
String
,
HashMap
<
String
,
List
<
SuggestionModel
>>>()
private
var
editor
:
WeakReference
<
EditText
>?
=
null
private
var
editor
:
WeakReference
<
EditText
>?
=
null
private
var
completion
StartIndex
=
AtomicInteger
(
NO_STATE_INDEX
)
private
var
completion
Offset
=
AtomicInteger
(
NO_STATE_INDEX
)
private
var
maxHeight
:
Int
=
0
private
var
maxHeight
:
Int
=
0
companion
object
{
companion
object
{
...
@@ -66,7 +62,7 @@ class SuggestionsView : FrameLayout, TextWatcher {
...
@@ -66,7 +62,7 @@ class SuggestionsView : FrameLayout, TextWatcher {
// If we have a deletion.
// If we have a deletion.
if
(
after
==
0
)
{
if
(
after
==
0
)
{
val
deleted
=
s
.
subSequence
(
start
,
start
+
count
).
toString
()
val
deleted
=
s
.
subSequence
(
start
,
start
+
count
).
toString
()
if
(
adaptersByToken
.
containsKey
(
deleted
)
&&
completion
StartIndex
.
get
()
>
NO_STATE_INDEX
)
{
if
(
adaptersByToken
.
containsKey
(
deleted
)
&&
completion
Offset
.
get
()
>
NO_STATE_INDEX
)
{
// We have removed the '@', '#' or any other action token so halt completion.
// We have removed the '@', '#' or any other action token so halt completion.
cancelSuggestions
(
true
)
cancelSuggestions
(
true
)
}
}
...
@@ -77,6 +73,11 @@ class SuggestionsView : FrameLayout, TextWatcher {
...
@@ -77,6 +73,11 @@ class SuggestionsView : FrameLayout, TextWatcher {
// If we don't have any adapter bound to any token bail out.
// If we don't have any adapter bound to any token bail out.
if
(
adaptersByToken
.
isEmpty
())
return
if
(
adaptersByToken
.
isEmpty
())
return
if
(
editor
?.
get
()
!=
null
&&
editor
?.
get
()
?.
selectionStart
?:
0
<=
completionOffset
.
get
())
{
completionOffset
.
set
(
NO_STATE_INDEX
)
collapse
()
}
val
new
=
s
.
subSequence
(
start
,
start
+
count
).
toString
()
val
new
=
s
.
subSequence
(
start
,
start
+
count
).
toString
()
if
(
adaptersByToken
.
containsKey
(
new
))
{
if
(
adaptersByToken
.
containsKey
(
new
))
{
val
constraint
=
adapter
(
new
).
constraint
val
constraint
=
adapter
(
new
).
constraint
...
@@ -84,8 +85,8 @@ class SuggestionsView : FrameLayout, TextWatcher {
...
@@ -84,8 +85,8 @@ class SuggestionsView : FrameLayout, TextWatcher {
return
return
}
}
swapAdapter
(
getAdapterForToken
(
new
)
!!
)
swapAdapter
(
getAdapterForToken
(
new
)
!!
)
completion
StartIndex
.
compareAndSet
(
NO_STATE_INDEX
,
start
+
1
)
completion
Offset
.
compareAndSet
(
NO_STATE_INDEX
,
start
+
1
)
editor
?.
let
{
this
.
editor
?.
let
{
// Disable keyboard suggestions when autocompleting.
// Disable keyboard suggestions when autocompleting.
val
editText
=
it
.
get
()
val
editText
=
it
.
get
()
if
(
editText
!=
null
)
{
if
(
editText
!=
null
)
{
...
@@ -97,13 +98,13 @@ class SuggestionsView : FrameLayout, TextWatcher {
...
@@ -97,13 +98,13 @@ class SuggestionsView : FrameLayout, TextWatcher {
if
(
new
.
startsWith
(
" "
))
{
if
(
new
.
startsWith
(
" "
))
{
// just halts the completion execution
// just halts the completion execution
cancelSuggestions
(
fals
e
)
cancelSuggestions
(
tru
e
)
return
return
}
}
val
prefixEndIndex
=
editor
?.
get
()
?.
selectionStart
?:
NO_STATE_INDEX
val
prefixEndIndex
=
this
.
editor
?.
get
()
?.
selectionStart
?:
NO_STATE_INDEX
if
(
prefixEndIndex
==
NO_STATE_INDEX
||
prefixEndIndex
<
completion
StartIndex
.
get
())
return
if
(
prefixEndIndex
==
NO_STATE_INDEX
||
prefixEndIndex
<
completion
Offset
.
get
())
return
val
prefix
=
s
.
subSequence
(
completion
StartIndex
.
get
(),
editor
?.
get
()
?.
selectionStart
?:
completionStartIndex
.
get
()).
toString
()
val
prefix
=
s
.
subSequence
(
completion
Offset
.
get
(),
this
.
editor
?.
get
()
?.
selectionStart
?:
completionOffset
.
get
()).
toString
()
recyclerView
.
adapter
?.
let
{
recyclerView
.
adapter
?.
let
{
it
as
SuggestionsAdapter
it
as
SuggestionsAdapter
// we need to look up only after the '@'
// we need to look up only after the '@'
...
@@ -157,7 +158,7 @@ class SuggestionsView : FrameLayout, TextWatcher {
...
@@ -157,7 +158,7 @@ class SuggestionsView : FrameLayout, TextWatcher {
val
adapter
=
adapter
(
token
)
val
adapter
=
adapter
(
token
)
localProvidersByToken
.
getOrPut
(
token
,
{
hashMapOf
()
})
localProvidersByToken
.
getOrPut
(
token
,
{
hashMapOf
()
})
.
put
(
adapter
.
term
(),
list
)
.
put
(
adapter
.
term
(),
list
)
if
(
completion
StartIndex
.
get
()
>
NO_STATE_INDEX
&&
adapter
.
itemCount
==
0
)
expand
()
if
(
completion
Offset
.
get
()
>
NO_STATE_INDEX
&&
adapter
.
itemCount
==
0
)
expand
()
adapter
.
addItems
(
list
)
adapter
.
addItems
(
list
)
}
}
return
this
return
this
...
@@ -199,7 +200,7 @@ class SuggestionsView : FrameLayout, TextWatcher {
...
@@ -199,7 +200,7 @@ class SuggestionsView : FrameLayout, TextWatcher {
// Reset completion start index only if we've deleted the token that triggered completion or
// Reset completion start index only if we've deleted the token that triggered completion or
// we finished the completion process.
// we finished the completion process.
if
(
haltCompletion
)
{
if
(
haltCompletion
)
{
completion
StartIndex
.
set
(
NO_STATE_INDEX
)
completion
Offset
.
set
(
NO_STATE_INDEX
)
}
}
collapse
()
collapse
()
// Re-enable keyboard suggestions.
// Re-enable keyboard suggestions.
...
@@ -212,7 +213,7 @@ class SuggestionsView : FrameLayout, TextWatcher {
...
@@ -212,7 +213,7 @@ class SuggestionsView : FrameLayout, TextWatcher {
private
fun
insertSuggestionOnEditor
(
item
:
SuggestionModel
)
{
private
fun
insertSuggestionOnEditor
(
item
:
SuggestionModel
)
{
editor
?.
get
()
?.
let
{
editor
?.
get
()
?.
let
{
val
suggestionText
=
item
.
text
val
suggestionText
=
item
.
text
it
.
text
.
replace
(
completion
StartIndex
.
get
(),
it
.
selectionStart
,
"$suggestionText "
)
it
.
text
.
replace
(
completion
Offset
.
get
(),
it
.
selectionStart
,
"$suggestionText "
)
}
}
}
}
...
...
app/src/main/java/chat/rocket/android/widget/emoji/EmojiParser.kt
View file @
8685b5dd
...
@@ -14,15 +14,21 @@ class EmojiParser {
...
@@ -14,15 +14,21 @@ class EmojiParser {
*/
*/
fun
parse
(
text
:
CharSequence
):
CharSequence
{
fun
parse
(
text
:
CharSequence
):
CharSequence
{
val
unicodedText
=
EmojiRepository
.
shortnameToUnicode
(
text
,
true
)
val
unicodedText
=
EmojiRepository
.
shortnameToUnicode
(
text
,
true
)
val
spannableString
=
SpannableString
.
valueOf
(
unicodedText
)
var
spannable
=
SpannableString
.
valueOf
(
unicodedText
)
// Look for groups of emojis, set a CustomTypefaceSpan with the emojione font
val
typeface
=
EmojiRepository
.
cachedTypeface
val
length
=
spannableString
.
length
// Look for groups of emojis, set a EmojiTypefaceSpan with the emojione font.
val
length
=
spannable
.
length
var
inEmoji
=
false
var
inEmoji
=
false
var
emojiStart
=
0
var
emojiStart
=
0
var
offset
=
0
var
offset
=
0
while
(
offset
<
length
)
{
while
(
offset
<
length
)
{
val
codepoint
=
unicodedText
.
codePointAt
(
offset
)
val
codepoint
=
unicodedText
.
codePointAt
(
offset
)
val
count
=
Character
.
charCount
(
codepoint
)
val
count
=
Character
.
charCount
(
codepoint
)
// Skip control characters.
if
(
codepoint
==
0
x2028
)
{
offset
+=
count
continue
}
if
(
codepoint
>=
0
x200
)
{
if
(
codepoint
>=
0
x200
)
{
if
(!
inEmoji
)
{
if
(!
inEmoji
)
{
emojiStart
=
offset
emojiStart
=
offset
...
@@ -30,18 +36,25 @@ class EmojiParser {
...
@@ -30,18 +36,25 @@ class EmojiParser {
inEmoji
=
true
inEmoji
=
true
}
else
{
}
else
{
if
(
inEmoji
)
{
if
(
inEmoji
)
{
spannable
String
.
setSpan
(
EmojiTypefaceSpan
(
"sans-serif"
,
EmojiRepository
.
cachedT
ypeface
),
spannable
.
setSpan
(
EmojiTypefaceSpan
(
"sans-serif"
,
t
ypeface
),
emojiStart
,
offset
,
Spanned
.
SPAN_EXCLUSIVE_EXCLUSIVE
)
emojiStart
,
offset
,
Spanned
.
SPAN_EXCLUSIVE_EXCLUSIVE
)
}
}
inEmoji
=
false
inEmoji
=
false
}
}
offset
+=
count
offset
+=
count
if
(
offset
>=
length
&&
inEmoji
)
{
if
(
offset
>=
length
&&
inEmoji
)
{
spannable
String
.
setSpan
(
EmojiTypefaceSpan
(
"sans-serif"
,
EmojiRepository
.
cachedT
ypeface
),
spannable
.
setSpan
(
EmojiTypefaceSpan
(
"sans-serif"
,
t
ypeface
),
emojiStart
,
offset
,
Spanned
.
SPAN_EXCLUSIVE_EXCLUSIVE
)
emojiStart
,
offset
,
Spanned
.
SPAN_EXCLUSIVE_EXCLUSIVE
)
}
}
}
}
return
spannableString
return
spannable
}
private
fun
calculateSurrogatePairs
(
scalar
:
Int
):
Pair
<
Int
,
Int
>
{
val
temp
:
Int
=
(
scalar
-
0
x10000
)
/
0
x400
val
s1
:
Int
=
Math
.
floor
(
temp
.
toDouble
()).
toInt
()
+
0
xD800
val
s2
:
Int
=
((
scalar
-
0
x10000
)
%
0
x400
)
+
0
xDC00
return
Pair
(
s1
,
s2
)
}
}
}
}
}
}
\ No newline at end of file
app/src/main/java/chat/rocket/android/widget/emoji/EmojiRepository.kt
View file @
8685b5dd
...
@@ -54,6 +54,10 @@ object EmojiRepository {
...
@@ -54,6 +54,10 @@ object EmojiRepository {
*/
*/
fun
getAll
()
=
ALL_EMOJIS
fun
getAll
()
=
ALL_EMOJIS
// fun findEmojiByUnicode(unicode: Int) {
// ALL_EMOJIS.find { it.unicode == }
// }
/**
/**
* Get all emojis for a given category.
* Get all emojis for a given category.
*
*
...
@@ -119,10 +123,7 @@ object EmojiRepository {
...
@@ -119,10 +123,7 @@ object EmojiRepository {
var
result
:
String
=
input
.
toString
()
var
result
:
String
=
input
.
toString
()
while
(
matcher
.
find
())
{
while
(
matcher
.
find
())
{
val
unicode
=
shortNameToUnicode
.
get
(
":${matcher.group(1)}:"
)
val
unicode
=
shortNameToUnicode
.
get
(
":${matcher.group(1)}:"
)
?:
continue
if
(
unicode
==
null
)
{
continue
}
if
(
supported
)
{
if
(
supported
)
{
result
=
result
.
replace
(
":"
+
matcher
.
group
(
1
)
+
":"
,
unicode
)
result
=
result
.
replace
(
":"
+
matcher
.
group
(
1
)
+
":"
,
unicode
)
...
@@ -159,9 +160,7 @@ object EmojiRepository {
...
@@ -159,9 +160,7 @@ object EmojiRepository {
private
fun
buildStringListFromJsonArray
(
array
:
JSONArray
):
List
<
String
>
{
private
fun
buildStringListFromJsonArray
(
array
:
JSONArray
):
List
<
String
>
{
val
list
=
ArrayList
<
String
>(
array
.
length
())
val
list
=
ArrayList
<
String
>(
array
.
length
())
for
(
i
in
0
..
array
.
length
()
-
1
)
{
(
0
until
array
.
length
()).
mapTo
(
list
)
{
array
.
getString
(
it
)
}
list
.
add
(
array
.
getString
(
i
))
}
return
list
return
list
}
}
...
...
app/src/main/java/chat/rocket/android/widget/emoji/EmojiTypefaceSpan.kt
View file @
8685b5dd
...
@@ -17,22 +17,22 @@ class EmojiTypefaceSpan(family: String, private val newType: Typeface) : Typefac
...
@@ -17,22 +17,22 @@ class EmojiTypefaceSpan(family: String, private val newType: Typeface) : Typefac
private
fun
applyCustomTypeFace
(
paint
:
Paint
,
tf
:
Typeface
)
{
private
fun
applyCustomTypeFace
(
paint
:
Paint
,
tf
:
Typeface
)
{
val
oldStyle
:
Int
val
oldStyle
:
Int
val
old
=
paint
.
getTypeface
()
val
old
=
paint
.
typeface
if
(
old
==
null
)
{
if
(
old
==
null
)
{
oldStyle
=
0
oldStyle
=
0
}
else
{
}
else
{
oldStyle
=
old
.
getStyle
()
oldStyle
=
old
.
style
}
}
val
fake
=
oldStyle
and
tf
.
style
.
inv
()
val
fake
=
oldStyle
and
tf
.
style
.
inv
()
if
(
fake
and
Typeface
.
BOLD
!=
0
)
{
if
(
fake
and
Typeface
.
BOLD
!=
0
)
{
paint
.
setFakeBoldText
(
true
)
paint
.
isFakeBoldText
=
true
}
}
if
(
fake
and
Typeface
.
ITALIC
!=
0
)
{
if
(
fake
and
Typeface
.
ITALIC
!=
0
)
{
paint
.
setTextSkewX
(-
0.25f
)
paint
.
textSkewX
=
-
0.25f
}
}
paint
.
setTypeface
(
tf
)
paint
.
typeface
=
tf
}
}
}
}
\ No newline at end of file
app/src/main/res/drawable/quote.xml
→
app/src/main/res/drawable/quote
_vertical_bar
.xml
View file @
8685b5dd
...
@@ -2,9 +2,11 @@
...
@@ -2,9 +2,11 @@
<shape
xmlns:android=
"http://schemas.android.com/apk/res/android"
<shape
xmlns:android=
"http://schemas.android.com/apk/res/android"
android:shape=
"rectangle"
>
android:shape=
"rectangle"
>
<solid
android:color=
"@color/
darkGra
y"
/>
<solid
android:color=
"@color/
colorPrimar
y"
/>
<size
<size
android:width=
"4dp"
android:width=
"4dp"
android:height=
"4dp"
/>
android:height=
"4dp"
/>
<corners
android:radius=
"8dp"
/>
</shape>
</shape>
\ No newline at end of file
app/src/main/res/layout/item_message_attachment.xml
0 → 100644
View file @
8685b5dd
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android=
"http://schemas.android.com/apk/res/android"
xmlns:app=
"http://schemas.android.com/apk/res-auto"
xmlns:tools=
"http://schemas.android.com/tools"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:background=
"?android:attr/selectableItemBackground"
android:clickable=
"true"
android:focusable=
"true"
android:paddingBottom=
"@dimen/message_item_top_and_bottom_padding"
android:paddingEnd=
"@dimen/screen_edge_left_and_right_padding"
android:paddingStart=
"@dimen/screen_edge_left_and_right_padding"
android:paddingTop=
"@dimen/message_item_top_and_bottom_padding"
>
<View
android:id=
"@+id/quote_bar"
android:layout_width=
"4dp"
android:layout_height=
"0dp"
android:layout_marginStart=
"56dp"
android:background=
"@drawable/quote_vertical_bar"
app:layout_constraintBottom_toTopOf=
"@+id/recycler_view_reactions"
app:layout_constraintStart_toStartOf=
"parent"
app:layout_constraintTop_toTopOf=
"parent"
/>
<LinearLayout
android:id=
"@+id/top_container"
android:layout_width=
"0dp"
android:layout_height=
"wrap_content"
android:layout_marginStart=
"8dp"
android:orientation=
"horizontal"
app:layout_constraintLeft_toRightOf=
"@+id/quote_bar"
app:layout_constraintTop_toBottomOf=
"@id/new_messages_notif"
>
<TextView
android:id=
"@+id/text_sender"
style=
"@style/Sender.Name.TextView"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:textColor=
"@color/colorPrimary"
tools:text=
"Ronald Perkins"
/>
<TextView
android:id=
"@+id/text_message_time"
style=
"@style/Timestamp.TextView"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_marginStart=
"10dp"
tools:text=
"11:45 PM"
/>
</LinearLayout>
<TextView
android:id=
"@+id/text_content"
style=
"@style/Message.Quote.TextView"
android:layout_width=
"0dp"
android:layout_height=
"wrap_content"
android:ellipsize=
"end"
android:singleLine=
"true"
app:layout_constraintEnd_toEndOf=
"parent"
app:layout_constraintStart_toStartOf=
"@+id/top_container"
app:layout_constraintTop_toBottomOf=
"@+id/top_container"
tools:text=
"This is a multiline chat message from Bertie that will take more than just one line of text. I have sure that everything is amazing!"
/>
<include
layout=
"@layout/layout_reactions"
android:layout_width=
"0dp"
android:layout_height=
"wrap_content"
app:layout_constraintStart_toStartOf=
"@+id/quote_bar"
app:layout_constraintTop_toBottomOf=
"@+id/text_content"
/>
</android.support.constraint.ConstraintLayout>
\ No newline at end of file
app/src/main/res/layout/message_action_bar.xml
View file @
8685b5dd
...
@@ -6,6 +6,17 @@
...
@@ -6,6 +6,17 @@
android:layout_height=
"wrap_content"
android:layout_height=
"wrap_content"
android:background=
"@color/colorPrimary"
>
android:background=
"@color/colorPrimary"
>
<View
android:id=
"@+id/quote_bar"
android:layout_width=
"4dp"
android:layout_height=
"0dp"
android:background=
"@drawable/quote_vertical_bar"
android:layout_marginTop=
"4dp"
android:layout_marginBottom=
"4dp"
app:layout_constraintBottom_toBottomOf=
"parent"
app:layout_constraintStart_toEndOf=
"@+id/image_view_action_cancel_quote"
app:layout_constraintTop_toTopOf=
"parent"
/>
<TextView
<TextView
android:id=
"@+id/text_view_action_text"
android:id=
"@+id/text_view_action_text"
android:layout_width=
"0dp"
android:layout_width=
"0dp"
...
...
app/src/main/res/layout/suggestion_member_item.xml
View file @
8685b5dd
...
@@ -6,9 +6,9 @@
...
@@ -6,9 +6,9 @@
android:layout_height=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_marginBottom=
"2dp"
android:layout_marginBottom=
"2dp"
android:layout_marginEnd=
"2dp"
android:layout_marginEnd=
"2dp"
android:layout_marginLeft=
"
4
dp"
android:layout_marginLeft=
"
8
dp"
android:layout_marginRight=
"2dp"
android:layout_marginRight=
"2dp"
android:layout_marginStart=
"
4
dp"
android:layout_marginStart=
"
8
dp"
android:layout_marginTop=
"2dp"
android:layout_marginTop=
"2dp"
android:background=
"@color/suggestion_background_color"
>
android:background=
"@color/suggestion_background_color"
>
...
@@ -22,7 +22,8 @@
...
@@ -22,7 +22,8 @@
android:id=
"@+id/image_avatar"
android:id=
"@+id/image_avatar"
android:layout_width=
"24dp"
android:layout_width=
"24dp"
android:layout_height=
"24dp"
android:layout_height=
"24dp"
android:layout_margin=
"4dp"
android:layout_marginTop=
"4dp"
android:layout_marginBottom=
"4dp"
app:roundedCornerRadius=
"3dp"
app:roundedCornerRadius=
"3dp"
tools:src=
"@tools:sample/avatars"
/>
tools:src=
"@tools:sample/avatars"
/>
...
...
app/src/main/res/values-pt-rBR/strings.xml
View file @
8685b5dd
...
@@ -70,6 +70,10 @@
...
@@ -70,6 +70,10 @@
<string
name=
"msg_new_password"
>
Informe a nova senha
</string>
<string
name=
"msg_new_password"
>
Informe a nova senha
</string>
<string
name=
"msg_confirm_password"
>
Confirme a nova senha
</string>
<string
name=
"msg_confirm_password"
>
Confirme a nova senha
</string>
<string
name=
"msg_unread_messages"
>
Mensagens não lidas
</string>
<string
name=
"msg_unread_messages"
>
Mensagens não lidas
</string>
<string
name=
"msg_preview_video"
>
Vídeo
</string>
<string
name=
"msg_preview_audio"
>
Audio
</string>
<string
name=
"msg_preview_photo"
>
Foto
</string>
<string
name=
"msg_no_messages_yet"
>
Nenhuma mensagem ainda
</string>
<!-- System messages -->
<!-- System messages -->
<string
name=
"message_room_name_changed"
>
Nome da sala alterado para: %1$s por %2$s
</string>
<string
name=
"message_room_name_changed"
>
Nome da sala alterado para: %1$s por %2$s
</string>
...
@@ -116,6 +120,10 @@
...
@@ -116,6 +120,10 @@
<string
name=
"status_disconnecting"
>
desconectando
</string>
<string
name=
"status_disconnecting"
>
desconectando
</string>
<string
name=
"status_waiting"
>
conectando em %d segundos
</string>
<string
name=
"status_waiting"
>
conectando em %d segundos
</string>
<!--Suggestions-->
<string
name=
"suggest_all_description"
>
Notifica todos nesta sala
</string>
<string
name=
"suggest_here_description"
>
Notifica usuários ativos nesta sala
</string>
<!-- Slash Commands -->
<!-- Slash Commands -->
<string
name=
"Slash_Gimme_Description"
>
Exibir ༼ つ ◕_◕ ༽つ antes de sua mensagem
</string>
<string
name=
"Slash_Gimme_Description"
>
Exibir ༼ つ ◕_◕ ༽つ antes de sua mensagem
</string>
<string
name=
"Slash_LennyFace_Description"
>
Exibir ( ͡° ͜ʖ ͡°) depois de sua mensagem
</string>
<string
name=
"Slash_LennyFace_Description"
>
Exibir ( ͡° ͜ʖ ͡°) depois de sua mensagem
</string>
...
...
app/src/main/res/values/strings.xml
View file @
8685b5dd
...
@@ -71,6 +71,10 @@
...
@@ -71,6 +71,10 @@
<string
name=
"msg_new_password"
>
Enter New Password
</string>
<string
name=
"msg_new_password"
>
Enter New Password
</string>
<string
name=
"msg_confirm_password"
>
Confirm New Password
</string>
<string
name=
"msg_confirm_password"
>
Confirm New Password
</string>
<string
name=
"msg_unread_messages"
>
Unread messages
</string>
<string
name=
"msg_unread_messages"
>
Unread messages
</string>
<string
name=
"msg_preview_video"
>
Video
</string>
<string
name=
"msg_preview_audio"
>
Audio
</string>
<string
name=
"msg_preview_photo"
>
Photo
</string>
<string
name=
"msg_no_messages_yet"
>
No messages yet
</string>
<!-- System messages -->
<!-- System messages -->
<string
name=
"message_room_name_changed"
>
Room name changed to: %1$s by %2$s
</string>
<string
name=
"message_room_name_changed"
>
Room name changed to: %1$s by %2$s
</string>
...
@@ -117,6 +121,10 @@
...
@@ -117,6 +121,10 @@
<string
name=
"status_disconnecting"
>
disconnecting
</string>
<string
name=
"status_disconnecting"
>
disconnecting
</string>
<string
name=
"status_waiting"
>
connecting in %d seconds
</string>
<string
name=
"status_waiting"
>
connecting in %d seconds
</string>
<!--Suggestions-->
<string
name=
"suggest_all_description"
>
Notify all in this room
</string>
<string
name=
"suggest_here_description"
>
Notify active users in this room
</string>
<!-- Slash Commands -->
<!-- Slash Commands -->
<string
name=
"Slash_Gimme_Description"
>
Displays ༼ つ ◕_◕ ༽つ before your message
</string>
<string
name=
"Slash_Gimme_Description"
>
Displays ༼ つ ◕_◕ ༽つ before your message
</string>
<string
name=
"Slash_LennyFace_Description"
>
Displays ( ͡° ͜ʖ ͡°) after your message
</string>
<string
name=
"Slash_LennyFace_Description"
>
Displays ( ͡° ͜ʖ ͡°) after your message
</string>
...
...
app/src/main/res/values/styles.xml
View file @
8685b5dd
...
@@ -88,6 +88,10 @@
...
@@ -88,6 +88,10 @@
<item
name=
"android:textColor"
>
@color/colorPrimaryText
</item>
<item
name=
"android:textColor"
>
@color/colorPrimaryText
</item>
</style>
</style>
<style
name=
"Message.Quote.TextView"
parent=
"Message.TextView"
>
<item
name=
"android:textColor"
>
@color/colorPrimaryText
</item>
</style>
<style
name=
"Timestamp.TextView"
parent=
"TextAppearance.AppCompat.Caption"
>
<style
name=
"Timestamp.TextView"
parent=
"TextAppearance.AppCompat.Caption"
>
<item
name=
"android:textSize"
>
10sp
</item>
<item
name=
"android:textSize"
>
10sp
</item>
</style>
</style>
...
...
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