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
52407887
Commit
52407887
authored
Aug 03, 2017
by
Leonardo Aramaki
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'develop' into fix/filtering_get_messages_flood
parents
260cb6c0
8ac51b53
Changes
19
Hide whitespace changes
Inline
Side-by-side
Showing
19 changed files
with
211 additions
and
476 deletions
+211
-476
build.gradle
app/build.gradle
+8
-2
OkHttpHelper.java
...rc/main/java/chat/rocket/android/helper/OkHttpHelper.java
+1
-1
RocketChatUserAvatar.kt
...n/java/chat/rocket/android/helper/RocketChatUserAvatar.kt
+0
-17
MessageRenderer.kt
...main/java/chat/rocket/android/renderer/MessageRenderer.kt
+12
-13
UserRenderer.kt
...rc/main/java/chat/rocket/android/renderer/UserRenderer.kt
+2
-2
build.gradle
build.gradle
+1
-1
build.gradle
rocket-chat-android-widgets/build.gradle
+8
-0
RocketChatAvatar.java
...ain/java/chat/rocket/android/widget/RocketChatAvatar.java
+11
-13
RocketChatWidgets.java
...in/java/chat/rocket/android/widget/RocketChatWidgets.java
+1
-7
ColorImage.java
...in/java/chat/rocket/android/widget/fresco/ColorImage.java
+0
-187
CustomImageFormatConfigurator.java
.../android/widget/fresco/CustomImageFormatConfigurator.java
+0
-24
SvgDecoder.java
...in/java/chat/rocket/android/widget/fresco/SvgDecoder.java
+0
-144
FrescoHelper.kt
...in/java/chat/rocket/android/widget/helper/FrescoHelper.kt
+29
-28
UserAvatarHelper.kt
...ava/chat/rocket/android/widget/helper/UserAvatarHelper.kt
+98
-0
RocketChatMessageAttachmentsLayout.java
...id/widget/message/RocketChatMessageAttachmentsLayout.java
+4
-8
RocketChatMessageUrlsLayout.java
...t/android/widget/message/RocketChatMessageUrlsLayout.java
+3
-6
UserViewHolder.java
...roid/widget/message/autocomplete/user/UserViewHolder.java
+5
-17
message_avatar.xml
...at-android-widgets/src/main/res/layout/message_avatar.xml
+6
-6
UserAvatarHelperTest.kt
...chat/rocket/android/widget/helper/UserAvatarHelperTest.kt
+22
-0
No files found.
app/build.gradle
View file @
52407887
...
...
@@ -31,6 +31,7 @@ buildscript {
android
{
compileSdkVersion
rootProject
.
ext
.
compileSdkVersion
buildToolsVersion
rootProject
.
ext
.
buildToolsVersion
defaultConfig
{
applicationId
"chat.rocket.android"
minSdkVersion
16
...
...
@@ -38,10 +39,10 @@ android {
versionCode
28
versionName
"1.0.16"
testInstrumentationRunner
"android.support.test.runner.AndroidJUnitRunner"
vectorDrawables
.
useSupportLibrary
=
true
multiDexEnabled
true
}
signingConfigs
{
release
{
storeFile
project
.
rootProject
.
file
(
'Rocket.jks'
).
getCanonicalFile
()
...
...
@@ -50,6 +51,7 @@ android {
keyPassword
System
.
getenv
(
"KEY_PASSWORD"
)
}
}
buildTypes
{
release
{
minifyEnabled
false
...
...
@@ -57,27 +59,31 @@ android {
signingConfig
signingConfigs
.
release
}
}
packagingOptions
{
exclude
'META-INF/LICENSE.txt'
exclude
'META-INF/NOTICE.txt'
exclude
'META-INF/rxjava.properties'
}
compileOptions
{
sourceCompatibility
JavaVersion
.
VERSION_1_8
targetCompatibility
JavaVersion
.
VERSION_1_8
}
lintOptions
{
//avoiding okio error: https://github.com/square/okhttp/issues/896
lintConfig
file
(
"lint.xml"
)
}
}
play
{
jsonFile
=
file
(
'rocket-chat.json'
)
track
=
"${track}"
}
ext
{
playLibVersion
=
'1
0.2.6
'
playLibVersion
=
'1
1.0.4
'
stethoVersion
=
'1.4.2'
rxbindingVersion
=
'2.0.0'
rxlifecycleVersion
=
'2.1.0'
...
...
app/src/main/java/chat/rocket/android/helper/OkHttpHelper.java
View file @
52407887
...
...
@@ -48,4 +48,4 @@ public class OkHttpHelper {
}
return
httpClientForWS
;
}
}
}
\ No newline at end of file
app/src/main/java/chat/rocket/android/helper/RocketChatUserAvatar.kt
deleted
100644 → 0
View file @
260cb6c0
package
chat.rocket.android.helper
import
java.net.URLEncoder
class
RocketChatUserAvatar
(
val
hostname
:
String
,
val
username
:
String
)
{
val
imageUri
:
String
/** REMARK
* This is often a SVG image (see Rocket.Chat:server/startup/avatar.js).
*/
get
()
{
return
"https://"
+
hostname
.
replace
(
"http://"
,
""
).
replace
(
"https://"
,
""
)
+
"/avatar/"
+
URLEncoder
.
encode
(
username
,
"UTF-8"
)
}
}
\ No newline at end of file
app/src/main/java/chat/rocket/android/renderer/MessageRenderer.kt
View file @
52407887
...
...
@@ -5,9 +5,9 @@ import android.widget.ImageView
import
android.widget.TextView
import
chat.rocket.android.R
import
chat.rocket.android.helper.DateTime
import
chat.rocket.android.helper.RocketChatUserAvatar
import
chat.rocket.android.widget.AbsoluteUrl
import
chat.rocket.android.widget.RocketChatAvatar
import
chat.rocket.android.widget.helper.UserAvatarHelper
import
chat.rocket.android.widget.message.RocketChatMessageAttachmentsLayout
import
chat.rocket.android.widget.message.RocketChatMessageLayout
import
chat.rocket.android.widget.message.RocketChatMessageUrlsLayout
...
...
@@ -20,20 +20,19 @@ class MessageRenderer(val message: Message, val autoLoadImage: Boolean) {
* Show user's avatar image in RocketChatAvatar widget.
*/
fun
showAvatar
(
rocketChatAvatarWidget
:
RocketChatAvatar
,
hostname
:
String
,
userNotFoundAvatarImageView
:
ImageView
)
{
if
(
message
.
avatar
!=
null
)
{
// Load user's avatar image from Oauth provider URI.
rocketChatAvatarWidget
.
loadImage
(
message
.
avatar
)
}
else
{
val
username
:
String
?
=
message
.
user
?.
username
if
(
username
!=
null
)
{
// Load user's avatar image from Rocket.Chat URI.
rocketChatAvatarWidget
.
loadImage
(
RocketChatUserAvatar
(
hostname
,
username
).
imageUri
)
userNotFoundAvatarImageView
.
visibility
=
View
.
GONE
rocketChatAvatarWidget
.
visibility
=
View
.
VISIBLE
val
username
:
String
?
=
message
.
user
?.
username
if
(
username
!=
null
)
{
userNotFoundAvatarImageView
.
visibility
=
View
.
GONE
val
placeholderDrawable
=
UserAvatarHelper
.
getTextDrawable
(
username
,
rocketChatAvatarWidget
.
context
)
if
(
message
.
avatar
!=
null
)
{
// Load user's avatar image from Oauth provider URI.
rocketChatAvatarWidget
.
loadImage
(
message
.
avatar
,
placeholderDrawable
)
}
else
{
rocketChatAvatarWidget
.
visibility
=
View
.
GONE
userNotFoundAvatarImageView
.
visibility
=
View
.
VISIBLE
rocketChatAvatarWidget
.
loadImage
(
UserAvatarHelper
.
getUri
(
hostname
,
username
),
placeholderDrawable
)
}
}
else
{
rocketChatAvatarWidget
.
visibility
=
View
.
GONE
userNotFoundAvatarImageView
.
visibility
=
View
.
VISIBLE
}
}
...
...
app/src/main/java/chat/rocket/android/renderer/UserRenderer.kt
View file @
52407887
...
...
@@ -4,8 +4,8 @@ import android.view.View
import
android.widget.ImageView
import
android.widget.TextView
import
chat.rocket.android.R
import
chat.rocket.android.helper.RocketChatUserAvatar
import
chat.rocket.android.widget.RocketChatAvatar
import
chat.rocket.android.widget.helper.UserAvatarHelper
import
chat.rocket.core.models.User
class
UserRenderer
(
val
user
:
User
)
{
...
...
@@ -16,7 +16,7 @@ class UserRenderer(val user: User) {
fun
showAvatar
(
rocketChatAvatarWidget
:
RocketChatAvatar
,
hostname
:
String
)
{
val
username
:
String
?
=
user
.
username
if
(
username
!=
null
)
{
rocketChatAvatarWidget
.
loadImage
(
RocketChatUserAvatar
(
hostname
,
username
).
imageUri
)
rocketChatAvatarWidget
.
loadImage
(
UserAvatarHelper
.
getUri
(
hostname
,
username
),
UserAvatarHelper
.
getTextDrawable
(
username
,
rocketChatAvatarWidget
.
context
)
)
}
else
{
rocketChatAvatarWidget
.
visibility
=
View
.
GONE
}
...
...
build.gradle
View file @
52407887
...
...
@@ -22,7 +22,7 @@ ext {
buildToolsVersion
=
"26.0.0"
supportLibraryVersion
=
"25.4.0"
constraintLayoutVersion
=
"1.0.2"
kotlinVersion
=
"1.1.3"
kotlinVersion
=
"1.1.3
-2
"
}
task
clean
(
type:
Delete
)
{
...
...
rocket-chat-android-widgets/build.gradle
View file @
52407887
...
...
@@ -24,12 +24,18 @@ android {
vectorDrawables
.
useSupportLibrary
=
true
}
buildTypes
{
release
{
minifyEnabled
false
proguardFiles
getDefaultProguardFile
(
'proguard-android.txt'
),
'proguard-rules.pro'
}
}
sourceSets
{
test
.
java
.
srcDirs
+=
'src/test/kotlin'
androidTest
.
java
.
srcDirs
+=
'src/androidTest/kotlin'
}
}
ext
{
...
...
@@ -49,6 +55,8 @@ dependencies {
compile
"com.android.support.constraint:constraint-layout:$rootProject.ext.constraintLayoutVersion"
compile
"org.jetbrains.kotlin:kotlin-stdlib-jre7:$rootProject.ext.kotlinVersion"
testCompile
"org.jetbrains.kotlin:kotlin-test:$rootProject.ext.kotlinVersion"
testCompile
"org.jetbrains.kotlin:kotlin-test-junit:$rootProject.ext.kotlinVersion"
compile
'org.nibor.autolink:autolink:0.6.0'
...
...
rocket-chat-android-widgets/src/main/java/chat/rocket/android/widget/RocketChatAvatar.java
View file @
52407887
...
...
@@ -2,6 +2,7 @@ package chat.rocket.android.widget;
import
android.annotation.TargetApi
;
import
android.content.Context
;
import
android.graphics.drawable.Drawable
;
import
android.os.Build
;
import
android.util.AttributeSet
;
import
android.view.LayoutInflater
;
...
...
@@ -11,38 +12,35 @@ import com.facebook.drawee.view.SimpleDraweeView;
public
class
RocketChatAvatar
extends
FrameLayout
{
private
SimpleDraweeView
draweeView
;
private
SimpleDraweeView
simpleDraweeViewAvatar
;
public
RocketChatAvatar
(
Context
context
)
{
super
(
context
);
initialize
(
context
,
null
);
initialize
(
context
);
}
public
RocketChatAvatar
(
Context
context
,
AttributeSet
attrs
)
{
super
(
context
,
attrs
);
initialize
(
context
,
attrs
);
initialize
(
context
);
}
public
RocketChatAvatar
(
Context
context
,
AttributeSet
attrs
,
int
defStyleAttr
)
{
super
(
context
,
attrs
,
defStyleAttr
);
initialize
(
context
,
attrs
);
initialize
(
context
);
}
@TargetApi
(
Build
.
VERSION_CODES
.
LOLLIPOP
)
public
RocketChatAvatar
(
Context
context
,
AttributeSet
attrs
,
int
defStyleAttr
,
int
defStyleRes
)
{
super
(
context
,
attrs
,
defStyleAttr
,
defStyleRes
);
initialize
(
context
,
attrs
);
initialize
(
context
);
}
private
void
initialize
(
Context
context
,
AttributeSet
attrs
)
{
LayoutInflater
.
from
(
context
)
.
inflate
(
R
.
layout
.
message_avatar
,
this
,
true
);
draweeView
=
findViewById
(
R
.
id
.
drawee_avatar
);
private
void
initialize
(
Context
context
)
{
LayoutInflater
.
from
(
context
).
inflate
(
R
.
layout
.
message_avatar
,
this
,
true
);
simpleDraweeViewAvatar
=
findViewById
(
R
.
id
.
drawee_avatar
);
}
public
void
loadImage
(
String
imageUri
)
{
FrescoHelper
.
loadImage
(
draweeView
,
imageUri
);
public
void
loadImage
(
String
imageUri
,
Drawable
placeholderDrawable
)
{
FrescoHelper
.
INSTANCE
.
loadImage
(
simpleDraweeViewAvatar
,
imageUri
,
placeholderDrawable
);
}
}
\ No newline at end of file
rocket-chat-android-widgets/src/main/java/chat/rocket/android/widget/RocketChatWidgets.java
View file @
52407887
...
...
@@ -3,7 +3,6 @@ package chat.rocket.android.widget;
import
android.content.Context
;
import
com.facebook.common.logging.FLog
;
import
com.facebook.drawee.backends.pipeline.DraweeConfig
;
import
com.facebook.drawee.backends.pipeline.Fresco
;
import
com.facebook.imagepipeline.backends.okhttp3.OkHttpImagePipelineConfigFactory
;
import
com.facebook.imagepipeline.core.ImagePipelineConfig
;
...
...
@@ -13,7 +12,6 @@ import com.facebook.imagepipeline.listener.RequestLoggingListener;
import
java.util.HashSet
;
import
java.util.Set
;
import
chat.rocket.android.widget.fresco.CustomImageFormatConfigurator
;
import
okhttp3.OkHttpClient
;
public
class
RocketChatWidgets
{
...
...
@@ -26,15 +24,11 @@ public class RocketChatWidgets {
ImagePipelineConfig
imagePipelineConfig
=
OkHttpImagePipelineConfigFactory
.
newBuilder
(
context
,
okHttpClient
)
.
setRequestListeners
(
listeners
)
.
setImageDecoderConfig
(
CustomImageFormatConfigurator
.
createImageDecoderConfig
())
.
setDownsampleEnabled
(
true
)
.
experiment
().
setBitmapPrepareToDraw
(
true
)
.
experiment
().
setPartialImageCachingEnabled
(
true
)
.
build
();
DraweeConfig
.
Builder
draweeConfigBuilder
=
DraweeConfig
.
newBuilder
();
CustomImageFormatConfigurator
.
addCustomDrawableFactories
(
draweeConfigBuilder
);
Fresco
.
initialize
(
context
,
imagePipelineConfig
,
draweeConfigBuilder
.
build
());
Fresco
.
initialize
(
context
,
imagePipelineConfig
);
}
}
\ No newline at end of file
rocket-chat-android-widgets/src/main/java/chat/rocket/android/widget/fresco/ColorImage.java
deleted
100644 → 0
View file @
260cb6c0
package
chat
.
rocket
.
android
.
widget
.
fresco
;
import
android.graphics.drawable.ColorDrawable
;
import
android.graphics.drawable.Drawable
;
import
android.support.annotation.ColorInt
;
import
android.support.v4.graphics.ColorUtils
;
import
com.facebook.common.internal.ByteStreams
;
import
com.facebook.imagepipeline.drawable.DrawableFactory
;
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.image.CloseableImage
;
import
com.facebook.imagepipeline.image.EncodedImage
;
import
com.facebook.imagepipeline.image.QualityInfo
;
import
java.io.IOException
;
import
javax.annotation.Nullable
;
/**
* 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/ColorImage.java
*/
class
ColorImage
{
/**
* XML color tag that our colors must start with.
*/
public
static
final
String
COLOR_TAG
=
"<color>"
;
/**
* Custom {@link ImageFormat} for color images.
*/
public
static
final
ImageFormat
IMAGE_FORMAT_COLOR
=
new
ImageFormat
(
"IMAGE_FORMAT_COLOR"
,
"color"
);
/**
* Create a new image format checker for {@link #IMAGE_FORMAT_COLOR}.
* @return the image format checker
*/
public
static
ImageFormat
.
FormatChecker
createFormatChecker
()
{
return
new
ColorFormatChecker
();
}
/**
* Create a new decoder that can decode {@link #IMAGE_FORMAT_COLOR} images.
* @return the decoder
*/
public
static
ImageDecoder
createDecoder
()
{
return
new
ColorDecoder
();
}
public
static
ColorDrawableFactory
createDrawableFactory
()
{
return
new
ColorDrawableFactory
();
}
/**
* Custom color format checker that verifies that the header of the file
* corresponds to our {@link #COLOR_TAG}.
*/
public
static
class
ColorFormatChecker
implements
ImageFormat
.
FormatChecker
{
public
static
final
byte
[]
HEADER
=
ImageFormatCheckerUtils
.
asciiBytes
(
COLOR_TAG
);
@Override
public
int
getHeaderSize
()
{
return
HEADER
.
length
;
}
@Nullable
@Override
public
ImageFormat
determineFormat
(
byte
[]
headerBytes
,
int
headerSize
)
{
if
(
headerSize
<
getHeaderSize
())
{
return
null
;
}
if
(
ImageFormatCheckerUtils
.
startsWithPattern
(
headerBytes
,
HEADER
))
{
return
IMAGE_FORMAT_COLOR
;
}
return
null
;
}
}
/**
* Custom closeable color image that holds a single color int value.
*/
public
static
class
CloseableColorImage
extends
CloseableImage
{
@ColorInt
private
final
int
mColor
;
private
boolean
mClosed
=
false
;
public
CloseableColorImage
(
int
color
)
{
mColor
=
color
;
}
@ColorInt
public
int
getColor
()
{
return
mColor
;
}
@Override
public
int
getSizeInBytes
()
{
return
0
;
}
@Override
public
void
close
()
{
mClosed
=
true
;
}
@Override
public
boolean
isClosed
()
{
return
mClosed
;
}
@Override
public
int
getWidth
()
{
return
0
;
}
@Override
public
int
getHeight
()
{
return
0
;
}
}
/**
* Decodes a color XML tag: <color>#rrggbb</color>
*/
public
static
class
ColorDecoder
implements
ImageDecoder
{
@Override
public
CloseableImage
decode
(
EncodedImage
encodedImage
,
int
length
,
QualityInfo
qualityInfo
,
ImageDecodeOptions
options
)
{
try
{
// Read the file as a string
String
text
=
new
String
(
ByteStreams
.
toByteArray
(
encodedImage
.
getInputStream
()));
// Check if the string matches "<color>#"
if
(!
text
.
startsWith
(
COLOR_TAG
+
"#"
))
{
return
null
;
}
// Parse the int value between # and <
int
startIndex
=
COLOR_TAG
.
length
()
+
1
;
int
endIndex
=
text
.
lastIndexOf
(
'<'
);
int
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
new
CloseableColorImage
(
color
);
}
catch
(
IOException
e
)
{
e
.
printStackTrace
();
}
// Return nothing if an error occurred
return
null
;
}
}
/**
* Color drawable factory that is able to render a {@link CloseableColorImage} by creating
* a new {@link ColorDrawable} for the given color.
*/
public
static
class
ColorDrawableFactory
implements
DrawableFactory
{
@Override
public
boolean
supportsImageType
(
CloseableImage
image
)
{
// We can only handle CloseableColorImages
return
image
instanceof
CloseableColorImage
;
}
@Nullable
@Override
public
Drawable
createDrawable
(
CloseableImage
image
)
{
// Just return a simple ColorDrawable with the given color value
return
new
ColorDrawable
(((
CloseableColorImage
)
image
).
getColor
());
}
}
}
rocket-chat-android-widgets/src/main/java/chat/rocket/android/widget/fresco/CustomImageFormatConfigurator.java
deleted
100644 → 0
View file @
260cb6c0
package
chat
.
rocket
.
android
.
widget
.
fresco
;
import
android.support.annotation.Nullable
;
import
com.facebook.drawee.backends.pipeline.DraweeConfig
;
import
com.facebook.imagepipeline.decoder.ImageDecoderConfig
;
/**
* Helper 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
*/
public
class
CustomImageFormatConfigurator
{
@Nullable
public
static
ImageDecoderConfig
createImageDecoderConfig
()
{
ImageDecoderConfig
.
Builder
config
=
ImageDecoderConfig
.
newBuilder
();
config
.
addDecodingCapability
(
SvgDecoder
.
SVG_FORMAT
,
new
SvgDecoder
.
SvgFormatChecker
(),
new
SvgDecoder
.
Decoder
());
return
config
.
build
();
}
public
static
void
addCustomDrawableFactories
(
DraweeConfig
.
Builder
draweeConfigBuilder
)
{
draweeConfigBuilder
.
addCustomDrawableFactory
(
ColorImage
.
createDrawableFactory
());
draweeConfigBuilder
.
addCustomDrawableFactory
(
new
SvgDecoder
.
SvgDrawableFactory
());
}
}
\ No newline at end of file
rocket-chat-android-widgets/src/main/java/chat/rocket/android/widget/fresco/SvgDecoder.java
deleted
100644 → 0
View file @
260cb6c0
package
chat
.
rocket
.
android
.
widget
.
fresco
;
import
android.graphics.Rect
;
import
android.graphics.drawable.Drawable
;
import
android.graphics.drawable.PictureDrawable
;
import
com.caverock.androidsvg.SVG
;
import
com.caverock.androidsvg.SVGParseException
;
import
com.facebook.imagepipeline.drawable.DrawableFactory
;
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.image.CloseableImage
;
import
com.facebook.imagepipeline.image.EncodedImage
;
import
com.facebook.imagepipeline.image.QualityInfo
;
import
javax.annotation.Nullable
;
/**
* 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
*/
public
class
SvgDecoder
{
public
static
final
ImageFormat
SVG_FORMAT
=
new
ImageFormat
(
"SVG_FORMAT"
,
"svg"
);
// We do not include the closing ">" since there can be additional information
private
static
final
String
HEADER_TAG
=
"<?xml"
;
public
static
class
SvgFormatChecker
implements
ImageFormat
.
FormatChecker
{
public
static
final
byte
[]
HEADER
=
ImageFormatCheckerUtils
.
asciiBytes
(
HEADER_TAG
);
@Override
public
int
getHeaderSize
()
{
return
HEADER
.
length
;
}
@Nullable
@Override
public
ImageFormat
determineFormat
(
byte
[]
headerBytes
,
int
headerSize
)
{
if
(
headerSize
<
getHeaderSize
())
{
return
null
;
}
if
(
ImageFormatCheckerUtils
.
startsWithPattern
(
headerBytes
,
HEADER
))
{
return
SVG_FORMAT
;
}
return
null
;
}
}
public
static
class
CloseableSvgImage
extends
CloseableImage
{
private
final
SVG
mSvg
;
private
boolean
mClosed
=
false
;
public
CloseableSvgImage
(
SVG
svg
)
{
mSvg
=
svg
;
}
public
SVG
getSvg
()
{
return
mSvg
;
}
@Override
public
int
getSizeInBytes
()
{
return
0
;
}
@Override
public
void
close
()
{
mClosed
=
true
;
}
@Override
public
boolean
isClosed
()
{
return
mClosed
;
}
@Override
public
int
getWidth
()
{
return
0
;
}
@Override
public
int
getHeight
()
{
return
0
;
}
}
/**
* Decodes a SVG_FORMAT image
*/
public
static
class
Decoder
implements
ImageDecoder
{
@Override
public
CloseableImage
decode
(
EncodedImage
encodedImage
,
int
length
,
QualityInfo
qualityInfo
,
ImageDecodeOptions
options
)
{
try
{
SVG
svg
=
SVG
.
getFromInputStream
(
encodedImage
.
getInputStream
());
return
new
CloseableSvgImage
(
svg
);
}
catch
(
SVGParseException
e
)
{
e
.
printStackTrace
();
}
return
null
;
}
}
/**
* SVG drawable factory that creates {@link PictureDrawable}s for SVG images.
*/
public
static
class
SvgDrawableFactory
implements
DrawableFactory
{
@Override
public
boolean
supportsImageType
(
CloseableImage
image
)
{
return
image
instanceof
CloseableSvgImage
;
}
@Nullable
@Override
public
Drawable
createDrawable
(
CloseableImage
image
)
{
return
new
SvgPictureDrawable
(((
CloseableSvgImage
)
image
).
getSvg
());
}
}
public
static
class
SvgPictureDrawable
extends
PictureDrawable
{
private
final
SVG
mSvg
;
public
SvgPictureDrawable
(
SVG
svg
)
{
super
(
null
);
mSvg
=
svg
;
}
@Override
protected
void
onBoundsChange
(
Rect
bounds
)
{
super
.
onBoundsChange
(
bounds
);
setPicture
(
mSvg
.
renderToPicture
(
bounds
.
width
(),
bounds
.
height
()));
}
}
}
\ No newline at end of file
rocket-chat-android-widgets/src/main/java/chat/rocket/android/widget/helper/FrescoHelper.kt
View file @
52407887
package
chat.rocket.android.widget.helper
import
android.graphics.drawable.Drawable
import
android.net.Uri
import
android.support.graphics.drawable.VectorDrawableCompat
import
chat.rocket.android.widget.R
...
...
@@ -8,36 +9,36 @@ import com.facebook.drawee.drawable.ProgressBarDrawable
import
com.facebook.drawee.generic.GenericDraweeHierarchy
import
com.facebook.drawee.view.SimpleDraweeView
class
FrescoHelper
{
companion
object
{
@JvmStatic
fun
loadImage
(
draweeView
:
SimpleDraweeView
,
imageUri
:
String
)
{
draweeView
.
setImageURI
(
imageUri
)
}
object
FrescoHelper
{
/** TODO
* Replace with:
* @JvmStatic fun loadImageWithCustomization(draweeView: SimpleDraweeView,
* imageUri: String,
* placeholderImageDrawableId : Int = R.drawable.image_dummy,
failureImageDrawableId: Int = R.drawable.image_error) {
* [...]
* }
* It is need to convert java files which uses loadImageWithCustomization(...) method to use the above method signature.
* See: https://kotlinlang.org/docs/reference/functions.html#default-arguments.
*/
@JvmStatic
fun
loadImageWithCustomization
(
draweeView
:
SimpleDraweeView
,
imageUri
:
String
)
{
val
hierarchy
:
GenericDraweeHierarchy
=
draweeView
.
hierarchy
hierarchy
.
setPlaceholderImage
(
VectorDrawableCompat
.
create
(
draweeView
.
resources
,
R
.
drawable
.
image_dummy
,
null
))
hierarchy
.
setFailureImage
(
VectorDrawableCompat
.
create
(
draweeView
.
resources
,
R
.
drawable
.
image_error
,
null
))
hierarchy
.
setProgressBarImage
(
ProgressBarDrawable
())
fun
loadImage
(
simpleDraweeView
:
SimpleDraweeView
,
imageUri
:
String
,
placeholderDrawable
:
Drawable
)
{
simpleDraweeView
.
hierarchy
.
setPlaceholderImage
(
placeholderDrawable
)
simpleDraweeView
.
controller
=
Fresco
.
newDraweeControllerBuilder
().
setUri
(
imageUri
).
setAutoPlayAnimations
(
true
).
build
()
}
/** TODO
* Replace with:
* fun loadImageWithCustomization(draweeView: SimpleDraweeView,
* imageUri: String,
* placeholderImageDrawableId : Int = R.drawable.image_dummy,
* failureImageDrawableId: Int = R.drawable.image_error) {
* [...]
* }
* It is need to convert java files which uses loadImageWithCustomization(...) method to use the above method signature.
* See: https://kotlinlang.org/docs/reference/functions.html#default-arguments.
*/
fun
loadImageWithCustomization
(
draweeView
:
SimpleDraweeView
,
imageUri
:
String
)
{
val
hierarchy
:
GenericDraweeHierarchy
=
draweeView
.
hierarchy
hierarchy
.
setPlaceholderImage
(
VectorDrawableCompat
.
create
(
draweeView
.
resources
,
R
.
drawable
.
image_dummy
,
null
))
hierarchy
.
setFailureImage
(
VectorDrawableCompat
.
create
(
draweeView
.
resources
,
R
.
drawable
.
image_error
,
null
))
hierarchy
.
setProgressBarImage
(
ProgressBarDrawable
())
val
controller
=
Fresco
.
newDraweeControllerBuilder
()
.
setUri
(
Uri
.
parse
(
imageUri
))
.
setAutoPlayAnimations
(
true
)
.
setTapToRetryEnabled
(
true
)
.
build
()
val
controller
=
Fresco
.
newDraweeControllerBuilder
()
.
setUri
(
Uri
.
parse
(
imageUri
))
.
setAutoPlayAnimations
(
true
)
.
setTapToRetryEnabled
(
true
)
.
build
()
draweeView
.
controller
=
controller
}
draweeView
.
controller
=
controller
}
}
\ No newline at end of file
rocket-chat-android-widgets/src/main/java/chat/rocket/android/widget/helper/UserAvatarHelper.kt
0 → 100644
View file @
52407887
package
chat.rocket.android.widget.helper
import
android.content.Context
import
android.graphics.Typeface
import
android.graphics.drawable.Drawable
import
chat.rocket.android.widget.AbsoluteUrl
import
com.amulyakhare.textdrawable.TextDrawable
import
java.net.URLEncoder
object
UserAvatarHelper
{
/**
* Returns the user avatar URI.
*
* REMARK: This is often a SVG image (Rocket.Chat:server/startup/avatar.js).
*
* @param hostname The server's hostname.
* @param username The username.
* @return The user avatar URI.
*/
fun
getUri
(
hostname
:
String
,
username
:
String
):
String
{
return
"https://"
+
hostname
.
replace
(
"http://"
,
""
).
replace
(
"https://"
,
""
)
+
"/avatar/"
+
URLEncoder
.
encode
(
username
,
"UTF-8"
)
}
/**
* Returns the user avatar absolute URI.
*
* REMARK: This is often a SVG image (Rocket.Chat:server/startup/avatar.js).
*
* @param absoluteUrl The AbsoluteUrl.
* @param username The username.
* @return The user avatar absolute URI.
*/
fun
getAbsoluteUri
(
absoluteUrl
:
AbsoluteUrl
,
username
:
String
):
String
{
val
avatarUri
=
"/avatar/"
+
URLEncoder
.
encode
(
username
,
"UTF-8"
)
return
absoluteUrl
.
from
(
avatarUri
)
}
/**
* Returns a drawable with username initials.
*
* @param username The username.
* @param context The context.
* @return A drawable with username initials.
* @see getUsernameInitials
*/
fun
getTextDrawable
(
username
:
String
,
context
:
Context
):
Drawable
{
val
round
=
(
4
*
context
.
resources
.
displayMetrics
.
density
).
toInt
()
return
TextDrawable
.
builder
()
.
beginConfig
()
.
useFont
(
Typeface
.
SANS_SERIF
)
.
endConfig
()
.
buildRoundRect
(
getUsernameInitials
(
username
),
getUserAvatarBackgroundColor
(
username
),
round
)
}
/**
* Returns a string with the username initials. For example: username John.Doe returns JD initials.
*
* @param username The username.
* @return A string with username initials.
*/
fun
getUsernameInitials
(
username
:
String
):
String
{
if
(
username
.
isEmpty
())
{
return
"?"
}
val
splitUsername
=
username
.
split
(
"."
)
if
(
splitUsername
.
size
>
1
)
{
return
(
splitUsername
[
0
].
substring
(
0
,
1
)
+
splitUsername
[
splitUsername
.
size
-
1
].
substring
(
0
,
1
)).
toUpperCase
()
}
else
{
if
(
username
.
length
>
1
)
{
return
username
.
substring
(
0
,
2
).
toUpperCase
()
}
else
{
return
username
.
substring
(
0
,
1
).
toUpperCase
()
}
}
}
/**
* Returns a background color to be rendered on the user avatar (Rocket.Chat:server/startup/avatar.js).
*
* @param username The username.
* @return A hexadecimal color.
*/
fun
getUserAvatarBackgroundColor
(
username
:
String
):
Int
{
return
COLORS
[
username
.
length
%
COLORS
.
size
]
}
private
val
COLORS
=
intArrayOf
(
0
xFFF44336
.
toInt
(),
0
xFFE91E63
.
toInt
(),
0
xFF9C27B0
.
toInt
(),
0
xFF673AB7
.
toInt
(),
0
xFF3F51B5
.
toInt
(),
0
xFF2196F3
.
toInt
(),
0
xFF03A9F4
.
toInt
(),
0
xFF00BCD4
.
toInt
(),
0
xFF009688
.
toInt
(),
0
xFF4CAF50
.
toInt
(),
0
xFF8BC34A
.
toInt
(),
0
xFFCDDC39
.
toInt
(),
0
xFFFFC107
.
toInt
(),
0
xFFFF9800
.
toInt
(),
0
xFFFF5722
.
toInt
(),
0
xFF795548
.
toInt
(),
0
xFF9E9E9E
.
toInt
(),
0
xFF607D8B
.
toInt
())
}
\ No newline at end of file
rocket-chat-android-widgets/src/main/java/chat/rocket/android/widget/message/RocketChatMessageAttachmentsLayout.java
View file @
52407887
...
...
@@ -119,8 +119,7 @@ public class RocketChatMessageAttachmentsLayout extends LinearLayout {
authorBox
.
setVisibility
(
VISIBLE
);
FrescoHelper
.
loadImageWithCustomization
((
SimpleDraweeView
)
attachmentView
.
findViewById
(
R
.
id
.
author_icon
),
absolutize
(
author
.
getIconUrl
()));
FrescoHelper
.
INSTANCE
.
loadImageWithCustomization
((
SimpleDraweeView
)
attachmentView
.
findViewById
(
R
.
id
.
author_icon
),
absolutize
(
author
.
getIconUrl
()));
final
TextView
authorName
=
(
TextView
)
attachmentView
.
findViewById
(
R
.
id
.
author_name
);
authorName
.
setText
(
author
.
getName
());
...
...
@@ -187,8 +186,7 @@ public class RocketChatMessageAttachmentsLayout extends LinearLayout {
thumbImage
.
setVisibility
(
GONE
);
}
else
{
thumbImage
.
setVisibility
(
VISIBLE
);
FrescoHelper
.
loadImageWithCustomization
(
thumbImage
,
absolutize
(
thumbUrl
));
FrescoHelper
.
INSTANCE
.
loadImageWithCustomization
(
thumbImage
,
absolutize
(
thumbUrl
));
}
final
TextView
refText
=
(
TextView
)
refBox
.
findViewById
(
R
.
id
.
text
);
...
...
@@ -253,8 +251,7 @@ public class RocketChatMessageAttachmentsLayout extends LinearLayout {
boolean
autoloadImage
)
{
if
(
autoloadImage
)
{
load
.
setVisibility
(
GONE
);
FrescoHelper
.
loadImageWithCustomization
(
drawee
,
url
);
FrescoHelper
.
INSTANCE
.
loadImageWithCustomization
(
drawee
,
url
);
return
;
}
...
...
@@ -263,8 +260,7 @@ public class RocketChatMessageAttachmentsLayout extends LinearLayout {
public
void
onClick
(
View
v
)
{
load
.
setVisibility
(
GONE
);
load
.
setOnClickListener
(
null
);
FrescoHelper
.
loadImageWithCustomization
(
drawee
,
url
);
FrescoHelper
.
INSTANCE
.
loadImageWithCustomization
(
drawee
,
url
);
}
});
}
...
...
rocket-chat-android-widgets/src/main/java/chat/rocket/android/widget/message/RocketChatMessageUrlsLayout.java
View file @
52407887
...
...
@@ -95,8 +95,7 @@ public class RocketChatMessageUrlsLayout extends LinearLayout {
if
(
TextUtils
.
isEmpty
(
imageURL
))
{
image
.
setVisibility
(
View
.
GONE
);
}
else
{
FrescoHelper
.
loadImageWithCustomization
(
image
,
imageURL
);
FrescoHelper
.
INSTANCE
.
loadImageWithCustomization
(
image
,
imageURL
);
image
.
setVisibility
(
View
.
VISIBLE
);
}
...
...
@@ -144,8 +143,7 @@ public class RocketChatMessageUrlsLayout extends LinearLayout {
boolean
autoloadImage
)
{
if
(
autoloadImage
)
{
load
.
setVisibility
(
GONE
);
FrescoHelper
.
loadImageWithCustomization
(
drawee
,
url
);
FrescoHelper
.
INSTANCE
.
loadImageWithCustomization
(
drawee
,
url
);
return
;
}
...
...
@@ -154,8 +152,7 @@ public class RocketChatMessageUrlsLayout extends LinearLayout {
public
void
onClick
(
View
v
)
{
load
.
setVisibility
(
GONE
);
load
.
setOnClickListener
(
null
);
FrescoHelper
.
loadImageWithCustomization
(
drawee
,
url
);
FrescoHelper
.
INSTANCE
.
loadImageWithCustomization
(
drawee
,
url
);
}
});
}
...
...
rocket-chat-android-widgets/src/main/java/chat/rocket/android/widget/message/autocomplete/user/UserViewHolder.java
View file @
52407887
package
chat
.
rocket
.
android
.
widget
.
message
.
autocomplete
.
user
;
import
android.graphics.drawable.Drawable
;
import
android.view.View
;
import
android.widget.ImageView
;
import
android.widget.TextView
;
import
chat.rocket.android.widget.AbsoluteUrl
;
import
chat.rocket.android.widget.R
;
import
chat.rocket.android.widget.RocketChatAvatar
;
import
chat.rocket.android.widget.helper.UserAvatarHelper
;
import
chat.rocket.android.widget.message.autocomplete.AutocompleteViewHolder
;
import
java.io.UnsupportedEncodingException
;
import
java.net.URLEncoder
;
public
class
UserViewHolder
extends
AutocompleteViewHolder
<
UserItem
>
{
private
final
TextView
titleTextView
;
private
final
RocketChatAvatar
avatar
;
private
final
ImageView
status
;
...
...
@@ -44,7 +45,9 @@ public class UserViewHolder extends AutocompleteViewHolder<UserItem> {
}
if
(
avatar
!=
null
)
{
avatar
.
loadImage
(
getImageUrl
(
suggestion
,
userItem
.
getAbsoluteUrl
()));
String
absoluteUri
=
UserAvatarHelper
.
INSTANCE
.
getAbsoluteUri
(
userItem
.
getAbsoluteUrl
(),
suggestion
);
Drawable
placeholderDrawable
=
UserAvatarHelper
.
INSTANCE
.
getTextDrawable
(
suggestion
,
itemView
.
getContext
());
avatar
.
loadImage
(
absoluteUri
,
placeholderDrawable
);
}
if
(
status
!=
null
)
{
...
...
@@ -58,19 +61,4 @@ public class UserViewHolder extends AutocompleteViewHolder<UserItem> {
avatar
.
setVisibility
(
View
.
GONE
);
titleTextView
.
setText
(
R
.
string
.
no_user_found
);
}
private
String
getImageUrl
(
String
username
,
AbsoluteUrl
absoluteUrl
)
{
//from Rocket.Chat:packages/rocketchat-ui/lib/avatar.coffee
//REMARK! this is often SVG image! (see: Rocket.Chat:server/startup/avatar.coffee)
try
{
final
String
avatarUrl
=
"/avatar/"
+
URLEncoder
.
encode
(
username
,
"UTF-8"
);
// TODO why absoluteUrl is nullable? By allowing that, the app tries to load non-existing images
if
(
absoluteUrl
==
null
)
{
return
avatarUrl
;
}
return
absoluteUrl
.
from
(
avatarUrl
);
}
catch
(
UnsupportedEncodingException
exception
)
{
return
null
;
}
}
}
\ No newline at end of file
rocket-chat-android-widgets/src/main/res/layout/message_avatar.xml
View file @
52407887
<?xml version="1.0" encoding="utf-8"?>
<com.facebook.drawee.view.SimpleDraweeView
xmlns:android=
"http://schemas.android.com/apk/res/android"
xmlns:fresco=
"http://schemas.android.com/apk/res-auto"
android:id=
"@+id/drawee_avatar"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
fresco:actualImageScaleType=
"fitCenter"
fresco:roundedCornerRadius=
"5dp"
/>
\ No newline at end of file
xmlns:fresco=
"http://schemas.android.com/apk/res-auto"
android:id=
"@+id/drawee_avatar"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
fresco:actualImageScaleType=
"fitXY"
fresco:roundedCornerRadius=
"5dp"
/>
\ No newline at end of file
rocket-chat-android-widgets/src/test/kotlin/chat/rocket/android/widget/helper/UserAvatarHelperTest.kt
0 → 100644
View file @
52407887
import
chat.rocket.android.widget.helper.UserAvatarHelper
import
org.junit.Test
class
UserAvatarHelperTest
{
@Test
fun
getUsernameInitialsTest
()
{
assert
(
UserAvatarHelper
.
getUsernameInitials
(
""
)
==
"?"
)
assert
(
UserAvatarHelper
.
getUsernameInitials
(
"?"
)
==
"?"
)
assert
(
UserAvatarHelper
.
getUsernameInitials
(
"f"
)
==
"F"
)
assert
(
UserAvatarHelper
.
getUsernameInitials
(
"B"
)
==
"B"
)
assert
(
UserAvatarHelper
.
getUsernameInitials
(
"fo"
)
==
"FO"
)
assert
(
UserAvatarHelper
.
getUsernameInitials
(
"FO"
)
==
"FO"
)
assert
(
UserAvatarHelper
.
getUsernameInitials
(
"fOo"
)
==
"FO"
)
assert
(
UserAvatarHelper
.
getUsernameInitials
(
"FOO"
)
==
"FO"
)
assert
(
UserAvatarHelper
.
getUsernameInitials
(
"F.O"
)
==
"FO"
)
assert
(
UserAvatarHelper
.
getUsernameInitials
(
"F.o"
)
==
"FO"
)
assert
(
UserAvatarHelper
.
getUsernameInitials
(
"Foo.bar"
)
==
"FB"
)
assert
(
UserAvatarHelper
.
getUsernameInitials
(
"Foobar.bar"
)
==
"FB"
)
assert
(
UserAvatarHelper
.
getUsernameInitials
(
"Foobar.bar.zab"
)
==
"FZ"
)
}
}
\ No newline at end of file
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment