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
f882e57c
Commit
f882e57c
authored
Mar 20, 2018
by
pcforgeek
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'upstream/develop-2.x' into add-day-marker-in-chatroom
parents
09302e5f
2e7a0037
Changes
66
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
66 changed files
with
1786 additions
and
491 deletions
+1786
-491
build.gradle
app/build.gradle
+3
-9
DrawableHelper.kt
app/src/main/java/chat/rocket/android/app/DrawableHelper.kt
+8
-7
User.kt
app/src/main/java/chat/rocket/android/app/User.kt
+0
-7
ColorImage.kt
...src/main/java/chat/rocket/android/app/utils/ColorImage.kt
+0
-134
CustomImageFormatConfigurator.kt
...rocket/android/app/utils/CustomImageFormatConfigurator.kt
+0
-24
SvgDecoder.kt
...src/main/java/chat/rocket/android/app/utils/SvgDecoder.kt
+0
-111
SignupFragment.kt
...rocket/android/authentication/signup/ui/SignupFragment.kt
+11
-10
AutoCompleteType.kt
.../chat/rocket/android/chatroom/adapter/AutoCompleteType.kt
+10
-0
ChatRoomAdapter.kt
...a/chat/rocket/android/chatroom/adapter/ChatRoomAdapter.kt
+0
-1
CommandSuggestionsAdapter.kt
...ket/android/chatroom/adapter/CommandSuggestionsAdapter.kt
+41
-0
ImageAttachmentViewHolder.kt
...ket/android/chatroom/adapter/ImageAttachmentViewHolder.kt
+12
-1
PeopleSuggestionsAdapter.kt
...cket/android/chatroom/adapter/PeopleSuggestionsAdapter.kt
+52
-0
RoomSuggestionsAdapter.kt
...rocket/android/chatroom/adapter/RoomSuggestionsAdapter.kt
+37
-0
ChatRoomPresenter.kt
...rocket/android/chatroom/presentation/ChatRoomPresenter.kt
+193
-18
ChatRoomView.kt
...chat/rocket/android/chatroom/presentation/ChatRoomView.kt
+17
-0
ChatRoomActivity.kt
.../java/chat/rocket/android/chatroom/ui/ChatRoomActivity.kt
+13
-2
ChatRoomFragment.kt
.../java/chat/rocket/android/chatroom/ui/ChatRoomFragment.kt
+74
-10
ViewModelMapper.kt
...chat/rocket/android/chatroom/viewmodel/ViewModelMapper.kt
+37
-15
ChatRoomSuggestionViewModel.kt
...troom/viewmodel/suggestion/ChatRoomSuggestionViewModel.kt
+9
-0
CommandSuggestionViewModel.kt
...atroom/viewmodel/suggestion/CommandSuggestionViewModel.kt
+7
-0
PeopleSuggestionViewModel.kt
...hatroom/viewmodel/suggestion/PeopleSuggestionViewModel.kt
+17
-0
ChatRoomsPresenter.kt
...cket/android/chatrooms/presentation/ChatRoomsPresenter.kt
+41
-5
ChatRoomsFragment.kt
...ava/chat/rocket/android/chatrooms/ui/ChatRoomsFragment.kt
+3
-1
AppModule.kt
.../main/java/chat/rocket/android/dagger/module/AppModule.kt
+14
-8
UrlHelper.kt
app/src/main/java/chat/rocket/android/helper/UrlHelper.kt
+2
-1
MainNavigator.kt
...va/chat/rocket/android/main/presentation/MainNavigator.kt
+8
-2
MembersFragment.kt
...in/java/chat/rocket/android/members/ui/MembersFragment.kt
+8
-0
MemberViewModel.kt
.../chat/rocket/android/members/viewmodel/MemberViewModel.kt
+1
-1
ProfilePresenter.kt
...t/rocket/android/profile/presentation/ProfilePresenter.kt
+8
-8
ProfileFragment.kt
...in/java/chat/rocket/android/profile/ui/ProfileFragment.kt
+16
-16
GetChatRoomsInteractor.kt
...at/rocket/android/server/domain/GetChatRoomsInteractor.kt
+8
-0
MessagesRepository.kt
...a/chat/rocket/android/server/domain/MessagesRepository.kt
+12
-0
RoomRepository.kt
.../java/chat/rocket/android/server/domain/RoomRepository.kt
+41
-0
UsersRepository.kt
...java/chat/rocket/android/server/domain/UsersRepository.kt
+42
-0
MemoryMessagesRepository.kt
...ndroid/server/infraestructure/MemoryMessagesRepository.kt
+5
-0
MemoryRoomRepository.kt
...et/android/server/infraestructure/MemoryRoomRepository.kt
+38
-0
MemoryUsersRepository.kt
...t/android/server/infraestructure/MemoryUsersRepository.kt
+39
-0
SuggestionModel.kt
...et/android/widget/autocompletion/model/SuggestionModel.kt
+18
-0
LocalSuggestionProvider.kt
...dget/autocompletion/repository/LocalSuggestionProvider.kt
+5
-0
CompletionStrategy.kt
...roid/widget/autocompletion/strategy/CompletionStrategy.kt
+10
-0
StringMatchingCompletionStrategy.kt
...letion/strategy/regex/StringMatchingCompletionStrategy.kt
+34
-0
TrieCompletionStrategy.kt
...et/autocompletion/strategy/trie/TrieCompletionStrategy.kt
+31
-0
Trie.kt
.../android/widget/autocompletion/strategy/trie/data/Trie.kt
+70
-0
TrieNode.kt
...roid/widget/autocompletion/strategy/trie/data/TrieNode.kt
+47
-0
BaseSuggestionViewHolder.kt
...roid/widget/autocompletion/ui/BaseSuggestionViewHolder.kt
+9
-0
PopupRecyclerView.kt
...ket/android/widget/autocompletion/ui/PopupRecyclerView.kt
+35
-0
SuggestionsAdapter.kt
...et/android/widget/autocompletion/ui/SuggestionsAdapter.kt
+97
-0
SuggestionsView.kt
...ocket/android/widget/autocompletion/ui/SuggestionsView.kt
+253
-0
hold.xml
app/src/main/res/anim/hold.xml
+1
-1
slide_up.xml
app/src/main/res/anim/slide_up.xml
+1
-1
suggestions_menu_decorator.xml
app/src/main/res/drawable/suggestions_menu_decorator.xml
+7
-0
user_status_white.xml
app/src/main/res/drawable/user_status_white.xml
+12
-0
fragment_authentication_log_in.xml
app/src/main/res/layout/fragment_authentication_log_in.xml
+0
-1
fragment_authentication_server.xml
app/src/main/res/layout/fragment_authentication_server.xml
+10
-10
fragment_authentication_sign_up.xml
app/src/main/res/layout/fragment_authentication_sign_up.xml
+75
-74
fragment_chat_room.xml
app/src/main/res/layout/fragment_chat_room.xml
+12
-4
message_composer.xml
app/src/main/res/layout/message_composer.xml
+12
-0
suggestion_command_item.xml
app/src/main/res/layout/suggestion_command_item.xml
+39
-0
suggestion_member_item.xml
app/src/main/res/layout/suggestion_member_item.xml
+74
-0
suggestion_room_item.xml
app/src/main/res/layout/suggestion_room_item.xml
+45
-0
strings.xml
app/src/main/res/values-pt-rBR/strings.xml
+26
-0
colors.xml
app/src/main/res/values/colors.xml
+4
-1
dimens.xml
app/src/main/res/values/dimens.xml
+4
-0
strings.xml
app/src/main/res/values/strings.xml
+24
-0
build.gradle
build.gradle
+1
-1
dependencies.gradle
dependencies.gradle
+3
-7
No files found.
app/build.gradle
View file @
f882e57c
...
@@ -12,8 +12,8 @@ android {
...
@@ -12,8 +12,8 @@ android {
applicationId
"chat.rocket.android"
applicationId
"chat.rocket.android"
minSdkVersion
21
minSdkVersion
21
targetSdkVersion
versions
.
targetSdk
targetSdkVersion
versions
.
targetSdk
versionCode
1011
versionCode
2000
versionName
"2.0.0-
dev9
"
versionName
"2.0.0-
alpha1
"
testInstrumentationRunner
"android.support.test.runner.AndroidJUnitRunner"
testInstrumentationRunner
"android.support.test.runner.AndroidJUnitRunner"
multiDexEnabled
true
multiDexEnabled
true
}
}
...
@@ -32,7 +32,6 @@ android {
...
@@ -32,7 +32,6 @@ android {
signingConfig
signingConfigs
.
release
signingConfig
signingConfigs
.
release
minifyEnabled
false
minifyEnabled
false
proguardFiles
getDefaultProguardFile
(
'proguard-android.txt'
),
'proguard-rules.pro'
proguardFiles
getDefaultProguardFile
(
'proguard-android.txt'
),
'proguard-rules.pro'
applicationIdSuffix
".dev"
}
}
debug
{
debug
{
...
@@ -95,14 +94,9 @@ dependencies {
...
@@ -95,14 +94,9 @@ dependencies {
implementation
libraries
.
kotshiApi
implementation
libraries
.
kotshiApi
implementation
libraries
.
frescoImageViewer
implementation
libraries
.
frescoImageViewer
implementation
(
libraries
.
androidSvg
)
{
exclude
group:
'org.jetbrains'
,
module:
'annotations-java5'
}
implementation
libraries
.
markwon
implementation
libraries
.
markwon
implementation
(
libraries
.
markwonImageLoader
)
{
implementation
libraries
.
markwonImageLoader
exclude
group:
'com.caverock'
,
module:
'androidsvg'
}
implementation
libraries
.
sheetMenu
implementation
libraries
.
sheetMenu
...
...
app/src/main/java/chat/rocket/android/app/DrawableHelper.kt
View file @
f882e57c
...
@@ -5,6 +5,7 @@ import android.support.v4.graphics.drawable.DrawableCompat
...
@@ -5,6 +5,7 @@ import android.support.v4.graphics.drawable.DrawableCompat
import
android.widget.EditText
import
android.widget.EditText
import
android.widget.TextView
import
android.widget.TextView
import
chat.rocket.android.R
import
chat.rocket.android.R
import
chat.rocket.common.model.UserStatus
object
DrawableHelper
{
object
DrawableHelper
{
...
@@ -78,7 +79,7 @@ object DrawableHelper {
...
@@ -78,7 +79,7 @@ object DrawableHelper {
* @param drawables The array of Drawable.
* @param drawables The array of Drawable.
* @see compoundDrawable
* @see compoundDrawable
*/
*/
fun
compoundDrawables
(
textView
:
Array
<
EditText
>,
drawables
:
Array
<
Drawable
>)
{
fun
compoundDrawables
(
textView
:
Array
<
TextView
>,
drawables
:
Array
<
Drawable
>)
{
if
(
textView
.
size
!=
drawables
.
size
)
{
if
(
textView
.
size
!=
drawables
.
size
)
{
return
return
}
else
{
}
else
{
...
@@ -104,15 +105,15 @@ object DrawableHelper {
...
@@ -104,15 +105,15 @@ object DrawableHelper {
* @param context The context.
* @param context The context.
* @return The user status drawable.
* @return The user status drawable.
*/
*/
fun
getUserStatusDrawable
(
userStatus
:
String
,
context
:
Context
):
Drawable
{
fun
getUserStatusDrawable
(
userStatus
:
UserStatus
,
context
:
Context
):
Drawable
{
val
userStatusDrawable
=
getDrawableFromId
(
R
.
drawable
.
ic_user_status_black
,
context
).
mutate
()
val
userStatusDrawable
=
getDrawableFromId
(
R
.
drawable
.
ic_user_status_black
,
context
).
mutate
()
wrapDrawable
(
userStatusDrawable
)
wrapDrawable
(
userStatusDrawable
)
when
(
userStatus
)
{
when
(
userStatus
)
{
// TODO: create a enum or check if it will come from the SDK
is
UserStatus
.
Online
->
tintDrawable
(
userStatusDrawable
,
context
,
R
.
color
.
colorUserStatusOnline
)
"online"
->
tintDrawable
(
userStatusDrawable
,
context
,
R
.
color
.
colorUserStatusOnline
)
is
UserStatus
.
Busy
->
tintDrawable
(
userStatusDrawable
,
context
,
R
.
color
.
colorUserStatusBusy
)
"busy"
->
tintDrawable
(
userStatusDrawable
,
context
,
R
.
color
.
colorUserStatusBus
y
)
is
UserStatus
.
Away
->
tintDrawable
(
userStatusDrawable
,
context
,
R
.
color
.
colorUserStatusAwa
y
)
"away"
->
tintDrawable
(
userStatusDrawable
,
context
,
R
.
color
.
colorUserStatusAway
)
is
UserStatus
.
Offline
->
tintDrawable
(
userStatusDrawable
,
context
,
R
.
color
.
colorUserStatusOffline
)
"offline"
->
tintDrawable
(
userStatusDrawable
,
context
,
R
.
color
.
colorUserStatusOffline
)
else
->
tintDrawable
(
userStatusDrawable
,
context
,
R
.
color
.
colorUserStatusOffline
)
}
}
return
userStatusDrawable
return
userStatusDrawable
}
}
...
...
app/src/main/java/chat/rocket/android/app/User.kt
deleted
100644 → 0
View file @
09302e5f
package
chat.rocket.android.app
data class
User
(
val
id
:
String
,
val
name
:
String
,
val
username
:
String
,
val
status
:
String
,
val
avatarUri
:
String
)
\ No newline at end of file
app/src/main/java/chat/rocket/android/app/utils/ColorImage.kt
deleted
100644 → 0
View file @
09302e5f
package
chat.rocket.android.app.utils
import
android.graphics.drawable.ColorDrawable
import
android.graphics.drawable.Drawable
import
android.support.annotation.ColorInt
import
android.support.annotation.Nullable
import
android.support.v4.graphics.ColorUtils
import
com.facebook.common.internal.ByteStreams
import
com.facebook.imageformat.ImageFormat
import
com.facebook.imageformat.ImageFormatCheckerUtils
import
com.facebook.imagepipeline.common.ImageDecodeOptions
import
com.facebook.imagepipeline.decoder.ImageDecoder
import
com.facebook.imagepipeline.drawable.DrawableFactory
import
com.facebook.imagepipeline.image.CloseableImage
import
com.facebook.imagepipeline.image.EncodedImage
import
com.facebook.imagepipeline.image.QualityInfo
import
java.io.IOException
/**
* Simple decoder that can decode color images that have the following format: <color>#FF5722</color>.
*
* @see {https://github.com/facebook/fresco/blob/master/samples/showcase/src/main/java/com/facebook/fresco/samples/showcase/imageformat/color/ColorImageExample.java}
*/
object
ColorImage
{
// Custom ImageFormat for color images.
private
val
imageFormatColor
=
ImageFormat
(
"IMAGE_FORMAT_COLOR"
,
"color"
)
// XML color tag that our colors must start with.
val
colorTag
=
"<color>"
/**
* Creates a new image format checker for [ColorImage.imageFormatColor].
*
* @return the image format checker.
*/
fun
createFormatChecker
():
ImageFormat
.
FormatChecker
=
ColorFormatChecker
()
/**
* Creates a new decoder that can decode [ColorImage.imageFormatColor] images.
*
* @return the decoder.
*/
fun
createDecoder
():
ImageDecoder
=
ColorDecoder
()
fun
createDrawableFactory
():
ColorDrawableFactory
=
ColorDrawableFactory
()
/**
* Custom color format checker that verifies that the header of the file corresponds to our [ColorImage.colorTag].
*/
class
ColorFormatChecker
:
ImageFormat
.
FormatChecker
{
private
val
header
=
ImageFormatCheckerUtils
.
asciiBytes
(
colorTag
)
override
fun
getHeaderSize
():
Int
{
return
header
.
size
}
@Nullable
override
fun
determineFormat
(
headerBytes
:
ByteArray
,
headerSize
:
Int
):
ImageFormat
?
{
if
(
headerSize
>
getHeaderSize
())
{
if
(
ImageFormatCheckerUtils
.
startsWithPattern
(
headerBytes
,
header
))
{
return
imageFormatColor
}
}
return
null
}
}
/**
* Custom closeable color image that holds a single color int value.
*/
class
CloseableColorImage
(
@field
:
ColorInt
@get
:
ColorInt
val
color
:
Int
)
:
CloseableImage
()
{
private
var
isClosed
=
false
override
fun
close
()
{
isClosed
=
true
}
override
fun
getSizeInBytes
():
Int
=
0
override
fun
isClosed
():
Boolean
=
isClosed
override
fun
getWidth
():
Int
=
0
override
fun
getHeight
():
Int
=
0
}
/**
* Decodes a color XML tag: <color>#rrggbb</color>.
*/
class
ColorDecoder
:
ImageDecoder
{
@Nullable
override
fun
decode
(
encodedImage
:
EncodedImage
,
length
:
Int
,
qualityInfo
:
QualityInfo
,
options
:
ImageDecodeOptions
):
CloseableImage
?
{
try
{
// Read the file as a string
val
text
=
String
(
ByteStreams
.
toByteArray
(
encodedImage
.
inputStream
))
// Check if the string matches "<color>#"
if
(!
text
.
startsWith
(
colorTag
+
"#"
))
{
return
null
}
// Parse the int value between # and <
val
startIndex
=
colorTag
.
length
+
1
val
endIndex
=
text
.
lastIndexOf
(
'<'
)
var
color
=
Integer
.
parseInt
(
text
.
substring
(
startIndex
,
endIndex
),
16
)
// Add the alpha component so that we actually see the color
color
=
ColorUtils
.
setAlphaComponent
(
color
,
255
)
// Return the CloseableImage
return
CloseableColorImage
(
color
)
}
catch
(
e
:
IOException
)
{
// TODO: are we using the android.util.Log for logging that type of errors? or should we use the SDK logger?
e
.
printStackTrace
()
}
// Return nothing if an error occurred
return
null
}
}
/**
* Color drawable factory that is able to render a [CloseableColorImage] by creating a new [ColorDrawable] for the given color.
*/
class
ColorDrawableFactory
:
DrawableFactory
{
override
fun
supportsImageType
(
image
:
CloseableImage
):
Boolean
{
// We can only handle CloseableColorImages.
return
image
is
CloseableColorImage
}
@Nullable
override
fun
createDrawable
(
image
:
CloseableImage
):
Drawable
?
{
// Just return a simple ColorDrawable with the given color value.
return
ColorDrawable
((
image
as
CloseableColorImage
).
color
)
}
}
}
\ No newline at end of file
app/src/main/java/chat/rocket/android/app/utils/CustomImageFormatConfigurator.kt
deleted
100644 → 0
View file @
09302e5f
package
chat.rocket.android.app.utils
import
com.facebook.drawee.backends.pipeline.DraweeConfig
import
com.facebook.imagepipeline.decoder.ImageDecoderConfig
/**
* Utility class to add custom decoders and drawable factories.
*
* @see {https://github.com/facebook/fresco/blob/master/samples/showcase/src/main/java/com/facebook/fresco/samples/showcase/CustomImageFormatConfigurator.java}
*/
object
CustomImageFormatConfigurator
{
fun
createImageDecoderConfig
()
:
ImageDecoderConfig
{
return
ImageDecoderConfig
.
newBuilder
()
.
addDecodingCapability
(
SvgDecoder
.
svgFormat
,
SvgDecoder
.
SvgFormatChecker
(),
SvgDecoder
.
Decoder
())
.
build
()
}
fun
addCustomDrawableFactories
(
draweeConfigBuilder
:
DraweeConfig
.
Builder
)
{
// We always add the color drawable factory so that it can be used for image decoder overrides.
draweeConfigBuilder
.
addCustomDrawableFactory
(
ColorImage
.
createDrawableFactory
())
draweeConfigBuilder
.
addCustomDrawableFactory
(
SvgDecoder
.
SvgDrawableFactory
())
}
}
\ No newline at end of file
app/src/main/java/chat/rocket/android/app/utils/SvgDecoder.kt
deleted
100644 → 0
View file @
09302e5f
package
chat.rocket.android.app.utils
import
android.graphics.Rect
import
android.graphics.drawable.Drawable
import
android.graphics.drawable.PictureDrawable
import
android.support.annotation.Nullable
import
com.caverock.androidsvg.SVG
import
com.caverock.androidsvg.SVGParseException
import
com.facebook.imageformat.ImageFormat
import
com.facebook.imageformat.ImageFormatCheckerUtils
import
com.facebook.imagepipeline.common.ImageDecodeOptions
import
com.facebook.imagepipeline.decoder.ImageDecoder
import
com.facebook.imagepipeline.drawable.DrawableFactory
import
com.facebook.imagepipeline.image.CloseableImage
import
com.facebook.imagepipeline.image.EncodedImage
import
com.facebook.imagepipeline.image.QualityInfo
/**
* SVG example that defines all classes required to decode and render SVG images.
*
* @see {https://github.com/facebook/fresco/blob/master/samples/showcase/src/main/java/com/facebook/fresco/samples/showcase/imageformat/svg/SvgDecoderExample.java}
*/
object
SvgDecoder
{
val
svgFormat
=
ImageFormat
(
"SVG_FORMAT"
,
"svg"
)
// We do not include the closing ">" since there can be additional information.
private
val
headerTag
=
"<svg"
private
val
possibleHeaderTags
=
arrayOf
(
ImageFormatCheckerUtils
.
asciiBytes
(
"<?xml"
))
/**
* Custom SVG format checker that verifies that the header of the file corresponds to our [SvgDecoder.headerTag] or [SvgDecoder.possibleHeaderTags].
*/
class
SvgFormatChecker
:
ImageFormat
.
FormatChecker
{
private
val
header
=
ImageFormatCheckerUtils
.
asciiBytes
(
headerTag
)
override
fun
getHeaderSize
():
Int
{
return
header
.
size
}
@Nullable
override
fun
determineFormat
(
headerBytes
:
ByteArray
,
headerSize
:
Int
):
ImageFormat
?
{
if
(
headerSize
>
getHeaderSize
())
{
if
(
ImageFormatCheckerUtils
.
startsWithPattern
(
headerBytes
,
header
))
{
return
svgFormat
}
if
(
possibleHeaderTags
.
any
{
ImageFormatCheckerUtils
.
startsWithPattern
(
headerBytes
,
it
)
&&
ImageFormatCheckerUtils
.
indexOfPattern
(
headerBytes
,
headerBytes
.
size
,
header
,
header
.
size
)
>
-
1
})
{
return
svgFormat
}
}
return
null
}
}
/**
* Custom closeable SVG image that holds a single SVG.
*/
class
CloseableSvgImage
(
val
svg
:
SVG
)
:
CloseableImage
()
{
private
var
isClose
=
false
override
fun
close
()
{
isClose
=
true
}
override
fun
getSizeInBytes
():
Int
=
0
override
fun
isClosed
():
Boolean
=
isClose
override
fun
getWidth
():
Int
=
0
override
fun
getHeight
():
Int
=
0
}
/**
* Decodes a [SvgDecoder.svgFormat] image.
*/
class
Decoder
:
ImageDecoder
{
@Nullable
override
fun
decode
(
encodedImage
:
EncodedImage
,
length
:
Int
,
qualityInfo
:
QualityInfo
,
options
:
ImageDecodeOptions
):
CloseableImage
?
{
try
{
val
svg
=
SVG
.
getFromInputStream
(
encodedImage
.
inputStream
)
return
CloseableSvgImage
(
svg
)
}
catch
(
e
:
SVGParseException
)
{
// TODO: are we using the android.util.Log for logging that type of errors? or should we use the SDK logger?
e
.
printStackTrace
()
}
// Return nothing if an error occurred
return
null
}
}
/**
* SVG drawable factory that creates [PictureDrawable]s for SVG images.
*/
class
SvgDrawableFactory
:
DrawableFactory
{
override
fun
supportsImageType
(
image
:
CloseableImage
):
Boolean
{
return
image
is
CloseableSvgImage
}
@Nullable
override
fun
createDrawable
(
image
:
CloseableImage
):
Drawable
?
{
return
SvgPictureDrawable
((
image
as
CloseableSvgImage
).
svg
)
}
}
class
SvgPictureDrawable
(
private
val
svg
:
SVG
)
:
PictureDrawable
(
null
)
{
override
fun
onBoundsChange
(
bounds
:
Rect
)
{
super
.
onBoundsChange
(
bounds
)
picture
=
svg
.
renderToPicture
(
bounds
.
width
(),
bounds
.
height
())
}
}
}
\ No newline at end of file
app/src/main/java/chat/rocket/android/authentication/signup/ui/SignupFragment.kt
View file @
f882e57c
...
@@ -19,12 +19,15 @@ import javax.inject.Inject
...
@@ -19,12 +19,15 @@ import javax.inject.Inject
class
SignupFragment
:
Fragment
(),
SignupView
{
class
SignupFragment
:
Fragment
(),
SignupView
{
@Inject
lateinit
var
presenter
:
SignupPresenter
@Inject
lateinit
var
presenter
:
SignupPresenter
private
val
layoutListener
=
ViewTreeObserver
.
OnGlobalLayoutListener
{
private
val
layoutListener
=
ViewTreeObserver
.
OnGlobalLayoutListener
{
if
(
KeyboardHelper
.
isSoftKeyboardShown
(
constraint
_layout
.
rootView
))
{
if
(
KeyboardHelper
.
isSoftKeyboardShown
(
relative
_layout
.
rootView
))
{
text_new_user_agreement
.
setVisible
(
false
)
bottom_container
.
setVisible
(
false
)
}
else
{
}
else
{
text_new_user_agreement
.
setVisible
(
true
)
bottom_container
.
apply
{
postDelayed
({
setVisible
(
true
)
},
3
)
}
}
}
}
}
...
@@ -42,24 +45,22 @@ class SignupFragment : Fragment(), SignupView {
...
@@ -42,24 +45,22 @@ class SignupFragment : Fragment(), SignupView {
override
fun
onViewCreated
(
view
:
View
,
savedInstanceState
:
Bundle
?)
{
override
fun
onViewCreated
(
view
:
View
,
savedInstanceState
:
Bundle
?)
{
super
.
onViewCreated
(
view
,
savedInstanceState
)
super
.
onViewCreated
(
view
,
savedInstanceState
)
activity
?.
window
?.
setSoftInputMode
(
WindowManager
.
LayoutParams
.
SOFT_INPUT_STATE_VISIBLE
)
if
(
Build
.
VERSION
.
SDK_INT
<=
Build
.
VERSION_CODES
.
M
)
{
if
(
Build
.
VERSION
.
SDK_INT
<=
Build
.
VERSION_CODES
.
M
)
{
tintEditTextDrawableStart
()
tintEditTextDrawableStart
()
}
}
constraint
_layout
.
viewTreeObserver
.
addOnGlobalLayoutListener
(
layoutListener
)
relative
_layout
.
viewTreeObserver
.
addOnGlobalLayoutListener
(
layoutListener
)
setUpNewUserAgreementListener
()
setUpNewUserAgreementListener
()
button_sign_up
.
setOnClickListener
{
button_sign_up
.
setOnClickListener
{
presenter
.
signup
(
text_name
.
textContent
,
text_username
.
textContent
,
text_password
.
textContent
,
text_email
.
textContent
)
presenter
.
signup
(
text_
user
name
.
textContent
,
text_username
.
textContent
,
text_password
.
textContent
,
text_email
.
textContent
)
}
}
}
}
override
fun
onDestroyView
()
{
override
fun
onDestroyView
()
{
relative_layout
.
viewTreeObserver
.
removeOnGlobalLayoutListener
(
layoutListener
)
super
.
onDestroyView
()
super
.
onDestroyView
()
constraint_layout
.
viewTreeObserver
.
removeOnGlobalLayoutListener
(
layoutListener
)
}
}
override
fun
alertBlankName
()
{
override
fun
alertBlankName
()
{
...
@@ -146,7 +147,7 @@ class SignupFragment : Fragment(), SignupView {
...
@@ -146,7 +147,7 @@ class SignupFragment : Fragment(), SignupView {
private
fun
enableUserInput
(
value
:
Boolean
)
{
private
fun
enableUserInput
(
value
:
Boolean
)
{
button_sign_up
.
isEnabled
=
value
button_sign_up
.
isEnabled
=
value
text_name
.
isEnabled
=
value
text_
user
name
.
isEnabled
=
value
text_username
.
isEnabled
=
value
text_username
.
isEnabled
=
value
text_password
.
isEnabled
=
value
text_password
.
isEnabled
=
value
text_email
.
isEnabled
=
value
text_email
.
isEnabled
=
value
...
...
app/src/main/java/chat/rocket/android/chatroom/adapter/AutoCompleteType.kt
0 → 100644
View file @
f882e57c
package
chat.rocket.android.chatroom.adapter
import
android.support.annotation.IntDef
const
val
PEOPLE
=
0L
const
val
ROOMS
=
1L
@Retention
(
AnnotationRetention
.
SOURCE
)
@IntDef
(
value
=
[
PEOPLE
,
ROOMS
])
annotation
class
AutoCompleteType
app/src/main/java/chat/rocket/android/chatroom/adapter/ChatRoomAdapter.kt
View file @
f882e57c
...
@@ -120,7 +120,6 @@ class ChatRoomAdapter(
...
@@ -120,7 +120,6 @@ class ChatRoomAdapter(
val
indexOfFirst
=
dataSet
.
indexOfFirst
{
it
.
messageId
==
message
.
messageId
}
val
indexOfFirst
=
dataSet
.
indexOfFirst
{
it
.
messageId
==
message
.
messageId
}
Timber
.
d
(
"index: $index"
)
Timber
.
d
(
"index: $index"
)
if
(
index
>
-
1
)
{
if
(
index
>
-
1
)
{
message
.
nextDownStreamMessage
=
dataSet
[
index
].
nextDownStreamMessage
dataSet
[
index
]
=
message
dataSet
[
index
]
=
message
notifyItemChanged
(
index
)
notifyItemChanged
(
index
)
while
(
dataSet
[
index
].
nextDownStreamMessage
!=
null
)
{
while
(
dataSet
[
index
].
nextDownStreamMessage
!=
null
)
{
...
...
app/src/main/java/chat/rocket/android/chatroom/adapter/CommandSuggestionsAdapter.kt
0 → 100644
View file @
f882e57c
package
chat.rocket.android.chatroom.adapter
import
android.view.LayoutInflater
import
android.view.View
import
android.view.ViewGroup
import
android.widget.TextView
import
chat.rocket.android.R
import
chat.rocket.android.chatroom.adapter.CommandSuggestionsAdapter.CommandSuggestionsViewHolder
import
chat.rocket.android.chatroom.viewmodel.suggestion.CommandSuggestionViewModel
import
chat.rocket.android.widget.autocompletion.model.SuggestionModel
import
chat.rocket.android.widget.autocompletion.ui.BaseSuggestionViewHolder
import
chat.rocket.android.widget.autocompletion.ui.SuggestionsAdapter
class
CommandSuggestionsAdapter
:
SuggestionsAdapter
<
CommandSuggestionsViewHolder
>(
token
=
"/"
,
constraint
=
CONSTRAINT_BOUND_TO_START
,
threshold
=
UNLIMITED_RESULT_COUNT
)
{
override
fun
onCreateViewHolder
(
parent
:
ViewGroup
,
viewType
:
Int
):
CommandSuggestionsViewHolder
{
val
view
=
LayoutInflater
.
from
(
parent
.
context
).
inflate
(
R
.
layout
.
suggestion_command_item
,
parent
,
false
)
return
CommandSuggestionsViewHolder
(
view
)
}
class
CommandSuggestionsViewHolder
(
view
:
View
)
:
BaseSuggestionViewHolder
(
view
)
{
override
fun
bind
(
item
:
SuggestionModel
,
itemClickListener
:
SuggestionsAdapter
.
ItemClickListener
?)
{
item
as
CommandSuggestionViewModel
with
(
itemView
)
{
val
nameTextView
=
itemView
.
findViewById
<
TextView
>(
R
.
id
.
text_command_name
)
val
descriptionTextView
=
itemView
.
findViewById
<
TextView
>(
R
.
id
.
text_command_description
)
nameTextView
.
text
=
"/${item.text}"
val
res
=
context
.
resources
val
id
=
res
.
getIdentifier
(
item
.
description
,
"string"
,
context
.
packageName
)
val
description
=
if
(
id
>
0
)
res
.
getString
(
id
)
else
""
descriptionTextView
.
text
=
description
.
toLowerCase
()
setOnClickListener
{
itemClickListener
?.
onClick
(
item
)
}
}
}
}
}
\ No newline at end of file
app/src/main/java/chat/rocket/android/chatroom/adapter/ImageAttachmentViewHolder.kt
View file @
f882e57c
...
@@ -2,6 +2,8 @@ package chat.rocket.android.chatroom.adapter
...
@@ -2,6 +2,8 @@ package chat.rocket.android.chatroom.adapter
import
android.view.View
import
android.view.View
import
chat.rocket.android.chatroom.viewmodel.ImageAttachmentViewModel
import
chat.rocket.android.chatroom.viewmodel.ImageAttachmentViewModel
import
com.facebook.drawee.backends.pipeline.Fresco
import
com.facebook.drawee.interfaces.DraweeController
import
chat.rocket.android.widget.emoji.EmojiReactionListener
import
chat.rocket.android.widget.emoji.EmojiReactionListener
import
com.stfalcon.frescoimageviewer.ImageViewer
import
com.stfalcon.frescoimageviewer.ImageViewer
import
kotlinx.android.synthetic.main.message_attachment.view.*
import
kotlinx.android.synthetic.main.message_attachment.view.*
...
@@ -20,12 +22,21 @@ class ImageAttachmentViewHolder(itemView: View,
...
@@ -20,12 +22,21 @@ class ImageAttachmentViewHolder(itemView: View,
override
fun
bindViews
(
data
:
ImageAttachmentViewModel
)
{
override
fun
bindViews
(
data
:
ImageAttachmentViewModel
)
{
with
(
itemView
)
{
with
(
itemView
)
{
image_attachment
.
setImageURI
(
data
.
attachmentUrl
)
val
controller
=
Fresco
.
newDraweeControllerBuilder
().
apply
{
setUri
(
data
.
attachmentUrl
)
autoPlayAnimations
=
true
oldController
=
image_attachment
.
controller
}.
build
()
image_attachment
.
controller
=
controller
file_name
.
text
=
data
.
attachmentTitle
file_name
.
text
=
data
.
attachmentTitle
image_attachment
.
setOnClickListener
{
view
->
image_attachment
.
setOnClickListener
{
view
->
// TODO - implement a proper image viewer with a proper Transition
// TODO - implement a proper image viewer with a proper Transition
val
builder
=
ImageViewer
.
createPipelineDraweeControllerBuilder
()
.
setAutoPlayAnimations
(
true
)
ImageViewer
.
Builder
(
view
.
context
,
listOf
(
data
.
attachmentUrl
))
ImageViewer
.
Builder
(
view
.
context
,
listOf
(
data
.
attachmentUrl
))
.
setStartPosition
(
0
)
.
setStartPosition
(
0
)
.
hideStatusBar
(
false
)
.
setCustomDraweeControllerBuilder
(
builder
)
.
show
()
.
show
()
}
}
}
}
...
...
app/src/main/java/chat/rocket/android/chatroom/adapter/PeopleSuggestionsAdapter.kt
0 → 100644
View file @
f882e57c
package
chat.rocket.android.chatroom.adapter
import
DrawableHelper
import
android.view.LayoutInflater
import
android.view.View
import
android.view.ViewGroup
import
android.widget.ImageView
import
android.widget.TextView
import
chat.rocket.android.R
import
chat.rocket.android.chatroom.adapter.PeopleSuggestionsAdapter.PeopleSuggestionViewHolder
import
chat.rocket.android.chatroom.viewmodel.suggestion.PeopleSuggestionViewModel
import
chat.rocket.android.util.extensions.setVisible
import
chat.rocket.android.widget.autocompletion.model.SuggestionModel
import
chat.rocket.android.widget.autocompletion.ui.BaseSuggestionViewHolder
import
chat.rocket.android.widget.autocompletion.ui.SuggestionsAdapter
import
chat.rocket.common.model.UserStatus
import
com.facebook.drawee.view.SimpleDraweeView
class
PeopleSuggestionsAdapter
:
SuggestionsAdapter
<
PeopleSuggestionViewHolder
>(
"@"
)
{
override
fun
onCreateViewHolder
(
parent
:
ViewGroup
,
viewType
:
Int
):
PeopleSuggestionViewHolder
{
val
view
=
LayoutInflater
.
from
(
parent
.
context
).
inflate
(
R
.
layout
.
suggestion_member_item
,
parent
,
false
)
return
PeopleSuggestionViewHolder
(
view
)
}
class
PeopleSuggestionViewHolder
(
view
:
View
)
:
BaseSuggestionViewHolder
(
view
)
{
override
fun
bind
(
item
:
SuggestionModel
,
itemClickListener
:
SuggestionsAdapter
.
ItemClickListener
?)
{
item
as
PeopleSuggestionViewModel
with
(
itemView
)
{
val
username
=
itemView
.
findViewById
<
TextView
>(
R
.
id
.
text_username
)
val
name
=
itemView
.
findViewById
<
TextView
>(
R
.
id
.
text_name
)
val
avatar
=
itemView
.
findViewById
<
SimpleDraweeView
>(
R
.
id
.
image_avatar
)
val
statusView
=
itemView
.
findViewById
<
ImageView
>(
R
.
id
.
image_status
)
username
.
text
=
item
.
username
name
.
text
=
item
.
name
if
(
item
.
imageUri
.
isEmpty
())
{
avatar
.
setVisible
(
false
)
}
else
{
avatar
.
setVisible
(
true
)
avatar
.
setImageURI
(
item
.
imageUri
)
}
val
status
=
item
.
status
?:
UserStatus
.
Offline
()
val
statusDrawable
=
DrawableHelper
.
getUserStatusDrawable
(
status
,
itemView
.
context
)
statusView
.
setImageDrawable
(
statusDrawable
)
setOnClickListener
{
itemClickListener
?.
onClick
(
item
)
}
}
}
}
}
\ No newline at end of file
app/src/main/java/chat/rocket/android/chatroom/adapter/RoomSuggestionsAdapter.kt
0 → 100644
View file @
f882e57c
package
chat.rocket.android.chatroom.adapter
import
android.view.LayoutInflater
import
android.view.View
import
android.view.ViewGroup
import
android.widget.TextView
import
chat.rocket.android.R
import
chat.rocket.android.chatroom.adapter.RoomSuggestionsAdapter.RoomSuggestionsViewHolder
import
chat.rocket.android.chatroom.viewmodel.suggestion.ChatRoomSuggestionViewModel
import
chat.rocket.android.widget.autocompletion.model.SuggestionModel
import
chat.rocket.android.widget.autocompletion.ui.BaseSuggestionViewHolder
import
chat.rocket.android.widget.autocompletion.ui.SuggestionsAdapter
class
RoomSuggestionsAdapter
:
SuggestionsAdapter
<
RoomSuggestionsViewHolder
>(
"#"
)
{
override
fun
onCreateViewHolder
(
parent
:
ViewGroup
,
viewType
:
Int
):
RoomSuggestionsViewHolder
{
val
view
=
LayoutInflater
.
from
(
parent
.
context
).
inflate
(
R
.
layout
.
suggestion_room_item
,
parent
,
false
)
return
RoomSuggestionsViewHolder
(
view
)
}
class
RoomSuggestionsViewHolder
(
view
:
View
)
:
BaseSuggestionViewHolder
(
view
)
{
override
fun
bind
(
item
:
SuggestionModel
,
itemClickListener
:
SuggestionsAdapter
.
ItemClickListener
?)
{
item
as
ChatRoomSuggestionViewModel
with
(
itemView
)
{
val
fullname
=
itemView
.
findViewById
<
TextView
>(
R
.
id
.
text_fullname
)
val
name
=
itemView
.
findViewById
<
TextView
>(
R
.
id
.
text_name
)
name
.
text
=
item
.
name
fullname
.
text
=
item
.
fullName
setOnClickListener
{
itemClickListener
?.
onClick
(
item
)
}
}
}
}
}
\ No newline at end of file
app/src/main/java/chat/rocket/android/chatroom/presentation/ChatRoomPresenter.kt
View file @
f882e57c
This diff is collapsed.
Click to expand it.
app/src/main/java/chat/rocket/android/chatroom/presentation/ChatRoomView.kt
View file @
f882e57c
...
@@ -2,6 +2,9 @@ package chat.rocket.android.chatroom.presentation
...
@@ -2,6 +2,9 @@ package chat.rocket.android.chatroom.presentation
import
android.net.Uri
import
android.net.Uri
import
chat.rocket.android.chatroom.viewmodel.BaseViewModel
import
chat.rocket.android.chatroom.viewmodel.BaseViewModel
import
chat.rocket.android.chatroom.viewmodel.suggestion.ChatRoomSuggestionViewModel
import
chat.rocket.android.chatroom.viewmodel.suggestion.CommandSuggestionViewModel
import
chat.rocket.android.chatroom.viewmodel.suggestion.PeopleSuggestionViewModel
import
chat.rocket.android.core.behaviours.LoadingView
import
chat.rocket.android.core.behaviours.LoadingView
import
chat.rocket.android.core.behaviours.MessageView
import
chat.rocket.android.core.behaviours.MessageView
import
chat.rocket.core.internal.realtime.State
import
chat.rocket.core.internal.realtime.State
...
@@ -100,5 +103,19 @@ interface ChatRoomView : LoadingView, MessageView {
...
@@ -100,5 +103,19 @@ interface ChatRoomView : LoadingView, MessageView {
fun
showInvalidFileSize
(
fileSize
:
Int
,
maxFileSize
:
Int
)
fun
showInvalidFileSize
(
fileSize
:
Int
,
maxFileSize
:
Int
)
fun
showConnectionState
(
state
:
State
)
fun
showConnectionState
(
state
:
State
)
fun
populatePeopleSuggestions
(
members
:
List
<
PeopleSuggestionViewModel
>)
fun
populateRoomSuggestions
(
chatRooms
:
List
<
ChatRoomSuggestionViewModel
>)
/**
* This user has joined the chat callback.
*/
fun
onJoined
()
fun
showReactionsPopup
(
messageId
:
String
)
fun
showReactionsPopup
(
messageId
:
String
)
/**
* Show list of commands.
*
* @param commands The list of available commands.
*/
fun
populateCommandSuggestions
(
commands
:
List
<
CommandSuggestionViewModel
>)
}
}
\ No newline at end of file
app/src/main/java/chat/rocket/android/chatroom/ui/ChatRoomActivity.kt
View file @
f882e57c
...
@@ -23,13 +23,19 @@ import javax.inject.Inject
...
@@ -23,13 +23,19 @@ import javax.inject.Inject
import
timber.log.Timber
import
timber.log.Timber
fun
Context
.
chatRoomIntent
(
chatRoomId
:
String
,
chatRoomName
:
String
,
chatRoomType
:
String
,
isChatRoomReadOnly
:
Boolean
,
chatRoomLastSeen
:
Long
):
Intent
{
fun
Context
.
chatRoomIntent
(
chatRoomId
:
String
,
chatRoomName
:
String
,
chatRoomType
:
String
,
isChatRoomReadOnly
:
Boolean
,
chatRoomLastSeen
:
Long
,
isChatRoomSubscribed
:
Boolean
=
true
):
Intent
{
return
Intent
(
this
,
ChatRoomActivity
::
class
.
java
).
apply
{
return
Intent
(
this
,
ChatRoomActivity
::
class
.
java
).
apply
{
putExtra
(
INTENT_CHAT_ROOM_ID
,
chatRoomId
)
putExtra
(
INTENT_CHAT_ROOM_ID
,
chatRoomId
)
putExtra
(
INTENT_CHAT_ROOM_NAME
,
chatRoomName
)
putExtra
(
INTENT_CHAT_ROOM_NAME
,
chatRoomName
)
putExtra
(
INTENT_CHAT_ROOM_TYPE
,
chatRoomType
)
putExtra
(
INTENT_CHAT_ROOM_TYPE
,
chatRoomType
)
putExtra
(
INTENT_IS_CHAT_ROOM_READ_ONLY
,
isChatRoomReadOnly
)
putExtra
(
INTENT_IS_CHAT_ROOM_READ_ONLY
,
isChatRoomReadOnly
)
putExtra
(
INTENT_CHAT_ROOM_LAST_SEEN
,
chatRoomLastSeen
)
putExtra
(
INTENT_CHAT_ROOM_LAST_SEEN
,
chatRoomLastSeen
)
putExtra
(
INTENT_CHAT_IS_SUBSCRIBED
,
isChatRoomSubscribed
)
}
}
}
}
...
@@ -38,6 +44,7 @@ private const val INTENT_CHAT_ROOM_NAME = "chat_room_name"
...
@@ -38,6 +44,7 @@ private const val INTENT_CHAT_ROOM_NAME = "chat_room_name"
private
const
val
INTENT_CHAT_ROOM_TYPE
=
"chat_room_type"
private
const
val
INTENT_CHAT_ROOM_TYPE
=
"chat_room_type"
private
const
val
INTENT_IS_CHAT_ROOM_READ_ONLY
=
"is_chat_room_read_only"
private
const
val
INTENT_IS_CHAT_ROOM_READ_ONLY
=
"is_chat_room_read_only"
private
const
val
INTENT_CHAT_ROOM_LAST_SEEN
=
"chat_room_last_seen"
private
const
val
INTENT_CHAT_ROOM_LAST_SEEN
=
"chat_room_last_seen"
private
const
val
INTENT_CHAT_IS_SUBSCRIBED
=
"is_chat_room_subscribed"
class
ChatRoomActivity
:
AppCompatActivity
(),
HasSupportFragmentInjector
{
class
ChatRoomActivity
:
AppCompatActivity
(),
HasSupportFragmentInjector
{
@Inject
lateinit
var
fragmentDispatchingAndroidInjector
:
DispatchingAndroidInjector
<
Fragment
>
@Inject
lateinit
var
fragmentDispatchingAndroidInjector
:
DispatchingAndroidInjector
<
Fragment
>
...
@@ -50,6 +57,7 @@ class ChatRoomActivity : AppCompatActivity(), HasSupportFragmentInjector {
...
@@ -50,6 +57,7 @@ class ChatRoomActivity : AppCompatActivity(), HasSupportFragmentInjector {
private
lateinit
var
chatRoomName
:
String
private
lateinit
var
chatRoomName
:
String
private
lateinit
var
chatRoomType
:
String
private
lateinit
var
chatRoomType
:
String
private
var
isChatRoomReadOnly
:
Boolean
=
false
private
var
isChatRoomReadOnly
:
Boolean
=
false
private
var
isChatRoomSubscribed
:
Boolean
=
true
private
var
chatRoomLastSeen
:
Long
=
-
1L
private
var
chatRoomLastSeen
:
Long
=
-
1L
override
fun
onCreate
(
savedInstanceState
:
Bundle
?)
{
override
fun
onCreate
(
savedInstanceState
:
Bundle
?)
{
...
@@ -76,8 +84,11 @@ class ChatRoomActivity : AppCompatActivity(), HasSupportFragmentInjector {
...
@@ -76,8 +84,11 @@ class ChatRoomActivity : AppCompatActivity(), HasSupportFragmentInjector {
chatRoomLastSeen
=
intent
.
getLongExtra
(
INTENT_CHAT_ROOM_LAST_SEEN
,
-
1
)
chatRoomLastSeen
=
intent
.
getLongExtra
(
INTENT_CHAT_ROOM_LAST_SEEN
,
-
1
)
isChatRoomSubscribed
=
intent
.
getBooleanExtra
(
INTENT_CHAT_IS_SUBSCRIBED
,
true
)
addFragment
(
"ChatRoomFragment"
,
R
.
id
.
fragment_container
)
{
addFragment
(
"ChatRoomFragment"
,
R
.
id
.
fragment_container
)
{
newInstance
(
chatRoomId
,
chatRoomName
,
chatRoomType
,
isChatRoomReadOnly
,
chatRoomLastSeen
)
newInstance
(
chatRoomId
,
chatRoomName
,
chatRoomType
,
isChatRoomReadOnly
,
chatRoomLastSeen
,
isChatRoomSubscribed
)
}
}
}
}
...
...
app/src/main/java/chat/rocket/android/chatroom/ui/ChatRoomFragment.kt
View file @
f882e57c
...
@@ -15,11 +15,14 @@ import android.support.v7.widget.LinearLayoutManager
...
@@ -15,11 +15,14 @@ import android.support.v7.widget.LinearLayoutManager
import
android.support.v7.widget.RecyclerView
import
android.support.v7.widget.RecyclerView
import
android.view.*
import
android.view.*
import
chat.rocket.android.R
import
chat.rocket.android.R
import
chat.rocket.android.chatroom.adapter.
ChatRoomAdapter
import
chat.rocket.android.chatroom.adapter.
*
import
chat.rocket.android.chatroom.presentation.ChatRoomPresenter
import
chat.rocket.android.chatroom.presentation.ChatRoomPresenter
import
chat.rocket.android.chatroom.presentation.ChatRoomView
import
chat.rocket.android.chatroom.presentation.ChatRoomView
import
chat.rocket.android.chatroom.viewmodel.BaseViewModel
import
chat.rocket.android.chatroom.viewmodel.BaseViewModel
import
chat.rocket.android.chatroom.viewmodel.MessageViewModel
import
chat.rocket.android.chatroom.viewmodel.MessageViewModel
import
chat.rocket.android.chatroom.viewmodel.suggestion.ChatRoomSuggestionViewModel
import
chat.rocket.android.chatroom.viewmodel.suggestion.CommandSuggestionViewModel
import
chat.rocket.android.chatroom.viewmodel.suggestion.PeopleSuggestionViewModel
import
chat.rocket.android.helper.EndlessRecyclerViewScrollListener
import
chat.rocket.android.helper.EndlessRecyclerViewScrollListener
import
chat.rocket.android.helper.KeyboardHelper
import
chat.rocket.android.helper.KeyboardHelper
import
chat.rocket.android.helper.MessageParser
import
chat.rocket.android.helper.MessageParser
...
@@ -37,7 +40,12 @@ import kotlinx.android.synthetic.main.message_list.*
...
@@ -37,7 +40,12 @@ import kotlinx.android.synthetic.main.message_list.*
import
timber.log.Timber
import
timber.log.Timber
import
javax.inject.Inject
import
javax.inject.Inject
fun
newInstance
(
chatRoomId
:
String
,
chatRoomName
:
String
,
chatRoomType
:
String
,
isChatRoomReadOnly
:
Boolean
,
chatRoomLastSeen
:
Long
):
Fragment
{
fun
newInstance
(
chatRoomId
:
String
,
chatRoomName
:
String
,
chatRoomType
:
String
,
isChatRoomReadOnly
:
Boolean
,
chatRoomLastSeen
:
Long
,
isSubscribed
:
Boolean
=
true
):
Fragment
{
return
ChatRoomFragment
().
apply
{
return
ChatRoomFragment
().
apply
{
arguments
=
Bundle
(
1
).
apply
{
arguments
=
Bundle
(
1
).
apply
{
putString
(
BUNDLE_CHAT_ROOM_ID
,
chatRoomId
)
putString
(
BUNDLE_CHAT_ROOM_ID
,
chatRoomId
)
...
@@ -45,6 +53,7 @@ fun newInstance(chatRoomId: String, chatRoomName: String, chatRoomType: String,
...
@@ -45,6 +53,7 @@ fun newInstance(chatRoomId: String, chatRoomName: String, chatRoomType: String,
putString
(
BUNDLE_CHAT_ROOM_TYPE
,
chatRoomType
)
putString
(
BUNDLE_CHAT_ROOM_TYPE
,
chatRoomType
)
putBoolean
(
BUNDLE_IS_CHAT_ROOM_READ_ONLY
,
isChatRoomReadOnly
)
putBoolean
(
BUNDLE_IS_CHAT_ROOM_READ_ONLY
,
isChatRoomReadOnly
)
putLong
(
BUNDLE_CHAT_ROOM_LAST_SEEN
,
chatRoomLastSeen
)
putLong
(
BUNDLE_CHAT_ROOM_LAST_SEEN
,
chatRoomLastSeen
)
putBoolean
(
BUNDLE_CHAT_ROOM_IS_SUBSCRIBED
,
isSubscribed
)
}
}
}
}
}
}
...
@@ -55,17 +64,18 @@ private const val BUNDLE_CHAT_ROOM_TYPE = "chat_room_type"
...
@@ -55,17 +64,18 @@ private const val BUNDLE_CHAT_ROOM_TYPE = "chat_room_type"
private
const
val
BUNDLE_IS_CHAT_ROOM_READ_ONLY
=
"is_chat_room_read_only"
private
const
val
BUNDLE_IS_CHAT_ROOM_READ_ONLY
=
"is_chat_room_read_only"
private
const
val
REQUEST_CODE_FOR_PERFORM_SAF
=
42
private
const
val
REQUEST_CODE_FOR_PERFORM_SAF
=
42
private
const
val
BUNDLE_CHAT_ROOM_LAST_SEEN
=
"chat_room_last_seen"
private
const
val
BUNDLE_CHAT_ROOM_LAST_SEEN
=
"chat_room_last_seen"
private
const
val
BUNDLE_CHAT_ROOM_IS_SUBSCRIBED
=
"chat_room_is_subscribed"
class
ChatRoomFragment
:
Fragment
(),
ChatRoomView
,
EmojiKeyboardListener
,
EmojiReactionListener
{
class
ChatRoomFragment
:
Fragment
(),
ChatRoomView
,
EmojiKeyboardListener
,
EmojiReactionListener
{
@Inject
lateinit
var
presenter
:
ChatRoomPresenter
@Inject
lateinit
var
presenter
:
ChatRoomPresenter
@Inject
lateinit
var
parser
:
MessageParser
@Inject
lateinit
var
parser
:
MessageParser
private
lateinit
var
adapter
:
ChatRoomAdapter
private
lateinit
var
adapter
:
ChatRoomAdapter
private
lateinit
var
chatRoomId
:
String
private
lateinit
var
chatRoomId
:
String
private
lateinit
var
chatRoomName
:
String
private
lateinit
var
chatRoomName
:
String
private
lateinit
var
chatRoomType
:
String
private
lateinit
var
chatRoomType
:
String
private
lateinit
var
emojiKeyboardPopup
:
EmojiKeyboardPopup
private
var
isSubscribed
:
Boolean
=
true
private
var
isChatRoomReadOnly
:
Boolean
=
false
private
var
isChatRoomReadOnly
:
Boolean
=
false
private
lateinit
var
emojiKeyboardPopup
:
EmojiKeyboardPopup
private
var
chatRoomLastSeen
:
Long
=
-
1
private
var
chatRoomLastSeen
:
Long
=
-
1
private
lateinit
var
actionSnackbar
:
ActionSnackbar
private
lateinit
var
actionSnackbar
:
ActionSnackbar
private
var
citation
:
String
?
=
null
private
var
citation
:
String
?
=
null
...
@@ -91,6 +101,7 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
...
@@ -91,6 +101,7 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
chatRoomName
=
bundle
.
getString
(
BUNDLE_CHAT_ROOM_NAME
)
chatRoomName
=
bundle
.
getString
(
BUNDLE_CHAT_ROOM_NAME
)
chatRoomType
=
bundle
.
getString
(
BUNDLE_CHAT_ROOM_TYPE
)
chatRoomType
=
bundle
.
getString
(
BUNDLE_CHAT_ROOM_TYPE
)
isChatRoomReadOnly
=
bundle
.
getBoolean
(
BUNDLE_IS_CHAT_ROOM_READ_ONLY
)
isChatRoomReadOnly
=
bundle
.
getBoolean
(
BUNDLE_IS_CHAT_ROOM_READ_ONLY
)
isSubscribed
=
bundle
.
getBoolean
(
BUNDLE_CHAT_ROOM_IS_SUBSCRIBED
)
chatRoomLastSeen
=
bundle
.
getLong
(
BUNDLE_CHAT_ROOM_LAST_SEEN
)
chatRoomLastSeen
=
bundle
.
getLong
(
BUNDLE_CHAT_ROOM_LAST_SEEN
)
}
else
{
}
else
{
requireNotNull
(
bundle
)
{
"no arguments supplied when the fragment was instantiated"
}
requireNotNull
(
bundle
)
{
"no arguments supplied when the fragment was instantiated"
}
...
@@ -105,10 +116,11 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
...
@@ -105,10 +116,11 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
setupToolbar
(
chatRoomName
)
setupToolbar
(
chatRoomName
)
presenter
.
loadMessages
(
chatRoomId
,
chatRoomType
)
presenter
.
loadMessages
(
chatRoomId
,
chatRoomType
)
presenter
.
loadChatRooms
()
setupRecyclerView
()
setupRecyclerView
()
setupFab
()
setupFab
()
setupMessageComposer
()
setupMessageComposer
()
setupSuggestionsView
()
setupActionSnackbar
()
setupActionSnackbar
()
}
}
...
@@ -174,11 +186,12 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
...
@@ -174,11 +186,12 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
}
}
// track the message sent immediately after the current message
// track the message sent immediately after the current message
var
prevMessageViewModel
:
MessageViewModel
?
=
null
var
prevMessageViewModel
:
MessageViewModel
?
=
null
//Loop over received messages to determine first unread
//
Loop over received messages to determine first unread
for
(
i
in
dataSet
.
indices
)
{
for
(
i
in
dataSet
.
indices
)
{
val
msgModel
=
dataSet
[
i
]
val
msgModel
=
dataSet
[
i
]
if
(
msgModel
is
MessageViewModel
)
{
if
(
msgModel
is
MessageViewModel
)
{
val
msg
=
msgModel
.
rawData
val
msg
=
msgModel
.
rawData
if
(
msg
.
timestamp
<
chatRoomLastSeen
)
{
if
(
msg
.
timestamp
<
chatRoomLastSeen
)
{
...
@@ -217,12 +230,17 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
...
@@ -217,12 +230,17 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
if
(
oldMessagesCount
==
0
&&
dataSet
.
isNotEmpty
())
{
if
(
oldMessagesCount
==
0
&&
dataSet
.
isNotEmpty
())
{
recycler_view
.
scrollToPosition
(
0
)
recycler_view
.
scrollToPosition
(
0
)
}
}
presenter
.
loadActiveMembers
(
chatRoomId
,
chatRoomType
,
filterSelfOut
=
true
)
}
}
}
}
override
fun
sendMessage
(
text
:
String
)
{
override
fun
sendMessage
(
text
:
String
)
{
if
(!
text
.
isBlank
())
{
if
(!
text
.
isBlank
())
{
presenter
.
sendMessage
(
chatRoomId
,
text
,
editingMessageId
)
if
(!
text
.
startsWith
(
"/"
))
{
presenter
.
sendMessage
(
chatRoomId
,
text
,
editingMessageId
)
}
else
{
presenter
.
runCommand
(
text
,
chatRoomId
)
}
}
}
}
}
...
@@ -291,6 +309,18 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
...
@@ -291,6 +309,18 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
override
fun
showGenericErrorMessage
()
=
showMessage
(
getString
(
R
.
string
.
msg_generic_error
))
override
fun
showGenericErrorMessage
()
=
showMessage
(
getString
(
R
.
string
.
msg_generic_error
))
override
fun
populatePeopleSuggestions
(
members
:
List
<
PeopleSuggestionViewModel
>)
{
suggestions_view
.
addItems
(
"@"
,
members
)
}
override
fun
populateRoomSuggestions
(
chatRooms
:
List
<
ChatRoomSuggestionViewModel
>)
{
suggestions_view
.
addItems
(
"#"
,
chatRooms
)
}
override
fun
populateCommandSuggestions
(
commands
:
List
<
CommandSuggestionViewModel
>)
{
suggestions_view
.
addItems
(
"/"
,
commands
)
}
override
fun
copyToClipboard
(
message
:
String
)
{
override
fun
copyToClipboard
(
message
:
String
)
{
activity
?.
apply
{
activity
?.
apply
{
val
clipboard
=
getSystemService
(
Context
.
CLIPBOARD_SERVICE
)
as
ClipboardManager
val
clipboard
=
getSystemService
(
Context
.
CLIPBOARD_SERVICE
)
as
ClipboardManager
...
@@ -380,6 +410,13 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
...
@@ -380,6 +410,13 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
}
}
}
}
override
fun
onJoined
()
{
input_container
.
setVisible
(
true
)
button_join_chat
.
setVisible
(
false
)
isSubscribed
=
true
setupMessageComposer
()
}
private
val
dismissStatus
=
{
private
val
dismissStatus
=
{
connection_status_text
.
fadeOut
()
connection_status_text
.
fadeOut
()
}
}
...
@@ -410,6 +447,10 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
...
@@ -410,6 +447,10 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
if
(
isChatRoomReadOnly
)
{
if
(
isChatRoomReadOnly
)
{
text_room_is_read_only
.
setVisible
(
true
)
text_room_is_read_only
.
setVisible
(
true
)
input_container
.
setVisible
(
false
)
input_container
.
setVisible
(
false
)
}
else
if
(!
isSubscribed
)
{
input_container
.
setVisible
(
false
)
button_join_chat
.
setVisible
(
true
)
button_join_chat
.
setOnClickListener
{
presenter
.
joinChat
(
chatRoomId
)
}
}
else
{
}
else
{
button_send
.
alpha
=
0f
button_send
.
alpha
=
0f
button_send
.
setVisible
(
false
)
button_send
.
setVisible
(
false
)
...
@@ -476,14 +517,37 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
...
@@ -476,14 +517,37 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
}
}
}
}
private
fun
setupSuggestionsView
()
{
suggestions_view
.
anchorTo
(
text_message
)
.
setMaximumHeight
(
resources
.
getDimensionPixelSize
(
R
.
dimen
.
suggestions_box_max_height
))
.
addTokenAdapter
(
PeopleSuggestionsAdapter
())
.
addTokenAdapter
(
CommandSuggestionsAdapter
())
.
addTokenAdapter
(
RoomSuggestionsAdapter
())
.
addSuggestionProviderAction
(
"@"
)
{
query
->
if
(
query
.
isNotEmpty
())
{
presenter
.
spotlight
(
query
,
PEOPLE
,
true
)
}
}
.
addSuggestionProviderAction
(
"#"
)
{
query
->
if
(
query
.
isNotEmpty
())
{
presenter
.
loadChatRooms
()
}
}
.
addSuggestionProviderAction
(
"/"
)
{
_
->
presenter
.
loadCommands
()
}
presenter
.
loadCommands
()
}
private
fun
openEmojiKeyboardPopup
()
{
private
fun
openEmojiKeyboardPopup
()
{
if
(!
emojiKeyboardPopup
.
isShowing
()
)
{
if
(!
emojiKeyboardPopup
.
isShowing
)
{
// If keyboard is visible, simply show the popup
// If keyboard is visible, simply show the popup
if
(
emojiKeyboardPopup
.
isKeyboardOpen
)
{
if
(
emojiKeyboardPopup
.
isKeyboardOpen
)
{
emojiKeyboardPopup
.
showAtBottom
()
emojiKeyboardPopup
.
showAtBottom
()
}
else
{
}
else
{
// Open the text keyboard first and immediately after that show the emoji popup
// Open the text keyboard first and immediately after that show the emoji popup
text_message
.
setFocusableInTouchMode
(
true
)
text_message
.
isFocusableInTouchMode
=
true
text_message
.
requestFocus
()
text_message
.
requestFocus
()
emojiKeyboardPopup
.
showAtBottomPending
()
emojiKeyboardPopup
.
showAtBottomPending
()
KeyboardHelper
.
showSoftKeyboard
(
text_message
)
KeyboardHelper
.
showSoftKeyboard
(
text_message
)
...
...
app/src/main/java/chat/rocket/android/chatroom/viewmodel/ViewModelMapper.kt
View file @
f882e57c
...
@@ -96,31 +96,53 @@ class ViewModelMapper @Inject constructor(private val context: Context,
...
@@ -96,31 +96,53 @@ class ViewModelMapper @Inject constructor(private val context: Context,
}
}
private
fun
mapFileAttachment
(
message
:
Message
,
attachment
:
FileAttachment
):
BaseViewModel
<
*
>?
{
private
fun
mapFileAttachment
(
message
:
Message
,
attachment
:
FileAttachment
):
BaseViewModel
<
*
>?
{
val
attachmentUrl
=
attachmentUrl
(
"$baseUrl${attachment.url}"
)
val
attachmentUrl
=
attachmentUrl
(
attachment
)
val
attachmentTitle
=
attachment
.
title
val
attachmentTitle
=
attachment
Title
(
attachment
)
val
id
=
"${message.id}_${attachment.titleLink}"
.
hashCode
().
toLong
(
)
val
id
=
attachmentId
(
message
,
attachment
)
return
when
(
attachment
)
{
return
when
(
attachment
)
{
is
ImageAttachment
->
ImageAttachmentViewModel
(
message
,
attachment
,
message
.
id
,
is
ImageAttachment
->
ImageAttachmentViewModel
(
message
,
attachment
,
message
.
id
,
attachmentUrl
,
attachmentTitle
?:
""
,
id
,
getReactions
(
message
))
attachmentUrl
,
attachmentTitle
,
id
,
getReactions
(
message
))
is
VideoAttachment
->
VideoAttachmentViewModel
(
message
,
attachment
,
message
.
id
,
is
VideoAttachment
->
VideoAttachmentViewModel
(
message
,
attachment
,
message
.
id
,
attachmentUrl
,
attachmentTitle
?:
""
,
id
,
getReactions
(
message
))
attachmentUrl
,
attachmentTitle
,
id
,
getReactions
(
message
))
is
AudioAttachment
->
AudioAttachmentViewModel
(
message
,
attachment
,
message
.
id
,
is
AudioAttachment
->
AudioAttachmentViewModel
(
message
,
attachment
,
message
.
id
,
attachmentUrl
,
attachmentTitle
?:
""
,
id
,
getReactions
(
message
))
attachmentUrl
,
attachmentTitle
,
id
,
getReactions
(
message
))
else
->
null
else
->
null
}
}
}
}
private
fun
attachmentUrl
(
url
:
String
):
String
{
private
fun
attachmentId
(
message
:
Message
,
attachment
:
FileAttachment
):
Long
{
var
response
=
url
return
"${message.id}_${attachment.url}"
.
hashCode
().
toLong
()
val
httpUrl
=
HttpUrl
.
parse
(
url
)
}
httpUrl
?.
let
{
response
=
it
.
newBuilder
().
apply
{
private
fun
attachmentTitle
(
attachment
:
FileAttachment
):
CharSequence
{
addQueryParameter
(
"rc_uid"
,
token
?.
userId
)
return
with
(
attachment
)
{
addQueryParameter
(
"rc_token"
,
token
?.
authToken
)
title
?.
let
{
return
@with
it
}
}.
build
().
toString
()
val
fileUrl
=
HttpUrl
.
parse
(
url
)
fileUrl
?.
let
{
return
@with
it
.
pathSegments
().
last
()
}
return
@with
""
}
}
}
private
fun
attachmentUrl
(
attachment
:
FileAttachment
):
String
{
return
with
(
attachment
)
{
if
(
url
.
startsWith
(
"http"
))
return
@with
url
val
fullUrl
=
"$baseUrl$url"
val
httpUrl
=
HttpUrl
.
parse
(
fullUrl
)
httpUrl
?.
let
{
return
@with
it
.
newBuilder
().
apply
{
addQueryParameter
(
"rc_uid"
,
token
?.
userId
)
addQueryParameter
(
"rc_token"
,
token
?.
authToken
)
}.
build
().
toString
()
}
return
response
// Fallback to baseUrl + url
return
@with
fullUrl
}
}
}
private
suspend
fun
mapMessage
(
message
:
Message
):
MessageViewModel
=
withContext
(
CommonPool
)
{
private
suspend
fun
mapMessage
(
message
:
Message
):
MessageViewModel
=
withContext
(
CommonPool
)
{
...
...
app/src/main/java/chat/rocket/android/chatroom/viewmodel/suggestion/ChatRoomSuggestionViewModel.kt
0 → 100644
View file @
f882e57c
package
chat.rocket.android.chatroom.viewmodel.suggestion
import
chat.rocket.android.widget.autocompletion.model.SuggestionModel
class
ChatRoomSuggestionViewModel
(
text
:
String
,
val
fullName
:
String
,
val
name
:
String
,
searchList
:
List
<
String
>)
:
SuggestionModel
(
text
,
searchList
,
false
)
{
}
\ No newline at end of file
app/src/main/java/chat/rocket/android/chatroom/viewmodel/suggestion/CommandSuggestionViewModel.kt
0 → 100644
View file @
f882e57c
package
chat.rocket.android.chatroom.viewmodel.suggestion
import
chat.rocket.android.widget.autocompletion.model.SuggestionModel
class
CommandSuggestionViewModel
(
text
:
String
,
val
description
:
String
,
searchList
:
List
<
String
>)
:
SuggestionModel
(
text
,
searchList
)
\ No newline at end of file
app/src/main/java/chat/rocket/android/chatroom/viewmodel/suggestion/PeopleSuggestionViewModel.kt
0 → 100644
View file @
f882e57c
package
chat.rocket.android.chatroom.viewmodel.suggestion
import
chat.rocket.android.widget.autocompletion.model.SuggestionModel
import
chat.rocket.common.model.UserStatus
class
PeopleSuggestionViewModel
(
val
imageUri
:
String
,
text
:
String
,
val
username
:
String
,
val
name
:
String
,
val
status
:
UserStatus
?,
pinned
:
Boolean
=
false
,
searchList
:
List
<
String
>)
:
SuggestionModel
(
text
,
searchList
,
pinned
)
{
override
fun
toString
():
String
{
return
"PeopleSuggestionViewModel(imageUri='$imageUri', username='$username', name='$name', status=$status, pinned=$pinned)"
}
}
\ No newline at end of file
app/src/main/java/chat/rocket/android/chatrooms/presentation/ChatRoomsPresenter.kt
View file @
f882e57c
...
@@ -9,12 +9,12 @@ import chat.rocket.android.server.infraestructure.chatRooms
...
@@ -9,12 +9,12 @@ import chat.rocket.android.server.infraestructure.chatRooms
import
chat.rocket.android.server.infraestructure.state
import
chat.rocket.android.server.infraestructure.state
import
chat.rocket.android.util.extensions.launchUI
import
chat.rocket.android.util.extensions.launchUI
import
chat.rocket.common.RocketChatException
import
chat.rocket.common.RocketChatException
import
chat.rocket.common.model.BaseRoom
import
chat.rocket.common.model.*
import
chat.rocket.common.model.RoomType
import
chat.rocket.core.internal.model.Subscription
import
chat.rocket.core.internal.model.Subscription
import
chat.rocket.core.internal.realtime.State
import
chat.rocket.core.internal.realtime.State
import
chat.rocket.core.internal.realtime.StreamMessage
import
chat.rocket.core.internal.realtime.StreamMessage
import
chat.rocket.core.internal.realtime.Type
import
chat.rocket.core.internal.realtime.Type
import
chat.rocket.core.internal.rest.spotlight
import
chat.rocket.core.model.ChatRoom
import
chat.rocket.core.model.ChatRoom
import
chat.rocket.core.model.Room
import
chat.rocket.core.model.Room
import
kotlinx.coroutines.experimental.*
import
kotlinx.coroutines.experimental.*
...
@@ -34,6 +34,7 @@ class ChatRoomsPresenter @Inject constructor(private val view: ChatRoomsView,
...
@@ -34,6 +34,7 @@ class ChatRoomsPresenter @Inject constructor(private val view: ChatRoomsView,
factory
:
ConnectionManagerFactory
)
{
factory
:
ConnectionManagerFactory
)
{
private
val
manager
:
ConnectionManager
=
factory
.
create
(
serverInteractor
.
get
()
!!
)
private
val
manager
:
ConnectionManager
=
factory
.
create
(
serverInteractor
.
get
()
!!
)
private
val
currentServer
=
serverInteractor
.
get
()
!!
private
val
currentServer
=
serverInteractor
.
get
()
!!
private
val
client
=
manager
.
client
private
var
reloadJob
:
Deferred
<
List
<
ChatRoom
>>?
=
null
private
var
reloadJob
:
Deferred
<
List
<
ChatRoom
>>?
=
null
private
val
settings
=
settingsRepository
.
get
(
currentServer
)
!!
private
val
settings
=
settingsRepository
.
get
(
currentServer
)
!!
...
@@ -69,7 +70,9 @@ class ChatRoomsPresenter @Inject constructor(private val view: ChatRoomsView,
...
@@ -69,7 +70,9 @@ class ChatRoomsPresenter @Inject constructor(private val view: ChatRoomsView,
}
}
navigator
.
toChatRoom
(
chatRoom
.
id
,
roomName
,
navigator
.
toChatRoom
(
chatRoom
.
id
,
roomName
,
chatRoom
.
type
.
toString
(),
chatRoom
.
readonly
?:
false
,
chatRoom
.
lastSeen
?:
-
1
)
chatRoom
.
type
.
toString
(),
chatRoom
.
readonly
?:
false
,
chatRoom
.
lastSeen
?:
-
1
,
chatRoom
.
open
)
}
}
/**
/**
...
@@ -79,8 +82,41 @@ class ChatRoomsPresenter @Inject constructor(private val view: ChatRoomsView,
...
@@ -79,8 +82,41 @@ class ChatRoomsPresenter @Inject constructor(private val view: ChatRoomsView,
fun
chatRoomsByName
(
name
:
String
)
{
fun
chatRoomsByName
(
name
:
String
)
{
val
currentServer
=
serverInteractor
.
get
()
!!
val
currentServer
=
serverInteractor
.
get
()
!!
launchUI
(
strategy
)
{
launchUI
(
strategy
)
{
val
roomList
=
getChatRoomsInteractor
.
getByName
(
currentServer
,
name
)
try
{
view
.
updateChatRooms
(
roomList
)
val
roomList
=
getChatRoomsInteractor
.
getByName
(
currentServer
,
name
)
if
(
roomList
.
isEmpty
())
{
val
(
users
,
rooms
)
=
client
.
spotlight
(
name
)
val
chatRoomsCombined
=
mutableListOf
<
ChatRoom
>()
chatRoomsCombined
.
addAll
(
usersToChatRooms
(
users
))
chatRoomsCombined
.
addAll
(
roomsToChatRooms
(
rooms
))
view
.
updateChatRooms
(
chatRoomsCombined
)
}
else
{
view
.
updateChatRooms
(
roomList
)
}
}
catch
(
ex
:
RocketChatException
)
{
Timber
.
e
(
ex
)
}
}
}
private
suspend
fun
usersToChatRooms
(
users
:
List
<
User
>):
List
<
ChatRoom
>
{
return
users
.
map
{
ChatRoom
(
it
.
id
,
RoomType
.
DIRECT_MESSAGE
,
SimpleUser
(
username
=
it
.
username
,
name
=
it
.
name
,
id
=
null
),
it
.
name
?:
""
,
it
.
name
,
false
,
null
,
null
,
null
,
null
,
null
,
false
,
false
,
false
,
0L
,
null
,
0L
,
null
,
client
)
}
}
private
suspend
fun
roomsToChatRooms
(
rooms
:
List
<
Room
>):
List
<
ChatRoom
>
{
return
rooms
.
map
{
ChatRoom
(
it
.
id
,
it
.
type
,
it
.
user
,
it
.
name
?:
""
,
it
.
fullName
,
it
.
readonly
,
it
.
updatedAt
,
null
,
null
,
it
.
topic
,
it
.
announcement
,
false
,
false
,
false
,
0L
,
null
,
0L
,
it
.
lastMessage
,
client
)
}
}
}
}
...
...
app/src/main/java/chat/rocket/android/chatrooms/ui/ChatRoomsFragment.kt
View file @
f882e57c
...
@@ -134,7 +134,9 @@ class ChatRoomsFragment : Fragment(), ChatRoomsView {
...
@@ -134,7 +134,9 @@ class ChatRoomsFragment : Fragment(), ChatRoomsView {
}
}
private
val
dismissStatus
=
{
private
val
dismissStatus
=
{
connection_status_text
.
fadeOut
()
if
(
connection_status_text
!=
null
)
{
connection_status_text
.
fadeOut
()
}
}
}
private
fun
setupToolbar
()
{
private
fun
setupToolbar
()
{
...
...
app/src/main/java/chat/rocket/android/dagger/module/AppModule.kt
View file @
f882e57c
...
@@ -7,7 +7,6 @@ import android.content.SharedPreferences
...
@@ -7,7 +7,6 @@ import android.content.SharedPreferences
import
chat.rocket.android.BuildConfig
import
chat.rocket.android.BuildConfig
import
chat.rocket.android.R
import
chat.rocket.android.R
import
chat.rocket.android.app.RocketChatDatabase
import
chat.rocket.android.app.RocketChatDatabase
import
chat.rocket.android.app.utils.CustomImageFormatConfigurator
import
chat.rocket.android.authentication.infraestructure.MemoryTokenRepository
import
chat.rocket.android.authentication.infraestructure.MemoryTokenRepository
import
chat.rocket.android.authentication.infraestructure.SharedPreferencesMultiServerTokenRepository
import
chat.rocket.android.authentication.infraestructure.SharedPreferencesMultiServerTokenRepository
import
chat.rocket.android.dagger.qualifier.ForFresco
import
chat.rocket.android.dagger.qualifier.ForFresco
...
@@ -131,7 +130,6 @@ class AppModule {
...
@@ -131,7 +130,6 @@ class AppModule {
listeners
.
add
(
RequestLoggingListener
())
listeners
.
add
(
RequestLoggingListener
())
return
OkHttpImagePipelineConfigFactory
.
newBuilder
(
context
,
okHttpClient
)
return
OkHttpImagePipelineConfigFactory
.
newBuilder
(
context
,
okHttpClient
)
.
setImageDecoderConfig
(
CustomImageFormatConfigurator
.
createImageDecoderConfig
())
.
setRequestListeners
(
listeners
)
.
setRequestListeners
(
listeners
)
.
setDownsampleEnabled
(
true
)
.
setDownsampleEnabled
(
true
)
//.experiment().setBitmapPrepareToDraw(true).experiment()
//.experiment().setBitmapPrepareToDraw(true).experiment()
...
@@ -141,11 +139,7 @@ class AppModule {
...
@@ -141,11 +139,7 @@ class AppModule {
@Provides
@Provides
@Singleton
@Singleton
fun
provideDraweeConfig
():
DraweeConfig
{
fun
provideDraweeConfig
():
DraweeConfig
{
val
draweeConfigBuilder
=
DraweeConfig
.
newBuilder
()
return
DraweeConfig
.
newBuilder
().
build
()
CustomImageFormatConfigurator
.
addCustomDrawableFactories
(
draweeConfigBuilder
)
return
draweeConfigBuilder
.
build
()
}
}
@Provides
@Provides
...
@@ -185,7 +179,13 @@ class AppModule {
...
@@ -185,7 +179,13 @@ class AppModule {
@Provides
@Provides
@Singleton
@Singleton
fun
provideChatRoomsRepository
():
ChatRoomsRepository
{
fun
provideRoomRepository
():
RoomRepository
{
return
MemoryRoomRepository
()
}
@Provides
@Singleton
fun
provideChatRoomRepository
():
ChatRoomsRepository
{
return
MemoryChatRoomsRepository
()
return
MemoryChatRoomsRepository
()
}
}
...
@@ -207,6 +207,12 @@ class AppModule {
...
@@ -207,6 +207,12 @@ class AppModule {
return
MemoryMessagesRepository
()
return
MemoryMessagesRepository
()
}
}
@Provides
@Singleton
fun
provideUserRepository
():
UsersRepository
{
return
MemoryUsersRepository
()
}
@Provides
@Provides
@Singleton
@Singleton
fun
provideConfiguration
(
context
:
Application
,
client
:
OkHttpClient
):
SpannableConfiguration
{
fun
provideConfiguration
(
context
:
Application
,
client
:
OkHttpClient
):
SpannableConfiguration
{
...
...
app/src/main/java/chat/rocket/android/helper/UrlHelper.kt
View file @
f882e57c
...
@@ -11,7 +11,8 @@ object UrlHelper {
...
@@ -11,7 +11,8 @@ object UrlHelper {
* @param avatarName The avatar name.
* @param avatarName The avatar name.
* @return The avatar URL.
* @return The avatar URL.
*/
*/
fun
getAvatarUrl
(
serverUrl
:
String
,
avatarName
:
String
):
String
=
removeTrailingSlash
(
serverUrl
)
+
"/avatar/"
+
avatarName
fun
getAvatarUrl
(
serverUrl
:
String
,
avatarName
:
String
,
format
:
String
=
"jpeg"
):
String
=
removeTrailingSlash
(
serverUrl
)
+
"/avatar/"
+
removeTrailingSlash
(
avatarName
)
+
"?format=$format"
/**
/**
* Returns the CAS URL.
* Returns the CAS URL.
...
...
app/src/main/java/chat/rocket/android/main/presentation/MainNavigator.kt
View file @
f882e57c
...
@@ -29,8 +29,14 @@ class MainNavigator(internal val activity: MainActivity, internal val context: C
...
@@ -29,8 +29,14 @@ class MainNavigator(internal val activity: MainActivity, internal val context: C
}
}
}
}
fun
toChatRoom
(
chatRoomId
:
String
,
chatRoomName
:
String
,
chatRoomType
:
String
,
isChatRoomReadOnly
:
Boolean
,
chatRoomLastSeen
:
Long
)
{
fun
toChatRoom
(
chatRoomId
:
String
,
activity
.
startActivity
(
context
.
chatRoomIntent
(
chatRoomId
,
chatRoomName
,
chatRoomType
,
isChatRoomReadOnly
,
chatRoomLastSeen
))
chatRoomName
:
String
,
chatRoomType
:
String
,
isChatRoomReadOnly
:
Boolean
,
chatRoomLastSeen
:
Long
,
isChatRoomSubscribed
:
Boolean
)
{
activity
.
startActivity
(
context
.
chatRoomIntent
(
chatRoomId
,
chatRoomName
,
chatRoomType
,
isChatRoomReadOnly
,
chatRoomLastSeen
,
isChatRoomSubscribed
))
activity
.
overridePendingTransition
(
R
.
anim
.
open_enter
,
R
.
anim
.
open_exit
)
activity
.
overridePendingTransition
(
R
.
anim
.
open_enter
,
R
.
anim
.
open_exit
)
}
}
}
}
\ No newline at end of file
app/src/main/java/chat/rocket/android/members/ui/MembersFragment.kt
View file @
f882e57c
...
@@ -15,6 +15,7 @@ import chat.rocket.android.members.adapter.MembersAdapter
...
@@ -15,6 +15,7 @@ import chat.rocket.android.members.adapter.MembersAdapter
import
chat.rocket.android.members.presentation.MembersPresenter
import
chat.rocket.android.members.presentation.MembersPresenter
import
chat.rocket.android.members.presentation.MembersView
import
chat.rocket.android.members.presentation.MembersView
import
chat.rocket.android.members.viewmodel.MemberViewModel
import
chat.rocket.android.members.viewmodel.MemberViewModel
import
chat.rocket.android.util.extensions.hideKeyboard
import
chat.rocket.android.util.extensions.inflate
import
chat.rocket.android.util.extensions.inflate
import
chat.rocket.android.util.extensions.setVisible
import
chat.rocket.android.util.extensions.setVisible
import
chat.rocket.android.util.extensions.showToast
import
chat.rocket.android.util.extensions.showToast
...
@@ -22,6 +23,10 @@ import chat.rocket.android.widget.DividerItemDecoration
...
@@ -22,6 +23,10 @@ import chat.rocket.android.widget.DividerItemDecoration
import
dagger.android.support.AndroidSupportInjection
import
dagger.android.support.AndroidSupportInjection
import
kotlinx.android.synthetic.main.fragment_members.*
import
kotlinx.android.synthetic.main.fragment_members.*
import
javax.inject.Inject
import
javax.inject.Inject
import
android.view.inputmethod.InputMethodManager.HIDE_IMPLICIT_ONLY
import
android.app.Activity
import
android.view.inputmethod.InputMethodManager
fun
newInstance
(
chatRoomId
:
String
,
chatRoomType
:
String
):
Fragment
{
fun
newInstance
(
chatRoomId
:
String
,
chatRoomType
:
String
):
Fragment
{
return
MembersFragment
().
apply
{
return
MembersFragment
().
apply
{
...
@@ -60,6 +65,9 @@ class MembersFragment : Fragment(), MembersView {
...
@@ -60,6 +65,9 @@ class MembersFragment : Fragment(), MembersView {
override
fun
onViewCreated
(
view
:
View
,
savedInstanceState
:
Bundle
?)
{
override
fun
onViewCreated
(
view
:
View
,
savedInstanceState
:
Bundle
?)
{
super
.
onViewCreated
(
view
,
savedInstanceState
)
super
.
onViewCreated
(
view
,
savedInstanceState
)
val
imm
=
activity
?.
getSystemService
(
Activity
.
INPUT_METHOD_SERVICE
)
as
InputMethodManager
imm
.
toggleSoftInput
(
InputMethodManager
.
HIDE_IMPLICIT_ONLY
,
0
)
(
activity
as
AppCompatActivity
).
supportActionBar
?.
title
=
""
(
activity
as
AppCompatActivity
).
supportActionBar
?.
title
=
""
setupRecyclerView
()
setupRecyclerView
()
...
...
app/src/main/java/chat/rocket/android/members/viewmodel/MemberViewModel.kt
View file @
f882e57c
...
@@ -25,7 +25,7 @@ class MemberViewModel(private val member: User, private val settings: Map<String
...
@@ -25,7 +25,7 @@ class MemberViewModel(private val member: User, private val settings: Map<String
private
fun
getUserAvatar
():
String
?
{
private
fun
getUserAvatar
():
String
?
{
val
username
=
member
.
username
?:
"?"
val
username
=
member
.
username
?:
"?"
return
baseUrl
?.
let
{
return
baseUrl
?.
let
{
UrlHelper
.
getAvatarUrl
(
baseUrl
,
username
)
UrlHelper
.
getAvatarUrl
(
baseUrl
,
username
,
"png"
)
}
}
}
}
...
...
app/src/main/java/chat/rocket/android/profile/presentation/ProfilePresenter.kt
View file @
f882e57c
...
@@ -13,10 +13,10 @@ import chat.rocket.core.internal.rest.setAvatar
...
@@ -13,10 +13,10 @@ import chat.rocket.core.internal.rest.setAvatar
import
chat.rocket.core.internal.rest.updateProfile
import
chat.rocket.core.internal.rest.updateProfile
import
javax.inject.Inject
import
javax.inject.Inject
class
ProfilePresenter
@Inject
constructor
(
private
val
view
:
ProfileView
,
class
ProfilePresenter
@Inject
constructor
(
private
val
view
:
ProfileView
,
private
val
strategy
:
CancelStrategy
,
private
val
strategy
:
CancelStrategy
,
serverInteractor
:
GetCurrentServerInteractor
,
serverInteractor
:
GetCurrentServerInteractor
,
factory
:
RocketChatClientFactory
)
{
factory
:
RocketChatClientFactory
)
{
private
val
serverUrl
=
serverInteractor
.
get
()
!!
private
val
serverUrl
=
serverInteractor
.
get
()
!!
private
val
client
:
RocketChatClient
=
factory
.
create
(
serverUrl
)
private
val
client
:
RocketChatClient
=
factory
.
create
(
serverUrl
)
private
lateinit
var
myselfId
:
String
private
lateinit
var
myselfId
:
String
...
@@ -29,10 +29,10 @@ class ProfilePresenter @Inject constructor (private val view: ProfileView,
...
@@ -29,10 +29,10 @@ class ProfilePresenter @Inject constructor (private val view: ProfileView,
myselfId
=
myself
.
id
myselfId
=
myself
.
id
val
avatarUrl
=
UrlHelper
.
getAvatarUrl
(
serverUrl
,
myself
.
username
!!
)
val
avatarUrl
=
UrlHelper
.
getAvatarUrl
(
serverUrl
,
myself
.
username
!!
)
view
.
showProfile
(
view
.
showProfile
(
avatarUrl
,
avatarUrl
,
myself
.
name
!!
,
myself
.
name
?:
""
,
myself
.
username
!!
,
myself
.
username
?:
""
,
myself
.
emails
?.
get
(
0
)
?.
address
!!
myself
.
emails
?.
get
(
0
)
?.
address
!!
)
)
}
catch
(
exception
:
RocketChatException
)
{
}
catch
(
exception
:
RocketChatException
)
{
exception
.
message
?.
let
{
exception
.
message
?.
let
{
...
...
app/src/main/java/chat/rocket/android/profile/ui/ProfileFragment.kt
View file @
f882e57c
...
@@ -56,8 +56,8 @@ class ProfileFragment : Fragment(), ProfileView, ActionMode.Callback {
...
@@ -56,8 +56,8 @@ class ProfileFragment : Fragment(), ProfileView, ActionMode.Callback {
text_email
.
textContent
=
email
text_email
.
textContent
=
email
text_avatar_url
.
textContent
=
""
text_avatar_url
.
textContent
=
""
currentName
=
name
currentName
=
user
name
currentUsername
=
user
name
currentUsername
=
name
currentEmail
=
email
currentEmail
=
email
currentAvatar
=
avatarUrl
currentAvatar
=
avatarUrl
...
@@ -129,20 +129,20 @@ class ProfileFragment : Fragment(), ProfileView, ActionMode.Callback {
...
@@ -129,20 +129,20 @@ class ProfileFragment : Fragment(), ProfileView, ActionMode.Callback {
private
fun
listenToChanges
()
{
private
fun
listenToChanges
()
{
Observables
.
combineLatest
(
text_name
.
asObservable
(),
Observables
.
combineLatest
(
text_name
.
asObservable
(),
text_username
.
asObservable
(),
text_username
.
asObservable
(),
text_email
.
asObservable
(),
text_email
.
asObservable
(),
text_avatar_url
.
asObservable
())
{
text_name
,
text_username
,
text_email
,
text_avatar_url
->
text_avatar_url
.
asObservable
())
{
text_name
,
text_username
,
text_email
,
text_avatar_url
->
return
@combineLatest
(
text_name
.
toString
()
!=
currentName
||
return
@combineLatest
(
text_name
.
toString
()
!=
currentName
||
text_username
.
toString
()
!=
currentUsername
||
text_username
.
toString
()
!=
currentUsername
||
text_email
.
toString
()
!=
currentEmail
||
text_email
.
toString
()
!=
currentEmail
||
(
text_avatar_url
.
toString
()
!=
""
&&
text_avatar_url
.
toString
()!=
currentAvatar
))
(
text_avatar_url
.
toString
()
!=
""
&&
text_avatar_url
.
toString
()
!=
currentAvatar
))
}.
subscribe
({
isValid
->
}.
subscribe
({
isValid
->
if
(
isValid
)
{
if
(
isValid
)
{
startActionMode
()
startActionMode
()
}
else
{
}
else
{
finishActionMode
()
finishActionMode
()
}
}
})
})
}
}
private
fun
startActionMode
()
{
private
fun
startActionMode
()
{
...
@@ -154,7 +154,7 @@ class ProfileFragment : Fragment(), ProfileView, ActionMode.Callback {
...
@@ -154,7 +154,7 @@ class ProfileFragment : Fragment(), ProfileView, ActionMode.Callback {
private
fun
finishActionMode
()
=
actionMode
?.
finish
()
private
fun
finishActionMode
()
=
actionMode
?.
finish
()
private
fun
enableUserInput
(
value
:
Boolean
)
{
private
fun
enableUserInput
(
value
:
Boolean
)
{
text_name
.
isEnabled
=
value
text_
user
name
.
isEnabled
=
value
text_username
.
isEnabled
=
value
text_username
.
isEnabled
=
value
text_email
.
isEnabled
=
value
text_email
.
isEnabled
=
value
text_avatar_url
.
isEnabled
=
value
text_avatar_url
.
isEnabled
=
value
...
...
app/src/main/java/chat/rocket/android/server/domain/GetChatRoomsInteractor.kt
View file @
f882e57c
...
@@ -6,6 +6,14 @@ import kotlinx.coroutines.experimental.withContext
...
@@ -6,6 +6,14 @@ import kotlinx.coroutines.experimental.withContext
import
javax.inject.Inject
import
javax.inject.Inject
class
GetChatRoomsInteractor
@Inject
constructor
(
private
val
repository
:
ChatRoomsRepository
)
{
class
GetChatRoomsInteractor
@Inject
constructor
(
private
val
repository
:
ChatRoomsRepository
)
{
/**
* Get all ChatRoom objects.
*
* @param url The server url.
*
* @return All the ChatRoom objects.
*/
fun
get
(
url
:
String
)
=
repository
.
get
(
url
)
fun
get
(
url
:
String
)
=
repository
.
get
(
url
)
/**
/**
...
...
app/src/main/java/chat/rocket/android/server/domain/MessagesRepository.kt
View file @
f882e57c
...
@@ -8,6 +8,7 @@ interface MessagesRepository {
...
@@ -8,6 +8,7 @@ interface MessagesRepository {
* Get message by its message id.
* Get message by its message id.
*
*
* @param id The id of the message to get.
* @param id The id of the message to get.
*
* @return The Message object given by the id or null if message wasn't found.
* @return The Message object given by the id or null if message wasn't found.
*/
*/
fun
getById
(
id
:
String
):
Message
?
fun
getById
(
id
:
String
):
Message
?
...
@@ -20,8 +21,19 @@ interface MessagesRepository {
...
@@ -20,8 +21,19 @@ interface MessagesRepository {
*/
*/
fun
getByRoomId
(
rid
:
String
):
List
<
Message
>
fun
getByRoomId
(
rid
:
String
):
List
<
Message
>
/**
* Get most recent messages up to count different users.
*
* @param rid The id of the room the messages are.
* @param count The count last messages to get.
*
* @return List of last count messages.
*/
fun
getRecentMessages
(
rid
:
String
,
count
:
Long
):
List
<
Message
>
/**
/**
* Get all messages. Use carefully!
* Get all messages. Use carefully!
*
* @return All messages or an empty list.
* @return All messages or an empty list.
*/
*/
fun
getAll
():
List
<
Message
>
fun
getAll
():
List
<
Message
>
...
...
app/src/main/java/chat/rocket/android/server/domain/RoomRepository.kt
0 → 100644
View file @
f882e57c
package
chat.rocket.android.server.domain
import
chat.rocket.common.model.RoomType
import
chat.rocket.core.model.Room
interface
RoomRepository
{
/**
* Get all rooms. Use carefully!
*
* @return All rooms or an empty list.
*/
fun
getAll
():
List
<
Room
>
fun
get
(
query
:
Query
.()
->
Unit
):
List
<
Room
>
/**
* Save a single room object.
*
* @param room The room object to save.
*/
fun
save
(
room
:
Room
)
/**
* Save a list of rooms.
*
* @param roomList The list of rooms to save.
*/
fun
saveAll
(
roomList
:
List
<
Room
>)
/**
* Removes all rooms.
*/
fun
clear
()
data class
Query
(
var
id
:
String
?
=
null
,
var
name
:
String
?
=
null
,
var
fullName
:
String
?
=
null
,
var
type
:
RoomType
?
=
null
,
var
readonly
:
Boolean
?
=
null
)
}
\ No newline at end of file
app/src/main/java/chat/rocket/android/server/domain/UsersRepository.kt
0 → 100644
View file @
f882e57c
package
chat.rocket.android.server.domain
import
chat.rocket.common.model.Email
import
chat.rocket.common.model.User
import
chat.rocket.common.model.UserStatus
interface
UsersRepository
{
/**
* Get all users. Use carefully!
*
* @return All users or an empty list.
*/
fun
getAll
():
List
<
User
>
fun
get
(
query
:
Query
.()
->
Unit
):
List
<
User
>
/**
* Save a single user object.
*
* @param user The user object to save.
*/
fun
save
(
user
:
User
)
/**
* Save a list of users.
*
* @param users The list of users to save.
*/
fun
saveAll
(
userList
:
List
<
User
>)
/**
* Removes all users.
*/
fun
clear
()
data class
Query
(
var
id
:
String
?
=
null
,
var
name
:
String
?
=
null
,
var
username
:
String
?
=
null
,
var
emails
:
List
<
Email
>?
=
null
,
var
utfOffset
:
Float
?
=
null
,
var
status
:
UserStatus
?
=
null
,
var
limit
:
Long
=
0L
)
}
\ No newline at end of file
app/src/main/java/chat/rocket/android/server/infraestructure/MemoryMessagesRepository.kt
View file @
f882e57c
...
@@ -15,6 +15,11 @@ class MemoryMessagesRepository : MessagesRepository {
...
@@ -15,6 +15,11 @@ class MemoryMessagesRepository : MessagesRepository {
return
messages
.
filter
{
it
.
value
.
roomId
==
rid
}.
values
.
toList
()
return
messages
.
filter
{
it
.
value
.
roomId
==
rid
}.
values
.
toList
()
}
}
override
fun
getRecentMessages
(
rid
:
String
,
count
:
Long
):
List
<
Message
>
{
return
getByRoomId
(
rid
).
sortedByDescending
{
it
.
timestamp
}
.
distinctBy
{
it
.
sender
}.
take
(
count
.
toInt
())
}
override
fun
getAll
():
List
<
Message
>
=
messages
.
values
.
toList
()
override
fun
getAll
():
List
<
Message
>
=
messages
.
values
.
toList
()
override
fun
save
(
message
:
Message
)
{
override
fun
save
(
message
:
Message
)
{
...
...
app/src/main/java/chat/rocket/android/server/infraestructure/MemoryRoomRepository.kt
0 → 100644
View file @
f882e57c
package
chat.rocket.android.server.infraestructure
import
chat.rocket.android.server.domain.RoomRepository
import
chat.rocket.android.server.domain.RoomRepository.Query
import
chat.rocket.core.model.Room
import
java.util.concurrent.CopyOnWriteArrayList
class
MemoryRoomRepository
:
RoomRepository
{
private
val
rooms
=
CopyOnWriteArrayList
<
Room
>()
override
fun
getAll
()
=
rooms
.
toList
()
override
fun
get
(
query
:
Query
.()
->
Unit
):
List
<
Room
>
{
val
q
=
Query
().
apply
(
query
)
return
rooms
.
filter
{
with
(
q
)
{
if
(
name
!=
null
&&
it
.
name
?.
contains
(
name
!!
.
toRegex
())
==
true
)
return
@filter
false
if
(
fullName
!=
null
&&
it
.
fullName
?.
contains
(
fullName
!!
.
toRegex
())
==
true
)
return
@filter
false
if
(
id
!=
null
&&
id
==
it
.
id
)
return
@filter
false
if
(
readonly
!=
null
&&
readonly
==
it
.
readonly
)
return
@filter
false
if
(
type
!=
null
&&
type
==
it
.
type
)
return
@filter
false
return
@filter
true
}
}
}
override
fun
save
(
room
:
Room
)
{
rooms
.
addIfAbsent
(
room
)
}
override
fun
saveAll
(
roomList
:
List
<
Room
>)
{
rooms
.
addAllAbsent
(
roomList
)
}
override
fun
clear
()
{
rooms
.
clear
()
}
}
\ No newline at end of file
app/src/main/java/chat/rocket/android/server/infraestructure/MemoryUsersRepository.kt
0 → 100644
View file @
f882e57c
package
chat.rocket.android.server.infraestructure
import
chat.rocket.android.server.domain.UsersRepository
import
chat.rocket.android.server.domain.UsersRepository.Query
import
chat.rocket.common.model.User
import
java.util.concurrent.CopyOnWriteArrayList
class
MemoryUsersRepository
:
UsersRepository
{
private
val
users
=
CopyOnWriteArrayList
<
User
>()
override
fun
getAll
():
List
<
User
>
{
return
users
.
toList
()
}
override
fun
get
(
query
:
Query
.()
->
Unit
):
List
<
User
>
{
val
q
=
Query
().
apply
(
query
)
return
users
.
filter
{
with
(
q
)
{
if
(
name
!=
null
&&
it
.
name
?.
contains
(
name
!!
.
toRegex
())
==
true
)
return
@filter
false
if
(
username
!=
null
&&
it
.
username
?.
contains
(
username
!!
.
toRegex
())
==
true
)
return
@filter
false
if
(
id
!=
null
&&
id
==
it
.
id
)
return
@filter
false
if
(
status
!=
null
&&
status
==
it
.
status
)
return
@filter
false
return
@filter
true
}
}
}
override
fun
save
(
user
:
User
)
{
users
.
addIfAbsent
(
user
)
}
override
fun
saveAll
(
userList
:
List
<
User
>)
{
users
.
addAllAbsent
(
userList
)
}
override
fun
clear
()
{
this
.
users
.
clear
()
}
}
\ No newline at end of file
app/src/main/java/chat/rocket/android/widget/autocompletion/model/SuggestionModel.kt
0 → 100644
View file @
f882e57c
package
chat.rocket.android.widget.autocompletion.model
abstract
class
SuggestionModel
(
val
text
:
String
,
// This is the text key for searches, must be unique.
val
searchList
:
List
<
String
>
=
emptyList
(),
// Where to search for matches.
val
pinned
:
Boolean
=
false
/* If pinned item will have priority to show */
)
{
override
fun
equals
(
other
:
Any
?):
Boolean
{
if
(
this
===
other
)
return
true
if
(
other
!
is
SuggestionModel
)
return
false
if
(
text
!=
other
.
text
)
return
false
return
true
}
override
fun
hashCode
():
Int
{
return
text
.
hashCode
()
}
}
\ No newline at end of file
app/src/main/java/chat/rocket/android/widget/autocompletion/repository/LocalSuggestionProvider.kt
0 → 100644
View file @
f882e57c
package
chat.rocket.android.widget.autocompletion.repository
interface
LocalSuggestionProvider
{
fun
find
(
prefix
:
String
)
}
\ No newline at end of file
app/src/main/java/chat/rocket/android/widget/autocompletion/strategy/CompletionStrategy.kt
0 → 100644
View file @
f882e57c
package
chat.rocket.android.widget.autocompletion.strategy
import
chat.rocket.android.widget.autocompletion.model.SuggestionModel
interface
CompletionStrategy
{
fun
getItem
(
prefix
:
String
,
position
:
Int
):
SuggestionModel
fun
autocompleteItems
(
prefix
:
String
):
List
<
SuggestionModel
>
fun
addAll
(
list
:
List
<
SuggestionModel
>)
fun
size
():
Int
}
\ No newline at end of file
app/src/main/java/chat/rocket/android/widget/autocompletion/strategy/regex/StringMatchingCompletionStrategy.kt
0 → 100644
View file @
f882e57c
package
chat.rocket.android.widget.autocompletion.strategy.regex
import
chat.rocket.android.widget.autocompletion.model.SuggestionModel
import
chat.rocket.android.widget.autocompletion.strategy.CompletionStrategy
import
chat.rocket.android.widget.autocompletion.ui.SuggestionsAdapter
import
java.util.concurrent.CopyOnWriteArrayList
internal
class
StringMatchingCompletionStrategy
(
private
val
threshold
:
Int
=
-
1
)
:
CompletionStrategy
{
private
val
list
=
CopyOnWriteArrayList
<
SuggestionModel
>()
override
fun
autocompleteItems
(
prefix
:
String
):
List
<
SuggestionModel
>
{
val
result
=
list
.
filter
{
it
.
searchList
.
forEach
{
word
->
if
(
word
.
contains
(
prefix
,
ignoreCase
=
true
))
{
return
@filter
true
}
}
false
}.
sortedByDescending
{
it
.
pinned
}
return
if
(
threshold
==
SuggestionsAdapter
.
UNLIMITED_RESULT_COUNT
)
result
else
result
.
take
(
threshold
)
}
override
fun
addAll
(
list
:
List
<
SuggestionModel
>)
{
this
.
list
.
addAllAbsent
(
list
)
}
override
fun
getItem
(
prefix
:
String
,
position
:
Int
):
SuggestionModel
{
return
list
[
position
]
}
override
fun
size
():
Int
{
return
list
.
size
}
}
\ No newline at end of file
app/src/main/java/chat/rocket/android/widget/autocompletion/strategy/trie/TrieCompletionStrategy.kt
0 → 100644
View file @
f882e57c
package
chat.rocket.android.widget.autocompletion.strategy.trie
import
chat.rocket.android.widget.autocompletion.model.SuggestionModel
import
chat.rocket.android.widget.autocompletion.strategy.CompletionStrategy
import
chat.rocket.android.widget.autocompletion.strategy.trie.data.Trie
class
TrieCompletionStrategy
:
CompletionStrategy
{
private
val
items
=
mutableListOf
<
SuggestionModel
>()
private
val
trie
=
Trie
()
override
fun
getItem
(
prefix
:
String
,
position
:
Int
):
SuggestionModel
{
val
item
:
SuggestionModel
if
(
prefix
.
isEmpty
())
{
item
=
items
[
position
]
}
else
{
item
=
autocompleteItems
(
prefix
)[
position
]
}
return
item
}
override
fun
autocompleteItems
(
prefix
:
String
)
=
trie
.
autocompleteItems
(
prefix
)
override
fun
addAll
(
list
:
List
<
SuggestionModel
>)
{
items
.
addAll
(
list
)
list
.
forEach
{
trie
.
insert
(
it
)
}
}
override
fun
size
()
=
items
.
size
}
\ No newline at end of file
app/src/main/java/chat/rocket/android/widget/autocompletion/strategy/trie/data/Trie.kt
0 → 100644
View file @
f882e57c
package
chat.rocket.android.widget.autocompletion.strategy.trie.data
import
chat.rocket.android.widget.autocompletion.model.SuggestionModel
internal
class
Trie
{
private
val
root
=
TrieNode
(
' '
)
private
var
count
=
0
fun
insert
(
item
:
SuggestionModel
)
{
val
sanitizedWord
=
item
.
text
.
trim
().
toLowerCase
()
// Word exists, bail out.
if
(
search
(
sanitizedWord
))
return
var
current
=
root
sanitizedWord
.
forEach
{
ch
->
val
child
=
current
.
getChild
(
ch
)
if
(
child
==
null
)
{
val
node
=
TrieNode
(
ch
,
current
)
current
.
children
[
ch
]
=
node
current
=
node
count
++
}
else
{
current
=
child
}
}
// Set last node as leaf.
if
(
current
!=
root
)
{
current
.
isLeaf
=
true
current
.
item
=
item
}
}
fun
search
(
word
:
String
):
Boolean
{
val
sanitizedWord
=
word
.
trim
().
toLowerCase
()
var
current
=
root
sanitizedWord
.
forEach
{
ch
->
val
child
=
current
.
getChild
(
ch
)
if
(
child
==
null
)
{
return
false
}
current
=
child
}
if
(
current
.
isLeaf
)
{
return
true
}
return
false
}
fun
autocomplete
(
prefix
:
String
):
List
<
String
>
{
val
sanitizedPrefix
=
prefix
.
trim
().
toLowerCase
()
var
lastNode
:
TrieNode
?
=
root
sanitizedPrefix
.
forEach
{
ch
->
lastNode
=
lastNode
?.
getChild
(
ch
)
if
(
lastNode
==
null
)
return
emptyList
()
}
return
lastNode
!!
.
getWords
()
}
fun
autocompleteItems
(
prefix
:
String
):
List
<
SuggestionModel
>
{
val
sanitizedPrefix
=
prefix
.
trim
().
toLowerCase
()
var
lastNode
:
TrieNode
?
=
root
sanitizedPrefix
.
forEach
{
ch
->
lastNode
=
lastNode
?.
getChild
(
ch
)
if
(
lastNode
==
null
)
return
emptyList
()
}
return
lastNode
!!
.
getItems
()
}
fun
getCount
()
=
count
}
\ No newline at end of file
app/src/main/java/chat/rocket/android/widget/autocompletion/strategy/trie/data/TrieNode.kt
0 → 100644
View file @
f882e57c
package
chat.rocket.android.widget.autocompletion.strategy.trie.data
import
chat.rocket.android.widget.autocompletion.model.SuggestionModel
internal
class
TrieNode
(
internal
var
data
:
Char
,
internal
var
parent
:
TrieNode
?
=
null
,
internal
var
isLeaf
:
Boolean
=
false
,
internal
var
item
:
SuggestionModel
?
=
null
)
{
val
children
=
hashMapOf
<
Char
,
TrieNode
>()
fun
getChild
(
c
:
Char
):
TrieNode
?
{
children
.
forEach
{
if
(
it
.
key
==
c
)
return
it
.
value
}
return
null
}
fun
getWords
():
List
<
String
>
{
val
list
=
arrayListOf
<
String
>()
if
(
isLeaf
)
{
list
.
add
(
toString
())
}
children
.
forEach
{
node
->
node
.
value
.
let
{
list
.
addAll
(
it
.
getWords
())
}
}
return
list
}
class
X
:
SuggestionModel
(
""
)
fun
getItems
():
List
<
SuggestionModel
>
{
val
list
=
arrayListOf
<
SuggestionModel
>()
if
(
isLeaf
)
{
list
.
add
(
item
!!
)
}
children
.
forEach
{
node
->
node
.
value
.
let
{
list
.
addAll
(
it
.
getItems
())
}
}
return
list
}
override
fun
toString
():
String
=
if
(
parent
==
null
)
""
else
"${parent.toString()}$data"
}
\ No newline at end of file
app/src/main/java/chat/rocket/android/widget/autocompletion/ui/BaseSuggestionViewHolder.kt
0 → 100644
View file @
f882e57c
package
chat.rocket.android.widget.autocompletion.ui
import
android.support.v7.widget.RecyclerView
import
android.view.View
import
chat.rocket.android.widget.autocompletion.model.SuggestionModel
abstract
class
BaseSuggestionViewHolder
(
view
:
View
)
:
RecyclerView
.
ViewHolder
(
view
)
{
abstract
fun
bind
(
item
:
SuggestionModel
,
itemClickListener
:
SuggestionsAdapter
.
ItemClickListener
?)
}
\ No newline at end of file
app/src/main/java/chat/rocket/android/widget/autocompletion/ui/PopupRecyclerView.kt
0 → 100644
View file @
f882e57c
package
chat.rocket.android.widget.autocompletion.ui
import
android.content.Context
import
android.support.v7.widget.RecyclerView
import
android.util.AttributeSet
import
android.util.DisplayMetrics
import
android.view.WindowManager
import
chat.rocket.android.R
internal
class
PopupRecyclerView
:
RecyclerView
{
private
var
displayWidth
:
Int
=
0
constructor
(
context
:
Context
?)
:
this
(
context
,
null
)
constructor
(
context
:
Context
?,
attrs
:
AttributeSet
?)
:
this
(
context
,
attrs
,
0
)
constructor
(
context
:
Context
?,
attrs
:
AttributeSet
?,
defStyle
:
Int
)
:
super
(
context
,
attrs
,
defStyle
)
{
val
wm
=
context
!!
.
getSystemService
(
Context
.
WINDOW_SERVICE
)
as
WindowManager
val
display
=
wm
.
defaultDisplay
val
size
=
DisplayMetrics
()
display
.
getMetrics
(
size
)
val
screenWidth
=
size
.
widthPixels
displayWidth
=
screenWidth
}
override
fun
onMeasure
(
widthSpec
:
Int
,
heightSpec
:
Int
)
{
val
hSpec
=
MeasureSpec
.
makeMeasureSpec
(
resources
.
getDimensionPixelSize
(
R
.
dimen
.
popup_max_height
),
MeasureSpec
.
AT_MOST
)
val
wSpec
=
MeasureSpec
.
makeMeasureSpec
(
displayWidth
,
MeasureSpec
.
EXACTLY
)
super
.
onMeasure
(
wSpec
,
hSpec
)
}
override
fun
onLayout
(
changed
:
Boolean
,
l
:
Int
,
t
:
Int
,
r
:
Int
,
b
:
Int
)
{
super
.
onLayout
(
changed
,
l
+
40
,
t
,
r
-
40
,
b
)
}
}
\ No newline at end of file
app/src/main/java/chat/rocket/android/widget/autocompletion/ui/SuggestionsAdapter.kt
0 → 100644
View file @
f882e57c
package
chat.rocket.android.widget.autocompletion.ui
import
android.support.v7.widget.RecyclerView
import
chat.rocket.android.widget.autocompletion.model.SuggestionModel
import
chat.rocket.android.widget.autocompletion.strategy.CompletionStrategy
import
chat.rocket.android.widget.autocompletion.strategy.regex.StringMatchingCompletionStrategy
import
java.lang.reflect.Type
import
kotlin.properties.Delegates
abstract
class
SuggestionsAdapter
<
VH
:
BaseSuggestionViewHolder
>(
val
token
:
String
,
val
constraint
:
Int
=
CONSTRAINT_UNBOUND
,
threshold
:
Int
=
MAX_RESULT_COUNT
)
:
RecyclerView
.
Adapter
<
VH
>()
{
companion
object
{
// Any number of results.
const
val
UNLIMITED_RESULT_COUNT
=
-
1
// Trigger suggestions only if on the line start.
const
val
CONSTRAINT_BOUND_TO_START
=
0
// Trigger suggestions from anywhere.
const
val
CONSTRAINT_UNBOUND
=
1
// Maximum number of results to display by default.
private
const
val
MAX_RESULT_COUNT
=
5
}
private
var
itemType
:
Type
?
=
null
private
var
itemClickListener
:
ItemClickListener
?
=
null
// Called to gather results when no results have previously matched.
private
var
providerExternal
:
((
query
:
String
)
->
Unit
)?
=
null
// Maximum number of results/suggestions to display.
private
var
resultsThreshold
:
Int
=
if
(
threshold
>
0
)
threshold
else
UNLIMITED_RESULT_COUNT
// The strategy used for suggesting completions.
private
val
strategy
:
CompletionStrategy
=
StringMatchingCompletionStrategy
(
resultsThreshold
)
// Current input term to look up for suggestions.
private
var
currentTerm
:
String
by
Delegates
.
observable
(
""
,
{
_
,
_
,
newTerm
->
val
items
=
strategy
.
autocompleteItems
(
newTerm
)
notifyDataSetChanged
()
})
init
{
setHasStableIds
(
true
)
}
override
fun
getItemId
(
position
:
Int
):
Long
{
return
getItem
(
position
).
text
.
hashCode
().
toLong
()
}
override
fun
onBindViewHolder
(
holder
:
VH
,
position
:
Int
)
{
holder
.
bind
(
getItem
(
position
),
itemClickListener
)
}
override
fun
getItemCount
()
=
strategy
.
autocompleteItems
(
currentTerm
).
size
private
fun
getItem
(
position
:
Int
):
SuggestionModel
{
return
strategy
.
autocompleteItems
(
currentTerm
)[
position
]
}
fun
autocomplete
(
newTerm
:
String
)
{
this
.
currentTerm
=
newTerm
.
toLowerCase
().
trim
()
}
fun
addItems
(
list
:
List
<
SuggestionModel
>)
{
strategy
.
addAll
(
list
)
// Since we've just added new items we should check for possible new completion suggestions.
strategy
.
autocompleteItems
(
currentTerm
)
notifyDataSetChanged
()
}
fun
setOnClickListener
(
clickListener
:
ItemClickListener
)
{
this
.
itemClickListener
=
clickListener
}
fun
hasItemClickListener
()
=
itemClickListener
!=
null
/**
* Return the current searched term.
*/
fun
term
()
=
this
.
currentTerm
/**
* Set the maximum number of results to show.
*
* @param threshold The maximum number of suggestions to display.
*/
fun
setResultsThreshold
(
threshold
:
Int
)
{
check
(
threshold
>
0
)
resultsThreshold
=
threshold
}
fun
cancel
()
{
strategy
.
addAll
(
emptyList
())
strategy
.
autocompleteItems
(
currentTerm
)
notifyDataSetChanged
()
}
interface
ItemClickListener
{
fun
onClick
(
item
:
SuggestionModel
)
}
}
\ No newline at end of file
app/src/main/java/chat/rocket/android/widget/autocompletion/ui/SuggestionsView.kt
0 → 100644
View file @
f882e57c
This diff is collapsed.
Click to expand it.
app/src/main/res/anim/hold.xml
View file @
f882e57c
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<set
xmlns:android=
"http://schemas.android.com/apk/res/android"
>
<set
xmlns:android=
"http://schemas.android.com/apk/res/android"
>
<translate
<translate
android:duration=
"
8
00"
android:duration=
"
5
00"
android:fromYDelta=
"0.0%p"
android:fromYDelta=
"0.0%p"
android:toYDelta=
"0.0%p"
/>
android:toYDelta=
"0.0%p"
/>
</set>
</set>
\ No newline at end of file
app/src/main/res/anim/slide_up.xml
View file @
f882e57c
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<set
xmlns:android=
"http://schemas.android.com/apk/res/android"
>
<set
xmlns:android=
"http://schemas.android.com/apk/res/android"
>
<translate
xmlns:android=
"http://schemas.android.com/apk/res/android"
<translate
xmlns:android=
"http://schemas.android.com/apk/res/android"
android:duration=
"
3
50"
android:duration=
"
2
50"
android:fromYDelta=
"100.0%"
android:fromYDelta=
"100.0%"
android:toYDelta=
"0.0%"
/>
android:toYDelta=
"0.0%"
/>
</set>
</set>
\ No newline at end of file
app/src/main/res/drawable/suggestions_menu_decorator.xml
0 → 100644
View file @
f882e57c
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android=
"http://schemas.android.com/apk/res/android"
android:shape=
"rectangle"
>
<solid
android:color=
"#10000000"
/>
<corners
android:radius=
"5dp"
/>
<size
android:height=
"2dp"
/>
</shape>
\ No newline at end of file
app/src/main/res/drawable/user_status_white.xml
0 → 100644
View file @
f882e57c
<?xml version="1.0" encoding="utf-8"?>
<vector
xmlns:android=
"http://schemas.android.com/apk/res/android"
android:width=
"10dp"
android:height=
"10dp"
android:viewportWidth=
"10.0"
android:viewportHeight=
"10.0"
>
<path
android:pathData=
"M5,5m-5,0a5,5 0,1 1,10 0a5,5 0,1 1,-10 0"
android:fillType=
"evenOdd"
android:fillColor=
"#FFFFFF"
android:strokeWidth=
"1"
/>
</vector>
\ No newline at end of file
app/src/main/res/layout/fragment_authentication_log_in.xml
View file @
f882e57c
...
@@ -9,7 +9,6 @@
...
@@ -9,7 +9,6 @@
tools:context=
".authentication.login.ui.LoginFragment"
>
tools:context=
".authentication.login.ui.LoginFragment"
>
<android.support.constraint.ConstraintLayout
<android.support.constraint.ConstraintLayout
android:id=
"@+id/middle_container"
android:layout_width=
"match_parent"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
>
android:layout_height=
"wrap_content"
>
...
...
app/src/main/res/layout/fragment_authentication_server.xml
View file @
f882e57c
...
@@ -14,19 +14,11 @@
...
@@ -14,19 +14,11 @@
android:layout_centerHorizontal=
"true"
android:layout_centerHorizontal=
"true"
android:text=
"@string/title_sign_in_your_server"
/>
android:text=
"@string/title_sign_in_your_server"
/>
<TextView
android:id=
"@+id/text_server_protocol"
style=
"@style/Authentication.TextView"
android:layout_below=
"@id/text_headline"
android:layout_marginTop=
"32dp"
android:gravity=
"center_vertical"
android:text=
"@string/default_protocol"
/>
<EditText
<EditText
android:id=
"@+id/text_server_url"
android:id=
"@+id/text_server_url"
style=
"@style/Authentication.EditText"
style=
"@style/Authentication.EditText"
android:layout_below=
"@id/text_headline"
android:layout_below=
"@id/text_headline"
android:layout_marginStart=
"
0
dp"
android:layout_marginStart=
"
-4
dp"
android:layout_marginTop=
"32dp"
android:layout_marginTop=
"32dp"
android:layout_toEndOf=
"@id/text_server_protocol"
android:layout_toEndOf=
"@id/text_server_protocol"
android:cursorVisible=
"false"
android:cursorVisible=
"false"
...
@@ -35,7 +27,15 @@
...
@@ -35,7 +27,15 @@
android:digits=
"0123456789abcdefghijklmnopqrstuvwxyz.-/:"
android:digits=
"0123456789abcdefghijklmnopqrstuvwxyz.-/:"
android:inputType=
"textUri"
android:inputType=
"textUri"
android:paddingEnd=
"0dp"
android:paddingEnd=
"0dp"
android:paddingStart=
"0dp"
/>
android:paddingStart=
"2dp"
/>
<TextView
android:id=
"@+id/text_server_protocol"
style=
"@style/Authentication.TextView"
android:layout_below=
"@id/text_headline"
android:layout_marginTop=
"32dp"
android:gravity=
"center_vertical"
android:text=
"@string/default_protocol"
/>
<com.wang.avi.AVLoadingIndicatorView
<com.wang.avi.AVLoadingIndicatorView
android:id=
"@+id/view_loading"
android:id=
"@+id/view_loading"
...
...
app/src/main/res/layout/fragment_authentication_sign_up.xml
View file @
f882e57c
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<
android.support.constraint.Constraint
Layout
xmlns:android=
"http://schemas.android.com/apk/res/android"
<
Relative
Layout
xmlns:android=
"http://schemas.android.com/apk/res/android"
xmlns:app=
"http://schemas.android.com/apk/res-auto"
xmlns:app=
"http://schemas.android.com/apk/res-auto"
xmlns:tools=
"http://schemas.android.com/tools"
xmlns:tools=
"http://schemas.android.com/tools"
android:id=
"@+id/
constraint
_layout"
android:id=
"@+id/
relative
_layout"
android:layout_width=
"match_parent"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
android:layout_height=
"match_parent"
android:focusableInTouchMode=
"true"
tools:context=
".authentication.signup.ui.SignupFragment"
>
tools:context=
".authentication.signup.ui.SignupFragment"
>
<TextView
<ScrollView
android:id=
"@+id/text_headline"
android:id=
"@+id/scroll_view"
style=
"@style/Authentication.Headline.TextView"
android:layout_width=
"match_parent"
android:text=
"@string/title_sign_up"
android:layout_height=
"wrap_content"
>
app:layout_constraintLeft_toLeftOf=
"parent"
app:layout_constraintRight_toRightOf=
"parent"
app:layout_constraintTop_toTopOf=
"parent"
/>
<EditText
<LinearLayout
android:id=
"@+id/text_name"
android:layout_width=
"match_parent"
style=
"@style/Authentication.EditText"
android:layout_height=
"wrap_content"
android:layout_marginTop=
"32dp"
android:orientation=
"vertical"
>
android:drawableStart=
"@drawable/ic_person_black_24dp"
android:hint=
"@string/msg_name"
android:imeOptions=
"actionNext"
android:inputType=
"textCapWords"
app:layout_constraintLeft_toLeftOf=
"parent"
app:layout_constraintRight_toRightOf=
"parent"
app:layout_constraintTop_toBottomOf=
"@+id/text_headline"
/>
<EditText
<TextView
android:id=
"@+id/text_username"
android:id=
"@+id/text_headline"
style=
"@style/Authentication.EditText"
style=
"@style/Authentication.Headline.TextView"
android:layout_marginTop=
"16dp"
android:layout_gravity=
"center"
android:drawableStart=
"@drawable/ic_at_black_24dp"
android:text=
"@string/title_sign_up"
/>
android:hint=
"@string/msg_username"
android:imeOptions=
"actionNext"
android:inputType=
"text"
app:layout_constraintLeft_toLeftOf=
"parent"
app:layout_constraintRight_toRightOf=
"parent"
app:layout_constraintTop_toBottomOf=
"@+id/text_name"
/>
<EditText
<EditText
android:id=
"@+id/text_password"
android:id=
"@+id/text_name"
style=
"@style/Authentication.EditText"
style=
"@style/Authentication.EditText"
android:layout_marginTop=
"16dp"
android:layout_marginTop=
"32dp"
android:drawableStart=
"@drawable/ic_lock_black_24dp"
android:drawableStart=
"@drawable/ic_person_black_24dp"
android:hint=
"@string/msg_password"
android:hint=
"@string/msg_name"
android:imeOptions=
"actionNext"
android:imeOptions=
"actionNext"
android:inputType=
"textPassword"
android:inputType=
"textCapWords"
/>
app:layout_constraintLeft_toLeftOf=
"parent"
app:layout_constraintRight_toRightOf=
"parent"
app:layout_constraintTop_toBottomOf=
"@+id/text_username"
/>
<EditText
<EditText
android:id=
"@+id/text_email"
android:id=
"@+id/text_username"
style=
"@style/Authentication.EditText"
style=
"@style/Authentication.EditText"
android:layout_marginTop=
"16dp"
android:layout_marginTop=
"16dp"
android:drawableStart=
"@drawable/ic_email_black_24dp"
android:drawableStart=
"@drawable/ic_at_black_24dp"
android:hint=
"@string/msg_email"
android:hint=
"@string/msg_username"
android:imeOptions=
"actionDone"
android:imeOptions=
"actionNext"
android:inputType=
"textEmailAddress"
android:inputType=
"text"
/>
app:layout_constraintLeft_toLeftOf=
"parent"
app:layout_constraintRight_toRightOf=
"parent"
<EditText
app:layout_constraintTop_toBottomOf=
"@+id/text_password"
/>
android:id=
"@+id/text_password"
style=
"@style/Authentication.EditText"
android:layout_marginTop=
"16dp"
android:drawableStart=
"@drawable/ic_lock_black_24dp"
android:hint=
"@string/msg_password"
android:imeOptions=
"actionNext"
android:inputType=
"textPassword"
/>
<EditText
android:id=
"@+id/text_email"
style=
"@style/Authentication.EditText"
android:layout_marginBottom=
"16dp"
android:layout_marginTop=
"16dp"
android:drawableStart=
"@drawable/ic_email_black_24dp"
android:hint=
"@string/msg_email"
android:imeOptions=
"actionDone"
android:inputType=
"textEmailAddress"
/>
</LinearLayout>
</ScrollView>
<com.wang.avi.AVLoadingIndicatorView
<com.wang.avi.AVLoadingIndicatorView
android:id=
"@+id/view_loading"
android:id=
"@+id/view_loading"
android:layout_width=
"wrap_content"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_centerInParent=
"true"
android:layout_below=
"@id/scroll_view"
android:layout_centerHorizontal=
"true"
android:layout_marginTop=
"16dp"
android:layout_marginTop=
"16dp"
android:visibility=
"gone"
android:visibility=
"gone"
app:indicatorName=
"BallPulseIndicator"
app:indicatorName=
"BallPulseIndicator"
app:layout_constraintLeft_toLeftOf=
"parent"
app:layout_constraintRight_toRightOf=
"parent"
app:layout_constraintTop_toBottomOf=
"@+id/text_email"
tools:visibility=
"visible"
/>
tools:visibility=
"visible"
/>
<
TextView
<
LinearLayout
android:id=
"@+id/
text_new_user_agreement
"
android:id=
"@+id/
bottom_container
"
android:layout_width=
"
wrap_cont
ent"
android:layout_width=
"
match_par
ent"
android:layout_height=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_marginBottom=
"16dp"
android:layout_alignParentBottom=
"true"
android:layout_marginEnd=
"@dimen/screen_edge_left_and_right_margins"
android:orientation=
"vertical"
>
android:layout_marginStart=
"@dimen/screen_edge_left_and_right_margins"
android:gravity=
"center"
<TextView
android:textColorLink=
"@color/colorAccent"
android:id=
"@+id/text_new_user_agreement"
app:layout_constraintBottom_toTopOf=
"@+id/button_sign_up"
android:layout_width=
"wrap_content"
app:layout_constraintLeft_toLeftOf=
"parent"
android:layout_height=
"wrap_content"
app:layout_constraintRight_toRightOf=
"parent"
/>
android:layout_gravity=
"center"
android:layout_margin=
"@dimen/screen_edge_left_and_right_margins"
android:gravity=
"center"
android:textColorLink=
"@color/colorAccent"
/>
<Button
<Button
android:id=
"@+id/button_sign_up"
android:id=
"@+id/button_sign_up"
style=
"@style/Authentication.Button"
style=
"@style/Authentication.Button"
android:text=
"@string/title_sign_up"
android:text=
"@string/title_sign_up"
/>
app:layout_constraintBottom_toBottomOf=
"parent"
/
>
</LinearLayout
>
</android.support.constraint.ConstraintLayout>
</RelativeLayout>
\ No newline at end of file
\ No newline at end of file
app/src/main/res/layout/fragment_chat_room.xml
View file @
f882e57c
...
@@ -28,8 +28,16 @@
...
@@ -28,8 +28,16 @@
layout=
"@layout/message_list"
layout=
"@layout/message_list"
android:layout_width=
"match_parent"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
/>
android:layout_height=
"match_parent"
/>
</FrameLayout>
</FrameLayout>
<chat.rocket.android.widget.autocompletion.ui.SuggestionsView
android:id=
"@+id/suggestions_view"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:layout_above=
"@+id/layout_message_composer"
android:background=
"@color/suggestion_background_color"
/>
<include
<include
android:id=
"@+id/layout_message_composer"
android:id=
"@+id/layout_message_composer"
layout=
"@layout/message_composer"
layout=
"@layout/message_composer"
...
@@ -58,15 +66,15 @@
...
@@ -58,15 +66,15 @@
android:id=
"@+id/connection_status_text"
android:id=
"@+id/connection_status_text"
android:layout_width=
"match_parent"
android:layout_width=
"match_parent"
android:layout_height=
"32dp"
android:layout_height=
"32dp"
android:alpha=
"0"
android:background=
"@color/colorPrimary"
android:background=
"@color/colorPrimary"
android:elevation=
"4dp"
android:elevation=
"4dp"
android:textColor=
"@color/white"
android:gravity=
"center"
android:gravity=
"center"
android:textAppearance=
"@style/TextAppearance.AppCompat.Body2"
android:textAppearance=
"@style/TextAppearance.AppCompat.Body2"
android:textColor=
"@color/white"
android:visibility=
"gone"
android:visibility=
"gone"
android:alpha=
"0"
tools:alpha=
"1"
tools:alpha=
"1"
tools:
visibility=
"visible
"
tools:
text=
"connected
"
tools:
text=
"connected"
/>
tools:
visibility=
"visible"
/>
</RelativeLayout>
</RelativeLayout>
app/src/main/res/layout/message_composer.xml
View file @
f882e57c
...
@@ -27,6 +27,18 @@
...
@@ -27,6 +27,18 @@
android:visibility=
"gone"
android:visibility=
"gone"
app:layout_constraintTop_toBottomOf=
"@+id/divider"
/>
app:layout_constraintTop_toBottomOf=
"@+id/divider"
/>
<Button
android:id=
"@+id/button_join_chat"
android:layout_width=
"match_parent"
android:layout_height=
"45dp"
android:background=
"@color/white"
android:text=
"@string/action_join_chat"
android:textColor=
"@color/colorAccent"
android:visibility=
"gone"
app:layout_constraintEnd_toEndOf=
"parent"
app:layout_constraintStart_toStartOf=
"parent"
app:layout_constraintTop_toBottomOf=
"@+id/divider"
/>
<LinearLayout
<LinearLayout
android:id=
"@+id/input_container"
android:id=
"@+id/input_container"
android:layout_width=
"match_parent"
android:layout_width=
"match_parent"
...
...
app/src/main/res/layout/suggestion_command_item.xml
0 → 100644
View file @
f882e57c
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android=
"http://schemas.android.com/apk/res/android"
xmlns:tools=
"http://schemas.android.com/tools"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:layout_marginBottom=
"4dp"
android:layout_marginTop=
"4dp"
android:background=
"@color/suggestion_background_color"
android:orientation=
"horizontal"
android:paddingTop=
"2dp"
>
<TextView
android:id=
"@+id/text_command_name"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_alignParentLeft=
"true"
android:layout_alignParentStart=
"true"
android:layout_marginStart=
"8dp"
android:ellipsize=
"end"
android:maxLines=
"1"
android:textColor=
"@color/black"
android:textSize=
"14sp"
tools:text=
"/leave"
/>
<TextView
android:id=
"@+id/text_command_description"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:layout_marginEnd=
"8dp"
android:layout_marginStart=
"16dp"
android:layout_toRightOf=
"@id/text_command_name"
android:ellipsize=
"end"
android:gravity=
"start"
android:maxLines=
"1"
android:textColor=
"@color/gray_material"
android:textSize=
"14sp"
tools:text=
"Leave a channel"
/>
</RelativeLayout>
\ No newline at end of file
app/src/main/res/layout/suggestion_member_item.xml
0 → 100644
View file @
f882e57c
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
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:layout_marginBottom=
"2dp"
android:layout_marginEnd=
"2dp"
android:layout_marginLeft=
"4dp"
android:layout_marginRight=
"2dp"
android:layout_marginStart=
"4dp"
android:layout_marginTop=
"2dp"
android:background=
"@color/suggestion_background_color"
>
<FrameLayout
android:id=
"@+id/image_avatar_container"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_centerVertical=
"true"
>
<com.facebook.drawee.view.SimpleDraweeView
android:id=
"@+id/image_avatar"
android:layout_width=
"24dp"
android:layout_height=
"24dp"
android:layout_margin=
"4dp"
app:roundedCornerRadius=
"3dp"
tools:src=
"@tools:sample/avatars"
/>
<ImageView
android:id=
"@+id/image_status"
android:layout_width=
"12dp"
android:layout_height=
"12dp"
android:layout_gravity=
"bottom|end"
android:background=
"@drawable/user_status_white"
android:padding=
"2dp"
/>
</FrameLayout>
<RelativeLayout
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:layout_centerVertical=
"true"
android:layout_toEndOf=
"@id/image_avatar_container"
android:layout_toRightOf=
"@id/image_avatar_container"
android:background=
"@color/suggestion_background_color"
>
<TextView
android:id=
"@+id/text_username"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_centerVertical=
"true"
android:maxLines=
"1"
android:textColor=
"@color/black"
android:textSize=
"16sp"
tools:text=
"@tools:sample/full_names"
/>
<TextView
android:id=
"@+id/text_name"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_alignParentEnd=
"true"
android:layout_alignParentRight=
"true"
android:layout_centerVertical=
"true"
android:layout_toEndOf=
"@+id/text_username"
android:layout_toRightOf=
"@+id/text_username"
android:maxLines=
"1"
android:paddingLeft=
"8dp"
android:paddingStart=
"8dp"
android:textColor=
"@color/gray_material"
android:textSize=
"16sp"
tools:text=
"@tools:sample/full_names"
/>
</RelativeLayout>
</RelativeLayout>
\ No newline at end of file
app/src/main/res/layout/suggestion_room_item.xml
0 → 100644
View file @
f882e57c
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android=
"http://schemas.android.com/apk/res/android"
xmlns:tools=
"http://schemas.android.com/tools"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:layout_margin=
"2dp"
android:background=
"@color/suggestion_background_color"
>
<RelativeLayout
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:layout_centerVertical=
"true"
android:layout_toEndOf=
"@id/image_avatar_container"
android:layout_toRightOf=
"@id/image_avatar_container"
android:background=
"@color/suggestion_background_color"
>
<TextView
android:id=
"@+id/text_name"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_centerVertical=
"true"
android:maxLines=
"1"
android:textColor=
"@color/black"
android:textSize=
"16sp"
tools:text=
"@tools:sample/full_names"
/>
<TextView
android:id=
"@+id/text_fullname"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_alignParentEnd=
"true"
android:layout_alignParentRight=
"true"
android:layout_centerVertical=
"true"
android:layout_toEndOf=
"@+id/text_name"
android:layout_toRightOf=
"@+id/text_name"
android:maxLines=
"1"
android:paddingLeft=
"8dp"
android:paddingStart=
"8dp"
android:textColor=
"@color/gray_material"
android:textSize=
"16sp"
tools:text=
"@tools:sample/full_names"
/>
</RelativeLayout>
</RelativeLayout>
\ No newline at end of file
app/src/main/res/values-pt-rBR/strings.xml
View file @
f882e57c
...
@@ -24,6 +24,8 @@
...
@@ -24,6 +24,8 @@
<string
name=
"action_logout"
>
Sair
</string>
<string
name=
"action_logout"
>
Sair
</string>
<string
name=
"action_files"
>
Arquivos
</string>
<string
name=
"action_files"
>
Arquivos
</string>
<string
name=
"action_confirm_password"
>
Confirme a nova senha
</string>
<string
name=
"action_confirm_password"
>
Confirme a nova senha
</string>
<string
name=
"action_join_chat"
>
Entrar no Chat
</string>
<!-- Settings List -->
<!-- Settings List -->
<string-array
name=
"settings_actions"
>
<string-array
name=
"settings_actions"
>
...
@@ -112,4 +114,28 @@
...
@@ -112,4 +114,28 @@
<string
name=
"status_authenticating"
>
autenticando
</string>
<string
name=
"status_authenticating"
>
autenticando
</string>
<string
name=
"status_disconnecting"
>
desconectando
</string>
<string
name=
"status_disconnecting"
>
desconectando
</string>
<string
name=
"status_waiting"
>
conectando em %d segundos
</string>
<string
name=
"status_waiting"
>
conectando em %d segundos
</string>
<!-- Slash Commands -->
<string
name=
"Slash_Gimme_Description"
>
Exibir ༼ つ ◕_◕ ༽つ antes de sua mensagem
</string>
<string
name=
"Slash_LennyFace_Description"
>
Exibir ( ͡° ͜ʖ ͡°) depois de sua mensagem
</string>
<string
name=
"Slash_Shrug_Description"
>
Exibir ¯\_(ツ)_/¯ depois de sua mensagem
</string>
<string
name=
"Slash_Tableflip_Description"
>
Exibir (╯°□°)╯︵ ┻━┻
</string>
<string
name=
"Slash_TableUnflip_Description"
>
Exibir ┬─┬ ノ( ゜-゜ノ)
</string>
<string
name=
"Create_A_New_Channel"
>
Criar um novo canal
</string>
<string
name=
"Show_the_keyboard_shortcut_list"
>
Show the keyboard shortcut list
</string>
<string
name=
"Invite_user_to_join_channel_all_from"
>
do [#canal] para entrar neste
</string>
<string
name=
"Invite_user_to_join_channel_all_to"
>
Convidar todos os usuários deste canal para entrar no [#canal]
</string>
<string
name=
"Archive"
>
Arquivar
</string>
<string
name=
"Remove_someone_from_room"
>
Remover alguém do canal
</string>
<string
name=
"Leave_the_current_channel"
>
Sair do canal atual
</string>
<string
name=
"Displays_action_text"
>
Exibir texto de ação
</string>
<string
name=
"Direct_message_someone"
>
Enviar DM para alguém
</string>
<string
name=
"Mute_someone_in_room"
>
Mutar alguém
</string>
<string
name=
"Unmute_someone_in_room"
>
Desmutar alguém na sala
</string>
<string
name=
"Invite_user_to_join_channel"
>
Convidar algum usuário para entrar neste canal
</string>
<string
name=
"Unarchive"
>
Desarquivar
</string>
<string
name=
"Join_the_given_channel"
>
Entrar no canal especificado
</string>
<string
name=
"Guggy_Command_Description"
>
Gera um gif baseado no texto dado
</string>
<string
name=
"Slash_Topic_Description"
>
Definir tópico
</string>
</resources>
</resources>
\ No newline at end of file
app/src/main/res/values/colors.xml
View file @
f882e57c
...
@@ -15,7 +15,7 @@
...
@@ -15,7 +15,7 @@
<color
name=
"colorUserStatusOnline"
>
#2FE1A8
</color>
<color
name=
"colorUserStatusOnline"
>
#2FE1A8
</color>
<color
name=
"colorUserStatusBusy"
>
#F33E5B
</color>
<color
name=
"colorUserStatusBusy"
>
#F33E5B
</color>
<color
name=
"colorUserStatusAway"
>
#FDD236
</color>
<color
name=
"colorUserStatusAway"
>
#FDD236
</color>
<color
name=
"colorUserStatusOffline"
>
#
1F2228
</color>
<color
name=
"colorUserStatusOffline"
>
#
d9d9d9
</color>
<color
name=
"colorDrawableTintGrey"
>
#9FA2A8
</color>
<color
name=
"colorDrawableTintGrey"
>
#9FA2A8
</color>
...
@@ -38,4 +38,7 @@
...
@@ -38,4 +38,7 @@
<color
name=
"colorDivider"
>
#1F000000
</color>
<color
name=
"colorDivider"
>
#1F000000
</color>
<!-- Suggestions -->
<color
name=
"suggestion_background_color"
>
@android:color/white
</color>
</resources>
</resources>
app/src/main/res/values/dimens.xml
View file @
f882e57c
...
@@ -32,4 +32,8 @@
...
@@ -32,4 +32,8 @@
<dimen
name=
"padding_mention"
>
4dp
</dimen>
<dimen
name=
"padding_mention"
>
4dp
</dimen>
<dimen
name=
"radius_mention"
>
6dp
</dimen>
<dimen
name=
"radius_mention"
>
6dp
</dimen>
<!-- Autocomplete Popup -->
<dimen
name=
"popup_max_height"
>
150dp
</dimen>
<dimen
name=
"suggestions_box_max_height"
>
250dp
</dimen>
</resources>
</resources>
\ No newline at end of file
app/src/main/res/values/strings.xml
View file @
f882e57c
...
@@ -25,6 +25,7 @@
...
@@ -25,6 +25,7 @@
<string
name=
"action_logout"
>
Logout
</string>
<string
name=
"action_logout"
>
Logout
</string>
<string
name=
"action_files"
>
Files
</string>
<string
name=
"action_files"
>
Files
</string>
<string
name=
"action_confirm_password"
>
Confirm Password Change
</string>
<string
name=
"action_confirm_password"
>
Confirm Password Change
</string>
<string
name=
"action_join_chat"
>
Join Chat
</string>
<!-- Settings List -->
<!-- Settings List -->
<string-array
name=
"settings_actions"
>
<string-array
name=
"settings_actions"
>
...
@@ -115,4 +116,27 @@
...
@@ -115,4 +116,27 @@
<string
name=
"status_disconnecting"
>
disconnecting
</string>
<string
name=
"status_disconnecting"
>
disconnecting
</string>
<string
name=
"status_waiting"
>
connecting in %d seconds
</string>
<string
name=
"status_waiting"
>
connecting in %d seconds
</string>
<!-- Slash Commands -->
<string
name=
"Slash_Gimme_Description"
>
Displays ༼ つ ◕_◕ ༽つ before your message
</string>
<string
name=
"Slash_LennyFace_Description"
>
Displays ( ͡° ͜ʖ ͡°) after your message
</string>
<string
name=
"Slash_Shrug_Description"
>
Displays ¯\_(ツ)_/¯ after your message
</string>
<string
name=
"Slash_Tableflip_Description"
>
Displays (╯°□°)╯︵ ┻━┻
</string>
<string
name=
"Slash_TableUnflip_Description"
>
Displays ┬─┬ ノ( ゜-゜ノ)
</string>
<string
name=
"Create_A_New_Channel"
>
Create a new channel
</string>
<string
name=
"Show_the_keyboard_shortcut_list"
>
Show the keyboard shortcut list
</string>
<string
name=
"Invite_user_to_join_channel_all_from"
>
Invite all users from [#channel] to join this channel
</string>
<string
name=
"Invite_user_to_join_channel_all_to"
>
Invite all users from this channel to join [#channel]
</string>
<string
name=
"Archive"
>
Archive
</string>
<string
name=
"Remove_someone_from_room"
>
Remove someone from the room
</string>
<string
name=
"Leave_the_current_channel"
>
Leave the current channel
</string>
<string
name=
"Displays_action_text"
>
Displays action text
</string>
<string
name=
"Direct_message_someone"
>
Direct message someone
</string>
<string
name=
"Mute_someone_in_room"
>
Mute someone in the room
</string>
<string
name=
"Unmute_someone_in_room"
>
Unmute someone in the room
</string>
<string
name=
"Invite_user_to_join_channel"
>
Invite one user to join this channel
</string>
<string
name=
"Unarchive"
>
Unarchive
</string>
<string
name=
"Join_the_given_channel"
>
Join the given channel
</string>
<string
name=
"Guggy_Command_Description"
>
Generates a gif based upon the provided text
</string>
<string
name=
"Slash_Topic_Description"
>
Set topic
</string>
</resources>
</resources>
\ No newline at end of file
build.gradle
View file @
f882e57c
...
@@ -14,7 +14,7 @@ buildscript {
...
@@ -14,7 +14,7 @@ buildscript {
classpath
"org.jetbrains.kotlin:kotlin-gradle-plugin:${versions.kotlin}"
classpath
"org.jetbrains.kotlin:kotlin-gradle-plugin:${versions.kotlin}"
classpath
"org.jetbrains.dokka:dokka-gradle-plugin:${versions.dokka}"
classpath
"org.jetbrains.dokka:dokka-gradle-plugin:${versions.dokka}"
classpath
'com.google.gms:google-services:3.2.0'
classpath
'com.google.gms:google-services:3.2.0'
classpath
'io.fabric.tools:gradle:1.
+
'
classpath
'io.fabric.tools:gradle:1.
25.1
'
// NOTE: Do not place your application dependencies here; they belong
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
// in the individual module build.gradle files
...
...
dependencies.gradle
View file @
f882e57c
...
@@ -4,7 +4,7 @@ ext {
...
@@ -4,7 +4,7 @@ ext {
compileSdk
:
27
,
compileSdk
:
27
,
targetSdk
:
27
,
targetSdk
:
27
,
buildTools
:
'27.0.3'
,
buildTools
:
'27.0.3'
,
kotlin
:
'1.2.
21
'
,
kotlin
:
'1.2.
30
'
,
coroutine
:
'0.22'
,
coroutine
:
'0.22'
,
dokka
:
'0.9.15'
,
dokka
:
'0.9.15'
,
...
@@ -25,8 +25,7 @@ ext {
...
@@ -25,8 +25,7 @@ ext {
rxBinding
:
'2.0.0'
,
rxBinding
:
'2.0.0'
,
fresco
:
'1.8.1'
,
fresco
:
'1.8.1'
,
kotshi
:
'0.3.0'
,
kotshi
:
'0.3.0'
,
frescoImageViewer
:
'0.5.0'
,
frescoImageViewer
:
'0.5.1'
,
androidSvg
:
'master-SNAPSHOT'
,
markwon
:
'1.0.3'
,
markwon
:
'1.0.3'
,
sheetMenu
:
'1.3.3'
,
sheetMenu
:
'1.3.3'
,
aVLoadingIndicatorView
:
'2.1.3'
,
aVLoadingIndicatorView
:
'2.1.3'
,
...
@@ -86,8 +85,7 @@ ext {
...
@@ -86,8 +85,7 @@ ext {
kotshiApi
:
"se.ansman.kotshi:api:${versions.kotshi}"
,
kotshiApi
:
"se.ansman.kotshi:api:${versions.kotshi}"
,
kotshiCompiler
:
"se.ansman.kotshi:compiler:${versions.kotshi}"
,
kotshiCompiler
:
"se.ansman.kotshi:compiler:${versions.kotshi}"
,
frescoImageViewer
:
"com.github.stfalcon:frescoimageviewer:${versions.frescoImageViewer}"
,
frescoImageViewer
:
"com.github.luciofm:FrescoImageViewer:${versions.frescoImageViewer}"
,
androidSvg
:
"com.github.BigBadaboom:androidsvg:${versions.androidSvg}"
,
markwon
:
"ru.noties:markwon:${versions.markwon}"
,
markwon
:
"ru.noties:markwon:${versions.markwon}"
,
markwonImageLoader
:
"ru.noties:markwon-image-loader:${versions.markwon}"
,
markwonImageLoader
:
"ru.noties:markwon-image-loader:${versions.markwon}"
,
...
@@ -96,8 +94,6 @@ ext {
...
@@ -96,8 +94,6 @@ ext {
aVLoadingIndicatorView
:
"com.wang.avi:library:${versions.aVLoadingIndicatorView}"
,
aVLoadingIndicatorView
:
"com.wang.avi:library:${versions.aVLoadingIndicatorView}"
,
swipeBackLayout
:
"me.imid.swipebacklayout.lib:library:${versions.swipeBackLayout}"
,
// For testing
// For testing
junit
:
"junit:junit:$versions.junit"
,
junit
:
"junit:junit:$versions.junit"
,
expressoCore
:
"com.android.support.test.espresso:espresso-core:${versions.expresso}"
,
expressoCore
:
"com.android.support.test.espresso:espresso-core:${versions.expresso}"
,
...
...
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