Commit fe3ac9e8 authored by Rafael Kellermann Streit's avatar Rafael Kellermann Streit Committed by GitHub

Merge branch 'develop' into feature/message-actions

parents b125b252 12247fd5
...@@ -9,7 +9,6 @@ import kotlinx.android.synthetic.main.activity_room.* ...@@ -9,7 +9,6 @@ import kotlinx.android.synthetic.main.activity_room.*
class RoomActivity : AppCompatActivity() { class RoomActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContentView(R.layout.activity_room) setContentView(R.layout.activity_room)
...@@ -35,8 +34,7 @@ class RoomActivity : AppCompatActivity() { ...@@ -35,8 +34,7 @@ class RoomActivity : AppCompatActivity() {
} }
private fun addFragment(fragment: Fragment, tag: String) { private fun addFragment(fragment: Fragment, tag: String) {
supportFragmentManager supportFragmentManager.beginTransaction()
.beginTransaction()
.add(R.id.fragment_container, fragment, tag) .add(R.id.fragment_container, fragment, tag)
.commit() .commit()
} }
......
...@@ -96,6 +96,7 @@ object RestApiHelper { ...@@ -96,6 +96,7 @@ object RestApiHelper {
val parsedHttpUrl = HttpUrl.parse(getEndpointUrlForFileList(roomType, hostname)) val parsedHttpUrl = HttpUrl.parse(getEndpointUrlForFileList(roomType, hostname))
?.newBuilder() ?.newBuilder()
?.addQueryParameter("roomId", roomId) ?.addQueryParameter("roomId", roomId)
?.addQueryParameter("sort", "{\"uploadedAt\":-1}")
?.addQueryParameter("offset", offset) ?.addQueryParameter("offset", offset)
?.build() ?.build()
......
...@@ -316,9 +316,9 @@ public class RoomFragment extends AbstractChatRoomFragment implements ...@@ -316,9 +316,9 @@ public class RoomFragment extends AbstractChatRoomFragment implements
case R.id.action_favorite_messages: case R.id.action_favorite_messages:
showRoomListFragment(R.id.action_favorite_messages); showRoomListFragment(R.id.action_favorite_messages);
break; break;
// case R.id.action_file_list: case R.id.action_file_list:
// showRoomListFragment(R.id.action_file_list); showRoomListFragment(R.id.action_file_list);
// break; break;
case R.id.action_member_list: case R.id.action_member_list:
showRoomListFragment(R.id.action_member_list); showRoomListFragment(R.id.action_member_list);
break; break;
......
package chat.rocket.android.fragment.chatroom.list package chat.rocket.android.fragment.chatroom.list
import chat.rocket.core.models.Attachment
import chat.rocket.core.models.Message import chat.rocket.core.models.Message
import chat.rocket.core.models.User import chat.rocket.core.models.User
...@@ -32,7 +33,7 @@ interface RoomListContract { ...@@ -32,7 +33,7 @@ interface RoomListContract {
* @param dataSet The file data set to show. * @param dataSet The file data set to show.
* @param total The total number of files. * @param total The total number of files.
*/ */
fun showFileList(dataSet: ArrayList<String>, total: String) fun showFileList(dataSet: ArrayList<Attachment>, total: String)
/** /**
* Shows a list of members of a room. * Shows a list of members of a room.
......
...@@ -9,8 +9,10 @@ import android.view.View ...@@ -9,8 +9,10 @@ import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import chat.rocket.android.R import chat.rocket.android.R
import chat.rocket.android.helper.EndlessRecyclerViewScrollListener import chat.rocket.android.helper.EndlessRecyclerViewScrollListener
import chat.rocket.android.layouthelper.chatroom.list.RoomFileListAdapter
import chat.rocket.android.layouthelper.chatroom.list.RoomMemberListAdapter import chat.rocket.android.layouthelper.chatroom.list.RoomMemberListAdapter
import chat.rocket.android.layouthelper.chatroom.list.RoomMessagesAdapter import chat.rocket.android.layouthelper.chatroom.list.RoomMessagesAdapter
import chat.rocket.core.models.Attachment
import chat.rocket.core.models.Message import chat.rocket.core.models.Message
import chat.rocket.core.models.User import chat.rocket.core.models.User
import kotlinx.android.synthetic.main.fragment_room_list.* import kotlinx.android.synthetic.main.fragment_room_list.*
...@@ -84,6 +86,14 @@ class RoomListFragment : Fragment(), RoomListContract.View { ...@@ -84,6 +86,14 @@ class RoomListFragment : Fragment(), RoomListContract.View {
userId, userId,
offset) offset)
} }
R.id.action_file_list -> {
presenter.requestFileList(roomId,
roomType,
hostname,
token,
userId,
offset)
}
R.id.action_favorite_messages -> { R.id.action_favorite_messages -> {
presenter.requestFavoriteMessages(roomId, presenter.requestFavoriteMessages(roomId,
roomType, roomType,
...@@ -139,8 +149,23 @@ class RoomListFragment : Fragment(), RoomListContract.View { ...@@ -139,8 +149,23 @@ class RoomListFragment : Fragment(), RoomListContract.View {
} }
} }
// TODO (after REST api fixes) override fun showFileList(dataSet: ArrayList<Attachment>, total: String) {
override fun showFileList(dataSet: ArrayList<String>, total: String) {} activity.title = getString(R.string.fragment_room_list_file_list_title, total)
if (recyclerView.adapter == null) {
recyclerView.adapter = RoomFileListAdapter(dataSet)
val linearLayoutManager = LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false)
recyclerView.layoutManager = linearLayoutManager
if (dataSet.size >= 50) {
recyclerView.addOnScrollListener(object : EndlessRecyclerViewScrollListener(linearLayoutManager) {
override fun onLoadMore(page: Int, totalItemsCount: Int, recyclerView: RecyclerView?) {
loadNextDataFromApi(page)
}
})
}
} else {
(recyclerView.adapter as RoomFileListAdapter).addDataSet(dataSet)
}
}
override fun showMemberList(dataSet: ArrayList<User>, total: String) { override fun showMemberList(dataSet: ArrayList<User>, total: String) {
activity.title = getString(R.string.fragment_room_list_member_list_title, total) activity.title = getString(R.string.fragment_room_list_member_list_title, total)
......
...@@ -2,11 +2,13 @@ package chat.rocket.android.fragment.chatroom.list ...@@ -2,11 +2,13 @@ package chat.rocket.android.fragment.chatroom.list
import android.content.Context import android.content.Context
import android.os.Handler import android.os.Handler
import android.util.Log
import chat.rocket.android.R import chat.rocket.android.R
import chat.rocket.android.api.rest.RestApiHelper import chat.rocket.android.api.rest.RestApiHelper
import chat.rocket.android.helper.OkHttpHelper import chat.rocket.android.helper.OkHttpHelper
import chat.rocket.android.helper.UrlHelper
import chat.rocket.core.SyncState import chat.rocket.core.SyncState
import chat.rocket.core.models.Attachment
import chat.rocket.core.models.AttachmentTitle
import chat.rocket.core.models.Message import chat.rocket.core.models.Message
import chat.rocket.core.models.User import chat.rocket.core.models.User
import okhttp3.Call import okhttp3.Call
...@@ -98,13 +100,43 @@ class RoomListPresenter(val context: Context, val view: RoomListContract.View) : ...@@ -98,13 +100,43 @@ class RoomListPresenter(val context: Context, val view: RoomListContract.View) :
}) })
} }
// TODO (after the REST api fixes)
override fun requestFileList(roomId: String, override fun requestFileList(roomId: String,
roomType: String, roomType: String,
hostname: String, hostname: String,
token: String, token: String,
userId: String, userId: String,
offset: Int) {} offset: Int) {
view.showWaitingView(true)
OkHttpHelper.getClient()
.newCall(RestApiHelper.getRequestForFileList(roomId,
roomType,
hostname,
token,
userId,
offset.toString()))
.enqueue(object : Callback {
override fun onFailure(call: Call, e: IOException) {
if (!call.isCanceled) {
val message = e.message
if (message != null) {
showErrorMessage(message)
}
}
}
@Throws(IOException::class)
override fun onResponse(call: Call, response: Response) {
if (response.isSuccessful) {
val result = response.body()?.string()
if (result != null) {
handleFilesJson(result, hostname)
}
} else {
showErrorMessage(response.message())
}
}
})
}
override fun requestMemberList(roomId: String, override fun requestMemberList(roomId: String,
roomType: String, roomType: String,
...@@ -159,27 +191,13 @@ class RoomListPresenter(val context: Context, val view: RoomListContract.View) : ...@@ -159,27 +191,13 @@ class RoomListPresenter(val context: Context, val view: RoomListContract.View) :
val messageJsonObject = messagesJSONArray.getJSONObject(it) val messageJsonObject = messagesJSONArray.getJSONObject(it)
val userJsonObject = messageJsonObject.getJSONObject("u") val userJsonObject = messageJsonObject.getJSONObject("u")
val timestampString = messageJsonObject.optString("ts")
val timestamp = if (timestampString.isBlank()) {
0
} else {
Timestamp.valueOf(timestampString.replace("T", " ").replace("Z", "")).time
}
val editedAtString = messageJsonObject.optString("_updatedAt")
val editedAt = if (editedAtString.isBlank()) {
0
} else {
Timestamp.valueOf(editedAtString.replace("T", " ").replace("Z", "")).time
}
Message.builder() Message.builder()
.setId(messageJsonObject.optString("_id")) .setId(messageJsonObject.optString("_id"))
.setRoomId(messageJsonObject.optString("rid")) .setRoomId(messageJsonObject.optString("rid"))
.setMessage(messageJsonObject.optString("msg")) .setMessage(messageJsonObject.optString("msg"))
.setUser(getUserFromJsonObject(userJsonObject)) .setUser(getUserFromJsonObject(userJsonObject))
.setTimestamp(timestamp) .setTimestamp(getLongTimestamp(messageJsonObject.optString("ts")))
.setEditedAt(editedAt) .setEditedAt(getLongTimestamp(messageJsonObject.optString("_updatedAt")))
.setGroupable(messageJsonObject.optBoolean("groupable")) .setGroupable(messageJsonObject.optBoolean("groupable"))
.setSyncState(SyncState.SYNCED) .setSyncState(SyncState.SYNCED)
.build() .build()
...@@ -202,6 +220,52 @@ class RoomListPresenter(val context: Context, val view: RoomListContract.View) : ...@@ -202,6 +220,52 @@ class RoomListPresenter(val context: Context, val view: RoomListContract.View) :
} }
} }
private fun handleFilesJson(json: String, hostname: String) {
try {
val jsonObject = JSONObject(json)
val filesJsonArray = jsonObject.getJSONArray("files")
val total = filesJsonArray.length()
val dataSet = ArrayList<Attachment>(total)
(0 until total).mapTo(dataSet) {
val fileJsonObject = filesJsonArray.getJSONObject(it)
val fileLink = UrlHelper.getAttachmentLink(hostname, fileJsonObject.optString("_id"), fileJsonObject.optString("name"))
val attachmentTitle = AttachmentTitle.builder()
.setTitle(fileJsonObject.optString("name"))
.setLink(fileLink)
.setDownloadLink(fileLink)
.build()
val attachment = Attachment.builder()
val type = fileJsonObject.optString("type")
when {
type.startsWith("image") -> attachment.setImageUrl(fileLink)
type.startsWith("audio") -> attachment.setAudioUrl(fileLink)
type.startsWith("video") -> attachment.setVideoUrl(fileLink)
}
attachment.setCollapsed(false)
.setAttachmentTitle(attachmentTitle)
.setTimestamp(getSafeTimestamp(fileJsonObject.optString("uploadedAt")))
.build()
}
if (dataSet.isEmpty() && !hasItem) {
showEmptyViewMessage(context.getString(R.string.fragment_room_list_no_file_list_to_show))
} else {
if (dataSet.isNotEmpty()) {
hasItem = true
showFileList(dataSet, jsonObject.optString("total"))
}
}
} catch (exception: JSONException) {
showInvalidRequest()
}
}
private fun handleMembersJson(json: String) { private fun handleMembersJson(json: String) {
try { try {
val jsonObject = JSONObject(json) val jsonObject = JSONObject(json)
...@@ -221,7 +285,7 @@ class RoomListPresenter(val context: Context, val view: RoomListContract.View) : ...@@ -221,7 +285,7 @@ class RoomListPresenter(val context: Context, val view: RoomListContract.View) :
showMemberList(dataSet, jsonObject.optString("total")) showMemberList(dataSet, jsonObject.optString("total"))
} }
} }
}catch (exception: JSONException) { } catch (exception: JSONException) {
showInvalidRequest() showInvalidRequest()
} }
} }
...@@ -236,6 +300,17 @@ class RoomListPresenter(val context: Context, val view: RoomListContract.View) : ...@@ -236,6 +300,17 @@ class RoomListPresenter(val context: Context, val view: RoomListContract.View) :
.build() .build()
} }
private fun getLongTimestamp(timestamp: String): Long {
return if (timestamp.isNotBlank()) {
Timestamp.valueOf(getSafeTimestamp(timestamp)).time
} else {
0
}
}
private fun getSafeTimestamp(timestamp: String): String =
timestamp.replace("T", " ").replace("Z", "")
private fun showPinnedMessageList(dataSet: ArrayList<Message>, total: String) { private fun showPinnedMessageList(dataSet: ArrayList<Message>, total: String) {
mainHandler.post { mainHandler.post {
view.showWaitingView(false) view.showWaitingView(false)
...@@ -250,6 +325,13 @@ class RoomListPresenter(val context: Context, val view: RoomListContract.View) : ...@@ -250,6 +325,13 @@ class RoomListPresenter(val context: Context, val view: RoomListContract.View) :
} }
} }
private fun showFileList(dataSet: ArrayList<Attachment>, total: String) {
mainHandler.post {
view.showWaitingView(false)
view.showFileList(dataSet, total)
}
}
private fun showMemberList(dataSet: ArrayList<User>, total: String) { private fun showMemberList(dataSet: ArrayList<User>, total: String) {
mainHandler.post { mainHandler.post {
view.showWaitingView(false) view.showWaitingView(false)
......
...@@ -8,7 +8,8 @@ object UrlHelper { ...@@ -8,7 +8,8 @@ object UrlHelper {
* @param uri The URI. * @param uri The URI.
* @return The URI whit no scheme (HTTP or HTTPS) * @return The URI whit no scheme (HTTP or HTTPS)
*/ */
fun removeUriScheme(uri: String) = uri.replace("http://", "").replace("https://", "") fun removeUriScheme(uri: String) =
uri.replace("http://", "").replace("https://", "")
/** /**
* Returns the hostname with the security protocol (scheme) HTTPS. * Returns the hostname with the security protocol (scheme) HTTPS.
...@@ -17,7 +18,7 @@ object UrlHelper { ...@@ -17,7 +18,7 @@ object UrlHelper {
* @return The hostname with the security protocol (scheme) HTTPS. * @return The hostname with the security protocol (scheme) HTTPS.
*/ */
fun getSafeHostname(hostname: String): String = fun getSafeHostname(hostname: String): String =
"https://" + hostname.replace("http://", "").replace("https://", "") "https://" + removeUriScheme(hostname)
/** /**
* Returns an URL with no spaces and inverted slashes. * Returns an URL with no spaces and inverted slashes.
...@@ -25,17 +26,17 @@ object UrlHelper { ...@@ -25,17 +26,17 @@ object UrlHelper {
* @param url The URL. * @param url The URL.
* @return The URL with no spaces and inverted slashes. * @return The URL with no spaces and inverted slashes.
*/ */
fun getUrl(url: String) = fun getSafeUrl(url: String) =
url.replace(" ", "%20").replace("\\", "") url.replace(" ", "%20").replace("\\", "")
/** /**
* Returns an URL for a file. * Returns an attachment link.
* *
* @param path The path to the file. * @param hostname The hostname.
* @param userId The user ID. * @param fileId The file ID.
* @param token The token. * @param fileName The file name.
* @return The URL for a file * @return The attachment link.
*/ */
fun getUrlForFile(path: String, userId: String, token: String): String = fun getAttachmentLink(hostname: String, fileId: String, fileName: String): String =
"https://" + removeUriScheme(getUrl(path)) + "?rc_uid=$userId" + "&rc_token=$token" getSafeUrl(getSafeHostname(hostname) + "/file-upload/" + fileId + "/" + fileName)
} }
\ No newline at end of file
...@@ -4,14 +4,19 @@ import android.support.v7.widget.RecyclerView ...@@ -4,14 +4,19 @@ import android.support.v7.widget.RecyclerView
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.TextView
import chat.rocket.android.R import chat.rocket.android.R
import chat.rocket.android.widget.message.RocketChatMessageLayout import chat.rocket.android.helper.DateTime
import chat.rocket.android.widget.message.RocketChatMessageAttachmentsLayout
import chat.rocket.core.models.Attachment
import kotlinx.android.synthetic.main.day.view.*
import kotlinx.android.synthetic.main.item_room_file.view.* import kotlinx.android.synthetic.main.item_room_file.view.*
import java.sql.Timestamp
/** /**
* Created by Filipe de Lima Brito (filipedelimabrito@gmail.com) on 9/22/17. * Created by Filipe de Lima Brito (filipedelimabrito@gmail.com) on 9/22/17.
*/ */
class RoomFileListAdapter(private var dataSet: List<String>) : RecyclerView.Adapter<RoomFileListAdapter.ViewHolder>() { class RoomFileListAdapter(private var dataSet: List<Attachment>) : RecyclerView.Adapter<RoomFileListAdapter.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.item_room_file, parent, false) val view = LayoutInflater.from(parent.context).inflate(R.layout.item_room_file, parent, false)
...@@ -19,17 +24,22 @@ class RoomFileListAdapter(private var dataSet: List<String>) : RecyclerView.Adap ...@@ -19,17 +24,22 @@ class RoomFileListAdapter(private var dataSet: List<String>) : RecyclerView.Adap
} }
override fun onBindViewHolder(holder: ViewHolder, position: Int) { override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.fileNameLink.setText(dataSet[position]) val attachment = dataSet[position]
holder.newDay.text = DateTime.fromEpocMs(Timestamp.valueOf(attachment.timestamp).time, DateTime.Format.DATE)
holder.attachment.appendAttachmentView(attachment, true, false)
} }
override fun getItemCount(): Int = dataSet.size override fun getItemCount(): Int = dataSet.size
fun setDataSet(dataSet: List<String>) { fun addDataSet(dataSet: List<Attachment>) {
this.dataSet = dataSet val previousDataSetSize = this.dataSet.size
notifyDataSetChanged() this.dataSet += dataSet
notifyItemRangeInserted(previousDataSetSize, dataSet.size)
} }
class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val fileNameLink : RocketChatMessageLayout = itemView.fileLink val newDay: TextView = itemView.day
val attachment: RocketChatMessageAttachmentsLayout = itemView.attachment
} }
} }
\ No newline at end of file
...@@ -3,20 +3,20 @@ ...@@ -3,20 +3,20 @@
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:padding="@dimen/margin_16"> android:paddingRight="@dimen/margin_16"
android:paddingStart="@dimen/margin_16"
android:paddingLeft="@dimen/margin_16"
android:paddingEnd="@dimen/margin_16"
android:paddingBottom="@dimen/margin_16">
<chat.rocket.android.widget.message.RocketChatMessageLayout <include
android:id="@+id/fileLink" android:id="@+id/dayLayout"
android:layout_width="wrap_content" layout="@layout/day" />
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/margin_16"
android:layout_marginStart="@dimen/margin_16" />
<View <chat.rocket.android.widget.message.RocketChatMessageAttachmentsLayout
android:layout_width="0dp" android:id="@+id/attachment"
android:layout_height="1dp" android:layout_width="match_parent"
android:layout_weight="1" android:layout_height="wrap_content"
android:background="@color/colorDivider" android:layout_marginTop="@dimen/margin_16"
android:layout_marginTop="@dimen/margin_8" app:layout_constraintTop_toBottomOf="@+id/dayLayout" />
app:layout_constraintTop_toBottomOf="@+id/fileLink" />
</android.support.constraint.ConstraintLayout> </android.support.constraint.ConstraintLayout>
\ No newline at end of file
...@@ -10,9 +10,9 @@ ...@@ -10,9 +10,9 @@
android:title="@string/menu_favorite_messages" android:title="@string/menu_favorite_messages"
app:showAsAction="never" /> app:showAsAction="never" />
<!--<item android:id="@+id/action_file_list"--> <item android:id="@+id/action_file_list"
<!--android:title="@string/menu_file_list"--> android:title="@string/menu_file_list"
<!--app:showAsAction="never" />--> app:showAsAction="never" />
<item android:id="@+id/action_member_list" <item android:id="@+id/action_member_list"
android:title="@string/menu_member_list" android:title="@string/menu_member_list"
......
...@@ -21,20 +21,17 @@ class UrlHelperTest { ...@@ -21,20 +21,17 @@ class UrlHelperTest {
@Test @Test
fun getUrlTest() { fun getUrlTest() {
assertEquals("https://demo.rocket.chat/GENERAL/file.txt", UrlHelper.getUrl("https://demo.rocket.chat/GENERAL/file.txt")) assertEquals("https://demo.rocket.chat/GENERAL/file.txt", UrlHelper.getSafeUrl("https://demo.rocket.chat/GENERAL/file.txt"))
assertEquals("http://demo.rocket.chat/GENERAL/file.txt", UrlHelper.getUrl("http://demo.rocket.chat/GENERAL/file.txt")) assertEquals("http://demo.rocket.chat/GENERAL/file.txt", UrlHelper.getSafeUrl("http://demo.rocket.chat/GENERAL/file.txt"))
assertEquals("demo.rocket.chat/GENERAL/file.txt", UrlHelper.getUrl("demo.rocket.chat/GENERAL/file.txt")) assertEquals("demo.rocket.chat/GENERAL/file.txt", UrlHelper.getSafeUrl("demo.rocket.chat/GENERAL/file.txt"))
assertEquals("demo.rocket.chat/GENERAL/a%20sample%20file.txt", UrlHelper.getUrl("demo.rocket.chat/GENERAL/a sample file.txt")) assertEquals("demo.rocket.chat/GENERAL/a%20sample%20file.txt", UrlHelper.getSafeUrl("demo.rocket.chat/GENERAL/a sample file.txt"))
assertEquals("demo.rocket.chat/GENERAL/file.txt", UrlHelper.getUrl("demo.rocket.chat\\/GENERAL\\/file.txt")) assertEquals("demo.rocket.chat/GENERAL/file.txt", UrlHelper.getSafeUrl("demo.rocket.chat\\/GENERAL\\/file.txt"))
} }
@Test @Test
fun getUrlForFileTest() { fun getAttachmentLinkTest() {
assertEquals("https://demo.rocket.chat/GENERAL/file.txt?rc_uid=userId&rc_token=token", UrlHelper.getUrlForFile("https://demo.rocket.chat/GENERAL/file.txt","userId", "token")) assertEquals("https://demo.rocket.chat/file-upload/aFileId/aFileName.txt", UrlHelper.getAttachmentLink("https://demo.rocket.chat", "aFileId", "aFileName.txt"))
assertEquals("https://demo.rocket.chat/GENERAL/file.txt?rc_uid=userId&rc_token=token", UrlHelper.getUrlForFile("http://demo.rocket.chat/GENERAL/file.txt","userId", "token")) assertEquals("https://demo.rocket.chat/file-upload/aFileId/aFileName.txt", UrlHelper.getAttachmentLink("http://demo.rocket.chat", "aFileId", "aFileName.txt"))
assertEquals("https://demo.rocket.chat/GENERAL/file.txt?rc_uid=userId&rc_token=token", UrlHelper.getUrlForFile("demo.rocket.chat/GENERAL/file.txt","userId", "token")) assertEquals("https://demo.rocket.chat/file-upload/aFileId/aFileName.txt", UrlHelper.getAttachmentLink("demo.rocket.chat", "aFileId", "aFileName.txt"))
assertEquals("https://demo.rocket.chat/GENERAL/a%20sample%20file.txt?rc_uid=userId&rc_token=token", UrlHelper.getUrlForFile("demo.rocket.chat/GENERAL/a sample file.txt","userId", "token"))
assertEquals("https://demo.rocket.chat/GENERAL/file.txt?rc_uid=userId&rc_token=token", UrlHelper.getUrlForFile("demo.rocket.chat\\/GENERAL\\/file.txt","userId", "token"))
} }
} }
\ No newline at end of file
...@@ -6,7 +6,9 @@ import android.support.graphics.drawable.VectorDrawableCompat ...@@ -6,7 +6,9 @@ import android.support.graphics.drawable.VectorDrawableCompat
import chat.rocket.android.widget.R import chat.rocket.android.widget.R
import com.facebook.drawee.backends.pipeline.Fresco import com.facebook.drawee.backends.pipeline.Fresco
import com.facebook.drawee.drawable.ProgressBarDrawable import com.facebook.drawee.drawable.ProgressBarDrawable
import com.facebook.drawee.drawable.ScalingUtils
import com.facebook.drawee.generic.GenericDraweeHierarchy import com.facebook.drawee.generic.GenericDraweeHierarchy
import com.facebook.drawee.generic.RoundingParams
import com.facebook.drawee.view.SimpleDraweeView import com.facebook.drawee.view.SimpleDraweeView
object FrescoHelper { object FrescoHelper {
...@@ -31,6 +33,8 @@ object FrescoHelper { ...@@ -31,6 +33,8 @@ object FrescoHelper {
val hierarchy: GenericDraweeHierarchy = draweeView.hierarchy val hierarchy: GenericDraweeHierarchy = draweeView.hierarchy
hierarchy.setPlaceholderImage(VectorDrawableCompat.create(draweeView.resources, R.drawable.image_dummy, null)) hierarchy.setPlaceholderImage(VectorDrawableCompat.create(draweeView.resources, R.drawable.image_dummy, null))
hierarchy.setFailureImage(VectorDrawableCompat.create(draweeView.resources, R.drawable.image_error, null)) hierarchy.setFailureImage(VectorDrawableCompat.create(draweeView.resources, R.drawable.image_error, null))
hierarchy.roundingParams = RoundingParams().setCornersRadii(5F, 5F, 5F, 5F)
hierarchy.actualImageScaleType = ScalingUtils.ScaleType.FIT_CENTER
hierarchy.setProgressBarImage(ProgressBarDrawable()) hierarchy.setProgressBarImage(ProgressBarDrawable())
val controller = Fresco.newDraweeControllerBuilder() val controller = Fresco.newDraweeControllerBuilder()
......
...@@ -71,21 +71,21 @@ public class RocketChatMessageAttachmentsLayout extends LinearLayout { ...@@ -71,21 +71,21 @@ public class RocketChatMessageAttachmentsLayout extends LinearLayout {
return; return;
} }
this.attachments = attachments; this.attachments = attachments;
removeAllViews();
for (int i = 0, size = attachments.size(); i < size; i++) { for (int i = 0, size = attachments.size(); i < size; i++) {
appendAttachmentView(attachments.get(i), autoloadImages); appendAttachmentView(attachments.get(i), autoloadImages, true);
} }
} }
private void appendAttachmentView(Attachment attachment, boolean autoloadImages) { public void appendAttachmentView(Attachment attachment, boolean autoloadImages, boolean showAttachmentStrip) {
if (attachment == null) { if (attachment == null) {
return; return;
} }
removeAllViews();
View attachmentView = inflater.inflate(R.layout.message_inline_attachment, this, false); View attachmentView = inflater.inflate(R.layout.message_inline_attachment, this, false);
colorizeAttachmentBar(attachment, attachmentView); colorizeAttachmentBar(attachment, attachmentView, showAttachmentStrip);
showAuthorAttachment(attachment, attachmentView); showAuthorAttachment(attachment, attachmentView);
showTitleAttachment(attachment, attachmentView); showTitleAttachment(attachment, attachmentView);
showReferenceAttachment(attachment, attachmentView); showReferenceAttachment(attachment, attachmentView);
...@@ -97,19 +97,23 @@ public class RocketChatMessageAttachmentsLayout extends LinearLayout { ...@@ -97,19 +97,23 @@ public class RocketChatMessageAttachmentsLayout extends LinearLayout {
addView(attachmentView); addView(attachmentView);
} }
private void colorizeAttachmentBar(Attachment attachment, View attachmentView) { private void colorizeAttachmentBar(Attachment attachment, View attachmentView, boolean showAttachmentStrip) {
final View attachmentStrip = attachmentView.findViewById(R.id.attachment_strip); final View attachmentStrip = attachmentView.findViewById(R.id.attachment_strip);
final String colorString = attachment.getColor(); if (showAttachmentStrip) {
if (TextUtils.isEmpty(colorString)) { final String colorString = attachment.getColor();
attachmentStrip.setBackgroundResource(R.color.inline_attachment_quote_line); if (TextUtils.isEmpty(colorString)) {
return; attachmentStrip.setBackgroundResource(R.color.inline_attachment_quote_line);
} return;
}
try { try {
attachmentStrip.setBackgroundColor(Color.parseColor(colorString)); attachmentStrip.setBackgroundColor(Color.parseColor(colorString));
} catch (Exception e) { } catch (Exception e) {
attachmentStrip.setBackgroundResource(R.color.inline_attachment_quote_line); attachmentStrip.setBackgroundResource(R.color.inline_attachment_quote_line);
}
} else {
attachmentStrip.setVisibility(GONE);
} }
} }
...@@ -204,8 +208,7 @@ public class RocketChatMessageAttachmentsLayout extends LinearLayout { ...@@ -204,8 +208,7 @@ public class RocketChatMessageAttachmentsLayout extends LinearLayout {
} }
} }
private void showImageAttachment(Attachment attachment, View attachmentView, private void showImageAttachment(Attachment attachment, View attachmentView, boolean autoloadImages) {
boolean autoloadImages) {
final View imageContainer = attachmentView.findViewById(R.id.image_container); final View imageContainer = attachmentView.findViewById(R.id.image_container);
if (attachment.getImageUrl() == null) { if (attachment.getImageUrl() == null) {
imageContainer.setVisibility(GONE); imageContainer.setVisibility(GONE);
......
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"> <shape xmlns:android="http://schemas.android.com/apk/res/android">
<stroke <stroke
android:color="@color/inline_attachment_box_outline" android:width="1dp"
android:width="1dp"/> android:color="@color/inline_attachment_box_outline" />
<solid android:color="@color/inline_attachment_box_background"/>
<corners android:radius="2dp"/> <solid
android:color="@color/inline_attachment_box_background" />
<corners
android:radius="2dp" />
</shape> </shape>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" xmlns:fresco="http://schemas.android.com/apk/res-auto"
xmlns:fresco="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="horizontal" android:orientation="horizontal"
android:paddingTop="4dp" android:paddingBottom="4dp"
android:paddingBottom="4dp"> android:paddingTop="4dp">
<View <View
android:id="@+id/attachment_strip" android:id="@+id/attachment_strip"
android:layout_width="3dp" android:layout_width="3dp"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_marginRight="5dp" android:layout_marginEnd="5dp"
android:background="@color/inline_attachment_quote_line" /> android:layout_marginRight="5dp"
android:background="@color/inline_attachment_quote_line" />
<LinearLayout <LinearLayout
android:id="@+id/attachment_content" android:id="@+id/attachment_content"
android:layout_width="0px" android:layout_width="0px"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="1" android:layout_weight="1"
android:orientation="vertical"> android:orientation="vertical">
<LinearLayout <LinearLayout
android:id="@+id/author_box" android:id="@+id/author_box"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:gravity="center_vertical" android:layout_marginBottom="8dp"
android:orientation="horizontal" android:gravity="center_vertical"
android:layout_marginBottom="8dp"> android:orientation="horizontal">
<com.facebook.drawee.view.SimpleDraweeView <com.facebook.drawee.view.SimpleDraweeView
android:id="@+id/author_icon" android:id="@+id/author_icon"
android:layout_width="16dp" android:layout_width="16dp"
android:layout_height="16dp" android:layout_height="16dp"
tools:src="@drawable/circle_black" fresco:actualImageScaleType="fitCenter"
fresco:actualImageScaleType="fitCenter" /> tools:src="@drawable/circle_black" />
<android.support.v4.widget.Space <android.support.v4.widget.Space
android:layout_width="8dp" android:layout_width="8dp"
android:layout_height="8dp" /> android:layout_height="8dp" />
<TextView <TextView
android:id="@+id/author_name" android:id="@+id/author_name"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:textAppearance="@style/TextAppearance.RocketChat.MessageAttachment.Title.Link" android:textAppearance="@style/TextAppearance.RocketChat.MessageAttachment.Title.Link"
tools:text="Bradley Hilton" /> tools:text="Bradley Hilton" />
<android.support.v4.widget.Space <android.support.v4.widget.Space
android:layout_width="8dp" android:layout_width="8dp"
android:layout_height="8dp" /> android:layout_height="8dp" />
<TextView <TextView
android:id="@+id/timestamp" android:id="@+id/timestamp"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
tools:text="14:53" /> tools:text="14:53" />
</LinearLayout> </LinearLayout>
<TextView <TextView
android:id="@+id/title" android:id="@+id/title"
android:layout_width="match_parent" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginBottom="8dp" android:layout_gravity="center"
android:textAppearance="@style/TextAppearance.RocketChat.MessageAttachment.Title" android:background="?attr/selectableItemBackground"
android:background="?attr/selectableItemBackground" android:textAppearance="@style/TextAppearance.RocketChat.MessageAttachment.Title"
tools:text="Attachment Example" /> tools:text="Attachment Example" />
<LinearLayout <LinearLayout
android:id="@+id/ref_box" android:id="@+id/ref_box"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:gravity="center_vertical" android:layout_marginBottom="8dp"
android:orientation="horizontal" android:gravity="center_vertical"
android:layout_marginBottom="8dp"> android:orientation="horizontal">
<com.facebook.drawee.view.SimpleDraweeView <com.facebook.drawee.view.SimpleDraweeView
android:id="@+id/thumb" android:id="@+id/thumb"
android:layout_width="32dp" android:layout_width="32dp"
android:layout_height="32dp" android:layout_height="32dp"
tools:src="@drawable/circle_black" fresco:actualImageScaleType="fitCenter"
fresco:actualImageScaleType="fitCenter" /> tools:src="@drawable/circle_black" />
<android.support.v4.widget.Space <android.support.v4.widget.Space
android:layout_width="8dp" android:layout_width="8dp"
android:layout_height="8dp" /> android:layout_height="8dp" />
<TextView <TextView
android:id="@+id/text" android:id="@+id/text"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
tools:text="Bradley Hilton" /> tools:text="Bradley Hilton" />
</LinearLayout> </LinearLayout>
<FrameLayout <FrameLayout
android:id="@+id/image_container" android:id="@+id/image_container"
android:layout_width="match_parent" android:layout_width="wrap_content"
android:layout_height="wrap_content"> android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="8dp"
android:padding="5dp"
android:background="@drawable/inline_attachment_background">
<com.facebook.drawee.view.SimpleDraweeView <com.facebook.drawee.view.SimpleDraweeView
android:id="@+id/image" android:id="@+id/image"
android:layout_width="match_parent" android:layout_width="200dp"
android:layout_height="150dp" android:layout_height="200dp"/>
android:layout_marginBottom="8dp"
fresco:actualImageScaleType="fitStart" />
<TextView <TextView
android:id="@+id/image_load" android:id="@+id/image_load"
android:layout_width="match_parent" android:layout_width="200dp"
android:layout_height="150dp" android:layout_height="200dp"
android:gravity="center_horizontal|bottom" android:gravity="center_horizontal|bottom"
android:paddingBottom="16dp" android:paddingBottom="16dp"
android:text="@string/click_to_load" /> android:text="@string/click_to_load" />
</FrameLayout> </FrameLayout>
<!-- audio --> <!-- audio -->
<!-- video --> <!-- video -->
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment