Unverified Commit 657cd088 authored by Filipe de Lima Brito's avatar Filipe de Lima Brito Committed by GitHub

Merge pull request #1237 from RocketChat/beta

[CHORE] Merge beta into develop
parents 416e5f39 5122f1fd
...@@ -58,6 +58,9 @@ jobs: ...@@ -58,6 +58,9 @@ jobs:
- run: - run:
name: Run Unit test name: Run Unit test
command: ./gradlew test command: ./gradlew test
- run:
name: Compile Instrumentation test
command: ./gradlew assembleAndroidTest
- store_artifacts: - store_artifacts:
path: app/build/reports/ path: app/build/reports/
destination: reports destination: reports
......
...@@ -13,7 +13,7 @@ android { ...@@ -13,7 +13,7 @@ android {
applicationId "chat.rocket.android" applicationId "chat.rocket.android"
minSdkVersion 21 minSdkVersion 21
targetSdkVersion versions.targetSdk targetSdkVersion versions.targetSdk
versionCode 2015 versionCode 2018
versionName "2.1.0" versionName "2.1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
multiDexEnabled true multiDexEnabled true
...@@ -114,9 +114,9 @@ dependencies { ...@@ -114,9 +114,9 @@ dependencies {
} }
testImplementation libraries.junit testImplementation libraries.junit
androidTestImplementation(libraries.expressoCore, { testImplementation libraries.truth
exclude group: 'com.android.support', module: 'support-annotations' androidTestImplementation libraries.espressoCore
}) androidTestImplementation libraries.espressoIntents
} }
kotlin { kotlin {
......
package chat.rocket.android.chatroom.ui
import android.content.Intent
import android.support.test.espresso.intent.rule.IntentsTestRule
import android.support.test.filters.LargeTest
import org.junit.Rule
import org.junit.Test
import android.app.Activity
import android.app.Instrumentation.ActivityResult
import android.support.test.InstrumentationRegistry
import android.support.test.espresso.intent.Intents.intended
import android.support.test.espresso.intent.Intents.intending
import android.support.test.espresso.intent.matcher.IntentMatchers.*
import org.hamcrest.Matchers.allOf
import org.hamcrest.Matchers.not
import org.junit.Before
@LargeTest
class ChatRoomFragmentTest {
@JvmField
@Rule
val activityRule = IntentsTestRule<ChatRoomActivity>(ChatRoomActivity::class.java, false, false)
@Before
fun stubAllExternalIntents() {
val activityIntent = InstrumentationRegistry.getTargetContext().chatRoomIntent("id", "name", "type", false, 0L)
activityRule.launchActivity(activityIntent)
intending(not(isInternal())).respondWith(ActivityResult(Activity.RESULT_OK, null))
}
@Test
fun showFileSelection_nonNullFiltersAreApplied() {
val fragment = activityRule.activity.supportFragmentManager.findFragmentByTag(ChatRoomActivity.TAG_CHAT_ROOM_FRAGMENT) as ChatRoomFragment
val filters = arrayOf("image/*")
fragment.showFileSelection(filters)
intended(allOf(
hasAction(Intent.ACTION_GET_CONTENT),
hasType("*/*"),
hasCategories(setOf(Intent.CATEGORY_OPENABLE)),
hasExtra(Intent.EXTRA_MIME_TYPES, filters)))
}
@Test
fun showFileSelection_nullFiltersAreNotApplied() {
val fragment = activityRule.activity.supportFragmentManager.findFragmentByTag(ChatRoomActivity.TAG_CHAT_ROOM_FRAGMENT) as ChatRoomFragment
fragment.showFileSelection(null)
intended(allOf(
hasAction(Intent.ACTION_GET_CONTENT),
hasType("*/*"),
hasCategories(setOf(Intent.CATEGORY_OPENABLE)),
not(hasExtraWithKey(Intent.EXTRA_MIME_TYPES))))
}
}
\ No newline at end of file
...@@ -268,16 +268,15 @@ class LoginPresenter @Inject constructor( ...@@ -268,16 +268,15 @@ class LoginPresenter @Inject constructor(
val token = retryIO("login") { val token = retryIO("login") {
when (loginType) { when (loginType) {
TYPE_LOGIN_USER_EMAIL -> { TYPE_LOGIN_USER_EMAIL -> {
if (usernameOrEmail.isEmail()) { when {
client.loginWithEmail(usernameOrEmail, password) settings.isLdapAuthenticationEnabled() ->
} else {
if (settings.isLdapAuthenticationEnabled()) {
client.loginWithLdap(usernameOrEmail, password) client.loginWithLdap(usernameOrEmail, password)
} else { usernameOrEmail.isEmail() ->
client.loginWithEmail(usernameOrEmail, password)
else ->
client.login(usernameOrEmail, password) client.login(usernameOrEmail, password)
} }
} }
}
TYPE_LOGIN_CAS -> { TYPE_LOGIN_CAS -> {
delay(3, TimeUnit.SECONDS) delay(3, TimeUnit.SECONDS)
client.loginWithCas(credentialToken) client.loginWithCas(credentialToken)
......
...@@ -14,10 +14,9 @@ class AudioAttachmentViewHolder(itemView: View, ...@@ -14,10 +14,9 @@ class AudioAttachmentViewHolder(itemView: View,
init { init {
with(itemView) { with(itemView) {
setupActionMenu(attachment_container)
image_attachment.setVisible(false) image_attachment.setVisible(false)
audio_video_attachment.setVisible(true) audio_video_attachment.setVisible(true)
setupActionMenu(attachment_container)
setupActionMenu(audio_video_attachment)
} }
} }
......
...@@ -19,12 +19,9 @@ class AuthorAttachmentViewHolder(itemView: View, ...@@ -19,12 +19,9 @@ class AuthorAttachmentViewHolder(itemView: View,
init { init {
with(itemView) { with(itemView) {
setupActionMenu(author_attachment_container) setupActionMenu(author_attachment_container)
setupActionMenu(text_fields)
setupActionMenu(text_author_name)
} }
} }
override fun bindViews(data: AuthorAttachmentViewModel) { override fun bindViews(data: AuthorAttachmentViewModel) {
with(itemView) { with(itemView) {
data.icon?.let { icon -> data.icon?.let { icon ->
......
...@@ -3,6 +3,8 @@ package chat.rocket.android.chatroom.adapter ...@@ -3,6 +3,8 @@ package chat.rocket.android.chatroom.adapter
import android.support.v7.widget.RecyclerView import android.support.v7.widget.RecyclerView
import android.view.MenuItem import android.view.MenuItem
import android.view.View import android.view.View
import android.view.ViewGroup
import androidx.core.view.children
import chat.rocket.android.R import chat.rocket.android.R
import chat.rocket.android.chatroom.ui.bottomsheet.BottomSheetMenu import chat.rocket.android.chatroom.ui.bottomsheet.BottomSheetMenu
import chat.rocket.android.chatroom.ui.bottomsheet.adapter.ActionListAdapter import chat.rocket.android.chatroom.ui.bottomsheet.adapter.ActionListAdapter
...@@ -74,7 +76,7 @@ abstract class BaseViewHolder<T : BaseViewModel<*>>( ...@@ -74,7 +76,7 @@ abstract class BaseViewHolder<T : BaseViewModel<*>>(
fun onActionSelected(item: MenuItem, message: Message) fun onActionSelected(item: MenuItem, message: Message)
} }
val longClickListener = { view: View -> private val longClickListener = { view: View ->
if (data?.message?.isSystemMessage() == false) { if (data?.message?.isSystemMessage() == false) {
val menuItems = view.context.inflate(R.menu.message_actions).toList() val menuItems = view.context.inflate(R.menu.message_actions).toList()
menuItems.find { it.itemId == R.id.action_menu_msg_pin_unpin }?.apply { menuItems.find { it.itemId == R.id.action_menu_msg_pin_unpin }?.apply {
...@@ -90,6 +92,13 @@ abstract class BaseViewHolder<T : BaseViewModel<*>>( ...@@ -90,6 +92,13 @@ abstract class BaseViewHolder<T : BaseViewModel<*>>(
internal fun setupActionMenu(view: View) { internal fun setupActionMenu(view: View) {
if (listener.isActionsEnabled()) { if (listener.isActionsEnabled()) {
if (view is ViewGroup) {
for (child in view.children) {
if (child !is RecyclerView && child.id != R.id.recycler_view_reactions) {
setupActionMenu(child)
}
}
}
view.setOnLongClickListener(longClickListener) view.setOnLongClickListener(longClickListener)
} }
} }
......
...@@ -20,7 +20,6 @@ class ColorAttachmentViewHolder(itemView: View, ...@@ -20,7 +20,6 @@ class ColorAttachmentViewHolder(itemView: View,
init { init {
with(itemView) { with(itemView) {
setupActionMenu(attachment_text)
setupActionMenu(color_attachment_container) setupActionMenu(color_attachment_container)
attachment_text.movementMethod = LinkMovementMethod() attachment_text.movementMethod = LinkMovementMethod()
} }
......
...@@ -17,11 +17,9 @@ class GenericFileAttachmentViewHolder(itemView: View, ...@@ -17,11 +17,9 @@ class GenericFileAttachmentViewHolder(itemView: View,
init { init {
with(itemView) { with(itemView) {
setupActionMenu(file_attachment_container) setupActionMenu(file_attachment_container)
setupActionMenu(text_file_name)
} }
} }
override fun bindViews(data: GenericFileAttachmentViewModel) { override fun bindViews(data: GenericFileAttachmentViewModel) {
with(itemView) { with(itemView) {
text_file_name.content = data.attachmentTitle text_file_name.content = data.attachmentTitle
......
...@@ -47,7 +47,6 @@ class ImageAttachmentViewHolder(itemView: View, ...@@ -47,7 +47,6 @@ class ImageAttachmentViewHolder(itemView: View,
init { init {
with(itemView) { with(itemView) {
setupActionMenu(attachment_container) setupActionMenu(attachment_container)
setupActionMenu(image_attachment)
} }
} }
......
...@@ -4,7 +4,7 @@ import android.text.method.LinkMovementMethod ...@@ -4,7 +4,7 @@ import android.text.method.LinkMovementMethod
import android.view.View import android.view.View
import chat.rocket.android.chatroom.viewmodel.MessageAttachmentViewModel import chat.rocket.android.chatroom.viewmodel.MessageAttachmentViewModel
import chat.rocket.android.widget.emoji.EmojiReactionListener import chat.rocket.android.widget.emoji.EmojiReactionListener
import kotlinx.android.synthetic.main.item_message.view.* import kotlinx.android.synthetic.main.item_message_attachment.view.*
class MessageAttachmentViewHolder( class MessageAttachmentViewHolder(
itemView: View, itemView: View,
...@@ -14,8 +14,8 @@ class MessageAttachmentViewHolder( ...@@ -14,8 +14,8 @@ class MessageAttachmentViewHolder(
init { init {
with(itemView) { with(itemView) {
setupActionMenu(attachment_container)
text_content.movementMethod = LinkMovementMethod() text_content.movementMethod = LinkMovementMethod()
setupActionMenu(text_content)
} }
} }
......
...@@ -18,8 +18,8 @@ class MessageViewHolder( ...@@ -18,8 +18,8 @@ class MessageViewHolder(
init { init {
with(itemView) { with(itemView) {
setupActionMenu(message_container)
text_content.movementMethod = LinkMovementMethod() text_content.movementMethod = LinkMovementMethod()
setupActionMenu(text_content)
} }
} }
......
...@@ -14,10 +14,9 @@ class VideoAttachmentViewHolder(itemView: View, ...@@ -14,10 +14,9 @@ class VideoAttachmentViewHolder(itemView: View,
init { init {
with(itemView) { with(itemView) {
setupActionMenu(attachment_container)
image_attachment.setVisible(false) image_attachment.setVisible(false)
audio_video_attachment.setVisible(true) audio_video_attachment.setVisible(true)
setupActionMenu(attachment_container)
setupActionMenu(audio_video_attachment)
} }
} }
......
...@@ -28,7 +28,7 @@ interface ChatRoomView : LoadingView, MessageView { ...@@ -28,7 +28,7 @@ interface ChatRoomView : LoadingView, MessageView {
/** /**
* Perform file selection with the mime type [filter] * Perform file selection with the mime type [filter]
*/ */
fun showFileSelection(filter: Array<String>) fun showFileSelection(filter: Array<String>?)
/** /**
* Uploads a file to a chat room. * Uploads a file to a chat room.
......
...@@ -93,8 +93,8 @@ class ChatRoomActivity : AppCompatActivity(), HasSupportFragmentInjector { ...@@ -93,8 +93,8 @@ class ChatRoomActivity : AppCompatActivity(), HasSupportFragmentInjector {
isChatRoomSubscribed = intent.getBooleanExtra(INTENT_CHAT_IS_SUBSCRIBED, true) isChatRoomSubscribed = intent.getBooleanExtra(INTENT_CHAT_IS_SUBSCRIBED, true)
if (supportFragmentManager.findFragmentByTag("ChatRoomFragment") == null) { if (supportFragmentManager.findFragmentByTag(TAG_CHAT_ROOM_FRAGMENT) == null) {
addFragment("ChatRoomFragment", R.id.fragment_container) { addFragment(TAG_CHAT_ROOM_FRAGMENT, R.id.fragment_container) {
newInstance(chatRoomId, chatRoomName, chatRoomType, isChatRoomReadOnly, chatRoomLastSeen, newInstance(chatRoomId, chatRoomName, chatRoomType, isChatRoomReadOnly, chatRoomLastSeen,
isChatRoomSubscribed) isChatRoomSubscribed)
} }
...@@ -156,4 +156,8 @@ class ChatRoomActivity : AppCompatActivity(), HasSupportFragmentInjector { ...@@ -156,4 +156,8 @@ class ChatRoomActivity : AppCompatActivity(), HasSupportFragmentInjector {
super.onBackPressed() super.onBackPressed()
overridePendingTransition(R.anim.close_enter, R.anim.close_exit) overridePendingTransition(R.anim.close_enter, R.anim.close_exit)
} }
companion object {
const val TAG_CHAT_ROOM_FRAGMENT = "ChatRoomFragment"
}
} }
\ No newline at end of file
...@@ -479,12 +479,18 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR ...@@ -479,12 +479,18 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
button_add_reaction.tag = drawableId button_add_reaction.tag = drawableId
} }
override fun showFileSelection(filter: Array<String>) { override fun showFileSelection(filter: Array<String>?) {
ui { ui {
val intent = Intent(Intent.ACTION_GET_CONTENT) val intent = Intent(Intent.ACTION_GET_CONTENT)
// Must set a type otherwise the intent won't resolve
intent.type = "*/*" intent.type = "*/*"
intent.putExtra(Intent.EXTRA_MIME_TYPES, filter)
intent.addCategory(Intent.CATEGORY_OPENABLE) intent.addCategory(Intent.CATEGORY_OPENABLE)
// Filter selectable files to those that match the whitelist for this particular server
if (filter != null) {
intent.putExtra(Intent.EXTRA_MIME_TYPES, filter)
}
startActivityForResult(intent, REQUEST_CODE_FOR_PERFORM_SAF) startActivityForResult(intent, REQUEST_CODE_FOR_PERFORM_SAF)
} }
} }
......
...@@ -64,6 +64,10 @@ class ChatRoomsPresenter @Inject constructor( ...@@ -64,6 +64,10 @@ class ChatRoomsPresenter @Inject constructor(
view.showLoading() view.showLoading()
subscribeStatusChange() subscribeStatusChange()
try { try {
// If we still don't have 'Store_Last_Message' setting, refresh the settings
if (!settings.hasShowLastMessage()) {
refreshSettingsInteractor.refresh(currentServer)
}
view.updateChatRooms(getUserChatRooms()) view.updateChatRooms(getUserChatRooms())
} catch (ex: RocketChatException) { } catch (ex: RocketChatException) {
ex.message?.let { ex.message?.let {
...@@ -226,9 +230,11 @@ class ChatRoomsPresenter @Inject constructor( ...@@ -226,9 +230,11 @@ class ChatRoomsPresenter @Inject constructor(
} }
ChatRoomsSortOrder.ACTIVITY -> { ChatRoomsSortOrder.ACTIVITY -> {
when (groupByType) { when (groupByType) {
true -> openChatRooms.sortedWith(compareBy(ChatRoom::type).thenByDescending { it.lastMessage?.timestamp }) true -> openChatRooms.sortedWith(compareBy(ChatRoom::type).thenByDescending { chatroom ->
chatRoomTimestamp(chatroom)
})
false -> openChatRooms.sortedByDescending { chatRoom -> false -> openChatRooms.sortedByDescending { chatRoom ->
chatRoom.lastMessage?.timestamp chatRoomTimestamp(chatRoom)
} }
} }
} }
...@@ -238,6 +244,14 @@ class ChatRoomsPresenter @Inject constructor( ...@@ -238,6 +244,14 @@ class ChatRoomsPresenter @Inject constructor(
} }
} }
private fun chatRoomTimestamp(chatRoom: ChatRoom): Long? {
return if (settings.hasShowLastMessage() && settings.showLastMessage()) {
chatRoom.lastMessage?.timestamp ?: chatRoom.updatedAt
} else {
chatRoom.updatedAt
}
}
private fun compareBy(selector: KProperty1<ChatRoom, RoomType>): Comparator<ChatRoom> { private fun compareBy(selector: KProperty1<ChatRoom, RoomType>): Comparator<ChatRoom> {
return Comparator { a, b -> getTypeConstant(a.type) - getTypeConstant(b.type) } return Comparator { a, b -> getTypeConstant(a.type) - getTypeConstant(b.type) }
} }
......
...@@ -16,12 +16,9 @@ import chat.rocket.android.R ...@@ -16,12 +16,9 @@ import chat.rocket.android.R
import chat.rocket.android.infrastructure.LocalRepository import chat.rocket.android.infrastructure.LocalRepository
import chat.rocket.android.infrastructure.checkIfMyself import chat.rocket.android.infrastructure.checkIfMyself
import chat.rocket.android.server.domain.PublicSettings import chat.rocket.android.server.domain.PublicSettings
import chat.rocket.android.server.domain.showLastMessage
import chat.rocket.android.server.domain.useRealName import chat.rocket.android.server.domain.useRealName
import chat.rocket.android.util.extensions.avatarUrl import chat.rocket.android.util.extensions.*
import chat.rocket.android.util.extensions.content
import chat.rocket.android.util.extensions.inflate
import chat.rocket.android.util.extensions.setVisible
import chat.rocket.android.util.extensions.textContent
import chat.rocket.common.model.RoomType import chat.rocket.common.model.RoomType
import chat.rocket.core.model.ChatRoom import chat.rocket.core.model.ChatRoom
import com.facebook.drawee.view.SimpleDraweeView import com.facebook.drawee.view.SimpleDraweeView
...@@ -51,8 +48,15 @@ class ChatRoomsAdapter(private val context: Context, ...@@ -51,8 +48,15 @@ class ChatRoomsAdapter(private val context: Context,
bindAvatar(chatRoom, image_avatar) bindAvatar(chatRoom, image_avatar)
bindName(chatRoom, text_chat_name) bindName(chatRoom, text_chat_name)
bindIcon(chatRoom, image_chat_icon) bindIcon(chatRoom, image_chat_icon)
if (settings.showLastMessage()) {
text_last_message.setVisible(true)
text_last_message_date_time.setVisible(true)
bindLastMessageDateTime(chatRoom, text_last_message_date_time) bindLastMessageDateTime(chatRoom, text_last_message_date_time)
bindLastMessage(chatRoom, text_last_message) bindLastMessage(chatRoom, text_last_message)
} else {
text_last_message.setVisible(false)
text_last_message_date_time.setVisible(false)
}
bindUnreadMessages(chatRoom, text_total_unread_messages) bindUnreadMessages(chatRoom, text_total_unread_messages)
if (chatRoom.alert || chatRoom.unread > 0) { if (chatRoom.alert || chatRoom.unread > 0) {
......
...@@ -23,6 +23,7 @@ import chat.rocket.android.helper.SharedPreferenceHelper ...@@ -23,6 +23,7 @@ import chat.rocket.android.helper.SharedPreferenceHelper
import chat.rocket.android.infrastructure.LocalRepository import chat.rocket.android.infrastructure.LocalRepository
import chat.rocket.android.server.domain.GetCurrentServerInteractor import chat.rocket.android.server.domain.GetCurrentServerInteractor
import chat.rocket.android.server.domain.SettingsRepository import chat.rocket.android.server.domain.SettingsRepository
import chat.rocket.android.server.domain.showLastMessage
import chat.rocket.android.util.extensions.* import chat.rocket.android.util.extensions.*
import chat.rocket.android.widget.DividerItemDecoration import chat.rocket.android.widget.DividerItemDecoration
import chat.rocket.common.model.RoomType import chat.rocket.common.model.RoomType
...@@ -240,6 +241,7 @@ class ChatRoomsFragment : Fragment(), ChatRoomsView { ...@@ -240,6 +241,7 @@ class ChatRoomsFragment : Fragment(), ChatRoomsView {
recycler_view.itemAnimator = DefaultItemAnimator() recycler_view.itemAnimator = DefaultItemAnimator()
// TODO - use a ViewModel Mapper instead of using settings on the adapter // TODO - use a ViewModel Mapper instead of using settings on the adapter
println(serverInteractor.get() + " -> ${settingsRepository.get(serverInteractor.get()!!).showLastMessage()}")
val baseAdapter = ChatRoomsAdapter(it, val baseAdapter = ChatRoomsAdapter(it,
settingsRepository.get(serverInteractor.get()!!), localRepository) { settingsRepository.get(serverInteractor.get()!!), localRepository) {
chatRoom -> presenter.loadChatRoom(chatRoom) chatRoom -> presenter.loadChatRoom(chatRoom)
......
...@@ -25,7 +25,7 @@ class RefreshSettingsInteractor @Inject constructor( ...@@ -25,7 +25,7 @@ class RefreshSettingsInteractor @Inject constructor(
HIDE_USER_JOIN, HIDE_USER_LEAVE, HIDE_USER_JOIN, HIDE_USER_LEAVE,
HIDE_TYPE_AU, HIDE_MUTE_UNMUTE, HIDE_TYPE_RU, ALLOW_MESSAGE_DELETING, HIDE_TYPE_AU, HIDE_MUTE_UNMUTE, HIDE_TYPE_RU, ALLOW_MESSAGE_DELETING,
ALLOW_MESSAGE_EDITING, ALLOW_MESSAGE_PINNING, SHOW_DELETED_STATUS, SHOW_EDITED_STATUS, ALLOW_MESSAGE_EDITING, ALLOW_MESSAGE_PINNING, SHOW_DELETED_STATUS, SHOW_EDITED_STATUS,
WIDE_TILE_310) WIDE_TILE_310, STORE_LAST_MESSAGE)
suspend fun refresh(server: String) { suspend fun refresh(server: String) {
withContext(CommonPool) { withContext(CommonPool) {
......
...@@ -49,6 +49,7 @@ const val ALLOW_MESSAGE_EDITING = "Message_AllowEditing" ...@@ -49,6 +49,7 @@ const val ALLOW_MESSAGE_EDITING = "Message_AllowEditing"
const val SHOW_DELETED_STATUS = "Message_ShowDeletedStatus" const val SHOW_DELETED_STATUS = "Message_ShowDeletedStatus"
const val SHOW_EDITED_STATUS = "Message_ShowEditedStatus" const val SHOW_EDITED_STATUS = "Message_ShowEditedStatus"
const val ALLOW_MESSAGE_PINNING = "Message_AllowPinning" const val ALLOW_MESSAGE_PINNING = "Message_AllowPinning"
const val STORE_LAST_MESSAGE = "Store_Last_Message"
/* /*
* Extension functions for Public Settings. * Extension functions for Public Settings.
...@@ -57,6 +58,7 @@ const val ALLOW_MESSAGE_PINNING = "Message_AllowPinning" ...@@ -57,6 +58,7 @@ const val ALLOW_MESSAGE_PINNING = "Message_AllowPinning"
* ServerPresenter.kt and a extension function to access it * ServerPresenter.kt and a extension function to access it
*/ */
fun PublicSettings.isLdapAuthenticationEnabled(): Boolean = this[LDAP_ENABLE]?.value == true fun PublicSettings.isLdapAuthenticationEnabled(): Boolean = this[LDAP_ENABLE]?.value == true
fun PublicSettings.isCasAuthenticationEnabled(): Boolean = this[CAS_ENABLE]?.value == true fun PublicSettings.isCasAuthenticationEnabled(): Boolean = this[CAS_ENABLE]?.value == true
fun PublicSettings.casLoginUrl(): String = this[CAS_LOGIN_URL]?.value.toString() fun PublicSettings.casLoginUrl(): String = this[CAS_LOGIN_URL]?.value.toString()
fun PublicSettings.isRegistrationEnabledForNewUsers(): Boolean = this[ACCOUNT_REGISTRATION]?.value == "Public" fun PublicSettings.isRegistrationEnabledForNewUsers(): Boolean = this[ACCOUNT_REGISTRATION]?.value == "Public"
...@@ -84,13 +86,15 @@ fun PublicSettings.allowedMessagePinning(): Boolean = this[ALLOW_MESSAGE_PINNING ...@@ -84,13 +86,15 @@ fun PublicSettings.allowedMessagePinning(): Boolean = this[ALLOW_MESSAGE_PINNING
fun PublicSettings.allowedMessageEditing(): Boolean = this[ALLOW_MESSAGE_EDITING]?.value == true fun PublicSettings.allowedMessageEditing(): Boolean = this[ALLOW_MESSAGE_EDITING]?.value == true
fun PublicSettings.allowedMessageDeleting(): Boolean = this[ALLOW_MESSAGE_DELETING]?.value == true fun PublicSettings.allowedMessageDeleting(): Boolean = this[ALLOW_MESSAGE_DELETING]?.value == true
fun PublicSettings.uploadMimeTypeFilter(): Array<String> { fun PublicSettings.hasShowLastMessage(): Boolean = this[STORE_LAST_MESSAGE] != null
val values = this[UPLOAD_WHITELIST_MIMETYPES]?.value fun PublicSettings.showLastMessage(): Boolean = this[STORE_LAST_MESSAGE]?.value == true
values?.let { it as String }?.split(",")?.let {
return it.mapToTypedArray { it.trim() }
}
return arrayOf("*/*") fun PublicSettings.uploadMimeTypeFilter(): Array<String>? {
val values = this[UPLOAD_WHITELIST_MIMETYPES]?.value as String?
if (!values.isNullOrBlank()) {
return values!!.split(",").mapToTypedArray { it.trim() }
}
return null
} }
fun PublicSettings.uploadMaxFileSize(): Int { fun PublicSettings.uploadMaxFileSize(): Int {
......
...@@ -22,46 +22,64 @@ ...@@ -22,46 +22,64 @@
<ImageView <ImageView
android:id="@+id/image_chat_icon" android:id="@+id/image_chat_icon"
android:layout_width="12dp" android:layout_width="12dp"
android:layout_height="12dp" android:layout_height="0dp"
android:layout_marginStart="16dp" android:layout_marginStart="16dp"
app:layout_constraintBottom_toBottomOf="@+id/text_chat_name"
app:layout_constraintStart_toEndOf="@+id/image_avatar" app:layout_constraintStart_toEndOf="@+id/image_avatar"
app:layout_constraintTop_toTopOf="@+id/image_avatar" app:layout_constraintTop_toTopOf="@+id/text_chat_name"
tools:src="@drawable/ic_hashtag_12dp" /> tools:src="@drawable/ic_hashtag_12dp" />
<TextView
android:id="@+id/text_last_message"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginTop="2dp"
android:layout_weight="0.8"
android:ellipsize="end"
android:maxLines="2"
android:textDirection="locale"
android:visibility="visible"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="@+id/image_chat_icon"
app:layout_constraintTop_toBottomOf="@+id/text_chat_name"
tools:text="Filipe de Lima Brito: Type something that is very big and need at least to lines, or maybe even more" />
<TextView <TextView
android:id="@+id/text_chat_name" android:id="@+id/text_chat_name"
style="@style/ChatRoom.Name.TextView" style="@style/ChatRoom.Name.TextView"
android:layout_width="wrap_content" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="8dp" android:layout_marginStart="8dp"
android:ellipsize="end"
android:lines="1"
android:maxLines="1"
android:textDirection="locale" android:textDirection="locale"
app:layout_constraintBottom_toTopOf="@+id/text_last_message"
app:layout_constraintEnd_toStartOf="@+id/text_last_message_date_time"
app:layout_constraintStart_toEndOf="@+id/image_chat_icon" app:layout_constraintStart_toEndOf="@+id/image_chat_icon"
app:layout_constraintTop_toTopOf="parent"
tools:text="general" /> tools:text="general" />
<TextView <TextView
android:id="@+id/text_last_message_date_time" android:id="@+id/text_last_message_date_time"
style="@style/Timestamp.TextView" style="@style/Timestamp.TextView"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="0dp"
android:layout_marginStart="8dp" android:gravity="center"
app:layout_constraintBottom_toBottomOf="@+id/text_chat_name"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@+id/text_chat_name"
tools:text="11:45 AM" />
<TextView
android:id="@+id/text_last_message"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp" android:layout_marginEnd="8dp"
app:layout_constraintBottom_toBottomOf="@+id/layout_unread_messages_badge"
android:layout_marginTop="2dp" android:layout_marginTop="2dp"
android:ellipsize="end" android:ellipsize="end"
android:maxLines="2" android:maxLines="2"
android:textDirection="locale" android:textDirection="locale"
tools:visibility="visible"
app:layout_constraintEnd_toStartOf="@+id/layout_unread_messages_badge" app:layout_constraintEnd_toStartOf="@+id/layout_unread_messages_badge"
app:layout_constraintStart_toStartOf="@+id/image_chat_icon" app:layout_constraintTop_toTopOf="@+id/text_chat_name"
app:layout_constraintTop_toBottomOf="@+id/text_chat_name" tools:text="11:45 AM" />
tools:text="Filipe de Lima Brito: Type something that is very big and need at least to lines, or maybe even more" />
<include <include
android:id="@+id/layout_unread_messages_badge" android:id="@+id/layout_unread_messages_badge"
...@@ -69,6 +87,6 @@ ...@@ -69,6 +87,6 @@
android:layout_width="18dp" android:layout_width="18dp"
android:layout_height="18dp" android:layout_height="18dp"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@+id/text_last_message" /> app:layout_constraintTop_toTopOf="@+id/text_chat_name" />
</android.support.constraint.ConstraintLayout> </android.support.constraint.ConstraintLayout>
\ No newline at end of file
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/message_container"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:background="?android:attr/selectableItemBackground" android:background="?android:attr/selectableItemBackground"
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/attachment_container"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:background="?android:attr/selectableItemBackground" android:background="?android:attr/selectableItemBackground"
......
package chat.rocket.android.server.domain
import chat.rocket.core.model.Value
import com.google.common.truth.Truth.assertThat
import org.junit.Test
class SettingsRepositoryTest {
@Test
fun `uploadMimeFilter returns null if not specified`() {
val settings = emptyMap<String, Value<Any>>()
val filter = settings.uploadMimeTypeFilter()
assertThat(filter).isNull()
}
}
\ No newline at end of file
package chat.rocket.android.server.domain
import chat.rocket.core.model.Value
import com.google.common.truth.Truth.assertThat
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.Parameterized
@RunWith(Parameterized::class)
class `SettingsRepository UploadMimeTypeFilter WhitelistIsSet Test`(private val allowedMimeTypes: String,
private val expectedFilter: Array<String>?) {
companion object {
@JvmStatic
@Parameterized.Parameters(name = "\"{0}\"")
fun data(): Collection<Array<Any?>> = listOf(
arrayOf<Any?>("", null),
arrayOf<Any?>(" ", null),
arrayOf<Any?>("image/*", arrayOf("image/*")),
arrayOf<Any?>("image/*,video/*", arrayOf("image/*", "video/*")),
arrayOf<Any?>("image/*, video/*", arrayOf("image/*", "video/*")),
arrayOf<Any?>("image/*,\tvideo/*", arrayOf("image/*", "video/*"))
)
}
@Test
fun test() {
val settings = mapOf<String, Value<Any>>(Pair(UPLOAD_WHITELIST_MIMETYPES, Value(allowedMimeTypes)))
val filter = settings.uploadMimeTypeFilter()
assertThat(filter).isEqualTo(expectedFilter)
}
}
...@@ -4,12 +4,12 @@ ext { ...@@ -4,12 +4,12 @@ ext {
compileSdk : 27, compileSdk : 27,
targetSdk : 27, targetSdk : 27,
buildTools : '27.0.3', buildTools : '27.0.3',
kotlin : '1.2.40', kotlin : '1.2.41',
coroutine : '0.22.5', coroutine : '0.22.5',
dokka : '0.9.16', dokka : '0.9.16',
// Main dependencies // Main dependencies
support : '27.1.0', support : '27.1.1',
constraintLayout : '1.1.0', constraintLayout : '1.1.0',
androidKtx : '0.3', androidKtx : '0.3',
dagger : '2.14.1', dagger : '2.14.1',
...@@ -35,7 +35,7 @@ ext { ...@@ -35,7 +35,7 @@ ext {
// For testing // For testing
junit : '4.12', junit : '4.12',
truth : '0.36', truth : '0.36',
expresso : '3.0.1', espresso : '3.0.2',
mockito : '2.10.0' mockito : '2.10.0'
] ]
libraries = [ libraries = [
...@@ -98,7 +98,8 @@ ext { ...@@ -98,7 +98,8 @@ ext {
// For testing // For testing
junit : "junit:junit:$versions.junit", junit : "junit:junit:$versions.junit",
expressoCore : "com.android.support.test.espresso:espresso-core:${versions.expresso}", espressoCore : "com.android.support.test.espresso:espresso-core:${versions.espresso}",
espressoIntents : "com.android.support.test.espresso:espresso-intents:${versions.espresso}",
roomTest : "android.arch.persistence.room:testing:${versions.room}", roomTest : "android.arch.persistence.room:testing:${versions.room}",
truth : "com.google.truth:truth:$versions.truth", truth : "com.google.truth:truth:$versions.truth",
] ]
......
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