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
3f3ca5c5
Unverified
Commit
3f3ca5c5
authored
May 08, 2018
by
Rafael Kellermann Streit
Committed by
GitHub
May 08, 2018
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'develop' into beta
parents
1a1213da
fe7af2e5
Changes
34
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
34 changed files
with
752 additions
and
158 deletions
+752
-158
build.gradle
app/build.gradle
+1
-1
BaseViewHolder.kt
...va/chat/rocket/android/chatroom/adapter/BaseViewHolder.kt
+2
-3
MessageViewHolder.kt
...chat/rocket/android/chatroom/adapter/MessageViewHolder.kt
+7
-0
ChatRoomPresenter.kt
...rocket/android/chatroom/presentation/ChatRoomPresenter.kt
+36
-9
ChatRoomView.kt
...chat/rocket/android/chatroom/presentation/ChatRoomView.kt
+5
-1
ChatRoomActivity.kt
.../java/chat/rocket/android/chatroom/ui/ChatRoomActivity.kt
+13
-6
ChatRoomFragment.kt
.../java/chat/rocket/android/chatroom/ui/ChatRoomFragment.kt
+47
-14
ViewModelMapper.kt
...chat/rocket/android/chatroom/viewmodel/ViewModelMapper.kt
+3
-0
ChatRoomsPresenter.kt
...cket/android/chatrooms/presentation/ChatRoomsPresenter.kt
+48
-7
ChatRoomsAdapter.kt
...java/chat/rocket/android/chatrooms/ui/ChatRoomsAdapter.kt
+7
-4
ChatRoomsFragment.kt
...ava/chat/rocket/android/chatrooms/ui/ChatRoomsFragment.kt
+24
-18
AppModule.kt
.../main/java/chat/rocket/android/dagger/module/AppModule.kt
+16
-35
LocalModule.kt
...ain/java/chat/rocket/android/dagger/module/LocalModule.kt
+56
-3
ForFresco.kt
...in/java/chat/rocket/android/dagger/qualifier/ForFresco.kt
+0
-7
FrescoAuthInterceptor.kt
.../java/chat/rocket/android/helper/FrescoAuthInterceptor.kt
+0
-30
UserHelper.kt
app/src/main/java/chat/rocket/android/helper/UserHelper.kt
+63
-0
LocalRepository.kt
...ava/chat/rocket/android/infrastructure/LocalRepository.kt
+6
-0
SharedPreferencesLocalRepository.kt
...ndroid/infrastructure/SharedPreferencesLocalRepository.kt
+19
-1
MainNavigator.kt
...va/chat/rocket/android/main/presentation/MainNavigator.kt
+3
-2
NavHeaderViewModel.kt
.../chat/rocket/android/main/viewmodel/NavHeaderViewModel.kt
+0
-1
PermissionsInteractor.kt
...hat/rocket/android/server/domain/PermissionsInteractor.kt
+72
-0
PermissionsRepository.kt
...hat/rocket/android/server/domain/PermissionsRepository.kt
+24
-0
SaveActiveUsersInteractor.kt
...rocket/android/server/domain/SaveActiveUsersInteractor.kt
+2
-1
SharedPreferencesPermissionsRepository.kt
...infraestructure/SharedPreferencesPermissionsRepository.kt
+30
-0
SharedPreferencesSettingsRepository.kt
...er/infraestructure/SharedPreferencesSettingsRepository.kt
+3
-1
Rx.kt
app/src/main/java/chat/rocket/android/util/extensions/Rx.kt
+1
-2
fragment_chat_rooms.xml
app/src/main/res/layout/fragment_chat_rooms.xml
+11
-0
item_message.xml
app/src/main/res/layout/item_message.xml
+10
-0
strings.xml
app/src/main/res/values-es/strings.xml
+4
-1
strings.xml
app/src/main/res/values-fr/strings.xml
+4
-0
strings.xml
app/src/main/res/values-hi-rIN/strings.xml
+4
-0
strings.xml
app/src/main/res/values-pt-rBR/strings.xml
+15
-11
strings.xml
app/src/main/res/values-uk-rUA/strings.xml
+212
-0
strings.xml
app/src/main/res/values/strings.xml
+4
-0
No files found.
app/build.gradle
View file @
3f3ca5c5
...
...
@@ -14,7 +14,7 @@ android {
minSdkVersion
21
targetSdkVersion
versions
.
targetSdk
versionCode
2020
versionName
"2.
1.1
"
versionName
"2.
2.0
"
testInstrumentationRunner
"android.support.test.runner.AndroidJUnitRunner"
multiDexEnabled
true
}
...
...
app/src/main/java/chat/rocket/android/chatroom/adapter/BaseViewHolder.kt
View file @
3f3ca5c5
...
...
@@ -76,7 +76,7 @@ abstract class BaseViewHolder<T : BaseViewModel<*>>(
fun
onActionSelected
(
item
:
MenuItem
,
message
:
Message
)
}
private
val
long
ClickListener
=
{
view
:
View
->
private
val
on
ClickListener
=
{
view
:
View
->
if
(
data
?.
message
?.
isSystemMessage
()
==
false
)
{
val
menuItems
=
view
.
context
.
inflate
(
R
.
menu
.
message_actions
).
toList
()
menuItems
.
find
{
it
.
itemId
==
R
.
id
.
action_menu_msg_pin_unpin
}
?.
apply
{
...
...
@@ -87,11 +87,11 @@ abstract class BaseViewHolder<T : BaseViewModel<*>>(
val
adapter
=
ActionListAdapter
(
menuItems
,
this
@BaseViewHolder
)
BottomSheetMenu
(
adapter
).
show
(
view
.
context
)
}
true
}
internal
fun
setupActionMenu
(
view
:
View
)
{
if
(
listener
.
isActionsEnabled
())
{
view
.
setOnClickListener
(
onClickListener
)
if
(
view
is
ViewGroup
)
{
for
(
child
in
view
.
children
)
{
if
(
child
!
is
RecyclerView
&&
child
.
id
!=
R
.
id
.
recycler_view_reactions
)
{
...
...
@@ -99,7 +99,6 @@ abstract class BaseViewHolder<T : BaseViewModel<*>>(
}
}
}
view
.
setOnLongClickListener
(
longClickListener
)
}
}
...
...
app/src/main/java/chat/rocket/android/chatroom/adapter/MessageViewHolder.kt
View file @
3f3ca5c5
...
...
@@ -4,7 +4,9 @@ import android.graphics.Color
import
android.text.method.LinkMovementMethod
import
android.view.View
import
chat.rocket.android.chatroom.viewmodel.MessageViewModel
import
chat.rocket.android.util.extensions.setVisible
import
chat.rocket.android.widget.emoji.EmojiReactionListener
import
chat.rocket.core.model.isSystemMessage
import
kotlinx.android.synthetic.main.avatar.view.*
import
kotlinx.android.synthetic.main.item_message.view.*
...
...
@@ -33,6 +35,11 @@ class MessageViewHolder(
text_content
.
setTextColor
(
if
(
data
.
isTemporary
)
Color
.
GRAY
else
Color
.
BLACK
)
if
(!
data
.
message
.
isSystemMessage
()
&&
data
.
message
.
editedBy
!=
null
){
text_edit_indicator
.
setVisible
(
true
)
}
else
{
text_edit_indicator
.
setVisible
(
false
)
}
}
}
}
\ No newline at end of file
app/src/main/java/chat/rocket/android/chatroom/presentation/ChatRoomPresenter.kt
View file @
3f3ca5c5
...
...
@@ -12,6 +12,7 @@ import chat.rocket.android.chatroom.viewmodel.suggestion.CommandSuggestionViewMo
import
chat.rocket.android.chatroom.viewmodel.suggestion.PeopleSuggestionViewModel
import
chat.rocket.android.core.behaviours.showMessage
import
chat.rocket.android.core.lifecycle.CancelStrategy
import
chat.rocket.android.helper.UserHelper
import
chat.rocket.android.infrastructure.LocalRepository
import
chat.rocket.android.infrastructure.username
import
chat.rocket.android.server.domain.*
...
...
@@ -26,6 +27,7 @@ import chat.rocket.common.model.SimpleUser
import
chat.rocket.common.model.UserStatus
import
chat.rocket.common.model.roomTypeOf
import
chat.rocket.common.util.ifNull
import
chat.rocket.core.internal.realtime.setTypingStatus
import
chat.rocket.core.internal.realtime.socket.model.State
import
chat.rocket.core.internal.rest.*
import
chat.rocket.core.model.Command
...
...
@@ -45,24 +47,25 @@ class ChatRoomPresenter @Inject constructor(
private
val
view
:
ChatRoomView
,
private
val
navigator
:
ChatRoomNavigator
,
private
val
strategy
:
CancelStrategy
,
getSettingsInteractor
:
GetSettingsInteractor
,
serverInteractor
:
GetCurrentServerInteractor
,
private
val
getChatRoomsInteractor
:
GetChatRoomsInteractor
,
private
val
permissions
:
Get
PermissionsInteractor
,
private
val
permissions
:
PermissionsInteractor
,
private
val
uriInteractor
:
UriInteractor
,
private
val
messagesRepository
:
MessagesRepository
,
private
val
usersRepository
:
UsersRepository
,
private
val
roomsRepository
:
RoomRepository
,
private
val
localRepository
:
LocalRepository
,
factory
:
ConnectionManagerFactory
,
private
val
userHelper
:
UserHelper
,
private
val
mapper
:
ViewModelMapper
,
private
val
jobSchedulerInteractor
:
JobSchedulerInteractor
private
val
jobSchedulerInteractor
:
JobSchedulerInteractor
,
getSettingsInteractor
:
GetSettingsInteractor
,
serverInteractor
:
GetCurrentServerInteractor
,
factory
:
ConnectionManagerFactory
)
{
private
val
currentServer
=
serverInteractor
.
get
()
!!
private
val
manager
=
factory
.
create
(
currentServer
)
private
val
client
=
manager
.
client
private
var
settings
:
PublicSettings
=
getSettingsInteractor
.
get
(
serverInteractor
.
get
()
!!
)
private
val
currentLoggedUsername
=
localRepository
.
username
()
private
val
messagesChannel
=
Channel
<
Message
>()
private
var
chatRoomId
:
String
?
=
null
...
...
@@ -70,6 +73,13 @@ class ChatRoomPresenter @Inject constructor(
private
val
stateChannel
=
Channel
<
State
>()
private
var
lastState
=
manager
.
state
fun
setupChatRoom
()
{
launchUI
(
strategy
)
{
val
canPost
=
permissions
.
canPostToReadOnlyChannels
()
view
.
onRoomChanged
(
canPost
)
}
}
fun
loadMessages
(
chatRoomId
:
String
,
chatRoomType
:
String
,
offset
:
Long
=
0
)
{
this
.
chatRoomId
=
chatRoomId
this
.
chatRoomType
=
chatRoomType
...
...
@@ -127,7 +137,7 @@ class ChatRoomPresenter @Inject constructor(
// ignore message for now, will receive it on the stream
val
id
=
UUID
.
randomUUID
().
toString
()
val
message
=
if
(
messageId
==
null
)
{
val
username
=
localRepository
.
username
()
val
username
=
userHelper
.
username
()
val
newMessage
=
Message
(
id
=
id
,
roomId
=
chatRoomId
,
...
...
@@ -219,6 +229,22 @@ class ChatRoomPresenter @Inject constructor(
}
}
fun
sendTyping
()
{
launch
(
CommonPool
+
strategy
.
jobs
)
{
if
(
chatRoomId
!=
null
&&
currentLoggedUsername
!=
null
)
{
client
.
setTypingStatus
(
chatRoomId
.
toString
(),
currentLoggedUsername
,
true
)
}
}
}
fun
sendNotTyping
()
{
launch
(
CommonPool
+
strategy
.
jobs
)
{
if
(
chatRoomId
!=
null
&&
currentLoggedUsername
!=
null
)
{
client
.
setTypingStatus
(
chatRoomId
.
toString
(),
currentLoggedUsername
,
false
)
}
}
}
private
fun
markRoomAsRead
(
roomId
:
String
)
{
launchUI
(
strategy
)
{
try
{
...
...
@@ -547,7 +573,8 @@ class ChatRoomPresenter @Inject constructor(
launchUI
(
strategy
)
{
try
{
retryIO
(
"joinChat($chatRoomId)"
)
{
client
.
joinChat
(
chatRoomId
)
}
view
.
onJoined
()
val
canPost
=
permissions
.
canPostToReadOnlyChannels
()
view
.
onJoined
(
canPost
)
}
catch
(
ex
:
RocketChatException
)
{
Timber
.
e
(
ex
)
}
...
...
@@ -560,7 +587,7 @@ class ChatRoomPresenter @Inject constructor(
fun
react
(
messageId
:
String
,
emoji
:
String
)
{
launchUI
(
strategy
)
{
try
{
retryIO
(
"to
o
gleEmoji($messageId, $emoji)"
)
{
retryIO
(
"to
g
gleEmoji($messageId, $emoji)"
)
{
client
.
toggleReaction
(
messageId
,
emoji
.
removeSurrounding
(
":"
))
}
}
catch
(
ex
:
RocketChatException
)
{
...
...
app/src/main/java/chat/rocket/android/chatroom/presentation/ChatRoomView.kt
View file @
3f3ca5c5
...
...
@@ -109,8 +109,10 @@ interface ChatRoomView : LoadingView, MessageView {
fun
populateRoomSuggestions
(
chatRooms
:
List
<
ChatRoomSuggestionViewModel
>)
/**
* This user has joined the chat callback.
*
* @param canPost Whether the user can post a message or not.
*/
fun
onJoined
()
fun
onJoined
(
canPost
:
Boolean
)
fun
showReactionsPopup
(
messageId
:
String
)
...
...
@@ -120,4 +122,6 @@ interface ChatRoomView : LoadingView, MessageView {
* @param commands The list of available commands.
*/
fun
populateCommandSuggestions
(
commands
:
List
<
CommandSuggestionViewModel
>)
fun
onRoomChanged
(
canPost
:
Boolean
)
}
\ No newline at end of file
app/src/main/java/chat/rocket/android/chatroom/ui/ChatRoomActivity.kt
View file @
3f3ca5c5
...
...
@@ -27,22 +27,25 @@ fun Context.chatRoomIntent(
chatRoomType
:
String
,
isChatRoomReadOnly
:
Boolean
,
chatRoomLastSeen
:
Long
,
isChatRoomSubscribed
:
Boolean
=
true
isChatRoomSubscribed
:
Boolean
=
true
,
isChatRoomOwner
:
Boolean
=
false
):
Intent
{
return
Intent
(
this
,
ChatRoomActivity
::
class
.
java
).
apply
{
putExtra
(
INTENT_CHAT_ROOM_ID
,
chatRoomId
)
putExtra
(
INTENT_CHAT_ROOM_NAME
,
chatRoomName
)
putExtra
(
INTENT_CHAT_ROOM_TYPE
,
chatRoomType
)
putExtra
(
INTENT_
IS_CHAT_ROOM
_READ_ONLY
,
isChatRoomReadOnly
)
putExtra
(
INTENT_
CHAT_ROOM_IS
_READ_ONLY
,
isChatRoomReadOnly
)
putExtra
(
INTENT_CHAT_ROOM_LAST_SEEN
,
chatRoomLastSeen
)
putExtra
(
INTENT_CHAT_IS_SUBSCRIBED
,
isChatRoomSubscribed
)
putExtra
(
INTENT_CHAT_ROOM_IS_OWNER
,
isChatRoomOwner
)
}
}
private
const
val
INTENT_CHAT_ROOM_ID
=
"chat_room_id"
private
const
val
INTENT_CHAT_ROOM_NAME
=
"chat_room_name"
private
const
val
INTENT_CHAT_ROOM_TYPE
=
"chat_room_type"
private
const
val
INTENT_IS_CHAT_ROOM_READ_ONLY
=
"is_chat_room_read_only"
private
const
val
INTENT_CHAT_ROOM_IS_READ_ONLY
=
"chat_room_is_read_only"
private
const
val
INTENT_CHAT_ROOM_IS_OWNER
=
"chat_room_is_owner"
private
const
val
INTENT_CHAT_ROOM_LAST_SEEN
=
"chat_room_last_seen"
private
const
val
INTENT_CHAT_IS_SUBSCRIBED
=
"is_chat_room_subscribed"
...
...
@@ -59,6 +62,7 @@ class ChatRoomActivity : AppCompatActivity(), HasSupportFragmentInjector {
private
lateinit
var
chatRoomType
:
String
private
var
isChatRoomReadOnly
:
Boolean
=
false
private
var
isChatRoomSubscribed
:
Boolean
=
true
private
var
isChatRoomOwner
:
Boolean
=
false
private
var
chatRoomLastSeen
:
Long
=
-
1L
override
fun
onCreate
(
savedInstanceState
:
Bundle
?)
{
...
...
@@ -84,8 +88,11 @@ class ChatRoomActivity : AppCompatActivity(), HasSupportFragmentInjector {
chatRoomType
=
intent
.
getStringExtra
(
INTENT_CHAT_ROOM_TYPE
)
requireNotNull
(
chatRoomType
)
{
"no chat_room_type provided in Intent extras"
}
isChatRoomReadOnly
=
intent
.
getBooleanExtra
(
INTENT_IS_CHAT_ROOM_READ_ONLY
,
true
)
requireNotNull
(
chatRoomType
)
{
"no is_chat_room_read_only provided in Intent extras"
}
isChatRoomReadOnly
=
intent
.
getBooleanExtra
(
INTENT_CHAT_ROOM_IS_READ_ONLY
,
true
)
requireNotNull
(
isChatRoomReadOnly
)
{
"no chat_room_is_read_only provided in Intent extras"
}
isChatRoomOwner
=
intent
.
getBooleanExtra
(
INTENT_CHAT_ROOM_IS_OWNER
,
false
)
requireNotNull
(
isChatRoomOwner
)
{
"no chat_room_is_owner provided in Intent extras"
}
setupToolbar
()
...
...
@@ -96,7 +103,7 @@ class ChatRoomActivity : AppCompatActivity(), HasSupportFragmentInjector {
if
(
supportFragmentManager
.
findFragmentByTag
(
TAG_CHAT_ROOM_FRAGMENT
)
==
null
)
{
addFragment
(
TAG_CHAT_ROOM_FRAGMENT
,
R
.
id
.
fragment_container
)
{
newInstance
(
chatRoomId
,
chatRoomName
,
chatRoomType
,
isChatRoomReadOnly
,
chatRoomLastSeen
,
isChatRoomSubscribed
)
isChatRoomSubscribed
,
isChatRoomOwner
)
}
}
}
...
...
app/src/main/java/chat/rocket/android/chatroom/ui/ChatRoomFragment.kt
View file @
3f3ca5c5
...
...
@@ -30,11 +30,14 @@ import chat.rocket.android.util.extensions.*
import
chat.rocket.android.widget.emoji.*
import
chat.rocket.core.internal.realtime.socket.model.State
import
dagger.android.support.AndroidSupportInjection
import
io.reactivex.Observable
import
io.reactivex.disposables.CompositeDisposable
import
io.reactivex.disposables.Disposable
import
kotlinx.android.synthetic.main.fragment_chat_room.*
import
kotlinx.android.synthetic.main.message_attachment_options.*
import
kotlinx.android.synthetic.main.message_composer.*
import
kotlinx.android.synthetic.main.message_list.*
import
java.util.concurrent.TimeUnit
import
java.util.concurrent.atomic.AtomicInteger
import
javax.inject.Inject
...
...
@@ -44,7 +47,8 @@ fun newInstance(
chatRoomType
:
String
,
isChatRoomReadOnly
:
Boolean
,
chatRoomLastSeen
:
Long
,
isSubscribed
:
Boolean
=
true
isSubscribed
:
Boolean
=
true
,
isChatRoomOwner
:
Boolean
=
false
):
Fragment
{
return
ChatRoomFragment
().
apply
{
arguments
=
Bundle
(
1
).
apply
{
...
...
@@ -54,6 +58,7 @@ fun newInstance(
putBoolean
(
BUNDLE_IS_CHAT_ROOM_READ_ONLY
,
isChatRoomReadOnly
)
putLong
(
BUNDLE_CHAT_ROOM_LAST_SEEN
,
chatRoomLastSeen
)
putBoolean
(
BUNDLE_CHAT_ROOM_IS_SUBSCRIBED
,
isSubscribed
)
putBoolean
(
BUNDLE_CHAT_ROOM_IS_OWNER
,
isChatRoomOwner
)
}
}
}
...
...
@@ -65,6 +70,7 @@ private const val BUNDLE_IS_CHAT_ROOM_READ_ONLY = "is_chat_room_read_only"
private
const
val
REQUEST_CODE_FOR_PERFORM_SAF
=
42
private
const
val
BUNDLE_CHAT_ROOM_LAST_SEEN
=
"chat_room_last_seen"
private
const
val
BUNDLE_CHAT_ROOM_IS_SUBSCRIBED
=
"chat_room_is_subscribed"
private
const
val
BUNDLE_CHAT_ROOM_IS_OWNER
=
"chat_room_is_owner"
class
ChatRoomFragment
:
Fragment
(),
ChatRoomView
,
EmojiKeyboardListener
,
EmojiReactionListener
{
@Inject
...
...
@@ -77,6 +83,7 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
private
lateinit
var
chatRoomType
:
String
private
var
isSubscribed
:
Boolean
=
true
private
var
isChatRoomReadOnly
:
Boolean
=
false
private
var
isChatRoomOwner
:
Boolean
=
false
private
lateinit
var
emojiKeyboardPopup
:
EmojiKeyboardPopup
private
var
chatRoomLastSeen
:
Long
=
-
1
private
lateinit
var
actionSnackbar
:
ActionSnackbar
...
...
@@ -106,6 +113,8 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
isChatRoomReadOnly
=
bundle
.
getBoolean
(
BUNDLE_IS_CHAT_ROOM_READ_ONLY
)
isSubscribed
=
bundle
.
getBoolean
(
BUNDLE_CHAT_ROOM_IS_SUBSCRIBED
)
chatRoomLastSeen
=
bundle
.
getLong
(
BUNDLE_CHAT_ROOM_LAST_SEEN
)
isChatRoomOwner
=
bundle
.
getBoolean
(
BUNDLE_CHAT_ROOM_IS_OWNER
)
}
else
{
requireNotNull
(
bundle
)
{
"no arguments supplied when the fragment was instantiated"
}
}
...
...
@@ -124,11 +133,11 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
super
.
onViewCreated
(
view
,
savedInstanceState
)
setupToolbar
(
chatRoomName
)
presenter
.
setupChatRoom
()
presenter
.
loadMessages
(
chatRoomId
,
chatRoomType
)
presenter
.
loadChatRooms
()
setupRecyclerView
()
setupFab
()
setupMessageComposer
()
setupSuggestionsView
()
setupActionSnackbar
()
activity
?.
apply
{
...
...
@@ -148,7 +157,7 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
presenter
.
unsubscribeMessages
(
chatRoomId
)
handler
.
removeCallbacksAndMessages
(
null
)
unsubscribeTextMessage
()
unsubscribe
Compose
TextMessage
()
// Hides the keyboard (if it's opened) before going to any view.
activity
?.
apply
{
...
...
@@ -227,6 +236,10 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
}
}
override
fun
onRoomChanged
(
canPost
:
Boolean
)
{
setupMessageComposer
(
isChatRoomOwner
||
canPost
)
}
private
fun
toggleNoChatView
(
size
:
Int
)
{
if
(
size
==
0
){
image_chat_icon
.
setVisible
(
true
)
...
...
@@ -517,12 +530,12 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
}
}
override
fun
onJoined
()
{
override
fun
onJoined
(
canPost
:
Boolean
)
{
ui
{
input_container
.
setVisible
(
true
)
button_join_chat
.
setVisible
(
false
)
isSubscribed
=
true
setupMessageComposer
()
setupMessageComposer
(
isChatRoomOwner
)
}
}
...
...
@@ -553,8 +566,8 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
}
}
private
fun
setupMessageComposer
()
{
if
(
isChatRoomReadOnly
)
{
private
fun
setupMessageComposer
(
canPost
:
Boolean
)
{
if
(
!
canPost
&&
isChatRoomReadOnly
)
{
text_room_is_read_only
.
setVisible
(
true
)
input_container
.
setVisible
(
false
)
}
else
if
(!
isSubscribed
)
{
...
...
@@ -567,7 +580,7 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
button_show_attachment_options
.
alpha
=
1f
button_show_attachment_options
.
setVisible
(
true
)
subscribeTextMessage
()
subscribe
Compose
TextMessage
()
emojiKeyboardPopup
=
EmojiKeyboardPopup
(
activity
!!
,
activity
!!
.
findViewById
(
R
.
id
.
fragment_container
))
emojiKeyboardPopup
.
listener
=
this
text_message
.
listener
=
object
:
ComposerEditText
.
ComposerEditTextListener
{
...
...
@@ -672,18 +685,30 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
})
}
private
fun
subscribeTextMessage
()
{
val
disposable
=
text_message
.
asObservable
(
0
)
.
subscribe
({
t
->
setupComposeMessageButtons
(
t
)
})
private
fun
subscribeComposeTextMessage
()
{
val
editTextObservable
=
text_message
.
asObservable
()
compositeDisposable
.
add
(
disposable
)
compositeDisposable
.
addAll
(
subscribeComposeButtons
(
editTextObservable
),
subscribeComposeTypingStatus
(
editTextObservable
)
)
}
private
fun
unsubscribeTextMessage
()
{
private
fun
unsubscribe
Compose
TextMessage
()
{
compositeDisposable
.
clear
()
}
private
fun
setupComposeMessageButtons
(
charSequence
:
CharSequence
)
{
private
fun
subscribeComposeButtons
(
observable
:
Observable
<
CharSequence
>):
Disposable
{
return
observable
.
subscribe
{
t
->
setupComposeButtons
(
t
)
}
}
private
fun
subscribeComposeTypingStatus
(
observable
:
Observable
<
CharSequence
>):
Disposable
{
return
observable
.
debounce
(
300
,
TimeUnit
.
MILLISECONDS
)
.
skip
(
1
)
.
subscribe
{
t
->
sendTypingStatus
(
t
)
}
}
private
fun
setupComposeButtons
(
charSequence
:
CharSequence
)
{
if
(
charSequence
.
isNotEmpty
()
&&
playComposeMessageButtonsAnimation
)
{
button_show_attachment_options
.
fadeOut
(
1F
,
0F
,
120
)
button_send
.
fadeIn
(
0F
,
1F
,
120
)
...
...
@@ -697,6 +722,14 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
}
}
private
fun
sendTypingStatus
(
charSequence
:
CharSequence
)
{
if
(
charSequence
.
isNotBlank
())
{
presenter
.
sendTyping
()
}
else
{
presenter
.
sendNotTyping
()
}
}
private
fun
showAttachmentOptions
()
{
view_dim
.
setVisible
(
true
)
...
...
app/src/main/java/chat/rocket/android/chatroom/viewmodel/ViewModelMapper.kt
View file @
3f3ca5c5
...
...
@@ -313,6 +313,7 @@ class ViewModelMapper @Inject constructor(
}
private
fun
getSystemMessage
(
message
:
Message
):
CharSequence
{
println
(
message
)
val
content
=
when
(
message
.
type
)
{
//TODO: Add implementation for Welcome type.
is
MessageType
.
MessageRemoved
->
context
.
getString
(
R
.
string
.
message_removed
)
...
...
@@ -322,6 +323,8 @@ class ViewModelMapper @Inject constructor(
is
MessageType
.
RoomNameChanged
->
context
.
getString
(
R
.
string
.
message_room_name_changed
,
message
.
message
,
message
.
sender
?.
username
)
is
MessageType
.
UserRemoved
->
context
.
getString
(
R
.
string
.
message_user_removed_by
,
message
.
message
,
message
.
sender
?.
username
)
is
MessageType
.
MessagePinned
->
context
.
getString
(
R
.
string
.
message_pinned
)
is
MessageType
.
UserMuted
->
context
.
getString
(
R
.
string
.
message_muted
,
message
.
message
,
message
.
sender
?.
username
)
is
MessageType
.
UserUnMuted
->
context
.
getString
(
R
.
string
.
message_unmuted
,
message
.
message
,
message
.
sender
?.
username
)
else
->
{
throw
InvalidParameterException
(
"Invalid message type: ${message.type}"
)
}
...
...
app/src/main/java/chat/rocket/android/chatrooms/presentation/ChatRoomsPresenter.kt
View file @
3f3ca5c5
package
chat.rocket.android.chatrooms.presentation
import
chat.rocket.android.R
import
chat.rocket.android.chatroom.viewmodel.ViewModelMapper
import
chat.rocket.android.core.lifecycle.CancelStrategy
import
chat.rocket.android.helper.ChatRoomsSortOrder
import
chat.rocket.android.helper.Constants
import
chat.rocket.android.helper.SharedPreferenceHelper
import
chat.rocket.android.helper.UserHelper
import
chat.rocket.android.infrastructure.LocalRepository
import
chat.rocket.android.main.presentation.MainNavigator
import
chat.rocket.android.server.domain.*
import
chat.rocket.android.server.infraestructure.ConnectionManager
...
...
@@ -23,6 +26,8 @@ import chat.rocket.core.internal.model.Subscription
import
chat.rocket.core.internal.realtime.socket.model.State
import
chat.rocket.core.internal.realtime.socket.model.StreamMessage
import
chat.rocket.core.internal.realtime.socket.model.Type
import
chat.rocket.core.internal.rest.me
import
chat.rocket.core.internal.rest.permissions
import
chat.rocket.core.internal.rest.spotlight
import
chat.rocket.core.model.ChatRoom
import
chat.rocket.core.model.Room
...
...
@@ -45,6 +50,9 @@ class ChatRoomsPresenter @Inject constructor(
private
val
refreshSettingsInteractor
:
RefreshSettingsInteractor
,
private
val
viewModelMapper
:
ViewModelMapper
,
private
val
jobSchedulerInteractor
:
JobSchedulerInteractor
,
private
val
permissionsInteractor
:
PermissionsInteractor
,
private
val
localRepository
:
LocalRepository
,
private
val
userHelper
:
UserHelper
,
settingsRepository
:
SettingsRepository
,
factory
:
ConnectionManagerFactory
)
{
...
...
@@ -69,6 +77,8 @@ class ChatRoomsPresenter @Inject constructor(
refreshSettingsInteractor
.
refresh
(
currentServer
)
}
view
.
updateChatRooms
(
getUserChatRooms
())
val
permissions
=
retryIO
{
client
.
permissions
()
}
permissionsInteractor
.
saveAll
(
permissions
)
}
catch
(
ex
:
RocketChatException
)
{
ex
.
message
?.
let
{
view
.
showMessage
(
it
)
...
...
@@ -85,7 +95,8 @@ class ChatRoomsPresenter @Inject constructor(
}
fun
loadChatRoom
(
chatRoom
:
ChatRoom
)
{
val
roomName
=
if
(
chatRoom
.
type
is
RoomType
.
DirectMessage
val
isDirectMessage
=
chatRoom
.
type
is
RoomType
.
DirectMessage
val
roomName
=
if
(
isDirectMessage
&&
chatRoom
.
fullName
!=
null
&&
settings
.
useRealName
())
{
chatRoom
.
fullName
!!
...
...
@@ -93,10 +104,40 @@ class ChatRoomsPresenter @Inject constructor(
chatRoom
.
name
}
navigator
.
toChatRoom
(
chatRoom
.
id
,
roomName
,
chatRoom
.
type
.
toString
(),
chatRoom
.
readonly
?:
false
,
chatRoom
.
lastSeen
?:
-
1
,
chatRoom
.
open
)
launchUI
(
strategy
)
{
val
myself
=
getCurrentUser
()
if
(
myself
?.
username
==
null
)
{
view
.
showMessage
(
R
.
string
.
msg_generic_error
)
}
else
{
val
isChatRoomOwner
=
chatRoom
.
user
?.
username
==
myself
.
username
||
isDirectMessage
navigator
.
toChatRoom
(
chatRoom
.
id
,
roomName
,
chatRoom
.
type
.
toString
(),
chatRoom
.
readonly
?:
false
,
chatRoom
.
lastSeen
?:
-
1
,
chatRoom
.
open
,
isChatRoomOwner
)
}
}
}
private
suspend
fun
getCurrentUser
():
User
?
{
userHelper
.
user
()
?.
let
{
return
it
}
try
{
val
myself
=
retryIO
{
client
.
me
()
}
val
user
=
User
(
id
=
myself
.
id
,
username
=
myself
.
username
,
name
=
myself
.
name
,
status
=
myself
.
status
,
utcOffset
=
myself
.
utcOffset
,
emails
=
null
,
roles
=
myself
.
roles
)
localRepository
.
saveCurrentUser
(
url
=
currentServer
,
user
=
user
)
}
catch
(
ex
:
RocketChatException
)
{
Timber
.
e
(
ex
)
}
return
null
}
/**
...
...
@@ -415,7 +456,7 @@ class ChatRoomsPresenter @Inject constructor(
val
newRoom
=
ChatRoom
(
id
=
room
.
id
,
type
=
room
.
type
,
user
=
room
.
user
?:
user
,
user
=
room
.
user
,
status
=
getActiveUsersInteractor
.
getActiveUserByUsername
(
currentServer
,
room
.
name
?:
name
...
...
@@ -454,7 +495,7 @@ class ChatRoomsPresenter @Inject constructor(
val
newRoom
=
ChatRoom
(
id
=
subscription
.
roomId
,
type
=
subscription
.
type
,
user
=
subscription
.
user
?:
user
,
user
=
user
,
status
=
getActiveUsersInteractor
.
getActiveUserByUsername
(
currentServer
,
subscription
.
name
...
...
app/src/main/java/chat/rocket/android/chatrooms/ui/ChatRoomsAdapter.kt
View file @
3f3ca5c5
...
...
@@ -25,10 +25,13 @@ import com.facebook.drawee.view.SimpleDraweeView
import
kotlinx.android.synthetic.main.item_chat.view.*
import
kotlinx.android.synthetic.main.unread_messages_badge.view.*
class
ChatRoomsAdapter
(
private
val
context
:
Context
,
private
val
settings
:
PublicSettings
,
private
val
localRepository
:
LocalRepository
,
private
val
listener
:
(
ChatRoom
)
->
Unit
)
:
RecyclerView
.
Adapter
<
ChatRoomsAdapter
.
ViewHolder
>()
{
class
ChatRoomsAdapter
(
private
val
context
:
Context
,
private
val
settings
:
PublicSettings
,
private
val
localRepository
:
LocalRepository
,
private
val
listener
:
(
ChatRoom
)
->
Unit
)
:
RecyclerView
.
Adapter
<
ChatRoomsAdapter
.
ViewHolder
>()
{
var
dataSet
:
MutableList
<
ChatRoom
>
=
ArrayList
()
override
fun
onCreateViewHolder
(
parent
:
ViewGroup
,
viewType
:
Int
):
ViewHolder
=
ViewHolder
(
parent
.
inflate
(
R
.
layout
.
item_chat
))
...
...
app/src/main/java/chat/rocket/android/chatrooms/ui/ChatRoomsFragment.kt
View file @
3f3ca5c5
...
...
@@ -23,7 +23,6 @@ import chat.rocket.android.helper.SharedPreferenceHelper
import
chat.rocket.android.infrastructure.LocalRepository
import
chat.rocket.android.server.domain.GetCurrentServerInteractor
import
chat.rocket.android.server.domain.SettingsRepository
import
chat.rocket.android.server.domain.showLastMessage
import
chat.rocket.android.util.extensions.*
import
chat.rocket.android.widget.DividerItemDecoration
import
chat.rocket.common.model.RoomType
...
...
@@ -37,10 +36,14 @@ import timber.log.Timber
import
javax.inject.Inject
class
ChatRoomsFragment
:
Fragment
(),
ChatRoomsView
{
@Inject
lateinit
var
presenter
:
ChatRoomsPresenter
@Inject
lateinit
var
serverInteractor
:
GetCurrentServerInteractor
@Inject
lateinit
var
settingsRepository
:
SettingsRepository
@Inject
lateinit
var
localRepository
:
LocalRepository
@Inject
lateinit
var
presenter
:
ChatRoomsPresenter
@Inject
lateinit
var
serverInteractor
:
GetCurrentServerInteractor
@Inject
lateinit
var
settingsRepository
:
SettingsRepository
@Inject
lateinit
var
localRepository
:
LocalRepository
private
lateinit
var
preferences
:
SharedPreferences
private
var
searchView
:
SearchView
?
=
null
private
val
handler
=
Handler
()
...
...
@@ -136,9 +139,9 @@ class ChatRoomsFragment : Fragment(), ChatRoomsView {
})
val
dialogSort
=
AlertDialog
.
Builder
(
context
)
.
setTitle
(
R
.
string
.
dialog_sort_title
)
.
setView
(
dialogLayout
)
.
setPositiveButton
(
"Done"
,
{
dialog
,
_
->
dialog
.
dismiss
()
})
.
setTitle
(
R
.
string
.
dialog_sort_title
)
.
setView
(
dialogLayout
)
.
setPositiveButton
(
"Done"
,
{
dialog
,
_
->
dialog
.
dismiss
()
})
dialogSort
.
show
()
}
...
...
@@ -146,9 +149,9 @@ class ChatRoomsFragment : Fragment(), ChatRoomsView {
return
super
.
onOptionsItemSelected
(
item
)
}
private
fun
invalidateQueryOnSearch
(){
private
fun
invalidateQueryOnSearch
()
{
searchView
?.
let
{
if
(!
searchView
!!
.
isIconified
){
if
(!
searchView
!!
.
isIconified
)
{
queryChatRoomsByName
(
searchView
!!
.
query
.
toString
())
}
}
...
...
@@ -163,7 +166,11 @@ class ChatRoomsFragment : Fragment(), ChatRoomsView {
/*val diff = async(CommonPool) {
DiffUtil.calculateDiff(RoomsDiffCallback(adapter.baseAdapter.dataSet, newDataSet))
}.await()*/
if
(
newDataSet
.
isEmpty
())
{
text_no_search
.
visibility
=
View
.
VISIBLE
}
else
{
text_no_search
.
visibility
=
View
.
GONE
}
if
(
isActive
)
{
adapter
.
baseAdapter
.
updateRooms
(
newDataSet
)
// TODO - fix crash to re-enable diff.dispatchUpdatesTo(adapter)
...
...
@@ -179,7 +186,7 @@ class ChatRoomsFragment : Fragment(), ChatRoomsView {
ui
{
text_no_data_to_display
.
setVisible
(
true
)
}
}
override
fun
showLoading
(){
override
fun
showLoading
()
{
ui
{
view_loading
.
setVisible
(
true
)
}
}
...
...
@@ -236,19 +243,18 @@ class ChatRoomsFragment : Fragment(), ChatRoomsView {
ui
{
recycler_view
.
layoutManager
=
LinearLayoutManager
(
it
,
LinearLayoutManager
.
VERTICAL
,
false
)
recycler_view
.
addItemDecoration
(
DividerItemDecoration
(
it
,
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_start
),
resources
.
getDimensionPixelSize
(
R
.
dimen
.
divider_item_decorator_bound_end
)))
recycler_view
.
itemAnimator
=
DefaultItemAnimator
()
// TODO - use a ViewModel Mapper instead of using settings on the adapter
println
(
serverInteractor
.
get
()
+
" -> ${settingsRepository.get(serverInteractor.get()!!).showLastMessage()}"
)
val
baseAdapter
=
ChatRoomsAdapter
(
it
,
settingsRepository
.
get
(
serverInteractor
.
get
()
!!
),
localRepository
)
{
chatRoom
->
presenter
.
loadChatRoom
(
chatRoom
)
settingsRepository
.
get
(
serverInteractor
.
get
()
!!
),
localRepository
)
{
chatRoom
->
presenter
.
loadChatRoom
(
chatRoom
)
}
sectionedAdapter
=
SimpleSectionedRecyclerViewAdapter
(
it
,
R
.
layout
.
item_chatroom_header
,
R
.
id
.
text_chatroom_header
,
baseAdapter
)
R
.
layout
.
item_chatroom_header
,
R
.
id
.
text_chatroom_header
,
baseAdapter
)
recycler_view
.
adapter
=
sectionedAdapter
}
}
...
...
app/src/main/java/chat/rocket/android/dagger/module/AppModule.kt
View file @
3f3ca5c5
...
...
@@ -14,12 +14,10 @@ import chat.rocket.android.app.RocketChatDatabase
import
chat.rocket.android.authentication.infraestructure.SharedPreferencesMultiServerTokenRepository
import
chat.rocket.android.authentication.infraestructure.SharedPreferencesTokenRepository
import
chat.rocket.android.chatroom.service.MessageService
import
chat.rocket.android.dagger.qualifier.ForFresco
import
chat.rocket.android.dagger.qualifier.ForMessages
import
chat.rocket.android.helper.FrescoAuthInterceptor
import
chat.rocket.android.helper.MessageParser
import
chat.rocket.android.infrastructure.LocalRepository
import
chat.rocket.android.infrastructure.SharedPrefsLocalRepository
import
chat.rocket.android.infrastructure.SharedPref
erence
sLocalRepository
import
chat.rocket.android.push.GroupedPush
import
chat.rocket.android.push.PushManager
import
chat.rocket.android.server.domain.*
...
...
@@ -43,7 +41,6 @@ import com.squareup.moshi.Moshi
import
dagger.Module
import
dagger.Provides
import
kotlinx.coroutines.experimental.Job
import
okhttp3.Interceptor
import
okhttp3.OkHttpClient
import
okhttp3.logging.HttpLoggingInterceptor
import
ru.noties.markwon.SpannableConfiguration
...
...
@@ -111,32 +108,16 @@ class AppModule {
@Singleton
fun
provideOkHttpClient
(
logger
:
HttpLoggingInterceptor
):
OkHttpClient
{
return
OkHttpClient
.
Builder
()
.
addInterceptor
(
logger
)
.
connectTimeout
(
15
,
TimeUnit
.
SECONDS
)
.
readTimeout
(
20
,
TimeUnit
.
SECONDS
)
.
writeTimeout
(
15
,
TimeUnit
.
SECONDS
)
.
build
()
}
@Provides
@ForFresco
@Singleton
fun
provideFrescoAuthInterceptor
(
tokenRepository
:
TokenRepository
,
currentServerInteractor
:
GetCurrentServerInteractor
):
Interceptor
{
return
FrescoAuthInterceptor
(
tokenRepository
,
currentServerInteractor
)
}
@Provides
@ForFresco
@Singleton
fun
provideFrescoOkHttpClient
(
okHttpClient
:
OkHttpClient
,
@ForFresco
authInterceptor
:
Interceptor
):
OkHttpClient
{
return
okHttpClient
.
newBuilder
().
apply
{
//addInterceptor(authInterceptor)
}.
build
()
.
addInterceptor
(
logger
)
.
connectTimeout
(
15
,
TimeUnit
.
SECONDS
)
.
readTimeout
(
20
,
TimeUnit
.
SECONDS
)
.
writeTimeout
(
15
,
TimeUnit
.
SECONDS
)
.
build
()
}
@Provides
@Singleton
fun
provideImagePipelineConfig
(
context
:
Context
,
@ForFresco
okHttpClient
:
OkHttpClient
):
ImagePipelineConfig
{
fun
provideImagePipelineConfig
(
context
:
Context
,
okHttpClient
:
OkHttpClient
):
ImagePipelineConfig
{
val
listeners
=
setOf
(
RequestLoggingListener
())
return
OkHttpImagePipelineConfigFactory
.
newBuilder
(
context
,
okHttpClient
)
...
...
@@ -177,8 +158,8 @@ class AppModule {
@Provides
@Singleton
fun
provideLocalRepository
(
prefs
:
SharedPreferences
):
LocalRepository
{
return
SharedPref
sLocalRepository
(
prefs
)
fun
provideLocalRepository
(
prefs
:
SharedPreferences
,
moshi
:
Moshi
):
LocalRepository
{
return
SharedPref
erencesLocalRepository
(
prefs
,
moshi
)
}
@Provides
...
...
@@ -193,6 +174,12 @@ class AppModule {
return
SharedPreferencesSettingsRepository
(
localRepository
)
}
@Provides
@Singleton
fun
providePermissionsRepository
(
localRepository
:
LocalRepository
,
moshi
:
Moshi
):
PermissionsRepository
{
return
SharedPreferencesPermissionsRepository
(
localRepository
,
moshi
)
}
@Provides
@Singleton
fun
provideRoomRepository
():
RoomRepository
{
...
...
@@ -258,7 +245,7 @@ class AppModule {
@Provides
@Singleton
fun
provideConfiguration
(
context
:
Application
,
client
:
OkHttpClient
):
SpannableConfiguration
{
fun
provideConfiguration
(
context
:
Application
):
SpannableConfiguration
{
val
res
=
context
.
resources
return
SpannableConfiguration
.
builder
(
context
)
.
theme
(
SpannableTheme
.
builder
()
...
...
@@ -273,12 +260,6 @@ class AppModule {
return
MessageParser
(
context
,
configuration
,
settingsInteractor
.
get
(
url
))
}
@Provides
@Singleton
fun
providePermissionInteractor
(
settingsRepository
:
SettingsRepository
,
serverRepository
:
CurrentServerRepository
):
GetPermissionsInteractor
{
return
GetPermissionsInteractor
(
settingsRepository
,
serverRepository
)
}
@Provides
@Singleton
fun
provideAccountsRepository
(
preferences
:
SharedPreferences
,
moshi
:
Moshi
):
AccountsRepository
=
...
...
app/src/main/java/chat/rocket/android/dagger/module/LocalModule.kt
View file @
3f3ca5c5
...
...
@@ -3,7 +3,21 @@ package chat.rocket.android.dagger.module
import
android.content.Context
import
android.content.SharedPreferences
import
chat.rocket.android.infrastructure.LocalRepository
import
chat.rocket.android.infrastructure.SharedPrefsLocalRepository
import
chat.rocket.android.infrastructure.SharedPreferencesLocalRepository
import
chat.rocket.android.server.domain.CurrentServerRepository
import
chat.rocket.android.server.domain.GetCurrentServerInteractor
import
chat.rocket.android.server.infraestructure.SharedPrefsCurrentServerRepository
import
chat.rocket.android.util.AppJsonAdapterFactory
import
chat.rocket.android.util.TimberLogger
import
chat.rocket.common.internal.FallbackSealedClassJsonAdapter
import
chat.rocket.common.internal.ISO8601Date
import
chat.rocket.common.model.TimestampAdapter
import
chat.rocket.common.util.CalendarISO8601Converter
import
chat.rocket.common.util.Logger
import
chat.rocket.common.util.PlatformLogger
import
chat.rocket.core.internal.AttachmentAdapterFactory
import
chat.rocket.core.internal.ReactionsAdapter
import
com.squareup.moshi.Moshi
import
dagger.Module
import
dagger.Provides
import
javax.inject.Singleton
...
...
@@ -11,14 +25,53 @@ import javax.inject.Singleton
@Module
class
LocalModule
{
@Provides
@Singleton
fun
providePlatformLogger
():
PlatformLogger
{
return
TimberLogger
}
@Provides
@Singleton
fun
provideCurrentServerRepository
(
prefs
:
SharedPreferences
):
CurrentServerRepository
{
return
SharedPrefsCurrentServerRepository
(
prefs
)
}
@Provides
@Singleton
fun
provideMoshi
(
logger
:
PlatformLogger
,
currentServerInteractor
:
GetCurrentServerInteractor
):
Moshi
{
val
url
=
currentServerInteractor
.
get
()
?:
""
return
Moshi
.
Builder
()
.
add
(
FallbackSealedClassJsonAdapter
.
ADAPTER_FACTORY
)
.
add
(
AppJsonAdapterFactory
.
INSTANCE
)
.
add
(
AttachmentAdapterFactory
(
Logger
(
logger
,
url
)))
.
add
(
java
.
lang
.
Long
::
class
.
java
,
ISO8601Date
::
class
.
java
,
TimestampAdapter
(
CalendarISO8601Converter
())
)
.
add
(
Long
::
class
.
java
,
ISO8601Date
::
class
.
java
,
TimestampAdapter
(
CalendarISO8601Converter
())
)
.
add
(
ReactionsAdapter
())
.
build
()
}
@Provides
fun
provideSharedPreferences
(
context
:
Context
):
SharedPreferences
{
return
context
.
getSharedPreferences
(
"rocket.chat"
,
Context
.
MODE_PRIVATE
)
}
@Provides
@Singleton
fun
provideLocalRepository
(
prefs
:
SharedPreferences
):
LocalRepository
{
return
SharedPref
sLocalRepository
(
prefs
)
fun
provideLocalRepository
(
sharedPreferences
:
SharedPreferences
,
moshi
:
Moshi
):
LocalRepository
{
return
SharedPref
erencesLocalRepository
(
sharedPreferences
,
moshi
)
}
}
\ No newline at end of file
app/src/main/java/chat/rocket/android/dagger/qualifier/ForFresco.kt
deleted
100644 → 0
View file @
1a1213da
package
chat.rocket.android.dagger.qualifier
import
javax.inject.Qualifier
@Qualifier
@Retention
(
AnnotationRetention
.
RUNTIME
)
annotation
class
ForFresco
\ No newline at end of file
app/src/main/java/chat/rocket/android/helper/FrescoAuthInterceptor.kt
deleted
100644 → 0
View file @
1a1213da
package
chat.rocket.android.helper
import
chat.rocket.android.server.domain.GetCurrentServerInteractor
import
chat.rocket.android.server.domain.TokenRepository
import
okhttp3.Interceptor
import
okhttp3.Response
class
FrescoAuthInterceptor
(
private
val
tokenRepository
:
TokenRepository
,
private
val
currentServerInteractor
:
GetCurrentServerInteractor
)
:
Interceptor
{
override
fun
intercept
(
chain
:
Interceptor
.
Chain
):
Response
{
var
request
=
chain
.
request
()
currentServerInteractor
.
get
()
?.
let
{
serverUrl
->
val
token
=
tokenRepository
.
get
(
serverUrl
)
return
@let
token
?.
let
{
val
url
=
request
.
url
().
newBuilder
().
apply
{
addQueryParameter
(
"rc_uid"
,
token
.
userId
)
addQueryParameter
(
"rc_token"
,
token
.
authToken
)
}.
build
()
request
=
request
.
newBuilder
().
apply
{
url
(
url
)
}.
build
()
}
}
return
chain
.
proceed
(
request
)
}
}
\ No newline at end of file
app/src/main/java/chat/rocket/android/helper/UserHelper.kt
0 → 100644
View file @
3f3ca5c5
package
chat.rocket.android.helper
import
chat.rocket.android.infrastructure.LocalRepository
import
chat.rocket.android.server.domain.GetCurrentServerInteractor
import
chat.rocket.android.server.domain.PublicSettings
import
chat.rocket.android.server.domain.SettingsRepository
import
chat.rocket.android.server.domain.useRealName
import
chat.rocket.common.model.User
import
javax.inject.Inject
class
UserHelper
@Inject
constructor
(
private
val
localRepository
:
LocalRepository
,
private
val
getCurrentServerInteractor
:
GetCurrentServerInteractor
,
settingsRepository
:
SettingsRepository
)
{
private
val
settings
:
PublicSettings
=
settingsRepository
.
get
(
getCurrentServerInteractor
.
get
()
!!
)
/**
* Return the display name for the given [user].
* If setting 'Use_Real_Name' is true then the real name will be given, or else
* the username without the '@' is yielded. The fallback for any case is the username, which
* could be null.
*/
fun
displayName
(
user
:
User
):
String
?
{
return
if
(
settings
.
useRealName
())
user
.
name
?:
user
.
username
else
user
.
username
}
/**
* Return current logged user's display name.
*
* @see displayName
*/
fun
displayName
():
String
?
{
user
()
?.
let
{
return
displayName
(
it
)
}
return
null
}
/**
* Return current logged [User].
*/
fun
user
():
User
?
{
return
localRepository
.
getCurrentUser
(
serverUrl
())
}
/**
* Return the username for the current logged [User].
*/
fun
username
():
String
?
=
user
()
?.
username
/**
* Whether current [User] is admin on the current server.
*/
fun
isAdmin
():
Boolean
{
return
user
()
?.
roles
?.
find
{
it
.
equals
(
"admin"
,
ignoreCase
=
true
)
}
!=
null
}
private
fun
serverUrl
():
String
{
return
getCurrentServerInteractor
.
get
()
!!
}
}
\ No newline at end of file
app/src/main/java/chat/rocket/android/infrastructure/LocalRepository.kt
View file @
3f3ca5c5
package
chat.rocket.android.infrastructure
import
chat.rocket.common.model.User
interface
LocalRepository
{
fun
save
(
key
:
String
,
value
:
String
?)
...
...
@@ -14,12 +16,16 @@ interface LocalRepository {
fun
getLong
(
key
:
String
,
defValue
:
Long
=
-
1L
):
Long
fun
clear
(
key
:
String
)
fun
clearAllFromServer
(
server
:
String
)
fun
getCurrentUser
(
url
:
String
):
User
?
fun
saveCurrentUser
(
url
:
String
,
user
:
User
)
companion
object
{
const
val
KEY_PUSH_TOKEN
=
"KEY_PUSH_TOKEN"
const
val
MIGRATION_FINISHED_KEY
=
"MIGRATION_FINISHED_KEY"
const
val
TOKEN_KEY
=
"token_"
const
val
SETTINGS_KEY
=
"settings_"
const
val
PERMISSIONS_KEY
=
"permissions_"
const
val
USER_KEY
=
"user_"
const
val
CURRENT_USERNAME_KEY
=
"username_"
}
}
...
...
app/src/main/java/chat/rocket/android/infrastructure/SharedPrefsLocalRepository.kt
→
app/src/main/java/chat/rocket/android/infrastructure/SharedPref
erence
sLocalRepository.kt
View file @
3f3ca5c5
...
...
@@ -2,8 +2,26 @@ package chat.rocket.android.infrastructure
import
android.content.SharedPreferences
import
androidx.core.content.edit
import
chat.rocket.common.model.User
import
com.squareup.moshi.Moshi
class
SharedPreferencesLocalRepository
(
private
val
preferences
:
SharedPreferences
,
moshi
:
Moshi
)
:
LocalRepository
{
private
val
userAdapter
=
moshi
.
adapter
(
User
::
class
.
java
)
override
fun
getCurrentUser
(
url
:
String
):
User
?
{
return
get
(
"${url}_${LocalRepository.USER_KEY}"
,
null
)
?.
let
{
userAdapter
.
fromJson
(
it
)
}
}
override
fun
saveCurrentUser
(
url
:
String
,
user
:
User
)
{
save
(
"${url}_${LocalRepository.USER_KEY}"
,
userAdapter
.
toJson
(
user
))
}
class
SharedPrefsLocalRepository
(
private
val
preferences
:
SharedPreferences
)
:
LocalRepository
{
override
fun
getBoolean
(
key
:
String
,
defValue
:
Boolean
)
=
preferences
.
getBoolean
(
key
,
defValue
)
override
fun
getFloat
(
key
:
String
,
defValue
:
Float
)
=
preferences
.
getFloat
(
key
,
defValue
)
...
...
app/src/main/java/chat/rocket/android/main/presentation/MainNavigator.kt
View file @
3f3ca5c5
...
...
@@ -36,9 +36,10 @@ class MainNavigator(internal val activity: MainActivity) {
chatRoomType
:
String
,
isChatRoomReadOnly
:
Boolean
,
chatRoomLastSeen
:
Long
,
isChatRoomSubscribed
:
Boolean
)
{
isChatRoomSubscribed
:
Boolean
,
isChatRoomOwner
:
Boolean
)
{
activity
.
startActivity
(
activity
.
chatRoomIntent
(
chatRoomId
,
chatRoomName
,
chatRoomType
,
isChatRoomReadOnly
,
chatRoomLastSeen
,
isChatRoomSubscribed
))
isChatRoomReadOnly
,
chatRoomLastSeen
,
isChatRoomSubscribed
,
isChatRoomOwner
))
activity
.
overridePendingTransition
(
R
.
anim
.
open_enter
,
R
.
anim
.
open_exit
)
}
...
...
app/src/main/java/chat/rocket/android/main/viewmodel/NavHeaderViewModel.kt
View file @
3f3ca5c5
...
...
@@ -2,7 +2,6 @@ package chat.rocket.android.main.viewmodel
import
chat.rocket.common.model.UserStatus
data class
NavHeaderViewModel
(
val
userDisplayName
:
String
?,
val
userStatus
:
UserStatus
?,
...
...
app/src/main/java/chat/rocket/android/server/domain/
Get
PermissionsInteractor.kt
→
app/src/main/java/chat/rocket/android/server/domain/PermissionsInteractor.kt
View file @
3f3ca5c5
package
chat.rocket.android.server.domain
import
chat.rocket.android.helper.UserHelper
import
chat.rocket.android.infrastructure.LocalRepository
import
chat.rocket.core.model.Permission
import
javax.inject.Inject
class
GetPermissionsInteractor
@Inject
constructor
(
private
val
settingsRepository
:
SettingsRepository
,
private
val
currentServerRepository
:
CurrentServerRepository
)
{
// Creating rooms
const
val
CREATE_PUBLIC_CHANNELS
=
"create-c"
const
val
CREATE_DIRECT_MESSAGES
=
"create-d"
const
val
CREATE_PRIVATE_CHANNELS
=
"create-p"
private
fun
publicSettings
():
PublicSettings
?
=
settingsRepository
.
get
(
currentServerRepository
.
get
()
!!
)
// Messages
const
val
DELETE_MESSAGE
=
"delete-message"
const
val
FORCE_DELETE_MESSAGE
=
"force-delete-message"
const
val
EDIT_MESSAGE
=
"edit-message"
const
val
PIN_MESSAGE
=
"pin-message"
const
val
POST_READONLY
=
"post-readonly"
class
PermissionsInteractor
@Inject
constructor
(
private
val
settingsRepository
:
SettingsRepository
,
private
val
permissionsRepository
:
PermissionsRepository
,
private
val
getCurrentServerInteractor
:
GetCurrentServerInteractor
,
private
val
userHelper
:
UserHelper
)
{
private
fun
publicSettings
():
PublicSettings
?
=
settingsRepository
.
get
(
currentServerUrl
()
!!
)
fun
saveAll
(
permissions
:
List
<
Permission
>)
{
val
url
=
currentServerUrl
()
!!
permissions
.
forEach
{
permissionsRepository
.
save
(
url
,
it
)
}
}
/**
* Check whether user is allowed to delete a message.
...
...
@@ -31,4 +55,18 @@ class GetPermissionsInteractor @Inject constructor(private val settingsRepositor
* Checks whether should show edited message status.
*/
fun
showEditedStatus
()
=
publicSettings
()
?.
showEditedStatus
()
?:
false
fun
canPostToReadOnlyChannels
():
Boolean
{
val
url
=
getCurrentServerInteractor
.
get
()
!!
val
currentUserRoles
=
userHelper
.
user
()
?.
roles
return
permissionsRepository
.
get
(
url
,
POST_READONLY
)
?.
let
{
permission
->
currentUserRoles
?.
isNotEmpty
()
==
true
&&
permission
.
roles
.
any
{
currentUserRoles
.
contains
(
it
)
}
}
==
true
||
userHelper
.
isAdmin
()
}
private
fun
currentServerUrl
():
String
?
{
return
getCurrentServerInteractor
.
get
()
}
}
\ No newline at end of file
app/src/main/java/chat/rocket/android/server/domain/PermissionsRepository.kt
0 → 100644
View file @
3f3ca5c5
package
chat.rocket.android.server.domain
import
chat.rocket.core.model.Permission
interface
PermissionsRepository
{
/**
* Store [permission] locally.
*
* @param url The server url from where we're interest to store the permission.
* @param permission The permission to store.
*/
fun
save
(
url
:
String
,
permission
:
Permission
)
/**
* Get permission given by the [permissionId] and for the server [url].
*
* @param url The server url from where we're interested on getting the permissions.
* @param permissionId the id of the permission to get.
*
* @return The interested [Permission] or null if not found.
*/
fun
get
(
url
:
String
,
permissionId
:
String
):
Permission
?
}
\ No newline at end of file
app/src/main/java/chat/rocket/android/server/domain/SaveActiveUsersInteractor.kt
View file @
3f3ca5c5
...
...
@@ -29,7 +29,8 @@ class SaveActiveUsersInteractor @Inject constructor(
username
=
user
.
username
?:
it
.
username
,
status
=
user
.
status
?:
it
.
status
,
emails
=
user
.
emails
?:
it
.
emails
,
utcOffset
=
user
.
utcOffset
?:
it
.
utcOffset
utcOffset
=
user
.
utcOffset
?:
it
.
utcOffset
,
roles
=
user
.
roles
?:
it
.
roles
)
val
activeUserList
:
MutableList
<
User
>
=
...
...
app/src/main/java/chat/rocket/android/server/infraestructure/SharedPreferencesPermissionsRepository.kt
0 → 100644
View file @
3f3ca5c5
package
chat.rocket.android.server.infraestructure
import
chat.rocket.android.infrastructure.LocalRepository
import
chat.rocket.android.server.domain.PermissionsRepository
import
chat.rocket.core.model.Permission
import
com.squareup.moshi.Moshi
class
SharedPreferencesPermissionsRepository
(
private
val
localRepository
:
LocalRepository
,
moshi
:
Moshi
)
:
PermissionsRepository
{
private
val
adapter
=
moshi
.
adapter
(
Permission
::
class
.
java
)
override
fun
save
(
url
:
String
,
permission
:
Permission
)
{
localRepository
.
save
(
getPermissionKey
(
url
,
permission
.
id
),
adapter
.
toJson
(
permission
))
}
override
fun
get
(
url
:
String
,
permissionId
:
String
):
Permission
?
{
return
localRepository
.
get
(
getPermissionKey
(
url
,
permissionId
))
?.
let
{
adapter
.
fromJson
(
it
)
}
}
// Create a key following the pattern: settings_[url]_[permission id]
// eg.: 'settings_https://open.rocket.chat_create-p'
private
fun
getPermissionKey
(
url
:
String
,
permissionId
:
String
):
String
{
return
"${LocalRepository.PERMISSIONS_KEY}${url}_$permissionId"
}
}
\ No newline at end of file
app/src/main/java/chat/rocket/android/server/infraestructure/SharedPreferencesSettingsRepository.kt
View file @
3f3ca5c5
...
...
@@ -6,7 +6,9 @@ import chat.rocket.android.server.domain.PublicSettings
import
chat.rocket.android.server.domain.SettingsRepository
import
chat.rocket.core.internal.SettingsAdapter
class
SharedPreferencesSettingsRepository
(
private
val
localRepository
:
LocalRepository
)
:
SettingsRepository
{
class
SharedPreferencesSettingsRepository
(
private
val
localRepository
:
LocalRepository
)
:
SettingsRepository
{
private
val
adapter
=
SettingsAdapter
().
lenient
()
...
...
app/src/main/java/chat/rocket/android/util/extensions/Rx.kt
View file @
3f3ca5c5
...
...
@@ -6,9 +6,8 @@ import io.reactivex.Observable
import
io.reactivex.android.schedulers.AndroidSchedulers
import
java.util.concurrent.TimeUnit
fun
EditText
.
asObservable
(
debounceTimeout
:
Long
=
100
):
Observable
<
CharSequence
>
{
fun
EditText
.
asObservable
():
Observable
<
CharSequence
>
{
return
RxTextView
.
textChanges
(
this
)
.
debounce
(
debounceTimeout
,
TimeUnit
.
MILLISECONDS
)
.
observeOn
(
AndroidSchedulers
.
mainThread
())
.
subscribeOn
(
AndroidSchedulers
.
mainThread
())
}
\ No newline at end of file
app/src/main/res/layout/fragment_chat_rooms.xml
View file @
3f3ca5c5
...
...
@@ -45,4 +45,15 @@
tools:text=
"connected"
tools:visibility=
"visible"
/>
<TextView
android:id=
"@+id/text_no_search"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_marginTop=
"56dp"
android:text=
"@string/msg_no_search_found"
android:textSize=
"20sp"
android:layout_centerHorizontal=
"true"
android:visibility=
"gone"
tools:visibility=
"visible"
/>
</RelativeLayout>
\ No newline at end of file
app/src/main/res/layout/item_message.xml
View file @
3f3ca5c5
...
...
@@ -75,6 +75,16 @@
android:layout_height=
"wrap_content"
android:layout_marginStart=
"10dp"
tools:text=
"11:45 PM"
/>
<TextView
android:id=
"@+id/text_edit_indicator"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:text=
"@string/msg_edited"
android:layout_marginStart=
"8dp"
android:textStyle=
"italic"
android:visibility=
"gone"
tools:visibility=
"visible"
/>
</LinearLayout>
<TextView
...
...
app/src/main/res/values-es/strings.xml
View file @
3f3ca5c5
...
...
@@ -100,7 +100,6 @@
<string
name=
"msg_ver_not_minimum"
>
Parece que la versión del servidor está por debajo de la versión mínima requerida %1$s.\nActualice su servidor para iniciar sesión!
</string>
<string
name=
"msg_proceed"
>
PROCEDER
</string>
<string
name=
"msg_cancel"
>
CANCELAR
</string>
<string
name=
"msg_warning"
>
ADVERTENCIA
</string>
...
...
@@ -111,6 +110,8 @@
<string
name=
"msg_image_saved_failed"
>
Error al guardar la imagen
</string>
<string
name=
"msg_no_chat_title"
>
Sin mensajes de chat
</string>
<string
name=
"msg_no_chat_description"
>
Comience a conversar para ver\nsus mensajes aquí.
</string>
<string
name=
"msg_edited"
>
(editado)
</string>
<string
name=
"msg_no_search_found"
>
No se han encontrado resultados
</string>
<!-- System messages -->
<string
name=
"message_room_name_changed"
>
Nombre de la sala cambiado para: %1$s por %2$s
</string>
...
...
@@ -121,6 +122,8 @@
<string
name=
"message_welcome"
>
Bienvenido %s
</string>
<string
name=
"message_removed"
>
Mensaje eliminado
</string>
<string
name=
"message_pinned"
>
Fijado una mensaje:
</string>
<string
name=
"message_muted"
>
Usuario %1$s silenciado por %2$s
</string>
<string
name=
"message_unmuted"
>
Usuario %1$s no silenciado por %2$s
</string>
<!-- Message actions -->
<string
name=
"action_msg_reply"
>
Respuesta
</string>
...
...
app/src/main/res/values-fr/strings.xml
View file @
3f3ca5c5
...
...
@@ -110,6 +110,8 @@
<string
name=
"msg_image_saved_failed"
>
Échec de l\'enregistrement de l\'image
</string>
<string
name=
"msg_no_chat_title"
>
Aucun message de discussion
</string>
<string
name=
"msg_no_chat_description"
>
Commencez à converser pour voir\nvos messages ici.
</string>
<string
name=
"msg_edited"
>
(édité)
</string>
<string
name=
"msg_no_search_found"
>
Aucun résultat trouvé
</string>
<!-- System messages -->
<string
name=
"message_room_name_changed"
>
Le nom de le salle a changé à: %1$s par %2$s
</string>
...
...
@@ -120,6 +122,8 @@
<string
name=
"message_welcome"
>
Bienvenue %s
</string>
<string
name=
"message_removed"
>
Message supprimé
</string>
<string
name=
"message_pinned"
>
Épinglé un message:
</string>
<string
name=
"message_muted"
>
Utilisateur %1$s mis en sourdine par %2$s
</string>
<string
name=
"message_unmuted"
>
Utilisateur %1$s non muté par %2$s
</string>
<!-- Message actions -->
<string
name=
"action_msg_reply"
>
Répondre
</string>
...
...
app/src/main/res/values-hi-rIN/strings.xml
View file @
3f3ca5c5
...
...
@@ -112,6 +112,8 @@
<string
name=
"msg_image_saved_failed"
>
छवि को सहेजने में विफल
</string>
<string
name=
"msg_no_chat_title"
>
कोई चैट संदेश नहीं
</string>
<string
name=
"msg_no_chat_description"
>
यहां अपने संदेश देखने के लिए\nबातचीत शुरू करें।
</string>
<string
name=
"msg_edited"
>
(संपादित)
</string>
<string
name=
"msg_no_search_found"
>
कोई परिणाम नहीं मिला
</string>
<!-- System messages -->
<string
name=
"message_room_name_changed"
>
%2$s ने रूम का नाम बदलकर %1$s किया
</string>
...
...
@@ -122,6 +124,8 @@
<string
name=
"message_welcome"
>
%s का स्वागत करते हैं
</string>
<string
name=
"message_removed"
>
संदेश हटाया गया
</string>
<string
name=
"message_pinned"
>
एक संदेश पिन किया:
</string>
<string
name=
"message_muted"
>
उपयोगकर्ता %1$s %2$s द्वारा म्यूट किया गया
</string>
<string
name=
"message_unmuted"
>
उपयोगकर्ता %1$s %2$s द्वारा अनम्यूट किया गया
</string>
<!-- Message actions -->
<string
name=
"action_msg_reply"
>
जवाब दें
</string>
...
...
app/src/main/res/values-pt-rBR/strings.xml
View file @
3f3ca5c5
...
...
@@ -106,16 +106,20 @@
<string
name=
"msg_invalid_server_protocol"
>
O protocolo selecionado não é suportado pelo servidor, por favor utilize HTTPS e tente novamente
</string>
<string
name=
"msg_image_saved_successfully"
>
Imagem salva na galeria
</string>
<string
name=
"msg_image_saved_failed"
>
Falha ao salvar a imagem
</string>
<string
name=
"msg_edited"
>
(editado)
</string>
<string
name=
"msg_no_search_found"
>
nenhum resultado encontrado
</string>
<!-- System messages -->
<string
name=
"message_room_name_changed"
>
Nome da sala alterado para: %1$s por %2$s
</string>
<string
name=
"message_user_added_by"
>
Usuário %1$s adicionado por %2$s
</string>
<string
name=
"message_user_removed_by"
>
Usuário %1$s removido por %2$s
</string>
<string
name=
"message_user_left"
>
Saiu da sala
.
</string>
<string
name=
"message_user_joined_channel"
>
Entrou na sala
.
</string>
<string
name=
"message_user_left"
>
Saiu da sala
</string>
<string
name=
"message_user_joined_channel"
>
Entrou na sala
</string>
<string
name=
"message_welcome"
>
Bem-vindo, %s
</string>
<string
name=
"message_removed"
>
Mensagem removida
</string>
<string
name=
"message_pinned"
>
Pinou uma mensagem:
</string>
<string
name=
"message_muted"
>
Usuário %1$s entrou no modo mudo por %2$s
</string>
<string
name=
"message_unmuted"
>
Usuário %1$s saiu do modo mudo por %2$s
</string>
<!-- Message actions -->
<string
name=
"action_msg_reply"
>
Responder
</string>
...
...
@@ -123,11 +127,11 @@
<string
name=
"action_msg_copy"
>
Copiar
</string>
<string
name=
"action_msg_quote"
>
Citar
</string>
<string
name=
"action_msg_delete"
>
Remover
</string>
<string
name=
"action_msg_pin"
>
Fixar M
ensagem
</string>
<string
name=
"action_msg_unpin"
>
Des
afixar M
ensagem
</string>
<string
name=
"action_msg_star"
>
Favoritar
M
ensagem
</string>
<string
name=
"action_msg_pin"
>
Pinar m
ensagem
</string>
<string
name=
"action_msg_unpin"
>
Des
pinar m
ensagem
</string>
<string
name=
"action_msg_star"
>
Favoritar
m
ensagem
</string>
<string
name=
"action_msg_share"
>
Compartilhar
</string>
<string
name=
"action_title_editing"
>
Editando
M
ensagem
</string>
<string
name=
"action_title_editing"
>
Editando
m
ensagem
</string>
<string
name=
"action_msg_add_reaction"
>
Adicionar reação
</string>
<!-- Permission messages -->
...
...
@@ -148,7 +152,7 @@
<!-- Socket status -->
<string
name=
"status_connected"
>
Conectado
</string>
<string
name=
"status_disconnected"
>
Desconetado
</string>
<string
name=
"status_disconnected"
>
Descone
c
tado
</string>
<string
name=
"status_connecting"
>
Conectando
</string>
<string
name=
"status_authenticating"
>
Autenticando
</string>
<string
name=
"status_disconnecting"
>
Desconectando
</string>
...
...
@@ -165,7 +169,7 @@
<string
name=
"Slash_Tableflip_Description"
>
Exibir (╯°□°)╯︵ ┻━┻
</string>
<string
name=
"Slash_TableUnflip_Description"
>
Exibir ┬─┬ ノ( ゜-゜ノ)
</string>
<string
name=
"Create_A_New_Channel"
>
Criar um novo canal
</string>
<string
name=
"Show_the_keyboard_shortcut_list"
>
Show the keyboard shortcut list
</string>
<string
name=
"Show_the_keyboard_shortcut_list"
>
Exibir a lista de atalhos do teclado
</string>
<string
name=
"Invite_user_to_join_channel_all_from"
>
do [#canal] para entrar neste
</string>
<string
name=
"Invite_user_to_join_channel_all_to"
>
Convidar todos os usuários deste canal para entrar no [#canal]
</string>
<string
name=
"Archive"
>
Arquivar
</string>
...
...
@@ -173,8 +177,8 @@
<string
name=
"Leave_the_current_channel"
>
Sair do canal atual
</string>
<string
name=
"Displays_action_text"
>
Exibir texto de ação
</string>
<string
name=
"Direct_message_someone"
>
Enviar DM para alguém
</string>
<string
name=
"Mute_someone_in_room"
>
Silenciar
alguém
</string>
<string
name=
"Unmute_someone_in_room"
>
De
-silenciar
alguém na sala
</string>
<string
name=
"Mute_someone_in_room"
>
Ativar o modo mudo em
alguém
</string>
<string
name=
"Unmute_someone_in_room"
>
De
sativar o modo mudo em
alguém na sala
</string>
<string
name=
"Invite_user_to_join_channel"
>
Convidar algum usuário para entrar neste canal
</string>
<string
name=
"Unarchive"
>
Desarquivar
</string>
<string
name=
"Join_the_given_channel"
>
Entrar no canal especificado
</string>
...
...
app/src/main/res/values-uk-rUA/strings.xml
0 → 100644
View file @
3f3ca5c5
This diff is collapsed.
Click to expand it.
app/src/main/res/values/strings.xml
View file @
3f3ca5c5
...
...
@@ -107,6 +107,8 @@
<string
name=
"msg_invalid_server_protocol"
>
The selected protocol is not accepted by this server, try using HTTPS
</string>
<string
name=
"msg_image_saved_successfully"
>
Image has been saved to gallery
</string>
<string
name=
"msg_image_saved_failed"
>
Failed to save image
</string>
<string
name=
"msg_edited"
>
(edited)
</string>
<string
name=
"msg_no_search_found"
>
No result found
</string>
<!-- System messages -->
<string
name=
"message_room_name_changed"
>
Room name changed to: %1$s by %2$s
</string>
...
...
@@ -117,6 +119,8 @@
<string
name=
"message_welcome"
>
Welcome %s
</string>
<string
name=
"message_removed"
>
Message removed
</string>
<string
name=
"message_pinned"
>
Pinned a message:
</string>
<string
name=
"message_muted"
>
User %1$s muted by %2$s
</string>
<string
name=
"message_unmuted"
>
User %1$s unmuted by %2$s
</string>
<!-- Message actions -->
<string
name=
"action_msg_reply"
>
Reply
</string>
...
...
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