Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
What's new
10
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Open sidebar
briar
briar
Commits
87377666
Commit
87377666
authored
Dec 13, 2018
by
Torsten Grote
1
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch '1473-display-multiple-images' into 'master'
UX for displaying multiple image attachments Closes
#1473
See merge request
!1010
parents
5c312b49
9d07b2e1
Pipeline
#2897
passed with stage
in 15 minutes and 21 seconds
Changes
22
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
22 changed files
with
609 additions
and
143 deletions
+609
-143
briar-android/src/main/java/org/briarproject/briar/android/conversation/AttachmentController.java
...ject/briar/android/conversation/AttachmentController.java
+25
-7
briar-android/src/main/java/org/briarproject/briar/android/conversation/ConversationActivity.java
...ject/briar/android/conversation/ConversationActivity.java
+2
-2
briar-android/src/main/java/org/briarproject/briar/android/conversation/ConversationAdapter.java
...oject/briar/android/conversation/ConversationAdapter.java
+15
-6
briar-android/src/main/java/org/briarproject/briar/android/conversation/ConversationItemViewHolder.java
...riar/android/conversation/ConversationItemViewHolder.java
+5
-2
briar-android/src/main/java/org/briarproject/briar/android/conversation/ConversationMessageViewHolder.java
...r/android/conversation/ConversationMessageViewHolder.java
+42
-90
briar-android/src/main/java/org/briarproject/briar/android/conversation/ConversationNoticeViewHolder.java
...ar/android/conversation/ConversationNoticeViewHolder.java
+5
-4
briar-android/src/main/java/org/briarproject/briar/android/conversation/ConversationRequestViewHolder.java
...r/android/conversation/ConversationRequestViewHolder.java
+5
-4
briar-android/src/main/java/org/briarproject/briar/android/conversation/ConversationViewModel.java
...ect/briar/android/conversation/ConversationViewModel.java
+5
-3
briar-android/src/main/java/org/briarproject/briar/android/conversation/ImageAdapter.java
...briarproject/briar/android/conversation/ImageAdapter.java
+155
-0
briar-android/src/main/java/org/briarproject/briar/android/conversation/ImageItemDecoration.java
...oject/briar/android/conversation/ImageItemDecoration.java
+54
-0
briar-android/src/main/java/org/briarproject/briar/android/conversation/ImageViewHolder.java
...arproject/briar/android/conversation/ImageViewHolder.java
+70
-0
briar-android/src/main/java/org/briarproject/briar/android/conversation/ImageViewModel.java
...iarproject/briar/android/conversation/ImageViewModel.java
+2
-2
briar-android/src/main/java/org/briarproject/briar/android/conversation/glide/BriarImageTransformation.java
.../android/conversation/glide/BriarImageTransformation.java
+2
-4
briar-android/src/main/java/org/briarproject/briar/android/conversation/glide/CustomCornersTransformation.java
...droid/conversation/glide/CustomCornersTransformation.java
+128
-0
briar-android/src/main/java/org/briarproject/briar/android/conversation/glide/Radii.java
.../briarproject/briar/android/conversation/glide/Radii.java
+41
-0
briar-android/src/main/java/org/briarproject/briar/android/util/UiUtils.java
...ain/java/org/briarproject/briar/android/util/UiUtils.java
+7
-0
briar-android/src/main/res/layout/list_item_conversation_msg_image.xml
.../src/main/res/layout/list_item_conversation_msg_image.xml
+10
-6
briar-android/src/main/res/layout/list_item_conversation_msg_image_text.xml
...main/res/layout/list_item_conversation_msg_image_text.xml
+9
-5
briar-android/src/main/res/layout/list_item_conversation_msg_in.xml
...oid/src/main/res/layout/list_item_conversation_msg_in.xml
+9
-4
briar-android/src/main/res/layout/list_item_conversation_msg_out.xml
...id/src/main/res/layout/list_item_conversation_msg_out.xml
+7
-3
briar-android/src/main/res/layout/list_item_image.xml
briar-android/src/main/res/layout/list_item_image.xml
+10
-0
briar-android/src/main/res/values/dimens.xml
briar-android/src/main/res/values/dimens.xml
+1
-1
No files found.
briar-android/src/main/java/org/briarproject/briar/android/conversation/AttachmentController.java
View file @
87377666
...
...
@@ -98,10 +98,11 @@ class AttachmentController {
*/
List
<
AttachmentItem
>
getAttachmentItems
(
List
<
Pair
<
AttachmentHeader
,
Attachment
>>
attachments
)
{
boolean
needsSize
=
attachments
.
size
()
==
1
;
List
<
AttachmentItem
>
items
=
new
ArrayList
<>(
attachments
.
size
());
for
(
Pair
<
AttachmentHeader
,
Attachment
>
a
:
attachments
)
{
AttachmentItem
item
=
getAttachmentItem
(
a
.
getFirst
(),
a
.
getSecond
());
getAttachmentItem
(
a
.
getFirst
(),
a
.
getSecond
()
,
needsSize
);
items
.
add
(
item
);
}
return
items
;
...
...
@@ -111,10 +112,22 @@ class AttachmentController {
* Creates an {@link AttachmentItem} from the {@link Attachment}'s
* {@link InputStream} which will be closed when this method returns.
*/
AttachmentItem
getAttachmentItem
(
AttachmentHeader
h
,
Attachment
a
)
{
AttachmentItem
getAttachmentItem
(
AttachmentHeader
h
,
Attachment
a
,
boolean
needsSize
)
{
MessageId
messageId
=
h
.
getMessageId
();
Size
size
=
new
Size
();
if
(!
needsSize
)
{
String
mimeType
=
h
.
getContentType
();
String
extension
=
getExtensionFromMimeType
(
mimeType
);
boolean
hasError
=
false
;
if
(
extension
==
null
)
{
extension
=
""
;
hasError
=
true
;
}
return
new
AttachmentItem
(
messageId
,
0
,
0
,
mimeType
,
extension
,
0
,
0
,
hasError
);
}
Size
size
=
new
Size
();
InputStream
is
=
new
BufferedInputStream
(
a
.
getStream
());
is
.
mark
(
Integer
.
MAX_VALUE
);
try
{
...
...
@@ -144,14 +157,19 @@ class AttachmentController {
getThumbnailSize
(
size
.
width
,
size
.
height
,
size
.
mimeType
);
}
// get file extension
MimeTypeMap
mimeTypeMap
=
MimeTypeMap
.
getSingleton
();
String
extension
=
mimeTypeMap
.
getExtensionFromMimeType
(
size
.
mimeType
);
String
extension
=
getExtensionFromMimeType
(
size
.
mimeType
);
if
(
extension
==
null
)
{
return
new
AttachmentItem
(
messageId
,
0
,
0
,
""
,
""
,
0
,
0
,
true
);
}
return
new
AttachmentItem
(
messageId
,
size
.
width
,
size
.
height
,
size
.
mimeType
,
extension
,
thumbnailSize
.
width
,
thumbnailSize
.
height
,
size
.
error
);
size
.
mimeType
,
extension
,
thumbnailSize
.
width
,
thumbnailSize
.
height
,
size
.
error
);
}
@Nullable
private
String
getExtensionFromMimeType
(
String
mimeType
)
{
MimeTypeMap
mimeTypeMap
=
MimeTypeMap
.
getSingleton
();
return
mimeTypeMap
.
getExtensionFromMimeType
(
mimeType
);
}
/**
...
...
briar-android/src/main/java/org/briarproject/briar/android/conversation/ConversationActivity.java
View file @
87377666
...
...
@@ -394,7 +394,7 @@ public class ConversationActivity extends BriarActivity
textCache
.
put
(
id
,
text
);
}
}
if
(
!
h
.
getAttachmentHeaders
().
isEmpty
()
)
{
if
(
h
.
getAttachmentHeaders
().
size
()
==
1
)
{
List
<
AttachmentItem
>
items
=
attachmentController
.
get
(
id
);
if
(
items
==
null
)
{
...
...
@@ -483,7 +483,7 @@ public class ConversationActivity extends BriarActivity
try
{
List
<
Pair
<
AttachmentHeader
,
Attachment
>>
attachments
=
attachmentController
.
getMessageAttachments
(
headers
);
// TODO move getting the items off to
the
IoExecutor
// TODO move getting the items off to IoExecutor
, if size == 1
List
<
AttachmentItem
>
items
=
attachmentController
.
getAttachmentItems
(
attachments
);
displayMessageAttachments
(
messageId
,
items
);
...
...
briar-android/src/main/java/org/briarproject/briar/android/conversation/ConversationAdapter.java
View file @
87377666
...
...
@@ -3,6 +3,7 @@ package org.briarproject.briar.android.conversation;
import
android.content.Context
;
import
android.support.annotation.LayoutRes
;
import
android.support.v7.widget.LinearLayoutManager
;
import
android.support.v7.widget.RecyclerView.RecycledViewPool
;
import
android.util.SparseArray
;
import
android.view.LayoutInflater
;
import
android.view.View
;
...
...
@@ -21,11 +22,17 @@ class ConversationAdapter
extends
BriarAdapter
<
ConversationItem
,
ConversationItemViewHolder
>
{
private
ConversationListener
listener
;
private
final
RecycledViewPool
imageViewPool
;
private
final
ImageItemDecoration
imageItemDecoration
;
ConversationAdapter
(
Context
ctx
,
ConversationListener
conversationListener
)
{
super
(
ctx
,
ConversationItem
.
class
);
listener
=
conversationListener
;
// This shares the same pool for view recycling between all image lists
imageViewPool
=
new
RecycledViewPool
();
// Share the item decoration as well
imageItemDecoration
=
new
ImageItemDecoration
(
ctx
);
}
@LayoutRes
...
...
@@ -42,15 +49,17 @@ class ConversationAdapter
type
,
viewGroup
,
false
);
switch
(
type
)
{
case
R
.
layout
.
list_item_conversation_msg_in
:
return
new
ConversationMessageViewHolder
(
v
,
true
);
return
new
ConversationMessageViewHolder
(
v
,
listener
,
true
,
imageViewPool
,
imageItemDecoration
);
case
R
.
layout
.
list_item_conversation_msg_out
:
return
new
ConversationMessageViewHolder
(
v
,
false
);
return
new
ConversationMessageViewHolder
(
v
,
listener
,
false
,
imageViewPool
,
imageItemDecoration
);
case
R
.
layout
.
list_item_conversation_notice_in
:
return
new
ConversationNoticeViewHolder
(
v
,
true
);
return
new
ConversationNoticeViewHolder
(
v
,
listener
,
true
);
case
R
.
layout
.
list_item_conversation_notice_out
:
return
new
ConversationNoticeViewHolder
(
v
,
false
);
return
new
ConversationNoticeViewHolder
(
v
,
listener
,
false
);
case
R
.
layout
.
list_item_conversation_request
:
return
new
ConversationRequestViewHolder
(
v
,
true
);
return
new
ConversationRequestViewHolder
(
v
,
listener
,
true
);
default
:
throw
new
IllegalArgumentException
(
"Unknown ConversationItem"
);
}
...
...
@@ -59,7 +68,7 @@ class ConversationAdapter
@Override
public
void
onBindViewHolder
(
ConversationItemViewHolder
ui
,
int
position
)
{
ConversationItem
item
=
items
.
get
(
position
);
ui
.
bind
(
item
,
listener
);
ui
.
bind
(
item
);
listener
.
onItemVisible
(
item
);
}
...
...
briar-android/src/main/java/org/briarproject/briar/android/conversation/ConversationItemViewHolder.java
View file @
87377666
...
...
@@ -18,14 +18,17 @@ import static org.briarproject.briar.android.util.UiUtils.formatDate;
@NotNullByDefault
abstract
class
ConversationItemViewHolder
extends
ViewHolder
{
protected
final
ConversationListener
listener
;
protected
final
ConstraintLayout
layout
;
@Nullable
private
final
OutItemViewHolder
outViewHolder
;
private
final
TextView
text
;
protected
final
TextView
time
;
ConversationItemViewHolder
(
View
v
,
boolean
isIncoming
)
{
ConversationItemViewHolder
(
View
v
,
ConversationListener
listener
,
boolean
isIncoming
)
{
super
(
v
);
this
.
listener
=
listener
;
this
.
outViewHolder
=
isIncoming
?
null
:
new
OutItemViewHolder
(
v
);
layout
=
v
.
findViewById
(
R
.
id
.
layout
);
text
=
v
.
findViewById
(
R
.
id
.
text
);
...
...
@@ -33,7 +36,7 @@ abstract class ConversationItemViewHolder extends ViewHolder {
}
@CallSuper
void
bind
(
ConversationItem
item
,
ConversationListener
listener
)
{
void
bind
(
ConversationItem
item
)
{
if
(
item
.
getText
()
!=
null
)
{
text
.
setText
(
trim
(
item
.
getText
()));
}
...
...
briar-android/src/main/java/org/briarproject/briar/android/conversation/ConversationMessageViewHolder.java
View file @
87377666
package
org.briarproject.briar.android.conversation
;
import
android.content.res.Configuration
;
import
android.graphics.Bitmap
;
import
android.support.annotation.DrawableRes
;
import
android.support.annotation.UiThread
;
import
android.support.constraint.ConstraintSet
;
import
android.support.v4.content.ContextCompat
;
import
android.support.v7.widget.RecyclerView
;
import
android.support.v7.widget.RecyclerView.RecycledViewPool
;
import
android.view.View
;
import
android.view.ViewGroup
;
import
android.widget.ImageView
;
import
com.bumptech.glide.load.Transformation
;
import
org.briarproject.bramble.api.nullsafety.NotNullByDefault
;
import
org.briarproject.briar.R
;
import
org.briarproject.briar.android.conversation.glide.BriarImageTransformation
;
import
org.briarproject.briar.android.conversation.glide.GlideApp
;
import
static
android
.
os
.
Build
.
VERSION
.
SDK_INT
;
import
static
android
.
support
.
v4
.
view
.
ViewCompat
.
LAYOUT_DIRECTION_RTL
;
import
static
com
.
bumptech
.
glide
.
load
.
engine
.
DiskCacheStrategy
.
NONE
;
import
static
com
.
bumptech
.
glide
.
load
.
resource
.
drawable
.
DrawableTransitionOptions
.
withCrossFade
;
import
static
android
.
support
.
constraint
.
ConstraintSet
.
WRAP_CONTENT
;
import
static
android
.
support
.
v4
.
content
.
ContextCompat
.
getColor
;
@UiThread
@NotNullByDefault
class
ConversationMessageViewHolder
extends
ConversationItemViewHolder
{
@DrawableRes
private
static
final
int
ERROR_RES
=
R
.
drawable
.
ic_image_broken
;
private
final
ImageView
imageView
;
private
final
ImageAdapter
adapter
;
private
final
ViewGroup
statusLayout
;
private
final
int
timeColor
,
timeColorBubble
;
private
final
int
radiusBig
,
radiusSmall
;
private
final
boolean
isRtl
;
private
final
ConstraintSet
textConstraints
=
new
ConstraintSet
();
private
final
ConstraintSet
imageConstraints
=
new
ConstraintSet
();
private
final
ConstraintSet
imageTextConstraints
=
new
ConstraintSet
();
ConversationMessageViewHolder
(
View
v
,
boolean
isIncoming
)
{
super
(
v
,
isIncoming
);
imageView
=
v
.
findViewById
(
R
.
id
.
imageView
);
ConversationMessageViewHolder
(
View
v
,
ConversationListener
listener
,
boolean
isIncoming
,
RecycledViewPool
imageViewPool
,
ImageItemDecoration
imageItemDecoration
)
{
super
(
v
,
listener
,
isIncoming
);
statusLayout
=
v
.
findViewById
(
R
.
id
.
statusLayout
);
radiusBig
=
v
.
getContext
().
getResources
()
.
getDimensionPixelSize
(
R
.
dimen
.
message_bubble_radius_big
);
radiusSmall
=
v
.
getContext
().
getResources
()
.
getDimensionPixelSize
(
R
.
dimen
.
message_bubble_radius_small
);
// image list
RecyclerView
list
=
v
.
findViewById
(
R
.
id
.
imageList
);
list
.
setRecycledViewPool
(
imageViewPool
);
adapter
=
new
ImageAdapter
(
v
.
getContext
(),
listener
);
list
.
setAdapter
(
adapter
);
list
.
addItemDecoration
(
imageItemDecoration
);
// remember original status text color
timeColor
=
time
.
getCurrentTextColor
();
timeColorBubble
=
ContextCompat
.
getColor
(
v
.
getContext
(),
R
.
color
.
briar_white
);
// find out if we are showing a RTL language, Use the configuration,
// because getting the layout direction of views is not reliable
Configuration
config
=
imageView
.
getContext
().
getResources
().
getConfiguration
();
isRtl
=
SDK_INT
>=
17
&&
config
.
getLayoutDirection
()
==
LAYOUT_DIRECTION_RTL
;
timeColorBubble
=
getColor
(
v
.
getContext
(),
R
.
color
.
briar_white
);
// clone constraint sets from layout files
textConstraints
...
...
@@ -77,85 +59,55 @@ class ConversationMessageViewHolder extends ConversationItemViewHolder {
}
@Override
void
bind
(
ConversationItem
conversationItem
,
ConversationListener
listener
)
{
super
.
bind
(
conversationItem
,
listener
);
void
bind
(
ConversationItem
conversationItem
)
{
super
.
bind
(
conversationItem
);
ConversationMessageItem
item
=
(
ConversationMessageItem
)
conversationItem
;
if
(
item
.
getAttachments
().
isEmpty
())
{
bindTextItem
();
}
else
{
bindImageItem
(
item
,
listener
);
bindImageItem
(
item
);
}
}
private
void
bindTextItem
()
{
clearImage
();
statusLayout
.
setBackgroundResource
(
0
);
// also reset padding (the background drawable defines some)
statusLayout
.
setPadding
(
0
,
0
,
0
,
0
);
time
.
setTextColor
(
timeColor
);
resetStatusLayoutForText
();
textConstraints
.
applyTo
(
layout
);
adapter
.
clear
();
}
private
void
bindImageItem
(
ConversationMessageItem
item
,
ConversationListener
listener
)
{
// TODO show more than just the first image
AttachmentItem
attachment
=
item
.
getAttachments
().
get
(
0
);
private
void
bindImageItem
(
ConversationMessageItem
item
)
{
ConstraintSet
constraintSet
;
if
(
item
.
getText
()
==
null
)
{
statusLayout
.
setBackgroundResource
(
R
.
drawable
.
msg_status_bubble
);
statusLayout
.
setBackgroundResource
(
R
.
drawable
.
msg_status_bubble
);
time
.
setTextColor
(
timeColorBubble
);
constraintSet
=
imageConstraints
;
}
else
{
statusLayout
.
setBackgroundResource
(
0
);
// also reset padding (the background drawable defines some)
statusLayout
.
setPadding
(
0
,
0
,
0
,
0
);
time
.
setTextColor
(
timeColor
);
resetStatusLayoutForText
();
constraintSet
=
imageTextConstraints
;
}
// apply image size constraints, so glides picks them up for scaling
int
width
=
attachment
.
getThumbnailWidth
();
int
height
=
attachment
.
getThumbnailHeight
();
constraintSet
.
constrainWidth
(
R
.
id
.
imageView
,
width
);
constraintSet
.
constrainHeight
(
R
.
id
.
imageView
,
height
);
constraintSet
.
applyTo
(
layout
);
if
(
attachment
.
hasError
())
{
clearImage
();
imageView
.
setImageResource
(
ERROR_RES
);
if
(
item
.
getAttachments
().
size
()
==
1
)
{
// apply image size constraints for a single image
AttachmentItem
attachment
=
item
.
getAttachments
().
get
(
0
);
int
width
=
attachment
.
getThumbnailWidth
();
int
height
=
attachment
.
getThumbnailHeight
();
constraintSet
.
constrainWidth
(
R
.
id
.
imageList
,
width
);
constraintSet
.
constrainHeight
(
R
.
id
.
imageList
,
height
);
}
else
{
loadImage
(
item
,
attachment
,
listener
);
// bubble adapts to size of image list
constraintSet
.
constrainWidth
(
R
.
id
.
imageList
,
WRAP_CONTENT
);
constraintSet
.
constrainHeight
(
R
.
id
.
imageList
,
WRAP_CONTENT
);
}
constraintSet
.
applyTo
(
layout
);
adapter
.
setConversationItem
(
item
);
}
private
void
clearImage
()
{
GlideApp
.
with
(
imageView
)
.
clear
(
imageView
);
imageView
.
setOnClickListener
(
null
);
}
private
void
loadImage
(
ConversationMessageItem
item
,
AttachmentItem
attachment
,
ConversationListener
listener
)
{
boolean
leftCornerSmall
=
(
isIncoming
()
&&
!
isRtl
)
||
(!
isIncoming
()
&&
isRtl
);
boolean
bottomRound
=
item
.
getText
()
==
null
;
Transformation
<
Bitmap
>
transformation
=
new
BriarImageTransformation
(
radiusSmall
,
radiusBig
,
leftCornerSmall
,
bottomRound
);
GlideApp
.
with
(
imageView
)
.
load
(
attachment
)
.
diskCacheStrategy
(
NONE
)
.
error
(
ERROR_RES
)
.
transform
(
transformation
)
.
transition
(
withCrossFade
())
.
into
(
imageView
)
.
waitForLayout
();
imageView
.
setOnClickListener
(
view
->
listener
.
onAttachmentClicked
(
view
,
item
,
attachment
));
private
void
resetStatusLayoutForText
()
{
statusLayout
.
setBackgroundResource
(
0
);
// also reset padding (the background drawable defines some)
statusLayout
.
setPadding
(
0
,
0
,
0
,
0
);
time
.
setTextColor
(
timeColor
);
}
}
briar-android/src/main/java/org/briarproject/briar/android/conversation/ConversationNoticeViewHolder.java
View file @
87377666
...
...
@@ -19,16 +19,17 @@ class ConversationNoticeViewHolder extends ConversationItemViewHolder {
private
final
TextView
msgText
;
ConversationNoticeViewHolder
(
View
v
,
boolean
isIncoming
)
{
super
(
v
,
isIncoming
);
ConversationNoticeViewHolder
(
View
v
,
ConversationListener
listener
,
boolean
isIncoming
)
{
super
(
v
,
listener
,
isIncoming
);
msgText
=
v
.
findViewById
(
R
.
id
.
msgText
);
}
@Override
@CallSuper
void
bind
(
ConversationItem
item
,
ConversationListener
listener
)
{
void
bind
(
ConversationItem
item
)
{
ConversationNoticeItem
notice
=
(
ConversationNoticeItem
)
item
;
super
.
bind
(
notice
,
listener
);
super
.
bind
(
notice
);
String
text
=
notice
.
getMsgText
();
if
(
isNullOrEmpty
(
text
))
{
...
...
briar-android/src/main/java/org/briarproject/briar/android/conversation/ConversationRequestViewHolder.java
View file @
87377666
...
...
@@ -17,16 +17,17 @@ class ConversationRequestViewHolder extends ConversationNoticeViewHolder {
private
final
Button
acceptButton
;
private
final
Button
declineButton
;
ConversationRequestViewHolder
(
View
v
,
boolean
isIncoming
)
{
super
(
v
,
isIncoming
);
ConversationRequestViewHolder
(
View
v
,
ConversationListener
listener
,
boolean
isIncoming
)
{
super
(
v
,
listener
,
isIncoming
);
acceptButton
=
v
.
findViewById
(
R
.
id
.
acceptButton
);
declineButton
=
v
.
findViewById
(
R
.
id
.
declineButton
);
}
@Override
void
bind
(
ConversationItem
item
,
ConversationListener
listener
)
{
void
bind
(
ConversationItem
item
)
{
ConversationRequestItem
request
=
(
ConversationRequestItem
)
item
;
super
.
bind
(
request
,
listener
);
super
.
bind
(
request
);
if
(
request
.
wasAnswered
()
&&
request
.
canBeOpened
())
{
acceptButton
.
setVisibility
(
VISIBLE
);
...
...
briar-android/src/main/java/org/briarproject/briar/android/conversation/ConversationViewModel.java
View file @
87377666
...
...
@@ -160,9 +160,11 @@ public class ConversationViewModel extends AndroidViewModel {
long
start
=
now
();
List
<
AttachmentHeader
>
attachments
=
new
ArrayList
<>();
List
<
AttachmentItem
>
items
=
new
ArrayList
<>();
boolean
needsSize
=
uris
.
size
()
==
1
;
for
(
Uri
uri
:
uris
)
{
Pair
<
AttachmentHeader
,
AttachmentItem
>
pair
=
createAttachmentHeader
(
groupId
,
uri
,
timestamp
);
createAttachmentHeader
(
groupId
,
uri
,
timestamp
,
needsSize
);
if
(
pair
==
null
)
continue
;
attachments
.
add
(
pair
.
getFirst
());
items
.
add
(
pair
.
getSecond
());
...
...
@@ -175,7 +177,7 @@ public class ConversationViewModel extends AndroidViewModel {
@Nullable
@DatabaseExecutor
private
Pair
<
AttachmentHeader
,
AttachmentItem
>
createAttachmentHeader
(
GroupId
groupId
,
Uri
uri
,
long
timestamp
)
{
GroupId
groupId
,
Uri
uri
,
long
timestamp
,
boolean
needsSize
)
{
InputStream
is
=
null
;
try
{
ContentResolver
contentResolver
=
...
...
@@ -191,7 +193,7 @@ public class ConversationViewModel extends AndroidViewModel {
is
=
contentResolver
.
openInputStream
(
uri
);
if
(
is
==
null
)
throw
new
IOException
();
AttachmentItem
item
=
attachmentController
.
getAttachmentItem
(
h
,
new
Attachment
(
is
));
.
getAttachmentItem
(
h
,
new
Attachment
(
is
)
,
needsSize
);
return
new
Pair
<>(
h
,
item
);
}
catch
(
DbException
|
IOException
e
)
{
logException
(
LOG
,
WARNING
,
e
);
...
...
briar-android/src/main/java/org/briarproject/briar/android/conversation/ImageAdapter.java
0 → 100644
View file @
87377666
package
org.briarproject.briar.android.conversation
;
import
android.content.Context
;
import
android.content.res.Resources
;
import
android.support.annotation.Nullable
;
import
android.support.v7.widget.RecyclerView.Adapter
;
import
android.util.DisplayMetrics
;
import
android.view.LayoutInflater
;
import
android.view.View
;
import
android.view.ViewGroup
;
import
android.view.WindowManager
;
import
org.briarproject.bramble.api.nullsafety.NotNullByDefault
;
import
org.briarproject.briar.R
;
import
org.briarproject.briar.android.conversation.glide.Radii
;
import
java.util.ArrayList
;
import
java.util.List
;
import
static
android
.
content
.
Context
.
WINDOW_SERVICE
;
import
static
java
.
util
.
Objects
.
requireNonNull
;
import
static
org
.
briarproject
.
briar
.
android
.
util
.
UiUtils
.
isRtl
;
@NotNullByDefault
class
ImageAdapter
extends
Adapter
<
ImageViewHolder
>
{
private
final
List
<
AttachmentItem
>
items
=
new
ArrayList
<>();
private
final
ConversationListener
listener
;
private
final
int
imageSize
;
private
final
int
radiusBig
,
radiusSmall
;
private
final
boolean
isRtl
;
@Nullable
private
ConversationMessageItem
conversationItem
;
ImageAdapter
(
Context
ctx
,
ConversationListener
listener
)
{
this
.
listener
=
listener
;
imageSize
=
getImageSize
(
ctx
);
Resources
res
=
ctx
.
getResources
();
radiusBig
=
res
.
getDimensionPixelSize
(
R
.
dimen
.
message_bubble_radius_big
);
radiusSmall
=
res
.
getDimensionPixelSize
(
R
.
dimen
.
message_bubble_radius_small
);
isRtl
=
isRtl
(
ctx
);
}
@Override
public
ImageViewHolder
onCreateViewHolder
(
ViewGroup
viewGroup
,
int
type
)
{
View
v
=
LayoutInflater
.
from
(
viewGroup
.
getContext
()).
inflate
(
R
.
layout
.
list_item_image
,
viewGroup
,
false
);
return
new
ImageViewHolder
(
v
,
imageSize
);
}
@Override
public
void
onBindViewHolder
(
ImageViewHolder
imageViewHolder
,
int
position
)
{
// get item
requireNonNull
(
conversationItem
);
AttachmentItem
item
=
items
.
get
(
position
);
// set onClick listener
imageViewHolder
.
itemView
.
setOnClickListener
(
v
->
listener
.
onAttachmentClicked
(
v
,
conversationItem
,
item
)
);
// bind view holder
int
size
=
items
.
size
();
boolean
isIncoming
=
conversationItem
.
isIncoming
();
boolean
hasText
=
conversationItem
.
getText
()
!=
null
;
Radii
r
=
getRadii
(
position
,
size
,
isIncoming
,
hasText
);
imageViewHolder
.
bind
(
item
,
r
,
size
==
1
,
singleInRow
(
position
,
size
));
}
@Override
public
int
getItemCount
()
{
return
items
.
size
();
}
void
setConversationItem
(
ConversationMessageItem
item
)
{
this
.
conversationItem
=
item
;
this
.
items
.
clear
();
this
.
items
.
addAll
(
item
.
getAttachments
());
notifyDataSetChanged
();
}
private
int
getImageSize
(
Context
ctx
)
{
Resources
res
=
ctx
.
getResources
();
WindowManager
windowManager
=
(
WindowManager
)
ctx
.
getSystemService
(
WINDOW_SERVICE
);
DisplayMetrics
displayMetrics
=
new
DisplayMetrics
();
if
(
windowManager
==
null
)
{
return
res
.
getDimensionPixelSize
(
R
.
dimen
.
message_bubble_image_default
);
}
windowManager
.
getDefaultDisplay
().
getMetrics
(
displayMetrics
);
int
imageSize
=
displayMetrics
.
widthPixels
/
3
;
int
maxSize
=
res
.
getDimensionPixelSize
(
R
.
dimen
.
message_bubble_image_max_width
);
return
Math
.
min
(
imageSize
,
maxSize
);
}
private
Radii
getRadii
(
int
pos
,
int
num
,
boolean
isIncoming
,
boolean
hasText
)
{
boolean
left
=
isLeft
(
pos
);
boolean
single
=
num
==
1
;
// Top Row
int
topLeft
;
int
topRight
;
if
(
single
)
{
topLeft
=
isIncoming
?
radiusSmall
:
radiusBig
;
topRight
=
!
isIncoming
?
radiusSmall
:
radiusBig
;
}
else
if
(
isTopRow
(
pos
))
{
topLeft
=
left
?
(
isIncoming
?
radiusSmall
:
radiusBig
)
:
0
;
topRight
=
!
left
?
(!
isIncoming
?
radiusSmall
:
radiusBig
)
:
0
;
}
else
{
topLeft
=
0
;
topRight
=
0
;