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
4b352b0f
Commit
4b352b0f
authored
May 24, 2018
by
Filipe de Lima Brito
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Adds file list feature.
parent
ca99f416
Changes
69
Hide whitespace changes
Inline
Side-by-side
Showing
69 changed files
with
1089 additions
and
352 deletions
+1089
-352
DateTimeHelper.kt
app/src/main/java/chat/rocket/android/app/DateTimeHelper.kt
+22
-6
ChatRoomAdapter.kt
...a/chat/rocket/android/chatroom/adapter/ChatRoomAdapter.kt
+11
-22
GenericFileAttachmentViewHolder.kt
...droid/chatroom/adapter/GenericFileAttachmentViewHolder.kt
+2
-1
ImageAttachmentViewHolder.kt
...ket/android/chatroom/adapter/ImageAttachmentViewHolder.kt
+6
-162
ChatRoomNavigator.kt
...rocket/android/chatroom/presentation/ChatRoomNavigator.kt
+12
-7
ChatRoomPresenter.kt
...rocket/android/chatroom/presentation/ChatRoomPresenter.kt
+9
-6
ChatRoomActivity.kt
.../java/chat/rocket/android/chatroom/ui/ChatRoomActivity.kt
+1
-1
ChatRoomFragment.kt
.../java/chat/rocket/android/chatroom/ui/ChatRoomFragment.kt
+6
-3
ActionListAdapter.kt
...roid/chatroom/ui/bottomsheet/adapter/ActionListAdapter.kt
+1
-1
ActivityBuilder.kt
...java/chat/rocket/android/dagger/module/ActivityBuilder.kt
+20
-14
FavoriteMessagesPresenter.kt
...avoritemessages/presentation/FavoriteMessagesPresenter.kt
+12
-13
FavoriteMessagesFragment.kt
...t/android/favoritemessages/ui/FavoriteMessagesFragment.kt
+2
-6
FilesAdapter.kt
...in/java/chat/rocket/android/files/adapter/FilesAdapter.kt
+71
-0
FilesFragmentModule.kt
.../java/chat/rocket/android/files/di/FilesFragmentModule.kt
+30
-0
FilesFragmentProvider.kt
...ava/chat/rocket/android/files/di/FilesFragmentProvider.kt
+12
-0
FilesPresenter.kt
.../chat/rocket/android/files/presentation/FilesPresenter.kt
+72
-0
FilesView.kt
.../java/chat/rocket/android/files/presentation/FilesView.kt
+39
-0
FilesFragment.kt
...c/main/java/chat/rocket/android/files/ui/FilesFragment.kt
+154
-0
FileViewModel.kt
...java/chat/rocket/android/files/viewmodel/FileViewModel.kt
+72
-0
FileViewModelMapper.kt
...hat/rocket/android/files/viewmodel/FileViewModelMapper.kt
+23
-0
ImageHelper.kt
app/src/main/java/chat/rocket/android/helper/ImageHelper.kt
+170
-0
MessageParser.kt
...src/main/java/chat/rocket/android/helper/MessageParser.kt
+1
-1
MembersPresenter.kt
...t/rocket/android/members/presentation/MembersPresenter.kt
+19
-14
MembersFragment.kt
...in/java/chat/rocket/android/members/ui/MembersFragment.kt
+3
-10
PinnedMessagesFragmentProvider.kt
...droid/pinnedmessages/di/PinnedMessagesFragmentProvider.kt
+2
-1
PinnedMessagesPresenter.kt
...id/pinnedmessages/presentation/PinnedMessagesPresenter.kt
+15
-15
PinnedMessagesFragment.kt
...ocket/android/pinnedmessages/ui/PinnedMessagesFragment.kt
+2
-7
SettingsRepository.kt
...a/chat/rocket/android/server/domain/SettingsRepository.kt
+1
-1
String.kt
...c/main/java/chat/rocket/android/util/extensions/String.kt
+14
-1
ic_file_download_white_24dp.xml
app/src/main/res/drawable/ic_file_download_white_24dp.xml
+10
-0
ic_insert_drive_file_black_24dp.xml
...src/main/res/drawable/ic_insert_drive_file_black_24dp.xml
+10
-0
ic_play_arrow_black_24dp.xml
app/src/main/res/drawable/ic_play_arrow_black_24dp.xml
+10
-0
activity_main.xml
app/src/main/res/layout/activity_main.xml
+1
-1
activity_web_view.xml
app/src/main/res/layout/activity_web_view.xml
+1
-1
app_bar_chat_room.xml
app/src/main/res/layout/app_bar_chat_room.xml
+1
-1
app_bar_password.xml
app/src/main/res/layout/app_bar_password.xml
+1
-1
emoji_keyboard.xml
app/src/main/res/layout/emoji_keyboard.xml
+1
-1
emoji_picker.xml
app/src/main/res/layout/emoji_picker.xml
+2
-2
fragment_authentication_log_in.xml
app/src/main/res/layout/fragment_authentication_log_in.xml
+1
-1
fragment_chat_room.xml
app/src/main/res/layout/fragment_chat_room.xml
+2
-2
fragment_chat_rooms.xml
app/src/main/res/layout/fragment_chat_rooms.xml
+2
-2
fragment_favorite_messages.xml
app/src/main/res/layout/fragment_favorite_messages.xml
+1
-1
fragment_files.xml
app/src/main/res/layout/fragment_files.xml
+74
-0
fragment_member_bottom_sheet.xml
app/src/main/res/layout/fragment_member_bottom_sheet.xml
+2
-2
fragment_members.xml
app/src/main/res/layout/fragment_members.xml
+1
-1
fragment_password.xml
app/src/main/res/layout/fragment_password.xml
+1
-1
fragment_pinned_messages.xml
app/src/main/res/layout/fragment_pinned_messages.xml
+1
-1
fragment_profile.xml
app/src/main/res/layout/fragment_profile.xml
+1
-1
item_generic_attachment.xml
app/src/main/res/layout/item_generic_attachment.xml
+74
-0
item_message.xml
app/src/main/res/layout/item_message.xml
+3
-3
message_action_bar.xml
app/src/main/res/layout/message_action_bar.xml
+1
-1
message_attachment.xml
app/src/main/res/layout/message_attachment.xml
+1
-1
message_composer.xml
app/src/main/res/layout/message_composer.xml
+3
-3
message_list.xml
app/src/main/res/layout/message_list.xml
+1
-1
nav_header.xml
app/src/main/res/layout/nav_header.xml
+3
-3
suggestion_command_item.xml
app/src/main/res/layout/suggestion_command_item.xml
+1
-1
suggestion_member_item.xml
app/src/main/res/layout/suggestion_member_item.xml
+1
-1
suggestion_room_item.xml
app/src/main/res/layout/suggestion_room_item.xml
+1
-1
unread_messages_badge.xml
app/src/main/res/layout/unread_messages_badge.xml
+1
-1
chatroom_actions.xml
app/src/main/res/menu/chatroom_actions.xml
+5
-0
image_actions.xml
app/src/main/res/menu/image_actions.xml
+3
-2
strings.xml
app/src/main/res/values-es/strings.xml
+12
-2
strings.xml
app/src/main/res/values-fr/strings.xml
+10
-1
strings.xml
app/src/main/res/values-hi-rIN/strings.xml
+10
-1
strings.xml
app/src/main/res/values-pt-rBR/strings.xml
+8
-2
colors.xml
app/src/main/res/values/colors.xml
+14
-12
strings.xml
app/src/main/res/values/strings.xml
+8
-1
dependencies.gradle
dependencies.gradle
+1
-1
PlayerActivity.kt
...rc/main/java/chat/rocket/android/player/PlayerActivity.kt
+1
-3
No files found.
app/src/main/java/chat/rocket/android/app/DateTimeHelper.kt
View file @
4b352b0f
...
...
@@ -12,7 +12,18 @@ object DateTimeHelper {
private
val
lastWeek
=
today
.
minusWeeks
(
1
)
/**
* Returns a date from a [LocalDateTime] or the textual representation if the [LocalDateTime] has a max period of a week from the current date.
* Returns a [LocalDateTime] from a [Long].
*
* @param long The [Long]
* @return The [LocalDateTime] from a [Long].
*/
fun
getLocalDateTime
(
long
:
Long
):
LocalDateTime
{
return
LocalDateTime
.
ofInstant
(
Instant
.
ofEpochMilli
(
long
),
ZoneId
.
systemDefault
())
}
/**
* Returns a date from a [LocalDateTime] or the textual representation if the [LocalDateTime]
* has a max period of a week from the current date.
*
* @param localDateTime The [LocalDateTime].
* @param context The context.
...
...
@@ -45,13 +56,18 @@ object DateTimeHelper {
}
/**
* Returns a
[LocalDateTime] from a [Long
].
* Returns a
date time from a [LocalDateTime
].
*
* @param lo
ng The [Long]
* @return The
[LocalDateTime] from a [Long
].
* @param lo
calDateTime The [LocalDateTime].
* @return The
time from a [LocalDateTime
].
*/
fun
getLocalDateTime
(
long
:
Long
):
LocalDateTime
{
return
LocalDateTime
.
ofInstant
(
Instant
.
ofEpochMilli
(
long
),
ZoneId
.
systemDefault
())
fun
getDateTime
(
localDateTime
:
LocalDateTime
):
String
{
return
formatLocalDateTime
(
localDateTime
)
}
private
fun
formatLocalDateTime
(
localDateTime
:
LocalDateTime
):
String
{
val
formatter
=
DateTimeFormatter
.
ofLocalizedDateTime
(
FormatStyle
.
SHORT
)
return
localDateTime
.
format
(
formatter
).
toString
()
}
private
fun
formatLocalDate
(
localDate
:
LocalDate
):
String
{
...
...
app/src/main/java/chat/rocket/android/chatroom/adapter/ChatRoomAdapter.kt
View file @
4b352b0f
...
...
@@ -5,21 +5,7 @@ import android.view.MenuItem
import
android.view.ViewGroup
import
chat.rocket.android.R
import
chat.rocket.android.chatroom.presentation.ChatRoomPresenter
import
chat.rocket.android.chatroom.ui.chatRoomIntent
import
chat.rocket.android.chatroom.viewmodel.AudioAttachmentViewModel
import
chat.rocket.android.chatroom.viewmodel.AuthorAttachmentViewModel
import
chat.rocket.android.chatroom.viewmodel.BaseFileAttachmentViewModel
import
chat.rocket.android.chatroom.viewmodel.BaseViewModel
import
chat.rocket.android.chatroom.viewmodel.ColorAttachmentViewModel
import
chat.rocket.android.chatroom.viewmodel.GenericFileAttachmentViewModel
import
chat.rocket.android.chatroom.viewmodel.ImageAttachmentViewModel
import
chat.rocket.android.chatroom.viewmodel.MessageAttachmentViewModel
import
chat.rocket.android.chatroom.viewmodel.MessageReplyViewModel
import
chat.rocket.android.chatroom.viewmodel.MessageViewModel
import
chat.rocket.android.chatroom.viewmodel.UrlPreviewViewModel
import
chat.rocket.android.chatroom.viewmodel.VideoAttachmentViewModel
import
chat.rocket.android.chatroom.viewmodel.toViewType
import
chat.rocket.android.main.presentation.MainNavigator
import
chat.rocket.android.chatroom.viewmodel.*
import
chat.rocket.android.util.extensions.inflate
import
chat.rocket.android.widget.emoji.EmojiReactionListener
import
chat.rocket.core.model.Message
...
...
@@ -28,13 +14,12 @@ import timber.log.Timber
import
java.security.InvalidParameterException
class
ChatRoomAdapter
(
private
val
roomType
:
String
,
private
val
roomName
:
String
,
private
val
presenter
:
ChatRoomPresenter
?,
private
val
roomType
:
String
?
=
null
,
private
val
roomName
:
String
?
=
null
,
private
val
presenter
:
ChatRoomPresenter
?
=
null
,
private
val
enableActions
:
Boolean
=
true
,
private
val
reactionListener
:
EmojiReactionListener
?
=
null
)
:
RecyclerView
.
Adapter
<
BaseViewHolder
<*>>()
{
private
val
dataSet
=
ArrayList
<
BaseViewModel
<*>>()
init
{
...
...
@@ -178,7 +163,7 @@ class ChatRoomAdapter(
}
fun
updateItem
(
message
:
BaseViewModel
<
*
>)
{
va
r
index
=
dataSet
.
indexOfLast
{
it
.
messageId
==
message
.
messageId
}
va
l
index
=
dataSet
.
indexOfLast
{
it
.
messageId
==
message
.
messageId
}
val
indexOfNext
=
dataSet
.
indexOfFirst
{
it
.
messageId
==
message
.
messageId
}
Timber
.
d
(
"index: $index"
)
if
(
index
>
-
1
)
{
...
...
@@ -219,10 +204,14 @@ class ChatRoomAdapter(
message
.
apply
{
when
(
item
.
itemId
)
{
R
.
id
.
action_message_reply
->
{
presenter
?.
citeMessage
(
roomName
,
roomType
,
id
,
true
)
if
(
roomName
!=
null
&&
roomType
!=
null
)
{
presenter
?.
citeMessage
(
roomName
,
roomType
,
id
,
true
)
}
}
R
.
id
.
action_message_quote
->
{
presenter
?.
citeMessage
(
roomName
,
roomType
,
id
,
false
)
if
(
roomName
!=
null
&&
roomType
!=
null
)
{
presenter
?.
citeMessage
(
roomName
,
roomType
,
id
,
false
)
}
}
R
.
id
.
action_message_copy
->
{
presenter
?.
copyMessage
(
id
)
...
...
app/src/main/java/chat/rocket/android/chatroom/adapter/GenericFileAttachmentViewHolder.kt
View file @
4b352b0f
...
...
@@ -3,6 +3,7 @@ package chat.rocket.android.chatroom.adapter
import
android.content.Intent
import
android.net.Uri
import
android.view.View
import
androidx.core.net.toUri
import
chat.rocket.android.chatroom.viewmodel.GenericFileAttachmentViewModel
import
chat.rocket.android.util.extensions.content
import
chat.rocket.android.widget.emoji.EmojiReactionListener
...
...
@@ -25,7 +26,7 @@ class GenericFileAttachmentViewHolder(itemView: View,
text_file_name
.
content
=
data
.
attachmentTitle
text_file_name
.
setOnClickListener
{
it
.
context
.
startActivity
(
Intent
(
Intent
.
ACTION_VIEW
,
Uri
.
parse
(
data
.
attachmentUrl
)))
it
.
context
.
startActivity
(
Intent
(
Intent
.
ACTION_VIEW
,
data
.
attachmentUrl
.
toUri
(
)))
}
}
}
...
...
app/src/main/java/chat/rocket/android/chatroom/adapter/ImageAttachmentViewHolder.kt
View file @
4b352b0f
package
chat.rocket.android.chatroom.adapter
import
android.Manifest
import
android.app.Activity
import
android.graphics.Color
import
android.graphics.Typeface
import
android.media.MediaScannerConnection
import
android.net.Uri
import
android.os.Environment
import
android.support.design.widget.AppBarLayout
import
android.support.v7.widget.Toolbar
import
android.text.TextUtils
import
android.util.TypedValue
import
android.view.ContextThemeWrapper
import
android.view.Gravity
import
android.view.View
import
android.view.ViewGroup
import
android.widget.ImageView
import
android.widget.TextView
import
android.widget.Toast
import
androidx.core.view.setPadding
import
chat.rocket.android.R
import
chat.rocket.android.chatroom.viewmodel.ImageAttachmentViewModel
import
chat.rocket.android.helper.
AndroidPermissions
Helper
import
chat.rocket.android.helper.
Image
Helper
import
chat.rocket.android.widget.emoji.EmojiReactionListener
import
com.facebook.binaryresource.FileBinaryResource
import
com.facebook.cache.common.CacheKey
import
com.facebook.drawee.backends.pipeline.Fresco
import
com.facebook.imageformat.ImageFormatChecker
import
com.facebook.imagepipeline.cache.DefaultCacheKeyFactory
import
com.facebook.imagepipeline.core.ImagePipelineFactory
import
com.facebook.imagepipeline.request.ImageRequest
import
com.facebook.imagepipeline.request.ImageRequestBuilder
import
com.stfalcon.frescoimageviewer.ImageViewer
import
kotlinx.android.synthetic.main.message_attachment.view.*
import
timber.log.Timber
import
java.io.File
class
ImageAttachmentViewHolder
(
itemView
:
View
,
listener
:
ActionsListener
,
reactionListener
:
EmojiReactionListener
?
=
null
)
:
BaseViewHolder
<
ImageAttachmentViewModel
>(
itemView
,
listener
,
reactionListener
)
{
private
var
cacheKey
:
CacheKey
?
=
null
init
{
with
(
itemView
)
{
...
...
@@ -59,138 +28,13 @@ class ImageAttachmentViewHolder(
}.
build
()
image_attachment
.
controller
=
controller
file_name
.
text
=
data
.
attachmentTitle
image_attachment
.
setOnClickListener
{
view
->
// TODO - implement a proper image viewer with a proper Transition
// TODO - We should definitely write our own ImageViewer
var
imageViewer
:
ImageViewer
?
=
null
val
request
=
ImageRequestBuilder
.
newBuilderWithSource
(
Uri
.
parse
(
data
.
attachmentUrl
))
.
setLowestPermittedRequestLevel
(
ImageRequest
.
RequestLevel
.
DISK_CACHE
)
.
build
()
cacheKey
=
DefaultCacheKeyFactory
.
getInstance
()
.
getEncodedCacheKey
(
request
,
null
)
val
pad
=
context
.
resources
.
getDimensionPixelSize
(
R
.
dimen
.
viewer_toolbar_padding
)
val
lparams
=
AppBarLayout
.
LayoutParams
(
ViewGroup
.
LayoutParams
.
MATCH_PARENT
,
ViewGroup
.
LayoutParams
.
WRAP_CONTENT
image_attachment
.
setOnClickListener
{
ImageHelper
.
openImage
(
it
.
context
,
data
.
attachmentUrl
,
data
.
attachmentTitle
.
toString
()
)
val
toolbar
=
Toolbar
(
context
).
also
{
it
.
inflateMenu
(
R
.
menu
.
image_actions
)
it
.
overflowIcon
?.
setTint
(
Color
.
WHITE
)
it
.
setOnMenuItemClickListener
{
return
@setOnMenuItemClickListener
when
(
it
.
itemId
)
{
R
.
id
.
action_save_image
->
saveImage
()
else
->
super
.
onMenuItemClick
(
it
)
}
}
val
titleSize
=
context
.
resources
.
getDimensionPixelSize
(
R
.
dimen
.
viewer_toolbar_title
)
val
titleTextView
=
TextView
(
context
).
also
{
it
.
text
=
data
.
attachmentTitle
it
.
setTextColor
(
Color
.
WHITE
)
it
.
setTextSize
(
TypedValue
.
COMPLEX_UNIT_PX
,
titleSize
.
toFloat
())
it
.
ellipsize
=
TextUtils
.
TruncateAt
.
END
it
.
setSingleLine
()
it
.
typeface
=
Typeface
.
DEFAULT_BOLD
it
.
setPadding
(
pad
)
}
val
backArrowView
=
ImageView
(
context
).
also
{
it
.
setImageResource
(
R
.
drawable
.
ic_arrow_back_white_24dp
)
it
.
setOnClickListener
{
imageViewer
?.
onDismiss
()
}
it
.
setPadding
(
0
,
pad
,
pad
,
pad
)
}
val
layoutParams
=
AppBarLayout
.
LayoutParams
(
AppBarLayout
.
LayoutParams
.
WRAP_CONTENT
,
AppBarLayout
.
LayoutParams
.
WRAP_CONTENT
)
it
.
addView
(
backArrowView
,
layoutParams
)
it
.
addView
(
titleTextView
,
layoutParams
)
}
val
appBarLayout
=
AppBarLayout
(
context
).
also
{
it
.
layoutParams
=
lparams
it
.
setBackgroundColor
(
Color
.
BLACK
)
it
.
addView
(
toolbar
,
AppBarLayout
.
LayoutParams
(
AppBarLayout
.
LayoutParams
.
MATCH_PARENT
,
ViewGroup
.
LayoutParams
.
WRAP_CONTENT
)
)
}
val
builder
=
ImageViewer
.
createPipelineDraweeControllerBuilder
()
.
setImageRequest
(
request
)
.
setAutoPlayAnimations
(
true
)
imageViewer
=
ImageViewer
.
Builder
(
view
.
context
,
listOf
(
data
.
attachmentUrl
))
.
setOverlayView
(
appBarLayout
)
.
setStartPosition
(
0
)
.
hideStatusBar
(
false
)
.
setCustomDraweeControllerBuilder
(
builder
)
.
show
()
}
}
}
private
fun
saveImage
():
Boolean
{
if
(!
canWriteToExternalStorage
())
{
checkWritingPermission
()
return
false
}
if
(
ImagePipelineFactory
.
getInstance
().
mainFileCache
.
hasKey
(
cacheKey
))
{
val
context
=
itemView
.
context
val
resource
=
ImagePipelineFactory
.
getInstance
().
mainFileCache
.
getResource
(
cacheKey
)
val
cachedFile
=
(
resource
as
FileBinaryResource
).
file
val
imageFormat
=
ImageFormatChecker
.
getImageFormat
(
resource
.
openStream
())
val
imageDir
=
"${Environment.DIRECTORY_PICTURES}/Rocket.Chat Images/"
val
imagePath
=
Environment
.
getExternalStoragePublicDirectory
(
imageDir
)
val
imageFile
=
File
(
imagePath
,
"${cachedFile.nameWithoutExtension}.${imageFormat.fileExtension}"
)
imagePath
.
mkdirs
()
imageFile
.
createNewFile
()
try
{
cachedFile
.
copyTo
(
imageFile
,
true
)
MediaScannerConnection
.
scanFile
(
context
,
arrayOf
(
imageFile
.
absolutePath
),
null
)
{
path
,
uri
->
Timber
.
i
(
"Scanned $path:"
)
Timber
.
i
(
"-> uri=$uri"
)
}
}
catch
(
ex
:
Exception
)
{
Timber
.
e
(
ex
)
val
message
=
context
.
getString
(
R
.
string
.
msg_image_saved_failed
)
Toast
.
makeText
(
context
,
message
,
Toast
.
LENGTH_SHORT
).
show
()
}
finally
{
val
message
=
context
.
getString
(
R
.
string
.
msg_image_saved_successfully
)
Toast
.
makeText
(
context
,
message
,
Toast
.
LENGTH_SHORT
).
show
()
}
}
return
true
}
private
fun
canWriteToExternalStorage
():
Boolean
{
return
AndroidPermissionsHelper
.
checkPermission
(
itemView
.
context
,
Manifest
.
permission
.
WRITE_EXTERNAL_STORAGE
)
}
private
fun
checkWritingPermission
()
{
val
context
=
itemView
.
context
if
(
context
is
ContextThemeWrapper
&&
context
.
baseContext
is
Activity
)
{
val
activity
=
context
.
baseContext
as
Activity
AndroidPermissionsHelper
.
requestPermission
(
activity
,
Manifest
.
permission
.
WRITE_EXTERNAL_STORAGE
,
AndroidPermissionsHelper
.
WRITE_EXTERNAL_STORAGE_CODE
)
}
}
}
\ No newline at end of file
app/src/main/java/chat/rocket/android/chatroom/presentation/ChatRoomNavigator.kt
View file @
4b352b0f
...
...
@@ -3,27 +3,32 @@ package chat.rocket.android.chatroom.presentation
import
chat.rocket.android.R
import
chat.rocket.android.chatroom.ui.ChatRoomActivity
import
chat.rocket.android.chatroom.ui.chatRoomIntent
import
chat.rocket.android.members.ui.newInstance
import
chat.rocket.android.server.ui.changeServerIntent
import
chat.rocket.android.util.extensions.addFragmentBackStack
class
ChatRoomNavigator
(
internal
val
activity
:
ChatRoomActivity
)
{
fun
toMembersList
(
chatRoomId
:
String
,
chatRoomType
:
String
)
{
fun
toMembersList
(
chatRoomId
:
String
)
{
activity
.
addFragmentBackStack
(
"MembersFragment"
,
R
.
id
.
fragment_container
)
{
newInstance
(
chatRoomId
,
chatRoomType
)
chat
.
rocket
.
android
.
members
.
ui
.
newInstance
(
chatRoomId
)
}
}
fun
toPinnedMessageList
(
chatRoomId
:
String
,
chatRoomType
:
String
)
{
fun
toPinnedMessageList
(
chatRoomId
:
String
)
{
activity
.
addFragmentBackStack
(
"PinnedMessages"
,
R
.
id
.
fragment_container
)
{
chat
.
rocket
.
android
.
pinnedmessages
.
ui
.
newInstance
(
chatRoomId
,
chatRoomType
)
chat
.
rocket
.
android
.
pinnedmessages
.
ui
.
newInstance
(
chatRoomId
)
}
}
fun
toFavoriteMessageList
(
chatRoomId
:
String
,
chatRoomType
:
String
)
{
fun
toFavoriteMessageList
(
chatRoomId
:
String
)
{
activity
.
addFragmentBackStack
(
"FavoriteMessages"
,
R
.
id
.
fragment_container
)
{
chat
.
rocket
.
android
.
favoritemessages
.
ui
.
newInstance
(
chatRoomId
,
chatRoomType
)
chat
.
rocket
.
android
.
favoritemessages
.
ui
.
newInstance
(
chatRoomId
)
}
}
fun
toFileList
(
chatRoomId
:
String
)
{
activity
.
addFragmentBackStack
(
"Files"
,
R
.
id
.
fragment_container
)
{
chat
.
rocket
.
android
.
files
.
ui
.
newInstance
(
chatRoomId
)
}
}
...
...
app/src/main/java/chat/rocket/android/chatroom/presentation/ChatRoomPresenter.kt
View file @
4b352b0f
...
...
@@ -638,14 +638,17 @@ class ChatRoomPresenter @Inject constructor(
}
}
fun
toMembersList
(
chatRoomId
:
String
,
chatRoomType
:
String
)
=
navigator
.
toMembersList
(
chatRoomId
,
chatRoomType
)
fun
toMembersList
(
chatRoomId
:
String
)
=
navigator
.
toMembersList
(
chatRoomId
)
fun
toPinnedMessageList
(
chatRoomId
:
String
,
chatRoomType
:
String
)
=
navigator
.
toPinnedMessageList
(
chatRoomId
,
chatRoomType
)
fun
toPinnedMessageList
(
chatRoomId
:
String
)
=
navigator
.
toPinnedMessageList
(
chatRoomId
)
fun
toFavoriteMessageList
(
chatRoomId
:
String
,
chatRoomType
:
String
)
=
navigator
.
toFavoriteMessageList
(
chatRoomId
,
chatRoomType
)
fun
toFavoriteMessageList
(
chatRoomId
:
String
)
=
navigator
.
toFavoriteMessageList
(
chatRoomId
)
fun
toFileList
(
chatRoomId
:
String
)
=
navigator
.
toFileList
(
chatRoomId
)
fun
loadChatRooms
()
{
launchUI
(
strategy
)
{
...
...
app/src/main/java/chat/rocket/android/chatroom/ui/ChatRoomActivity.kt
View file @
4b352b0f
...
...
@@ -154,7 +154,7 @@ class ChatRoomActivity : AppCompatActivity(), HasSupportFragmentInjector {
drawable
?.
let
{
val
wrappedDrawable
=
DrawableHelper
.
wrapDrawable
(
it
)
val
mutableDrawable
=
wrappedDrawable
.
mutate
()
DrawableHelper
.
tintDrawable
(
mutableDrawable
,
this
,
R
.
color
.
w
hite
)
DrawableHelper
.
tintDrawable
(
mutableDrawable
,
this
,
R
.
color
.
colorW
hite
)
DrawableHelper
.
compoundDrawable
(
text_room_name
,
mutableDrawable
)
}
}
else
{
...
...
app/src/main/java/chat/rocket/android/chatroom/ui/ChatRoomFragment.kt
View file @
4b352b0f
...
...
@@ -230,13 +230,16 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
override
fun
onOptionsItemSelected
(
item
:
MenuItem
):
Boolean
{
when
(
item
.
itemId
)
{
R
.
id
.
action_members_list
->
{
presenter
.
toMembersList
(
chatRoomId
,
chatRoomType
)
presenter
.
toMembersList
(
chatRoomId
)
}
R
.
id
.
action_pinned_messages
->
{
presenter
.
toPinnedMessageList
(
chatRoomId
,
chatRoomType
)
presenter
.
toPinnedMessageList
(
chatRoomId
)
}
R
.
id
.
action_favorite_messages
->
{
presenter
.
toFavoriteMessageList
(
chatRoomId
,
chatRoomType
)
presenter
.
toFavoriteMessageList
(
chatRoomId
)
}
R
.
id
.
action_files
->
{
presenter
.
toFileList
(
chatRoomId
)
}
}
return
true
...
...
app/src/main/java/chat/rocket/android/chatroom/ui/bottomsheet/adapter/ActionListAdapter.kt
View file @
4b352b0f
...
...
@@ -26,7 +26,7 @@ class ActionListAdapter(
holder
.
itemView
.
setOnClickListener
{
callback
?.
onMenuItemClick
(
item
)
}
val
deleteTextColor
=
holder
.
itemView
.
context
.
resources
.
getColor
(
R
.
color
.
r
ed
)
val
deleteTextColor
=
holder
.
itemView
.
context
.
resources
.
getColor
(
R
.
color
.
colorR
ed
)
val
color
=
if
(
item
.
itemId
==
R
.
id
.
action_message_delete
)
{
deleteTextColor
}
else
{
...
...
app/src/main/java/chat/rocket/android/dagger/module/ActivityBuilder.kt
View file @
4b352b0f
...
...
@@ -11,13 +11,14 @@ import chat.rocket.android.authentication.ui.AuthenticationActivity
import
chat.rocket.android.chatroom.di.ChatRoomFragmentProvider
import
chat.rocket.android.chatroom.di.ChatRoomModule
import
chat.rocket.android.chatroom.di.FavoriteMessagesFragmentProvider
import
chat.rocket.android.chatroom.di.PinnedMessagesFragmentProvider
import
chat.rocket.android.chatroom.ui.ChatRoomActivity
import
chat.rocket.android.chatrooms.di.ChatRoomsFragmentProvider
import
chat.rocket.android.dagger.scope.PerActivity
import
chat.rocket.android.files.di.FilesFragmentProvider
import
chat.rocket.android.main.di.MainModule
import
chat.rocket.android.main.ui.MainActivity
import
chat.rocket.android.members.di.MembersFragmentProvider
import
chat.rocket.android.pinnedmessages.di.PinnedMessagesFragmentProvider
import
chat.rocket.android.profile.di.ProfileFragmentProvider
import
chat.rocket.android.server.di.ChangeServerModule
import
chat.rocket.android.server.ui.ChangeServerActivity
...
...
@@ -30,21 +31,25 @@ import dagger.android.ContributesAndroidInjector
abstract
class
ActivityBuilder
{
@PerActivity
@ContributesAndroidInjector
(
modules
=
[
AuthenticationModule
::
class
,
ServerFragmentProvider
::
class
,
LoginFragmentProvider
::
class
,
RegisterUsernameFragmentProvider
::
class
,
ResetPasswordFragmentProvider
::
class
,
SignupFragmentProvider
::
class
,
TwoFAFragmentProvider
::
class
])
@ContributesAndroidInjector
(
modules
=
[
AuthenticationModule
::
class
,
ServerFragmentProvider
::
class
,
LoginFragmentProvider
::
class
,
RegisterUsernameFragmentProvider
::
class
,
ResetPasswordFragmentProvider
::
class
,
SignupFragmentProvider
::
class
,
TwoFAFragmentProvider
::
class
]
)
abstract
fun
bindAuthenticationActivity
():
AuthenticationActivity
@PerActivity
@ContributesAndroidInjector
(
modules
=
[
MainModule
::
class
,
ChatRoomsFragmentProvider
::
class
,
ProfileFragmentProvider
::
class
])
@ContributesAndroidInjector
(
modules
=
[
MainModule
::
class
,
ChatRoomsFragmentProvider
::
class
,
ProfileFragmentProvider
::
class
]
)
abstract
fun
bindMainActivity
():
MainActivity
@PerActivity
...
...
@@ -54,7 +59,8 @@ abstract class ActivityBuilder {
ChatRoomFragmentProvider
::
class
,
MembersFragmentProvider
::
class
,
PinnedMessagesFragmentProvider
::
class
,
FavoriteMessagesFragmentProvider
::
class
FavoriteMessagesFragmentProvider
::
class
,
FilesFragmentProvider
::
class
]
)
abstract
fun
bindChatRoomActivity
():
ChatRoomActivity
...
...
app/src/main/java/chat/rocket/android/favoritemessages/presentation/FavoriteMessagesPresenter.kt
View file @
4b352b0f
...
...
@@ -15,12 +15,13 @@ import javax.inject.Inject
class
FavoriteMessagesPresenter
@Inject
constructor
(
private
val
view
:
FavoriteMessagesView
,
private
val
strategy
:
CancelStrategy
,
private
val
serverInteractor
:
GetCurrentServerInteractor
,
private
val
roomsInteractor
:
ChatRoomsInteractor
,
private
val
mapper
:
ViewModelMapper
,
factory
:
RocketChatClientFactory
val
serverInteractor
:
GetCurrentServerInteractor
,
val
factory
:
RocketChatClientFactory
)
{
private
val
client
=
factory
.
create
(
serverInteractor
.
get
()
!!
)
private
val
serverUrl
=
serverInteractor
.
get
()
!!
private
val
client
=
factory
.
create
(
serverUrl
)
private
var
offset
:
Int
=
0
/**
...
...
@@ -31,21 +32,19 @@ class FavoriteMessagesPresenter @Inject constructor(
fun
loadFavoriteMessages
(
roomId
:
String
)
{
launchUI
(
strategy
)
{
try
{
val
serverUrl
=
serverInteractor
.
get
()
!!
val
chatRoom
=
roomsInteractor
.
getById
(
serverUrl
,
roomId
)
chatRoom
?.
let
{
room
->
view
.
showLoading
()
val
favoriteMessages
=
client
.
getFavoriteMessages
(
roomId
,
room
.
type
,
offset
)
offset
=
favoriteMessages
.
offset
.
toInt
()
view
.
showLoading
()
roomsInteractor
.
getById
(
serverUrl
,
roomId
)
?.
let
{
val
favoriteMessages
=
client
.
getFavoriteMessages
(
roomId
,
it
.
type
,
offset
)
val
messageList
=
mapper
.
map
(
favoriteMessages
.
result
)
view
.
showFavoriteMessages
(
messageList
)
view
.
hideLoading
()
offset
+=
1
*
30
}.
ifNull
{
Timber
.
e
(
"Couldn't find a room with id: $roomId at current server."
)
}
}
catch
(
e
:
RocketChatException
)
{
Timber
.
e
(
e
)
}
catch
(
exception
:
RocketChatException
)
{
Timber
.
e
(
exception
)
}
finally
{
view
.
hideLoading
()
}
}
}
...
...
app/src/main/java/chat/rocket/android/favoritemessages/ui/FavoriteMessagesFragment.kt
View file @
4b352b0f
...
...
@@ -23,21 +23,18 @@ import dagger.android.support.AndroidSupportInjection
import
kotlinx.android.synthetic.main.fragment_favorite_messages.*
import
javax.inject.Inject
fun
newInstance
(
chatRoomId
:
String
,
chatRoomType
:
String
):
Fragment
{
fun
newInstance
(
chatRoomId
:
String
):
Fragment
{
return
FavoriteMessagesFragment
().
apply
{
arguments
=
Bundle
(
1
).
apply
{
putString
(
INTENT_CHAT_ROOM_ID
,
chatRoomId
)
putString
(
INTENT_CHAT_ROOM_TYPE
,
chatRoomType
)
}
}
}
private
const
val
INTENT_CHAT_ROOM_ID
=
"chat_room_id"
private
const
val
INTENT_CHAT_ROOM_TYPE
=
"chat_room_type"
class
FavoriteMessagesFragment
:
Fragment
(),
FavoriteMessagesView
{
private
lateinit
var
chatRoomId
:
String
private
lateinit
var
chatRoomType
:
String
private
lateinit
var
adapter
:
ChatRoomAdapter
@Inject
lateinit
var
presenter
:
FavoriteMessagesPresenter
...
...
@@ -49,7 +46,6 @@ class FavoriteMessagesFragment : Fragment(), FavoriteMessagesView {
val
bundle
=
arguments
if
(
bundle
!=
null
)
{
chatRoomId
=
bundle
.
getString
(
INTENT_CHAT_ROOM_ID
)
chatRoomType
=
bundle
.
getString
(
INTENT_CHAT_ROOM_TYPE
)
}
else
{
requireNotNull
(
bundle
)
{
"no arguments supplied when the fragment was instantiated"
}
}
...
...
@@ -70,7 +66,7 @@ class FavoriteMessagesFragment : Fragment(), FavoriteMessagesView {
override
fun
showFavoriteMessages
(
favoriteMessages
:
List
<
BaseViewModel
<*
>>)
{
ui
{
if
(
recycler_view
.
adapter
==
null
)
{
adapter
=
ChatRoomAdapter
(
chatRoomType
,
""
,
null
,
false
)
adapter
=
ChatRoomAdapter
(
enableActions
=
false
)
recycler_view
.
adapter
=
adapter
val
linearLayoutManager
=
LinearLayoutManager
(
context
,
LinearLayoutManager
.
VERTICAL
,
false
)
...
...
app/src/main/java/chat/rocket/android/files/adapter/FilesAdapter.kt
0 → 100644
View file @
4b352b0f
package
chat.rocket.android.files.adapter
import
android.support.v7.widget.RecyclerView
import
android.view.View
import
android.view.ViewGroup
import
androidx.core.view.isVisible
import
chat.rocket.android.R
import
chat.rocket.android.files.viewmodel.FileViewModel
import
chat.rocket.android.util.extensions.inflate
import
kotlinx.android.synthetic.main.item_generic_attachment.view.*
class
FilesAdapter
(
private
val
listener
:
(
FileViewModel
)
->
Unit
)
:
RecyclerView
.
Adapter
<
FilesAdapter
.
ViewHolder
>()
{
private
var
dataSet
:
List
<
FileViewModel
>
=
ArrayList
()
override
fun
onCreateViewHolder
(
parent
:
ViewGroup
,
viewType
:
Int
):
FilesAdapter
.
ViewHolder
=
ViewHolder
(
parent
.
inflate
(
R
.
layout
.
item_generic_attachment
))
override
fun
onBindViewHolder
(
holder
:
FilesAdapter
.
ViewHolder
,
position
:
Int
)
=
holder
.
bind
(
dataSet
[
position
],
listener
)
override
fun
getItemCount
():
Int
=
dataSet
.
size
fun
prependData
(
dataSet
:
List
<
FileViewModel
>)
{
this
.
dataSet
=
dataSet
notifyItemRangeInserted
(
0
,
dataSet
.
size
)
}
fun
appendData
(
dataSet
:
List
<
FileViewModel
>)
{
val
previousDataSetSize
=
this
.
dataSet
.
size
this
.
dataSet
+=
dataSet
notifyItemRangeInserted
(
previousDataSetSize
,
dataSet
.
size
)
}
class
ViewHolder
(
itemView
:
View
)
:
RecyclerView
.
ViewHolder
(
itemView
)
{
fun
bind
(
fileViewModel
:
FileViewModel
,
listener
:
(
FileViewModel
)
->
Unit
)
{
with
(
itemView
)
{
when
{
fileViewModel
.
isImage
->
{
image_file_thumbnail
.
setImageURI
(
fileViewModel
.
url
)
image_file_media_thumbnail
.
isVisible
=
false
image_file_thumbnail
.
isVisible
=
true
}
fileViewModel
.
isMedia
->
{
image_file_media_thumbnail
.
setImageDrawable
(
context
.
resources
.
getDrawable
(
R
.
drawable
.
ic_play_arrow_black_24dp
,
null
)
)
image_file_thumbnail
.
isVisible
=
false
image_file_media_thumbnail
.
isVisible
=
true
}
else
->
{
image_file_media_thumbnail
.
setImageDrawable
(
context
.
resources
.
getDrawable
(
R
.
drawable
.
ic_insert_drive_file_black_24dp
,
null
)
)
image_file_thumbnail
.
isVisible
=
false
image_file_media_thumbnail
.
isVisible
=
true
}
}
text_file_name
.
text
=
fileViewModel
.
name
text_uploader
.
text
=
fileViewModel
.
uploader
text_upload_date
.
text
=
fileViewModel
.
uploadDate
setOnClickListener
{
listener
(
fileViewModel
)
}
}
}
}
}
\ No newline at end of file
app/src/main/java/chat/rocket/android/files/di/FilesFragmentModule.kt
0 → 100644
View file @
4b352b0f
package
chat.rocket.android.files.di
import
android.arch.lifecycle.LifecycleOwner
import
chat.rocket.android.core.lifecycle.CancelStrategy
import
chat.rocket.android.dagger.scope.PerFragment
import
chat.rocket.android.files.presentation.FilesView
import
chat.rocket.android.files.ui.FilesFragment
import
dagger.Module
import
dagger.Provides
import
kotlinx.coroutines.experimental.Job
@Module
@PerFragment
class
FilesFragmentModule
{
@Provides
fun
provideLifecycleOwner
(
frag
:
FilesFragment
):
LifecycleOwner
{
return
frag
}
@Provides
fun
provideCancelStrategy
(
owner
:
LifecycleOwner
,
jobs
:
Job
):
CancelStrategy
{
return
CancelStrategy
(
owner
,
jobs
)
}
@Provides
fun
provideFilesView
(
frag
:
FilesFragment
):
FilesView
{
return
frag
}
}
\ No newline at end of file
app/src/main/java/chat/rocket/android/files/di/FilesFragmentProvider.kt
0 → 100644
View file @
4b352b0f
package
chat.rocket.android.files.di
import
chat.rocket.android.files.ui.FilesFragment
import
dagger.Module
import
dagger.android.ContributesAndroidInjector
@Module
abstract
class
FilesFragmentProvider
{
@ContributesAndroidInjector
(
modules
=
[
FilesFragmentModule
::
class
])
abstract
fun
provideFilesFragment
():
FilesFragment
}
\ No newline at end of file
app/src/main/java/chat/rocket/android/files/presentation/FilesPresenter.kt
0 → 100644
View file @
4b352b0f
package
chat.rocket.android.files.presentation
import
androidx.core.net.toUri
import
chat.rocket.android.core.lifecycle.CancelStrategy
import
chat.rocket.android.files.viewmodel.FileViewModel
import
chat.rocket.android.files.viewmodel.FileViewModelMapper
import
chat.rocket.android.server.domain.ChatRoomsInteractor
import
chat.rocket.android.server.domain.GetCurrentServerInteractor
import
chat.rocket.android.server.infraestructure.RocketChatClientFactory
import
chat.rocket.android.util.extensions.launchUI
import
chat.rocket.common.RocketChatException
import
chat.rocket.common.util.ifNull
import
chat.rocket.core.internal.rest.getFiles
import
timber.log.Timber
import
javax.inject.Inject
class
FilesPresenter
@Inject
constructor
(
private
val
view
:
FilesView
,
private
val
strategy
:
CancelStrategy
,
private
val
roomsInteractor
:
ChatRoomsInteractor
,
private
val
mapper
:
FileViewModelMapper
,
val
serverInteractor
:
GetCurrentServerInteractor
,
val
factory
:
RocketChatClientFactory
)
{
private
val
serverUrl
=
serverInteractor
.
get
()
!!
private
val
client
=
factory
.
create
(
serverUrl
)
private
var
offset
:
Int
=
0
/**
* Load all files for the given room id.
*
* @param roomId The id of the room to get files from.
*/
fun
loadFiles
(
roomId
:
String
)
{
launchUI
(
strategy
)
{
try
{
view
.
showLoading
()
roomsInteractor
.
getById
(
serverUrl
,
roomId
)
?.
let
{
val
files
=
client
.
getFiles
(
roomId
,
it
.
type
,
offset
)
val
filesViewModel
=
mapper
.
mapToViewModelList
(
files
.
result
)
view
.
showFiles
(
filesViewModel
,
files
.
total
)
offset
+=
1
*
30
}.
ifNull
{
Timber
.
e
(
"Couldn't find a room with id: $roomId at current server."
)
}
}
catch
(
exception
:
RocketChatException
)
{
exception
.
message
?.
let
{
view
.
showMessage
(
it
)
}.
ifNull
{
view
.
showGenericErrorMessage
()
}
Timber
.
e
(
exception
)
}
finally
{
view
.
hideLoading
()
}
}
}
fun
openFile
(
fileViewModel
:
FileViewModel
)
{
when
{
fileViewModel
.
isImage
->
fileViewModel
.
url
?.
let
{
view
.
openImage
(
it
,
fileViewModel
.
name
?:
""
)
}
fileViewModel
.
isMedia
->
fileViewModel
.
url
?.
let
{
view
.
playMedia
(
it
)
}
else
->
fileViewModel
.
url
?.
let
{
view
.
openDocument
(
it
.
toUri
())
}
}
}
}
\ No newline at end of file
app/src/main/java/chat/rocket/android/files/presentation/FilesView.kt
0 → 100644
View file @
4b352b0f
package
chat.rocket.android.files.presentation
import
android.net.Uri
import
chat.rocket.android.core.behaviours.LoadingView
import
chat.rocket.android.core.behaviours.MessageView
import
chat.rocket.android.files.viewmodel.FileViewModel
interface
FilesView
:
MessageView
,
LoadingView
{
/**
* Show list of files for the current room.
*
* @param dataSet The data set to show.
* @param total The total number of files.
*/
fun
showFiles
(
dataSet
:
List
<
FileViewModel
>,
total
:
Long
)
/**
* Plays a media file (audio/video).
*
* @param url The file url to play its media.
*/
fun
playMedia
(
url
:
String
)
/**
* Opens an image file
*
* @param url The file url to open its image.
* @param name The file name.
*/
fun
openImage
(
url
:
String
,
name
:
String
)
/**
* Opens a document file (.pdf, .txt and so on).
*
* @param uri The file uri to open its document.
*/
fun
openDocument
(
uri
:
Uri
)
}
\ No newline at end of file
app/src/main/java/chat/rocket/android/files/ui/FilesFragment.kt
0 → 100644
View file @
4b352b0f
package
chat.rocket.android.files.ui
import
android.content.Intent
import
android.net.Uri
import
android.os.Bundle
import
android.support.v4.app.Fragment
import
android.support.v7.widget.LinearLayoutManager
import
android.support.v7.widget.RecyclerView
import
android.view.LayoutInflater
import
android.view.View
import
android.view.ViewGroup
import
androidx.core.view.isVisible
import
chat.rocket.android.R
import
chat.rocket.android.chatroom.ui.ChatRoomActivity
import
chat.rocket.android.files.adapter.FilesAdapter
import
chat.rocket.android.files.presentation.FilesPresenter
import
chat.rocket.android.files.presentation.FilesView
import
chat.rocket.android.files.viewmodel.FileViewModel
import
chat.rocket.android.helper.EndlessRecyclerViewScrollListener
import
chat.rocket.android.helper.ImageHelper
import
chat.rocket.android.player.PlayerActivity
import
chat.rocket.android.util.extensions.inflate
import
chat.rocket.android.util.extensions.showToast
import
chat.rocket.android.util.extensions.ui
import
chat.rocket.android.widget.DividerItemDecoration
import
dagger.android.support.AndroidSupportInjection
import
kotlinx.android.synthetic.main.fragment_files.*
import
javax.inject.Inject
fun
newInstance
(
chatRoomId
:
String
):
Fragment
{
return
FilesFragment
().
apply
{
arguments
=
Bundle
(
1
).
apply
{
putString
(
BUNDLE_CHAT_ROOM_ID
,
chatRoomId
)
}
}
}
private
const
val
BUNDLE_CHAT_ROOM_ID
=
"chat_room_id"
class
FilesFragment
:
Fragment
(),
FilesView
{
@Inject
lateinit
var
presenter
:
FilesPresenter
private
val
adapter
:
FilesAdapter
=
FilesAdapter
{
fileViewModel
->
presenter
.
openFile
(
fileViewModel
)
}
private
val
linearLayoutManager
=
LinearLayoutManager
(
context
,
LinearLayoutManager
.
VERTICAL
,
false
)
private
lateinit
var
chatRoomId
:
String
override
fun
onCreate
(
savedInstanceState
:
Bundle
?)
{
super
.
onCreate
(
savedInstanceState
)
AndroidSupportInjection
.
inject
(
this
)
val
bundle
=
arguments
if
(
bundle
!=
null
)
{
chatRoomId
=
bundle
.
getString
(
BUNDLE_CHAT_ROOM_ID
)
}
else
{
requireNotNull
(
bundle
)
{
"no arguments supplied when the fragment was instantiated"
}
}
}
override
fun
onCreateView
(
inflater
:
LayoutInflater
,
container
:
ViewGroup
?,
savedInstanceState
:
Bundle
?
):
View
?
=
container
?.
inflate
(
R
.
layout
.
fragment_files
)
override
fun
onViewCreated
(
view
:
View
,
savedInstanceState
:
Bundle
?)
{
super
.
onViewCreated
(
view
,
savedInstanceState
)
setupRecyclerView
()
presenter
.
loadFiles
(
chatRoomId
)
}
override
fun
showFiles
(
dataSet
:
List
<
FileViewModel
>,
total
:
Long
)
{
setupToolbar
(
total
)
if
(
adapter
.
itemCount
==
0
)
{
adapter
.
prependData
(
dataSet
)
if
(
dataSet
.
size
>=
30
)
{
recycler_view
.
addOnScrollListener
(
object
:
EndlessRecyclerViewScrollListener
(
linearLayoutManager
)
{
override
fun
onLoadMore
(
page
:
Int
,
totalItemsCount
:
Int
,
recyclerView
:
RecyclerView
?
)
{
presenter
.
loadFiles
(
chatRoomId
)
}
})
}
}
else
{
adapter
.
appendData
(
dataSet
)
}
}
override
fun
playMedia
(
url
:
String
)
{
ui
{
activity
?.
let
{
PlayerActivity
.
play
(
it
,
url
)
}
}
}
override
fun
openImage
(
url
:
String
,
name
:
String
)
{
ui
{
activity
?.
let
{
ImageHelper
.
openImage
(
it
,
url
,
name
)
}
}
}
override
fun
openDocument
(
uri
:
Uri
)
{
ui
{
startActivity
(
Intent
(
Intent
.
ACTION_VIEW
,
uri
))
}
}
override
fun
showMessage
(
resId
:
Int
)
{
ui
{
showToast
(
resId
)
}
}
override
fun
showMessage
(
message
:
String
)
{
ui
{
showToast
(
message
)
}
}
override
fun
showGenericErrorMessage
()
{
showMessage
(
getString
(
R
.
string
.
msg_generic_error
))
}
override
fun
showLoading
()
{
ui
{
view_loading
.
isVisible
=
true
}
}
override
fun
hideLoading
()
{
ui
{
view_loading
.
isVisible
=
false
}
}
private
fun
setupRecyclerView
()
{
ui
{
recycler_view
.
layoutManager
=
linearLayoutManager
recycler_view
.
addItemDecoration
(
DividerItemDecoration
(
it
))
recycler_view
.
adapter
=
adapter
}
}
private
fun
setupToolbar
(
totalFiles
:
Long
)
{
(
activity
as
ChatRoomActivity
?)
?.
setupToolbarTitle
(
getString
(
R
.
string
.
title_files_total
,
totalFiles
)
)
}
}
\ No newline at end of file
app/src/main/java/chat/rocket/android/files/viewmodel/FileViewModel.kt
0 → 100644
View file @
4b352b0f
package
chat.rocket.android.files.viewmodel
import
DateTimeHelper
import
chat.rocket.android.server.domain.TokenRepository
import
chat.rocket.android.server.domain.useRealName
import
chat.rocket.android.util.extensions.fileUrl
import
chat.rocket.core.model.Value
import
chat.rocket.core.model.attachment.GenericAttachment
class
FileViewModel
(
private
val
genericAttachment
:
GenericAttachment
,
private
val
settings
:
Map
<
String
,
Value
<
Any
>>,
private
val
tokenRepository
:
TokenRepository
,
private
val
baseUrl
:
String
)
{
val
name
:
String
?
val
uploader
:
String
?
val
uploadDate
:
String
?
val
url
:
String
?
val
isMedia
:
Boolean
val
isImage
:
Boolean
init
{
name
=
getFileName
()
uploader
=
getUserDisplayName
()
uploadDate
=
getFileUploadDate
()
url
=
getFileUrl
()
isMedia
=
isFileMedia
()
isImage
=
isFileImage
()
}
private
fun
getFileName
():
String
?
{
return
genericAttachment
.
name
}
private
fun
getUserDisplayName
():
String
{
val
username
=
"@${genericAttachment.user?.username}"
val
realName
=
genericAttachment
.
user
?.
name
val
uploaderName
=
if
(
settings
.
useRealName
())
realName
else
username
return
uploaderName
?:
username
}
private
fun
getFileUploadDate
():
String
{
return
DateTimeHelper
.
getDateTime
(
DateTimeHelper
.
getLocalDateTime
(
genericAttachment
.
uploadedAt
)
)
}
private
fun
getFileUrl
():
String
?
{
val
token
=
tokenRepository
.
get
(
baseUrl
)
if
(
token
!=
null
)
{
genericAttachment
.
path
?.
let
{
return
baseUrl
.
fileUrl
(
it
,
token
)
}
}
return
""
}
private
fun
isFileMedia
():
Boolean
{
genericAttachment
.
type
?.
let
{
return
it
.
contains
(
"audio"
)
||
it
.
contains
(
"video"
)
}
return
false
}
private
fun
isFileImage
():
Boolean
{
genericAttachment
.
type
?.
let
{
return
it
.
contains
(
"image"
)
}
return
false
}
}
\ No newline at end of file
app/src/main/java/chat/rocket/android/files/viewmodel/FileViewModelMapper.kt
0 → 100644
View file @
4b352b0f
package
chat.rocket.android.files.viewmodel
import
chat.rocket.android.server.domain.GetCurrentServerInteractor
import
chat.rocket.android.server.domain.GetSettingsInteractor
import
chat.rocket.android.server.domain.TokenRepository
import
chat.rocket.android.server.domain.baseUrl
import
chat.rocket.core.model.Value
import
chat.rocket.core.model.attachment.GenericAttachment
import
javax.inject.Inject
class
FileViewModelMapper
@Inject
constructor
(
serverInteractor
:
GetCurrentServerInteractor
,
getSettingsInteractor
:
GetSettingsInteractor
,
private
val
tokenRepository
:
TokenRepository
)
{
private
var
settings
:
Map
<
String
,
Value
<
Any
>>
=
getSettingsInteractor
.
get
(
serverInteractor
.
get
()
!!
)
private
val
baseUrl
=
settings
.
baseUrl
()
fun
mapToViewModelList
(
fileList
:
List
<
GenericAttachment
>):
List
<
FileViewModel
>
{
return
fileList
.
map
{
FileViewModel
(
it
,
settings
,
tokenRepository
,
baseUrl
)
}
}
}
\ No newline at end of file
app/src/main/java/chat/rocket/android/helper/ImageHelper.kt
0 → 100644
View file @
4b352b0f
package
chat.rocket.android.helper
import
android.Manifest
import
android.app.Activity
import
android.content.Context
import
android.graphics.Color
import
android.graphics.Typeface
import
android.media.MediaScannerConnection
import
android.os.Environment
import
android.support.design.widget.AppBarLayout
import
android.support.v7.widget.Toolbar
import
android.text.TextUtils
import
android.util.TypedValue
import
android.view.ContextThemeWrapper
import
android.view.ViewGroup
import
android.widget.ImageView
import
android.widget.TextView
import
android.widget.Toast
import
androidx.core.net.toUri
import
androidx.core.view.setPadding
import
chat.rocket.android.R
import
com.facebook.binaryresource.FileBinaryResource
import
com.facebook.cache.common.CacheKey
import
com.facebook.imageformat.ImageFormatChecker
import
com.facebook.imagepipeline.cache.DefaultCacheKeyFactory
import
com.facebook.imagepipeline.core.ImagePipelineFactory
import
com.facebook.imagepipeline.request.ImageRequest
import
com.facebook.imagepipeline.request.ImageRequestBuilder
import
com.stfalcon.frescoimageviewer.ImageViewer
import
timber.log.Timber
import
java.io.File
object
ImageHelper
{
private
var
cacheKey
:
CacheKey
?
=
null
// TODO - implement a proper image viewer with a proper Transition
// TODO - We should definitely write our own ImageViewer
fun
openImage
(
context
:
Context
,
imageUrl
:
String
,
imageName
:
String
)
{
var
imageViewer
:
ImageViewer
?
=
null
val
request
=
ImageRequestBuilder
.
newBuilderWithSource
(
imageUrl
.
toUri
())
.
setLowestPermittedRequestLevel
(
ImageRequest
.
RequestLevel
.
DISK_CACHE
)
.
build
()
cacheKey
=
DefaultCacheKeyFactory
.
getInstance
()
.
getEncodedCacheKey
(
request
,
null
)
val
pad
=
context
.
resources
.
getDimensionPixelSize
(
R
.
dimen
.
viewer_toolbar_padding
)
val
lparams
=
AppBarLayout
.
LayoutParams
(
ViewGroup
.
LayoutParams
.
MATCH_PARENT
,
ViewGroup
.
LayoutParams
.
WRAP_CONTENT
)
val
toolbar
=
Toolbar
(
context
).
also
{
it
.
inflateMenu
(
R
.
menu
.
image_actions
)
it
.
overflowIcon
?.
setTint
(
Color
.
WHITE
)
it
.
setOnMenuItemClickListener
{
return
@setOnMenuItemClickListener
when
(
it
.
itemId
)
{
R
.
id
.
action_save_image
->
saveImage
(
context
)
else
->
true
}
}
val
titleSize
=
context
.
resources
.
getDimensionPixelSize
(
R
.
dimen
.
viewer_toolbar_title
)
val
titleTextView
=
TextView
(
context
).
also
{
it
.
text
=
imageName
it
.
setTextColor
(
Color
.
WHITE
)
it
.
setTextSize
(
TypedValue
.
COMPLEX_UNIT_PX
,
titleSize
.
toFloat
())
it
.
ellipsize
=
TextUtils
.
TruncateAt
.
END
it
.
setSingleLine
()
it
.
typeface
=
Typeface
.
DEFAULT_BOLD
it
.
setPadding
(
pad
)
}
val
backArrowView
=
ImageView
(
context
).
also
{
it
.
setImageResource
(
R
.
drawable
.
ic_arrow_back_white_24dp
)
it
.
setOnClickListener
{
imageViewer
?.
onDismiss
()
}
it
.
setPadding
(
0
,
pad
,
pad
,
pad
)
}
val
layoutParams
=
AppBarLayout
.
LayoutParams
(
AppBarLayout
.
LayoutParams
.
WRAP_CONTENT
,
AppBarLayout
.
LayoutParams
.
WRAP_CONTENT
)
it
.
addView
(
backArrowView
,
layoutParams
)
it
.
addView
(
titleTextView
,
layoutParams
)
}
val
appBarLayout
=
AppBarLayout
(
context
).
also
{
it
.
layoutParams
=
lparams
it
.
setBackgroundColor
(
Color
.
BLACK
)
it
.
addView
(
toolbar
,
AppBarLayout
.
LayoutParams
(
AppBarLayout
.
LayoutParams
.
MATCH_PARENT
,
ViewGroup
.
LayoutParams
.
WRAP_CONTENT
)
)
}
val
builder
=
ImageViewer
.
createPipelineDraweeControllerBuilder
()
.
setImageRequest
(
request
)
.
setAutoPlayAnimations
(
true
)
imageViewer
=
ImageViewer
.
Builder
(
context
,
listOf
(
imageUrl
))
.
setOverlayView
(
appBarLayout
)
.
setStartPosition
(
0
)
.
hideStatusBar
(
false
)
.
setCustomDraweeControllerBuilder
(
builder
)
.
show
()
}
private
fun
saveImage
(
context
:
Context
):
Boolean
{
if
(!
canWriteToExternalStorage
(
context
))
{
checkWritingPermission
(
context
)
return
false
}
if
(
ImagePipelineFactory
.
getInstance
().
mainFileCache
.
hasKey
(
cacheKey
))
{
val
resource
=
ImagePipelineFactory
.
getInstance
().
mainFileCache
.
getResource
(
cacheKey
)
val
cachedFile
=
(
resource
as
FileBinaryResource
).
file
val
imageFormat
=
ImageFormatChecker
.
getImageFormat
(
resource
.
openStream
())
val
imageDir
=
"${Environment.DIRECTORY_PICTURES}/Rocket.Chat Images/"
val
imagePath
=
Environment
.
getExternalStoragePublicDirectory
(
imageDir
)
val
imageFile
=
File
(
imagePath
,
"${cachedFile.nameWithoutExtension}.${imageFormat.fileExtension}"
)
imagePath
.
mkdirs
()
imageFile
.
createNewFile
()
try
{
cachedFile
.
copyTo
(
imageFile
,
true
)
MediaScannerConnection
.
scanFile
(
context
,
arrayOf
(
imageFile
.
absolutePath
),
null
)
{
path
,
uri
->
Timber
.
i
(
"Scanned $path:"
)
Timber
.
i
(
"-> uri=$uri"
)
}
}
catch
(
ex
:
Exception
)
{
Timber
.
e
(
ex
)
val
message
=
context
.
getString
(
R
.
string
.
msg_image_saved_failed
)
Toast
.
makeText
(
context
,
message
,
Toast
.
LENGTH_SHORT
).
show
()
}
finally
{
val
message
=
context
.
getString
(
R
.
string
.
msg_image_saved_successfully
)
Toast
.
makeText
(
context
,
message
,
Toast
.
LENGTH_SHORT
).
show
()
}
}
return
true
}
private
fun
canWriteToExternalStorage
(
context
:
Context
):
Boolean
{
return
AndroidPermissionsHelper
.
checkPermission
(
context
,
Manifest
.
permission
.
WRITE_EXTERNAL_STORAGE
)
}
private
fun
checkWritingPermission
(
context
:
Context
)
{
if
(
context
is
ContextThemeWrapper
&&
context
.
baseContext
is
Activity
)
{
val
activity
=
context
.
baseContext
as
Activity
AndroidPermissionsHelper
.
requestPermission
(
activity
,
Manifest
.
permission
.
WRITE_EXTERNAL_STORAGE
,
AndroidPermissionsHelper
.
WRITE_EXTERNAL_STORAGE_CODE
)
}
}
}
\ No newline at end of file
app/src/main/java/chat/rocket/android/helper/MessageParser.kt
View file @
4b352b0f
...
...
@@ -93,7 +93,7 @@ class MessageParser @Inject constructor(
private
val
othersTextColor
=
ResourcesCompat
.
getColor
(
context
.
resources
,
R
.
color
.
colorAccent
,
context
.
theme
)
private
val
othersBackgroundColor
=
ResourcesCompat
.
getColor
(
context
.
resources
,
android
.
R
.
color
.
transparent
,
context
.
theme
)
private
val
myselfTextColor
=
ResourcesCompat
.
getColor
(
context
.
resources
,
R
.
color
.
w
hite
,
context
.
theme
)
private
val
myselfTextColor
=
ResourcesCompat
.
getColor
(
context
.
resources
,
R
.
color
.
colorW
hite
,
context
.
theme
)
private
val
myselfBackgroundColor
=
ResourcesCompat
.
getColor
(
context
.
resources
,
R
.
color
.
colorAccent
,
context
.
theme
)
private
val
mentionPadding
=
context
.
resources
.
getDimensionPixelSize
(
R
.
dimen
.
padding_mention
).
toFloat
()
private
val
mentionRadius
=
context
.
resources
.
getDimensionPixelSize
(
R
.
dimen
.
radius_mention
).
toFloat
()
...
...
app/src/main/java/chat/rocket/android/members/presentation/MembersPresenter.kt
View file @
4b352b0f
...
...
@@ -3,39 +3,44 @@ package chat.rocket.android.members.presentation
import
chat.rocket.android.core.lifecycle.CancelStrategy
import
chat.rocket.android.members.viewmodel.MemberViewModel
import
chat.rocket.android.members.viewmodel.MemberViewModelMapper
import
chat.rocket.android.server.domain.ChatRoomsInteractor
import
chat.rocket.android.server.domain.GetCurrentServerInteractor
import
chat.rocket.android.server.infraestructure.RocketChatClientFactory
import
chat.rocket.android.util.extensions.launchUI
import
chat.rocket.android.util.retryIO
import
chat.rocket.common.RocketChatException
import
chat.rocket.common.model.roomTypeOf
import
chat.rocket.common.util.ifNull
import
chat.rocket.core.RocketChatClient
import
chat.rocket.core.internal.rest.getMembers
import
timber.log.Timber
import
javax.inject.Inject
class
MembersPresenter
@Inject
constructor
(
private
val
view
:
MembersView
,
private
val
navigator
:
MembersNavigator
,
private
val
strategy
:
CancelStrategy
,
serverInteractor
:
GetCurrentServerInteractor
,
factory
:
RocketChatClientFactory
,
private
val
mapper
:
MemberViewModelMapper
private
val
roomsInteractor
:
ChatRoomsInteractor
,
private
val
mapper
:
MemberViewModelMapper
,
val
serverInteractor
:
GetCurrentServerInteractor
,
val
factory
:
RocketChatClientFactory
)
{
private
val
client
:
RocketChatClient
=
factory
.
create
(
serverInteractor
.
get
()
!!
)
private
val
serverUrl
=
serverInteractor
.
get
()
!!
private
val
client
:
RocketChatClient
=
factory
.
create
(
serverUrl
)
private
var
offset
:
Long
=
0
fun
loadChatRoomsMembers
(
chatRoomId
:
String
,
chatRoomType
:
String
,
offset
:
Long
=
0
)
{
fun
loadChatRoomsMembers
(
roomId
:
String
)
{
launchUI
(
strategy
)
{
try
{
view
.
showLoading
()
val
members
=
retryIO
(
"getMembers($chatRoomId, $chatRoomType, $offset)"
)
{
client
.
getMembers
(
chatRoomId
,
roomTypeOf
(
chatRoomType
),
offset
,
60
)
roomsInteractor
.
getById
(
serverUrl
,
roomId
)
?.
let
{
val
members
=
client
.
getMembers
(
it
.
id
,
it
.
type
,
offset
,
60
)
val
memberViewModels
=
mapper
.
mapToViewModelList
(
members
.
result
)
view
.
showMembers
(
memberViewModels
,
members
.
total
)
offset
+=
1
*
60L
}.
ifNull
{
Timber
.
e
(
"Couldn't find a room with id: $roomId at current server"
)
}
val
memberViewModels
=
mapper
.
mapToViewModelList
(
members
.
result
)
view
.
showMembers
(
memberViewModels
,
members
.
total
)
}
catch
(
ex
:
RocketChatException
)
{
ex
.
message
?.
let
{
}
catch
(
exception
:
RocketChatException
)
{
exception
.
message
?.
let
{
view
.
showMessage
(
it
)
}.
ifNull
{
view
.
showGenericErrorMessage
()
...
...
app/src/main/java/chat/rocket/android/members/ui/MembersFragment.kt
View file @
4b352b0f
...
...
@@ -2,7 +2,6 @@ package chat.rocket.android.members.ui
import
android.os.Bundle
import
android.support.v4.app.Fragment
import
android.support.v7.app.AppCompatActivity
import
android.support.v7.widget.LinearLayoutManager
import
android.support.v7.widget.RecyclerView
import
android.view.LayoutInflater
...
...
@@ -24,17 +23,15 @@ import dagger.android.support.AndroidSupportInjection
import
kotlinx.android.synthetic.main.fragment_members.*
import
javax.inject.Inject
fun
newInstance
(
chatRoomId
:
String
,
chatRoomType
:
String
):
Fragment
{
fun
newInstance
(
chatRoomId
:
String
):
Fragment
{
return
MembersFragment
().
apply
{
arguments
=
Bundle
(
1
).
apply
{
putString
(
BUNDLE_CHAT_ROOM_ID
,
chatRoomId
)
putString
(
BUNDLE_CHAT_ROOM_TYPE
,
chatRoomType
)
}
}
}
private
const
val
BUNDLE_CHAT_ROOM_ID
=
"chat_room_id"
private
const
val
BUNDLE_CHAT_ROOM_TYPE
=
"chat_room_type"
class
MembersFragment
:
Fragment
(),
MembersView
{
@Inject
...
...
@@ -43,9 +40,7 @@ class MembersFragment : Fragment(), MembersView {
MembersAdapter
{
memberViewModel
->
presenter
.
toMemberDetails
(
memberViewModel
)
}
private
val
linearLayoutManager
=
LinearLayoutManager
(
context
,
LinearLayoutManager
.
VERTICAL
,
false
)
private
lateinit
var
chatRoomId
:
String
private
lateinit
var
chatRoomType
:
String
override
fun
onCreate
(
savedInstanceState
:
Bundle
?)
{
super
.
onCreate
(
savedInstanceState
)
...
...
@@ -54,7 +49,6 @@ class MembersFragment : Fragment(), MembersView {
val
bundle
=
arguments
if
(
bundle
!=
null
)
{
chatRoomId
=
bundle
.
getString
(
BUNDLE_CHAT_ROOM_ID
)
chatRoomType
=
bundle
.
getString
(
BUNDLE_CHAT_ROOM_TYPE
)
}
else
{
requireNotNull
(
bundle
)
{
"no arguments supplied when the fragment was instantiated"
}
}
...
...
@@ -68,9 +62,8 @@ class MembersFragment : Fragment(), MembersView {
override
fun
onViewCreated
(
view
:
View
,
savedInstanceState
:
Bundle
?)
{
super
.
onViewCreated
(
view
,
savedInstanceState
)
setupRecyclerView
()
presenter
.
loadChatRoomsMembers
(
chatRoomId
,
chatRoomType
)
presenter
.
loadChatRoomsMembers
(
chatRoomId
)
}
override
fun
showMembers
(
dataSet
:
List
<
MemberViewModel
>,
total
:
Long
)
{
...
...
@@ -86,7 +79,7 @@ class MembersFragment : Fragment(), MembersView {
totalItemsCount
:
Int
,
recyclerView
:
RecyclerView
?
)
{
presenter
.
loadChatRoomsMembers
(
chatRoomId
,
chatRoomType
,
page
*
60L
)
presenter
.
loadChatRoomsMembers
(
chatRoomId
)
}
})
}
...
...
app/src/main/java/chat/rocket/android/pinnedmessages/di/PinnedMessagesFragmentProvider.kt
View file @
4b352b0f
package
chat.rocket.android.
chatroom
.di
package
chat.rocket.android.
pinnedmessages
.di
import
chat.rocket.android.chatroom.di.PinnedMessagesFragmentModule
import
chat.rocket.android.pinnedmessages.ui.PinnedMessagesFragment
import
dagger.Module
import
dagger.android.ContributesAndroidInjector
...
...
app/src/main/java/chat/rocket/android/pinnedmessages/presentation/PinnedMessagesPresenter.kt
View file @
4b352b0f
...
...
@@ -16,13 +16,14 @@ import javax.inject.Inject
class
PinnedMessagesPresenter
@Inject
constructor
(
private
val
view
:
PinnedMessagesView
,
private
val
strategy
:
CancelStrategy
,
private
val
serverInteractor
:
GetCurrentServerInteractor
,
private
val
roomsInteractor
:
ChatRoomsInteractor
,
private
val
mapper
:
ViewModelMapper
,
factory
:
RocketChatClientFactory
val
serverInteractor
:
GetCurrentServerInteractor
,
val
factory
:
RocketChatClientFactory
)
{
private
val
client
=
factory
.
create
(
serverInteractor
.
get
()
!!
)
private
var
pinnedMessagesListOffset
:
Int
=
0
private
val
serverUrl
=
serverInteractor
.
get
()
!!
private
val
client
=
factory
.
create
(
serverUrl
)
private
var
offset
:
Int
=
0
/**
* Load all pinned messages for the given room id.
...
...
@@ -32,21 +33,20 @@ class PinnedMessagesPresenter @Inject constructor(
fun
loadPinnedMessages
(
roomId
:
String
)
{
launchUI
(
strategy
)
{
try
{
val
serverUrl
=
serverInteractor
.
get
()
!!
val
chatRoom
=
roomsInteractor
.
getById
(
serverUrl
,
roomId
)
chatRoom
?.
let
{
room
->
view
.
showLoading
()
val
pinnedMessages
=
client
.
getPinnedMessages
(
roomId
,
room
.
type
,
pinnedMessagesListOffset
)
pinnedMessagesListOffset
=
pinnedMessages
.
offset
.
toInt
()
val
messageList
=
mapper
.
map
(
pinnedMessages
.
result
.
filterNot
{
it
.
isSystemMessage
()
})
view
.
showLoading
()
roomsInteractor
.
getById
(
serverUrl
,
roomId
)
?.
let
{
val
pinnedMessages
=
client
.
getPinnedMessages
(
roomId
,
it
.
type
,
offset
)
val
messageList
=
mapper
.
map
(
pinnedMessages
.
result
.
filterNot
{
it
.
isSystemMessage
()
})
view
.
showPinnedMessages
(
messageList
)
view
.
hideLoading
()
offset
+=
1
*
30
}.
ifNull
{
Timber
.
e
(
"Couldn't find a room with id: $roomId at current server."
)
}
}
catch
(
e
:
RocketChatException
)
{
Timber
.
e
(
e
)
}
catch
(
exception
:
RocketChatException
)
{
Timber
.
e
(
exception
)
}
finally
{
view
.
hideLoading
()
}
}
}
...
...
app/src/main/java/chat/rocket/android/pinnedmessages/ui/PinnedMessagesFragment.kt
View file @
4b352b0f
...
...
@@ -23,22 +23,19 @@ import dagger.android.support.AndroidSupportInjection
import
kotlinx.android.synthetic.main.fragment_pinned_messages.*
import
javax.inject.Inject
fun
newInstance
(
chatRoomId
:
String
,
chatRoomType
:
String
):
Fragment
{
fun
newInstance
(
chatRoomId
:
String
):
Fragment
{
return
PinnedMessagesFragment
().
apply
{
arguments
=
Bundle
(
1
).
apply
{
putString
(
BUNDLE_CHAT_ROOM_ID
,
chatRoomId
)
putString
(
BUNDLE_CHAT_ROOM_TYPE
,
chatRoomType
)
}
}
}
private
const
val
BUNDLE_CHAT_ROOM_ID
=
"chat_room_id"
private
const
val
BUNDLE_CHAT_ROOM_TYPE
=
"chat_room_type"
class
PinnedMessagesFragment
:
Fragment
(),
PinnedMessagesView
{
private
lateinit
var
chatRoomId
:
String
private
lateinit
var
chatRoomType
:
String
private
lateinit
var
adapter
:
ChatRoomAdapter
@Inject
lateinit
var
presenter
:
PinnedMessagesPresenter
...
...
@@ -50,7 +47,6 @@ class PinnedMessagesFragment : Fragment(), PinnedMessagesView {
val
bundle
=
arguments
if
(
bundle
!=
null
)
{
chatRoomId
=
bundle
.
getString
(
BUNDLE_CHAT_ROOM_ID
)
chatRoomType
=
bundle
.
getString
(
BUNDLE_CHAT_ROOM_TYPE
)
}
else
{
requireNotNull
(
bundle
)
{
"no arguments supplied when the fragment was instantiated"
}
}
...
...
@@ -66,14 +62,13 @@ class PinnedMessagesFragment : Fragment(), PinnedMessagesView {
super
.
onViewCreated
(
view
,
savedInstanceState
)
setupToolbar
()
presenter
.
loadPinnedMessages
(
chatRoomId
)
}
override
fun
showPinnedMessages
(
pinnedMessages
:
List
<
BaseViewModel
<*
>>)
{
ui
{
if
(
recycler_view_pinned
.
adapter
==
null
)
{
adapter
=
ChatRoomAdapter
(
chatRoomType
,
""
,
null
,
false
)
adapter
=
ChatRoomAdapter
(
enableActions
=
false
)
recycler_view_pinned
.
adapter
=
adapter
val
linearLayoutManager
=
LinearLayoutManager
(
context
,
LinearLayoutManager
.
VERTICAL
,
false
)
...
...
app/src/main/java/chat/rocket/android/server/domain/SettingsRepository.kt
View file @
4b352b0f
...
...
@@ -103,5 +103,5 @@ fun PublicSettings.uploadMaxFileSize(): Int {
return
this
[
UPLOAD_MAX_FILE_SIZE
]
?.
value
?.
let
{
it
as
Int
}
?:
Int
.
MAX_VALUE
}
fun
PublicSettings
.
baseUrl
():
String
?
=
this
[
SITE_URL
]
?.
value
as
String
?
fun
PublicSettings
.
baseUrl
():
String
=
this
[
SITE_URL
]
?.
value
as
String
fun
PublicSettings
.
siteName
():
String
?
=
this
[
SITE_NAME
]
?.
value
as
String
?
\ No newline at end of file
app/src/main/java/chat/rocket/android/util/extensions/String.kt
View file @
4b352b0f
...
...
@@ -2,6 +2,7 @@ package chat.rocket.android.util.extensions
import
android.graphics.Color
import
android.util.Patterns
import
chat.rocket.common.model.Token
import
timber.log.Timber
fun
String
.
removeTrailingSlash
():
String
{
...
...
@@ -17,7 +18,11 @@ fun String.sanitize(): String {
return
tmp
.
removeTrailingSlash
()
}
fun
String
.
avatarUrl
(
avatar
:
String
,
isGroupOrChannel
:
Boolean
=
false
,
format
:
String
=
"jpeg"
):
String
{
fun
String
.
avatarUrl
(
avatar
:
String
,
isGroupOrChannel
:
Boolean
=
false
,
format
:
String
=
"jpeg"
):
String
{
return
if
(
isGroupOrChannel
)
{
"${removeTrailingSlash()}/avatar/%23${avatar.removeTrailingSlash()}?format=$format"
}
else
{
...
...
@@ -25,6 +30,14 @@ fun String.avatarUrl(avatar: String, isGroupOrChannel: Boolean = false, format:
}
}
fun
String
.
fileUrl
(
path
:
String
,
token
:
Token
):
String
{
return
(
this
+
path
+
"?rc_uid=${token.userId}"
+
"&rc_token=${token.authToken}"
).
safeUrl
()
}
fun
String
.
safeUrl
():
String
{
return
this
.
replace
(
" "
,
"%20"
).
replace
(
"\\"
,
""
)
}
fun
String
.
serverLogoUrl
(
favicon
:
String
)
=
"${removeTrailingSlash()}/$favicon"
fun
String
.
casUrl
(
serverUrl
:
String
,
token
:
String
)
=
...
...
app/src/main/res/drawable/ic_file_download_white_24dp.xml
0 → 100644
View file @
4b352b0f
<vector
xmlns:android=
"http://schemas.android.com/apk/res/android"
android:width=
"24dp"
android:height=
"24dp"
android:viewportHeight=
"24.0"
android:viewportWidth=
"24.0"
>
<path
android:fillColor=
"#FFFFFF"
android:pathData=
"M19,9h-4V3H9v6H5l7,7 7,-7zM5,18v2h14v-2H5z"
/>
</vector>
\ No newline at end of file
app/src/main/res/drawable/ic_insert_drive_file_black_24dp.xml
0 → 100644
View file @
4b352b0f
<vector
xmlns:android=
"http://schemas.android.com/apk/res/android"
android:width=
"24dp"
android:height=
"24dp"
android:viewportHeight=
"24.0"
android:viewportWidth=
"24.0"
>
<path
android:fillColor=
"#FF000000"
android:pathData=
"M6,2c-1.1,0 -1.99,0.9 -1.99,2L4,20c0,1.1 0.89,2 1.99,2L18,22c1.1,0 2,-0.9 2,-2L20,8l-6,-6L6,2zM13,9L13,3.5L18.5,9L13,9z"
/>
</vector>
app/src/main/res/drawable/ic_play_arrow_black_24dp.xml
0 → 100644
View file @
4b352b0f
<vector
xmlns:android=
"http://schemas.android.com/apk/res/android"
android:width=
"24dp"
android:height=
"24dp"
android:viewportHeight=
"24.0"
android:viewportWidth=
"24.0"
>
<path
android:fillColor=
"#FF000000"
android:pathData=
"M8,5v14l11,-7z"
/>
</vector>
\ No newline at end of file
app/src/main/res/layout/activity_main.xml
View file @
4b352b0f
...
...
@@ -42,7 +42,7 @@
android:layout_height=
"match_parent"
android:layout_marginTop=
"@dimen/nav_header_height"
android:alpha=
"0"
android:background=
"@color/
w
hite"
android:background=
"@color/
colorW
hite"
android:elevation=
"20dp"
android:visibility=
"gone"
/>
</FrameLayout>
...
...
app/src/main/res/layout/activity_web_view.xml
View file @
4b352b0f
...
...
@@ -21,7 +21,7 @@
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_centerInParent=
"true"
app:indicatorColor=
"@color/
b
lack"
app:indicatorColor=
"@color/
colorB
lack"
app:indicatorName=
"BallPulseIndicator"
/>
</RelativeLayout>
\ No newline at end of file
app/src/main/res/layout/app_bar_chat_room.xml
View file @
4b352b0f
...
...
@@ -40,7 +40,7 @@
android:drawablePadding=
"@dimen/text_view_drawable_padding"
android:ellipsize=
"end"
android:maxLines=
"1"
android:textColor=
"@color/
w
hite"
android:textColor=
"@color/
colorW
hite"
android:textSize=
"18sp"
android:textStyle=
"bold"
tools:text=
"Developers"
/>
...
...
app/src/main/res/layout/app_bar_password.xml
View file @
4b352b0f
...
...
@@ -25,7 +25,7 @@
android:layout_alignParentStart=
"true"
android:ellipsize=
"end"
android:maxLines=
"1"
android:textColor=
"@color/
w
hite"
android:textColor=
"@color/
colorW
hite"
android:textSize=
"18sp"
android:textStyle=
"bold"
tools:text=
"@string/title_password"
/>
...
...
app/src/main/res/layout/emoji_keyboard.xml
View file @
4b352b0f
...
...
@@ -4,7 +4,7 @@
android:id=
"@+id/emoji_keyboard_container"
android:layout_width=
"match_parent"
android:layout_height=
"0dp"
android:background=
"@color/
w
hite"
>
android:background=
"@color/
colorW
hite"
>
<View
android:id=
"@+id/divider"
...
...
app/src/main/res/layout/emoji_picker.xml
View file @
4b352b0f
...
...
@@ -4,7 +4,7 @@
android:id=
"@+id/picker_container"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
android:background=
"@color/
w
hite"
android:background=
"@color/
colorW
hite"
android:orientation=
"vertical"
>
<android.support.design.widget.TabLayout
...
...
@@ -22,6 +22,6 @@
android:layout_height=
"match_parent"
android:layout_marginEnd=
"8dp"
android:layout_marginStart=
"8dp"
android:background=
"@color/
w
hite"
/>
android:background=
"@color/
colorW
hite"
/>
</LinearLayout>
\ No newline at end of file
app/src/main/res/layout/fragment_authentication_log_in.xml
View file @
4b352b0f
...
...
@@ -214,7 +214,7 @@
android:layout_height=
"wrap_content"
android:src=
"@drawable/ic_expand_more_black_24dp"
android:theme=
"@style/Theme.AppCompat"
android:tint=
"@color/
w
hite"
android:tint=
"@color/
colorW
hite"
android:visibility=
"gone"
app:backgroundTint=
"@color/colorAccent"
app:elevation=
"@dimen/fab_elevation"
...
...
app/src/main/res/layout/fragment_chat_room.xml
View file @
4b352b0f
...
...
@@ -12,7 +12,7 @@
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:visibility=
"gone"
app:indicatorColor=
"@color/
b
lack"
app:indicatorColor=
"@color/
colorB
lack"
app:indicatorName=
"BallPulseIndicator"
app:layout_constraintBottom_toBottomOf=
"parent"
app:layout_constraintEnd_toEndOf=
"parent"
...
...
@@ -136,7 +136,7 @@
android:elevation=
"4dp"
android:gravity=
"center"
android:textAppearance=
"@style/TextAppearance.AppCompat.Body2"
android:textColor=
"@color/
w
hite"
android:textColor=
"@color/
colorW
hite"
android:visibility=
"gone"
tools:alpha=
"1"
tools:text=
"connected"
...
...
app/src/main/res/layout/fragment_chat_rooms.xml
View file @
4b352b0f
...
...
@@ -17,7 +17,7 @@
android:layout_height=
"wrap_content"
android:layout_centerInParent=
"true"
android:visibility=
"gone"
app:indicatorColor=
"@color/
b
lack"
app:indicatorColor=
"@color/
colorB
lack"
app:indicatorName=
"BallPulseIndicator"
/>
<TextView
...
...
@@ -39,7 +39,7 @@
android:elevation=
"4dp"
android:gravity=
"center"
android:textAppearance=
"@style/TextAppearance.AppCompat.Body2"
android:textColor=
"@color/
w
hite"
android:textColor=
"@color/
colorW
hite"
android:visibility=
"gone"
tools:alpha=
"1"
tools:text=
"connected"
...
...
app/src/main/res/layout/fragment_favorite_messages.xml
View file @
4b352b0f
...
...
@@ -18,7 +18,7 @@
android:layout_height=
"wrap_content"
android:layout_centerInParent=
"true"
android:visibility=
"gone"
app:indicatorColor=
"@color/
b
lack"
app:indicatorColor=
"@color/
colorB
lack"
app:indicatorName=
"BallPulseIndicator"
app:layout_constraintBottom_toBottomOf=
"parent"
app:layout_constraintEnd_toEndOf=
"parent"
...
...
app/src/main/res/layout/fragment_files.xml
0 → 100644
View file @
4b352b0f
<?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=
"match_parent"
tools:context=
".files.ui.FilesFragment"
>
<android.support.v7.widget.RecyclerView
android:id=
"@+id/recycler_view"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
android:scrollbars=
"vertical"
/>
<com.wang.avi.AVLoadingIndicatorView
android:id=
"@+id/view_loading"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:visibility=
"gone"
app:indicatorColor=
"@color/colorBlack"
app:indicatorName=
"BallPulseIndicator"
app:layout_constraintBottom_toBottomOf=
"@+id/recycler_view"
app:layout_constraintEnd_toEndOf=
"parent"
app:layout_constraintStart_toStartOf=
"parent"
app:layout_constraintTop_toTopOf=
"parent"
/>
<ImageView
android:id=
"@+id/image_file"
android:layout_width=
"100dp"
android:layout_height=
"100dp"
android:src=
"@drawable/ic_insert_drive_file_black_24dp"
android:tint=
"@color/icon_grey"
app:layout_constraintBottom_toTopOf=
"@+id/text_no_file"
app:layout_constraintEnd_toEndOf=
"parent"
app:layout_constraintStart_toStartOf=
"parent"
app:layout_constraintTop_toTopOf=
"parent"
app:layout_constraintVertical_chainStyle=
"packed"
/>
<TextView
android:id=
"@+id/text_no_file"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_marginTop=
"24dp"
android:text=
"@string/msg_no_files"
android:textColor=
"@color/colorSecondaryText"
android:textSize=
"20sp"
android:textStyle=
"bold"
app:layout_constraintBottom_toTopOf=
"@+id/text_all_files_appear_here"
app:layout_constraintEnd_toEndOf=
"parent"
app:layout_constraintStart_toStartOf=
"parent"
app:layout_constraintTop_toBottomOf=
"@+id/image_file"
/>
<TextView
android:id=
"@+id/text_all_files_appear_here"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_marginTop=
"16dp"
android:text=
"@string/msg_all_files_appear_here"
android:textColor=
"@color/colorSecondaryTextLight"
android:textSize=
"16sp"
app:layout_constraintBottom_toBottomOf=
"parent"
app:layout_constraintEnd_toEndOf=
"parent"
app:layout_constraintStart_toStartOf=
"parent"
app:layout_constraintTop_toBottomOf=
"@+id/text_no_file"
/>
<android.support.constraint.Group
android:id=
"@+id/group_no_file"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:visibility=
"gone"
app:constraint_referenced_ids=
"image_file,text_no_file,text_all_files_appear_here"
tools:visibility=
"visible"
/>
</android.support.constraint.ConstraintLayout>
\ No newline at end of file
app/src/main/res/layout/fragment_member_bottom_sheet.xml
View file @
4b352b0f
...
...
@@ -30,7 +30,7 @@
style=
"@style/TextAppearance.AppCompat.Title"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:textColor=
"@color/
w
hite"
android:textColor=
"@color/
colorW
hite"
tools:text=
"Ronald Perkins"
/>
<TextView
...
...
@@ -39,7 +39,7 @@
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_marginTop=
"5dp"
android:textColor=
"@color/
w
hite"
android:textColor=
"@color/
colorW
hite"
tools:text=
"\@ronaldPerkins"
/>
</LinearLayout>
...
...
app/src/main/res/layout/fragment_members.xml
View file @
4b352b0f
...
...
@@ -18,7 +18,7 @@
android:layout_height=
"wrap_content"
android:layout_centerInParent=
"true"
android:layout_gravity=
"center"
app:indicatorColor=
"@color/
b
lack"
app:indicatorColor=
"@color/
colorB
lack"
app:indicatorName=
"BallPulseIndicator"
/>
</android.support.design.widget.CoordinatorLayout>
\ No newline at end of file
app/src/main/res/layout/fragment_password.xml
View file @
4b352b0f
...
...
@@ -48,7 +48,7 @@
android:layout_height=
"wrap_content"
tools:visibility=
"visible"
android:visibility=
"gone"
app:indicatorColor=
"@color/
b
lack"
app:indicatorColor=
"@color/
colorB
lack"
app:indicatorName=
"BallPulseIndicator"
app:layout_constraintStart_toStartOf=
"parent"
app:layout_constraintEnd_toEndOf=
"parent"
...
...
app/src/main/res/layout/fragment_pinned_messages.xml
View file @
4b352b0f
...
...
@@ -20,7 +20,7 @@
android:layout_marginBottom=
"8dp"
android:layout_marginTop=
"8dp"
android:visibility=
"gone"
app:indicatorColor=
"@color/
b
lack"
app:indicatorColor=
"@color/
colorB
lack"
app:indicatorName=
"BallPulseIndicator"
app:layout_constraintBottom_toBottomOf=
"@+id/recycler_view_pinned"
app:layout_constraintEnd_toEndOf=
"parent"
...
...
app/src/main/res/layout/fragment_profile.xml
View file @
4b352b0f
...
...
@@ -69,7 +69,7 @@
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_centerInParent=
"true"
app:indicatorColor=
"@color/
b
lack"
app:indicatorColor=
"@color/
colorB
lack"
app:indicatorName=
"BallPulseIndicator"
/>
</RelativeLayout>
\ No newline at end of file
app/src/main/res/layout/item_generic_attachment.xml
0 → 100644
View file @
4b352b0f
<?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:paddingBottom=
"@dimen/member_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/member_item_top_and_bottom_padding"
>
<LinearLayout
android:id=
"@+id/image_container"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:orientation=
"horizontal"
app:layout_constraintBottom_toBottomOf=
"parent"
app:layout_constraintStart_toStartOf=
"parent"
app:layout_constraintTop_toTopOf=
"parent"
>
<com.facebook.drawee.view.SimpleDraweeView
android:id=
"@+id/image_file_thumbnail"
android:layout_width=
"80dp"
android:layout_height=
"70dp"
android:visibility=
"gone"
app:roundedCornerRadius=
"3dp"
/>
<ImageView
android:id=
"@+id/image_file_media_thumbnail"
android:layout_width=
"80dp"
android:layout_height=
"70dp"
android:visibility=
"gone"
/>
</LinearLayout>
<TextView
android:id=
"@+id/text_file_name"
android:layout_width=
"0dp"
android:layout_height=
"wrap_content"
android:layout_marginStart=
"16dp"
android:ellipsize=
"end"
android:maxLines=
"1"
android:textColor=
"@color/colorPrimaryText"
app:layout_constraintEnd_toEndOf=
"parent"
app:layout_constraintStart_toEndOf=
"@+id/image_container"
app:layout_constraintTop_toTopOf=
"@+id/image_container"
tools:text=
"File.mp3"
/>
<TextView
android:id=
"@+id/text_uploader"
android:layout_width=
"0dp"
android:layout_height=
"wrap_content"
android:layout_marginStart=
"16dp"
android:ellipsize=
"end"
android:maxLines=
"1"
android:textColor=
"@color/colorSecondaryText"
app:layout_constraintBottom_toTopOf=
"@+id/text_upload_date"
app:layout_constraintEnd_toEndOf=
"parent"
app:layout_constraintStart_toEndOf=
"@+id/image_container"
tools:text=
"\@filipe.brito"
/>
<TextView
android:id=
"@+id/text_upload_date"
android:layout_width=
"0dp"
android:layout_height=
"wrap_content"
android:layout_marginStart=
"16dp"
android:textColor=
"@color/colorSecondaryTextLight"
app:layout_constraintBottom_toBottomOf=
"@+id/image_container"
app:layout_constraintEnd_toEndOf=
"parent"
app:layout_constraintStart_toEndOf=
"@+id/image_container"
tools:text=
"Ma 22, 2018 6:42 PM"
/>
</android.support.constraint.ConstraintLayout>
\ No newline at end of file
app/src/main/res/layout/item_message.xml
View file @
4b352b0f
...
...
@@ -38,13 +38,13 @@
android:layout_gravity=
"center"
android:layout_marginEnd=
"4dp"
android:layout_weight=
"1"
android:background=
"@color/
r
ed"
/>
android:background=
"@color/
colorR
ed"
/>
<TextView
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:text=
"@string/msg_unread_messages"
android:textColor=
"@color/
r
ed"
/>
android:textColor=
"@color/
colorR
ed"
/>
<View
android:layout_width=
"0dp"
...
...
@@ -52,7 +52,7 @@
android:layout_gravity=
"center"
android:layout_marginStart=
"4dp"
android:layout_weight=
"1"
android:background=
"@color/
r
ed"
/>
android:background=
"@color/
colorR
ed"
/>
</LinearLayout>
<LinearLayout
...
...
app/src/main/res/layout/message_action_bar.xml
View file @
4b352b0f
...
...
@@ -26,7 +26,7 @@
android:layout_marginStart=
"8dp"
android:ellipsize=
"end"
android:maxLines=
"2"
android:textColor=
"@color/
w
hite"
android:textColor=
"@color/
colorW
hite"
android:textSize=
"14sp"
android:typeface=
"normal"
app:layout_constraintBottom_toBottomOf=
"parent"
...
...
app/src/main/res/layout/message_attachment.xml
View file @
4b352b0f
...
...
@@ -22,7 +22,7 @@
android:id=
"@+id/audio_video_attachment"
android:layout_width=
"match_parent"
android:layout_height=
"150dp"
android:background=
"@color/
b
lack"
android:background=
"@color/
colorB
lack"
android:visibility=
"gone"
tools:visibility=
"visible"
>
...
...
app/src/main/res/layout/message_composer.xml
View file @
4b352b0f
...
...
@@ -21,10 +21,10 @@
android:id=
"@+id/text_room_is_read_only"
android:layout_width=
"match_parent"
android:layout_height=
"45dp"
android:background=
"@color/
w
hite"
android:background=
"@color/
colorW
hite"
android:gravity=
"center"
android:text=
"@string/msg_this_room_is_read_only"
android:textColor=
"@color/
b
lack"
android:textColor=
"@color/
colorB
lack"
android:visibility=
"gone"
app:layout_constraintTop_toBottomOf=
"@+id/divider"
/>
...
...
@@ -32,7 +32,7 @@
android:id=
"@+id/button_join_chat"
android:layout_width=
"match_parent"
android:layout_height=
"45dp"
android:background=
"@color/
w
hite"
android:background=
"@color/
colorW
hite"
android:text=
"@string/action_join_chat"
android:textColor=
"@color/colorAccent"
android:visibility=
"gone"
...
...
app/src/main/res/layout/message_list.xml
View file @
4b352b0f
...
...
@@ -19,7 +19,7 @@
android:theme=
"@style/Theme.AppCompat"
android:tint=
"@color/gray_material"
android:visibility=
"invisible"
app:backgroundTint=
"@color/
w
hite"
app:backgroundTint=
"@color/
colorW
hite"
app:fabSize=
"mini"
app:layout_anchor=
"@id/recycler_view"
app:layout_anchorGravity=
"bottom|end"
/>
...
...
app/src/main/res/layout/nav_header.xml
View file @
4b352b0f
...
...
@@ -54,7 +54,7 @@
android:layout_height=
"wrap_content"
android:layout_marginEnd=
"10dp"
android:layout_marginStart=
"10dp"
android:textColor=
"@color/
w
hite"
android:textColor=
"@color/
colorW
hite"
app:layout_constraintBottom_toBottomOf=
"@+id/image_user_status"
app:layout_constraintEnd_toStartOf=
"@+id/image_account_expand"
app:layout_constraintStart_toEndOf=
"@+id/image_user_status"
...
...
@@ -69,7 +69,7 @@
android:ellipsize=
"end"
android:maxLines=
"1"
android:textAppearance=
"@style/TextAppearance.AppCompat.Small"
android:textColor=
"@color/
w
hite"
android:textColor=
"@color/
colorW
hite"
app:layout_constraintEnd_toStartOf=
"@+id/image_account_expand"
app:layout_constraintStart_toStartOf=
"parent"
app:layout_constraintTop_toBottomOf=
"@+id/text_user_name"
...
...
@@ -80,7 +80,7 @@
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:src=
"@drawable/ic_expand_more_24dp"
android:tint=
"@color/
w
hite"
android:tint=
"@color/
colorW
hite"
app:layout_constraintBottom_toBottomOf=
"@+id/text_server_url"
app:layout_constraintEnd_toEndOf=
"parent"
/>
</android.support.constraint.ConstraintLayout>
...
...
app/src/main/res/layout/suggestion_command_item.xml
View file @
4b352b0f
...
...
@@ -18,7 +18,7 @@
android:layout_marginStart=
"8dp"
android:ellipsize=
"end"
android:maxLines=
"1"
android:textColor=
"@color/
b
lack"
android:textColor=
"@color/
colorB
lack"
android:textSize=
"14sp"
tools:text=
"/leave"
/>
...
...
app/src/main/res/layout/suggestion_member_item.xml
View file @
4b352b0f
...
...
@@ -32,7 +32,7 @@
android:layout_height=
"wrap_content"
android:layout_marginStart=
"5dp"
android:maxLines=
"1"
android:textColor=
"@color/
b
lack"
android:textColor=
"@color/
colorB
lack"
android:textSize=
"16sp"
app:layout_constraintBottom_toBottomOf=
"parent"
app:layout_constraintStart_toEndOf=
"@+id/image_status"
...
...
app/src/main/res/layout/suggestion_room_item.xml
View file @
4b352b0f
...
...
@@ -14,7 +14,7 @@
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:maxLines=
"1"
android:textColor=
"@color/
b
lack"
android:textColor=
"@color/
colorB
lack"
android:textSize=
"16sp"
tools:text=
"@tools:sample/full_names"
/>
...
...
app/src/main/res/layout/unread_messages_badge.xml
View file @
4b352b0f
...
...
@@ -11,7 +11,7 @@
android:layout_height=
"18dp"
android:background=
"@drawable/style_total_unread_messages"
android:gravity=
"center"
android:textColor=
"@color/
w
hite"
android:textColor=
"@color/
colorW
hite"
android:textSize=
"10sp"
android:visibility=
"gone"
tools:text=
"99+"
...
...
app/src/main/res/menu/chatroom_actions.xml
View file @
4b352b0f
...
...
@@ -16,4 +16,9 @@
android:id=
"@+id/action_favorite_messages"
android:title=
"@string/title_favorite_messages"
app:showAsAction=
"never"
/>
<item
android:id=
"@+id/action_files"
android:title=
"@string/msg_files"
app:showAsAction=
"never"
/>
</menu>
\ No newline at end of file
app/src/main/res/menu/image_actions.xml
View file @
4b352b0f
...
...
@@ -4,6 +4,7 @@
<item
android:id=
"@+id/action_save_image"
android:title=
"Save to Gallery"
app:showAsAction=
"never"
/>
android:icon=
"@drawable/ic_file_download_white_24dp"
android:title=
"@string/action_save_to_gallery"
app:showAsAction=
"always"
/>
</menu>
\ No newline at end of file
app/src/main/res/values-es/strings.xml
View file @
4b352b0f
...
...
@@ -17,7 +17,7 @@
<string
name=
"title_about"
>
Acerca de
</string>
<!-- Actions -->
<string
name=
"action_connect"
>
Conectar
</string>
"'
<string
name=
"action_connect"
>
Conectar
</string>
<string
name=
"action_use_this_username"
>
Usa este nombre de usuario
</string>
<string
name=
"action_login_or_sign_up"
>
Toca en este botón para iniciar sesión o crear una cuenta
</string>
<string
name=
"action_terms_of_service"
>
Términos de Servicio
</string>
...
...
@@ -34,6 +34,9 @@
<string
name=
"action_away"
>
Ausente
</string>
<string
name=
"action_busy"
>
Ocupado
</string>
<string
name=
"action_invisible"
>
Invisible
</string>
// TODO: Add proper translation.
<string
name=
"action_save_to_gallery"
>
Save to gallery
</string>
<!-- Settings List -->
<string-array
name=
"settings_actions"
>
...
...
@@ -158,7 +161,7 @@
<string
name=
"permission_starring_not_allowed"
>
Starring is not allowed
</string>
<!-- Members List -->
<string
name=
"title_members_list"
>
Lista de m
iembros
</string>
<string
name=
"title_members_list"
>
M
iembros
</string>
<!-- Pinned Messages -->
<string
name=
"title_pinned_messages"
>
Mensajes fijados
</string>
...
...
@@ -171,6 +174,13 @@
<string
name=
"no_favorite_messages"
>
No favorite messages
</string>
<string
name=
"no_favorite_description"
>
All the favorite messages\nappear here
</string>
<!-- Files -->
<!-- TODO Add proper translation-->
<string
name=
"msg_files"
>
Files
</string>
<string
name=
"title_files_total"
>
Files (%d)
</string>
<string
name=
"msg_no_files"
>
No files
</string>
<string
name=
"msg_all_files_appear_here"
>
All the files appear here
</string>
<!-- Upload Messages -->
<string
name=
"max_file_size_exceeded"
>
Tamaño del archivo (%1$d bytes) excedió el tamaño máximo de carga de %2$d bytes
</string>
...
...
app/src/main/res/values-fr/strings.xml
View file @
4b352b0f
...
...
@@ -34,6 +34,8 @@
<string
name=
"action_away"
>
Loin
</string>
<string
name=
"action_busy"
>
Occupé
</string>
<string
name=
"action_invisible"
>
Invisible
</string>
// TODO: Add proper translation.
<string
name=
"action_save_to_gallery"
>
Save to gallery
</string>
<!-- Settings List -->
<string-array
name=
"settings_actions"
>
...
...
@@ -159,7 +161,7 @@
<string
name=
"permission_starring_not_allowed"
>
Starring is not allowed
</string>
<!-- Members List -->
<string
name=
"title_members_list"
>
Liste des m
embres
</string>
<string
name=
"title_members_list"
>
M
embres
</string>
<!-- Pinned Messages -->
<string
name=
"title_pinned_messages"
>
Messages épinglés
</string>
...
...
@@ -172,6 +174,13 @@
<string
name=
"no_favorite_messages"
>
No favorite messages
</string>
<string
name=
"no_favorite_description"
>
All the favorite messages\nappear here
</string>
<!-- Files -->
<!-- TODO Add proper translation-->
<string
name=
"msg_files"
>
Files
</string>
<string
name=
"title_files_total"
>
Files (%d)
</string>
<string
name=
"msg_no_files"
>
No files
</string>
<string
name=
"msg_all_files_appear_here"
>
All the files appear here
</string>
<!-- Upload Messages -->
<string
name=
"max_file_size_exceeded"
>
Taille du fichier (%1$d bytes) dépassé la taille de téléchargement maximale de %2$d bytes
</string>
...
...
app/src/main/res/values-hi-rIN/strings.xml
View file @
4b352b0f
...
...
@@ -35,6 +35,8 @@
<string
name=
"action_away"
>
दूर
</string>
<string
name=
"action_busy"
>
व्यस्त
</string>
<string
name=
"action_invisible"
>
अदृश्य
</string>
// TODO: Add proper translation.
<string
name=
"action_save_to_gallery"
>
Save to gallery
</string>
<!-- Settings List -->
<string-array
name=
"settings_actions"
>
...
...
@@ -160,7 +162,7 @@
<string
name=
"permission_starring_not_allowed"
>
Starring is not allowed
</string>
<!-- Members List -->
<string
name=
"title_members_list"
>
सदस्य
ों की सूची
</string>
<string
name=
"title_members_list"
>
सदस्य
</string>
<!-- Pinned Messages -->
<string
name=
"title_pinned_messages"
>
पिन किए गए संदेश
</string>
...
...
@@ -173,6 +175,13 @@
<string
name=
"no_favorite_messages"
>
No favorite messages
</string>
<string
name=
"no_favorite_description"
>
All the favorite messages\nappear here
</string>
<!-- Files -->
<!-- TODO Add proper translation-->
<string
name=
"msg_files"
>
Files
</string>
<string
name=
"title_files_total"
>
Files (%d)
</string>
<string
name=
"msg_no_files"
>
No files
</string>
<string
name=
"msg_all_files_appear_here"
>
All the files appear here
</string>
<!-- Upload Messages -->
<string
name=
"max_file_size_exceeded"
>
फ़ाइल का आकार %1$d बाइट्स ने %2$d बाइट्स के अधिकतम अपलोड आकार को पार कर लिया है
</string>
...
...
app/src/main/res/values-pt-rBR/strings.xml
View file @
4b352b0f
...
...
@@ -34,6 +34,7 @@
<string
name=
"action_away"
>
Ausente
</string>
<string
name=
"action_busy"
>
Ocupado
</string>
<string
name=
"action_invisible"
>
Invisível
</string>
<string
name=
"action_save_to_gallery"
>
Salvar na galeria
</string>
<!-- Settings List -->
<string-array
name=
"settings_actions"
>
...
...
@@ -148,7 +149,7 @@
<string
name=
"permission_starring_not_allowed"
>
Favoritar não permitido
</string>
<!-- Members List -->
<string
name=
"title_members_list"
>
Lista de
Membros
</string>
<string
name=
"title_members_list"
>
Membros
</string>
<!-- Pinned Messages -->
<string
name=
"title_pinned_messages"
>
Mensagens Pinadas
</string>
...
...
@@ -156,11 +157,16 @@
<string
name=
"no_pinned_description"
>
Todas as mensagens pinadas\naparecerão aqui
</string>
<!-- Favorite Messages -->
<!-- TODO Add proper translation-->
<string
name=
"title_favorite_messages"
>
Messagens Favoritas
</string>
<string
name=
"no_favorite_messages"
>
Nenhuma messagem favorita
</string>
<string
name=
"no_favorite_description"
>
Todas as mensagens favoritas\naparecerão aqui
</string>
<!-- Files -->
<string
name=
"msg_files"
>
Arquivos
</string>
<string
name=
"title_files_total"
>
Arquivos (%d)
</string>
<string
name=
"msg_no_files"
>
Nenhum arquivo
</string>
<string
name=
"msg_all_files_appear_here"
>
Todos os arquivos aparecerão aqui
</string>
<!-- Upload Messages -->
<string
name=
"max_file_size_exceeded"
>
Tamanho de arquivo (%1$d bytes) excedeu tamanho máximo de upload (%2$d bytes)
</string>
...
...
app/src/main/res/values/colors.xml
View file @
4b352b0f
...
...
@@ -3,13 +3,13 @@
<!-- Main colors -->
<color
name=
"colorPrimary"
>
#FF303030
</color>
<!-- Material Grey 850 -->
<color
name=
"colorPrimaryDark"
>
#
ff
212121
</color>
<!-- Material Grey 900 -->
<color
name=
"colorPrimaryDark"
>
#
FF
212121
</color>
<!-- Material Grey 900 -->
<color
name=
"colorAccent"
>
#FF1976D2
</color>
<!-- Material Blue 700 -->
<!-- Text colors -->
<color
name=
"colorPrimaryText"
>
#DE000000
</color>
<color
name=
"colorSecondaryText"
>
#787878
</color>
<color
name=
"colorSecondaryTextLight"
>
#
c1c1c
1
</color>
<color
name=
"colorSecondaryText"
>
#
FF
787878
</color>
<color
name=
"colorSecondaryTextLight"
>
#
FFC1C1C
1
</color>
<!-- User status colors -->
<color
name=
"colorUserStatusOnline"
>
#2FE1A8
</color>
...
...
@@ -17,7 +17,16 @@
<color
name=
"colorUserStatusAway"
>
#FDD236
</color>
<color
name=
"colorUserStatusOffline"
>
#d9d9d9
</color>
<color
name=
"ic_launcher_background"
>
#FFFFFF
</color>
<!-- Normal colors -->
<color
name=
"colorWhite"
>
#FFFFFFFF
</color>
<color
name=
"colorBlack"
>
#FF000000
</color>
<color
name=
"colorRed"
>
#FFFF0000
</color>
<color
name=
"darkGray"
>
#FFa0a0a0
</color>
<color
name=
"actionMenuColor"
>
#FF727272
</color>
<color
name=
"whitesmoke"
>
#FFf1f1f1
</color>
<color
name=
"ic_launcher_background"
>
@color/colorWhite
</color>
<color
name=
"colorDrawableTintGrey"
>
#9FA2A8
</color>
...
...
@@ -29,13 +38,6 @@
<color
name=
"colorBackgroundMemberContainer"
>
#4D000000
</color>
<color
name=
"white"
>
#FFFFFFFF
</color>
<color
name=
"black"
>
#FF000000
</color>
<color
name=
"red"
>
#FFFF0000
</color>
<color
name=
"darkGray"
>
#FFa0a0a0
</color>
<color
name=
"actionMenuColor"
>
#FF727272
</color>
<color
name=
"whitesmoke"
>
#FFf1f1f1
</color>
<color
name=
"translucent_white"
>
#70F1F1F1
</color>
<color
name=
"colorEmojiIcon"
>
#FF767676
</color>
...
...
@@ -43,7 +45,7 @@
<color
name=
"quoteBar"
>
#A0A0A0
</color>
<!-- Suggestions -->
<color
name=
"suggestion_background_color"
>
@
android:color/w
hite
</color>
<color
name=
"suggestion_background_color"
>
@
color/colorW
hite
</color>
<color
name=
"icon_grey"
>
#AFADAF
</color>
...
...
app/src/main/res/values/strings.xml
View file @
4b352b0f
...
...
@@ -35,6 +35,7 @@
<string
name=
"action_away"
>
Away
</string>
<string
name=
"action_busy"
>
Busy
</string>
<string
name=
"action_invisible"
>
Invisible
</string>
<string
name=
"action_save_to_gallery"
>
Save to gallery
</string>
<!-- Settings List -->
<string-array
name=
"settings_actions"
>
...
...
@@ -149,7 +150,7 @@
<string
name=
"permission_starring_not_allowed"
>
Starring is not allowed
</string>
<!-- Members List -->
<string
name=
"title_members_list"
>
Members
List
</string>
<string
name=
"title_members_list"
>
Members
</string>
<!-- Pinned Messages -->
<string
name=
"title_pinned_messages"
>
Pinned Messages
</string>
...
...
@@ -161,6 +162,12 @@
<string
name=
"no_favorite_messages"
>
No favorite messages
</string>
<string
name=
"no_favorite_description"
>
All the favorite messages\nappear here
</string>
<!-- Files -->
<string
name=
"msg_files"
>
Files
</string>
<string
name=
"title_files_total"
>
Files (%d)
</string>
<string
name=
"msg_no_files"
>
No files
</string>
<string
name=
"msg_all_files_appear_here"
>
All the files appear here
</string>
<!-- Upload Messages -->
<string
name=
"max_file_size_exceeded"
>
File size %1$d bytes exceeded max upload size of %2$d bytes
</string>
...
...
dependencies.gradle
View file @
4b352b0f
...
...
@@ -24,7 +24,7 @@ ext {
timber
:
'4.7.0'
,
threeTenABP
:
'1.0.5'
,
rxBinding
:
'2.0.0'
,
fresco
:
'1.
8.1
'
,
fresco
:
'1.
9.0
'
,
kotshi
:
'1.0.2'
,
frescoImageViewer
:
'0.5.1'
,
markwon
:
'1.0.3'
,
...
...
player/src/main/java/chat/rocket/android/player/PlayerActivity.kt
View file @
4b352b0f
...
...
@@ -5,7 +5,6 @@ import android.content.Intent
import
android.net.Uri
import
android.os.Bundle
import
android.support.v7.app.AppCompatActivity
import
android.util.Log
import
android.view.View
import
com.google.android.exoplayer2.DefaultLoadControl
import
com.google.android.exoplayer2.DefaultRenderersFactory
...
...
@@ -72,7 +71,6 @@ class PlayerActivity : AppCompatActivity() {
}
val
uri
=
Uri
.
parse
(
videoUrl
)
val
mediaSource
=
buildMediaSource
(
uri
)
Log
.
d
(
"PlayerActivity"
,
"Player with: "
+
videoUrl
)
player
.
prepare
(
mediaSource
,
true
,
false
)
}
...
...
@@ -94,7 +92,7 @@ class PlayerActivity : AppCompatActivity() {
}
companion
object
{
const
private
val
URL_KEY
=
"URL_KEY"
private
const
val
URL_KEY
=
"URL_KEY"
fun
play
(
context
:
Context
,
url
:
String
)
{
context
.
startActivity
(
Intent
(
context
,
PlayerActivity
::
class
.
java
).
apply
{
putExtra
(
URL_KEY
,
url
)
...
...
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