Unverified Commit b5e748b3 authored by divyanshu bhargava's avatar divyanshu bhargava Committed by GitHub

Merge branch 'develop' into tap-on-message

parents 213c89fb d9242c67
......@@ -58,6 +58,9 @@ jobs:
- run:
name: Run Unit test
command: ./gradlew test
- run:
name: Compile Instrumentation test
command: ./gradlew assembleAndroidTest
- store_artifacts:
path: app/build/reports/
destination: reports
......
......@@ -13,7 +13,7 @@ android {
applicationId "chat.rocket.android"
minSdkVersion 21
targetSdkVersion versions.targetSdk
versionCode 2015
versionCode 2019
versionName "2.1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
multiDexEnabled true
......@@ -114,9 +114,9 @@ dependencies {
}
testImplementation libraries.junit
androidTestImplementation(libraries.expressoCore, {
exclude group: 'com.android.support', module: 'support-annotations'
})
testImplementation libraries.truth
androidTestImplementation libraries.espressoCore
androidTestImplementation libraries.espressoIntents
}
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
......@@ -80,12 +80,6 @@
android:theme="@style/AppTheme"
android:windowSoftInputMode="adjustResize|stateAlwaysHidden" />
<!-- TODO: Change to fragment-->
<activity
android:name=".chatroom.ui.PinnedMessagesActivity"
android:theme="@style/AppTheme"
android:windowSoftInputMode="adjustResize|stateAlwaysHidden" />
<!-- TODO: Change to fragment-->
<activity
android:name=".settings.password.ui.PasswordActivity"
......
......@@ -268,16 +268,15 @@ class LoginPresenter @Inject constructor(
val token = retryIO("login") {
when (loginType) {
TYPE_LOGIN_USER_EMAIL -> {
if (usernameOrEmail.isEmail()) {
client.loginWithEmail(usernameOrEmail, password)
} else {
if (settings.isLdapAuthenticationEnabled()) {
when {
settings.isLdapAuthenticationEnabled() ->
client.loginWithLdap(usernameOrEmail, password)
} else {
usernameOrEmail.isEmail() ->
client.loginWithEmail(usernameOrEmail, password)
else ->
client.login(usernameOrEmail, password)
}
}
}
TYPE_LOGIN_CAS -> {
delay(3, TimeUnit.SECONDS)
client.loginWithCas(credentialToken)
......
......@@ -14,10 +14,9 @@ class AudioAttachmentViewHolder(itemView: View,
init {
with(itemView) {
setupActionMenu(attachment_container)
image_attachment.setVisible(false)
audio_video_attachment.setVisible(true)
setupActionMenu(attachment_container)
setupActionMenu(audio_video_attachment)
}
}
......
......@@ -19,12 +19,9 @@ class AuthorAttachmentViewHolder(itemView: View,
init {
with(itemView) {
setupActionMenu(author_attachment_container)
setupActionMenu(text_fields)
setupActionMenu(text_author_name)
}
}
override fun bindViews(data: AuthorAttachmentViewModel) {
with(itemView) {
data.icon?.let { icon ->
......
......@@ -3,6 +3,8 @@ package chat.rocket.android.chatroom.adapter
import android.support.v7.widget.RecyclerView
import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
import androidx.core.view.children
import chat.rocket.android.R
import chat.rocket.android.chatroom.ui.bottomsheet.BottomSheetMenu
import chat.rocket.android.chatroom.ui.bottomsheet.adapter.ActionListAdapter
......@@ -74,7 +76,7 @@ abstract class BaseViewHolder<T : BaseViewModel<*>>(
fun onActionSelected(item: MenuItem, message: Message)
}
val onClickListener = { view: View ->
private val onClickListener = { view: View ->
if (data?.message?.isSystemMessage() == false) {
val menuItems = view.context.inflate(R.menu.message_actions).toList()
menuItems.find { it.itemId == R.id.action_menu_msg_pin_unpin }?.apply {
......@@ -90,6 +92,13 @@ abstract class BaseViewHolder<T : BaseViewModel<*>>(
internal fun setupActionMenu(view: View) {
if (listener.isActionsEnabled()) {
view.setOnClickListener(onClickListener)
if (view is ViewGroup) {
for (child in view.children) {
if (child !is RecyclerView && child.id != R.id.recycler_view_reactions) {
setupActionMenu(child)
}
}
}
}
}
......
......@@ -20,7 +20,6 @@ class ColorAttachmentViewHolder(itemView: View,
init {
with(itemView) {
setupActionMenu(attachment_text)
setupActionMenu(color_attachment_container)
attachment_text.movementMethod = LinkMovementMethod()
}
......
......@@ -17,11 +17,9 @@ class GenericFileAttachmentViewHolder(itemView: View,
init {
with(itemView) {
setupActionMenu(file_attachment_container)
setupActionMenu(text_file_name)
}
}
override fun bindViews(data: GenericFileAttachmentViewModel) {
with(itemView) {
text_file_name.content = data.attachmentTitle
......
......@@ -47,7 +47,6 @@ class ImageAttachmentViewHolder(itemView: View,
init {
with(itemView) {
setupActionMenu(attachment_container)
setupActionMenu(image_attachment)
}
}
......
......@@ -4,7 +4,7 @@ import android.text.method.LinkMovementMethod
import android.view.View
import chat.rocket.android.chatroom.viewmodel.MessageAttachmentViewModel
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(
itemView: View,
......@@ -14,8 +14,8 @@ class MessageAttachmentViewHolder(
init {
with(itemView) {
setupActionMenu(attachment_container)
text_content.movementMethod = LinkMovementMethod()
setupActionMenu(text_content)
}
}
......
......@@ -4,7 +4,9 @@ import android.graphics.Color
import android.text.method.LinkMovementMethod
import android.view.View
import chat.rocket.android.chatroom.viewmodel.MessageViewModel
import chat.rocket.android.util.extensions.setVisible
import chat.rocket.android.widget.emoji.EmojiReactionListener
import chat.rocket.core.model.isSystemMessage
import kotlinx.android.synthetic.main.avatar.view.*
import kotlinx.android.synthetic.main.item_message.view.*
......@@ -16,8 +18,8 @@ class MessageViewHolder(
init {
with(itemView) {
setupActionMenu(message_container)
text_content.movementMethod = LinkMovementMethod()
setupActionMenu(text_content)
}
}
......@@ -33,6 +35,11 @@ class MessageViewHolder(
text_content.setTextColor(
if (data.isTemporary) Color.GRAY else Color.BLACK
)
if (!data.message.isSystemMessage() && data.message.editedBy != null){
text_edit_indicator.setVisible(true)
}else{
text_edit_indicator.setVisible(false)
}
}
}
}
\ No newline at end of file
......@@ -5,6 +5,7 @@ import android.net.Uri
import android.view.View
import chat.rocket.android.chatroom.viewmodel.UrlPreviewViewModel
import chat.rocket.android.util.extensions.content
import chat.rocket.android.util.extensions.openTabbedUrl
import chat.rocket.android.util.extensions.setVisible
import chat.rocket.android.widget.emoji.EmojiReactionListener
import kotlinx.android.synthetic.main.message_url_preview.view.*
......@@ -32,10 +33,17 @@ class UrlPreviewViewHolder(itemView: View,
text_title.content = data.title
text_description.content = data.description ?: ""
url_preview_layout.setOnClickListener { view ->
view.context.startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(data.rawData.url)))
}
url_preview_layout.setOnClickListener(onClickListener)
text_host.setOnClickListener(onClickListener)
text_title.setOnClickListener(onClickListener)
image_preview.setOnClickListener(onClickListener)
text_description.setOnClickListener(onClickListener)
}
}
private val onClickListener = { view: View ->
if (data != null) {
view.openTabbedUrl(Uri.parse(data!!.rawData.url))
}
}
}
\ No newline at end of file
......@@ -14,10 +14,9 @@ class VideoAttachmentViewHolder(itemView: View,
init {
with(itemView) {
setupActionMenu(attachment_container)
image_attachment.setVisible(false)
audio_video_attachment.setVisible(true)
setupActionMenu(attachment_container)
setupActionMenu(audio_video_attachment)
}
}
......
......@@ -14,6 +14,12 @@ class ChatRoomNavigator(internal val activity: ChatRoomActivity) {
}
}
fun toPinnedMessageList(chatRoomId: String, chatRoomType: String) {
activity.addFragmentBackStack("PinnedMessages", R.id.fragment_container){
chat.rocket.android.pinnedmessages.ui.newInstance(chatRoomId,chatRoomType)
}
}
fun toNewServer() {
activity.startActivity(activity.changeServerIntent())
activity.finish()
......
......@@ -502,6 +502,8 @@ class ChatRoomPresenter @Inject constructor(
fun toMembersList(chatRoomId: String, chatRoomType: String) = navigator.toMembersList(chatRoomId, chatRoomType)
fun toPinnedMessageList(chatRoomId: String, chatRoomType: String) = navigator.toPinnedMessageList(chatRoomId,chatRoomType)
fun loadChatRooms() {
launchUI(strategy) {
try {
......
......@@ -28,7 +28,7 @@ interface ChatRoomView : LoadingView, MessageView {
/**
* 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.
......
......@@ -93,8 +93,8 @@ class ChatRoomActivity : AppCompatActivity(), HasSupportFragmentInjector {
isChatRoomSubscribed = intent.getBooleanExtra(INTENT_CHAT_IS_SUBSCRIBED, true)
if (supportFragmentManager.findFragmentByTag("ChatRoomFragment") == null) {
addFragment("ChatRoomFragment", R.id.fragment_container) {
if (supportFragmentManager.findFragmentByTag(TAG_CHAT_ROOM_FRAGMENT) == null) {
addFragment(TAG_CHAT_ROOM_FRAGMENT, R.id.fragment_container) {
newInstance(chatRoomId, chatRoomName, chatRoomType, isChatRoomReadOnly, chatRoomLastSeen,
isChatRoomSubscribed)
}
......@@ -156,4 +156,8 @@ class ChatRoomActivity : AppCompatActivity(), HasSupportFragmentInjector {
super.onBackPressed()
overridePendingTransition(R.anim.close_enter, R.anim.close_exit)
}
companion object {
const val TAG_CHAT_ROOM_FRAGMENT = "ChatRoomFragment"
}
}
\ No newline at end of file
......@@ -35,7 +35,6 @@ import kotlinx.android.synthetic.main.fragment_chat_room.*
import kotlinx.android.synthetic.main.message_attachment_options.*
import kotlinx.android.synthetic.main.message_composer.*
import kotlinx.android.synthetic.main.message_list.*
import timber.log.Timber
import java.util.concurrent.atomic.AtomicInteger
import javax.inject.Inject
......@@ -177,12 +176,7 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
presenter.toMembersList(chatRoomId, chatRoomType)
}
R.id.action_pinned_messages -> {
val intent = Intent(activity, PinnedMessagesActivity::class.java).apply {
putExtra(BUNDLE_CHAT_ROOM_ID, chatRoomId)
putExtra(BUNDLE_CHAT_ROOM_TYPE, chatRoomType)
putExtra(BUNDLE_CHAT_ROOM_NAME, chatRoomName)
}
startActivity(intent)
presenter.toPinnedMessageList(chatRoomId,chatRoomType)
}
}
return true
......@@ -485,12 +479,18 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
button_add_reaction.tag = drawableId
}
override fun showFileSelection(filter: Array<String>) {
override fun showFileSelection(filter: Array<String>?) {
ui {
val intent = Intent(Intent.ACTION_GET_CONTENT)
// Must set a type otherwise the intent won't resolve
intent.type = "*/*"
intent.putExtra(Intent.EXTRA_MIME_TYPES, filter)
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)
}
}
......
package chat.rocket.android.chatroom.ui
import android.os.Bundle
import android.support.v4.app.Fragment
import android.support.v7.app.AppCompatActivity
import chat.rocket.android.R
import chat.rocket.android.util.extensions.addFragment
import chat.rocket.android.util.extensions.textContent
import dagger.android.AndroidInjection
import dagger.android.AndroidInjector
import dagger.android.DispatchingAndroidInjector
import dagger.android.support.HasSupportFragmentInjector
import kotlinx.android.synthetic.main.app_bar_chat_room.*
import javax.inject.Inject
private const val INTENT_CHAT_ROOM_ID = "chat_room_id"
private const val INTENT_CHAT_ROOM_NAME = "chat_room_name"
private const val INTENT_CHAT_ROOM_TYPE = "chat_room_type"
class PinnedMessagesActivity : AppCompatActivity(), HasSupportFragmentInjector {
@Inject lateinit var fragmentDispatchingAndroidInjector: DispatchingAndroidInjector<Fragment>
private lateinit var chatRoomId: String
private lateinit var chatRoomName: String
private lateinit var chatRoomType: String
override fun onCreate(savedInstanceState: Bundle?) {
AndroidInjection.inject(this)
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_pinned_messages)
chatRoomId = intent.getStringExtra(INTENT_CHAT_ROOM_ID)
requireNotNull(chatRoomId) { "no chat_room_id provided in Intent extras" }
chatRoomName = intent.getStringExtra(INTENT_CHAT_ROOM_NAME)
requireNotNull(chatRoomName) { "no chat_room_name provided in Intent extras" }
chatRoomType = intent.getStringExtra(INTENT_CHAT_ROOM_TYPE)
requireNotNull(chatRoomType) { "no chat_room_type provided in Intent extras" }
setupToolbar()
addFragment("PinnedMessagesFragment", R.id.fragment_container) {
newPinnedMessagesFragment(chatRoomId, chatRoomName, chatRoomType)
}
}
override fun onBackPressed() = finishActivity()
override fun supportFragmentInjector(): AndroidInjector<Fragment> {
return fragmentDispatchingAndroidInjector
}
private fun setupToolbar() {
setSupportActionBar(toolbar)
supportActionBar?.setDisplayShowTitleEnabled(false)
text_room_name.textContent = getString(R.string.title_pinned_messages)
toolbar.setNavigationOnClickListener {
finishActivity()
}
}
private fun finishActivity() {
super.onBackPressed()
overridePendingTransition(R.anim.close_enter, R.anim.close_exit)
}
}
\ No newline at end of file
......@@ -64,6 +64,10 @@ class ChatRoomsPresenter @Inject constructor(
view.showLoading()
subscribeStatusChange()
try {
// If we still don't have 'Store_Last_Message' setting, refresh the settings
if (!settings.hasShowLastMessage()) {
refreshSettingsInteractor.refresh(currentServer)
}
view.updateChatRooms(getUserChatRooms())
} catch (ex: RocketChatException) {
ex.message?.let {
......@@ -226,9 +230,11 @@ class ChatRoomsPresenter @Inject constructor(
}
ChatRoomsSortOrder.ACTIVITY -> {
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 ->
chatRoom.lastMessage?.timestamp
chatRoomTimestamp(chatRoom)
}
}
}
......@@ -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> {
return Comparator { a, b -> getTypeConstant(a.type) - getTypeConstant(b.type) }
}
......@@ -289,8 +303,9 @@ class ChatRoomsPresenter @Inject constructor(
private suspend fun getChatRoomsWithPreviews(chatRooms: List<ChatRoom>): List<ChatRoom> {
return chatRooms.map {
if (it.lastMessage != null) {
it.copy(lastMessage = viewModelMapper.map(it.lastMessage!!).last().preview)
val lastMessage = it.lastMessage
if (lastMessage != null) {
it.copy(lastMessage = viewModelMapper.map(lastMessage).last().preview)
} else {
it
}
......
......@@ -16,12 +16,9 @@ import chat.rocket.android.R
import chat.rocket.android.infrastructure.LocalRepository
import chat.rocket.android.infrastructure.checkIfMyself
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.util.extensions.avatarUrl
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.android.util.extensions.*
import chat.rocket.common.model.RoomType
import chat.rocket.core.model.ChatRoom
import com.facebook.drawee.view.SimpleDraweeView
......@@ -51,8 +48,15 @@ class ChatRoomsAdapter(private val context: Context,
bindAvatar(chatRoom, image_avatar)
bindName(chatRoom, text_chat_name)
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)
bindLastMessage(chatRoom, text_last_message)
} else {
text_last_message.setVisible(false)
text_last_message_date_time.setVisible(false)
}
bindUnreadMessages(chatRoom, text_total_unread_messages)
if (chatRoom.alert || chatRoom.unread > 0) {
......@@ -112,7 +116,15 @@ class ChatRoomsAdapter(private val context: Context,
}
private fun bindName(chatRoom: ChatRoom, textView: TextView) {
textView.textContent = chatRoom.name
textView.textContent = chatRoomName(chatRoom)
}
private fun chatRoomName(chatRoom: ChatRoom): String {
return if (settings.useRealName()) {
chatRoom.fullName ?: chatRoom.name
} else {
chatRoom.name
}
}
private fun bindLastMessageDateTime(chatRoom: ChatRoom, textView: TextView) {
......
......@@ -23,6 +23,7 @@ import chat.rocket.android.helper.SharedPreferenceHelper
import chat.rocket.android.infrastructure.LocalRepository
import chat.rocket.android.server.domain.GetCurrentServerInteractor
import chat.rocket.android.server.domain.SettingsRepository
import chat.rocket.android.server.domain.showLastMessage
import chat.rocket.android.util.extensions.*
import chat.rocket.android.widget.DividerItemDecoration
import chat.rocket.common.model.RoomType
......@@ -240,6 +241,7 @@ class ChatRoomsFragment : Fragment(), ChatRoomsView {
recycler_view.itemAnimator = DefaultItemAnimator()
// TODO - use a ViewModel Mapper instead of using settings on the adapter
println(serverInteractor.get() + " -> ${settingsRepository.get(serverInteractor.get()!!).showLastMessage()}")
val baseAdapter = ChatRoomsAdapter(it,
settingsRepository.get(serverInteractor.get()!!), localRepository) {
chatRoom -> presenter.loadChatRoom(chatRoom)
......
......@@ -12,7 +12,6 @@ import chat.rocket.android.chatroom.di.ChatRoomFragmentProvider
import chat.rocket.android.chatroom.di.ChatRoomModule
import chat.rocket.android.chatroom.di.PinnedMessagesFragmentProvider
import chat.rocket.android.chatroom.ui.ChatRoomActivity
import chat.rocket.android.chatroom.ui.PinnedMessagesActivity
import chat.rocket.android.chatrooms.di.ChatRoomsFragmentProvider
import chat.rocket.android.dagger.scope.PerActivity
import chat.rocket.android.main.di.MainModule
......@@ -50,13 +49,10 @@ abstract class ActivityBuilder {
@PerActivity
@ContributesAndroidInjector(modules = [ChatRoomModule::class,
ChatRoomFragmentProvider::class,
MembersFragmentProvider::class])
MembersFragmentProvider::class,
PinnedMessagesFragmentProvider::class])
abstract fun bindChatRoomActivity(): ChatRoomActivity
@PerActivity
@ContributesAndroidInjector(modules = [PinnedMessagesFragmentProvider::class])
abstract fun bindPinnedMessagesActivity(): PinnedMessagesActivity
@PerActivity
@ContributesAndroidInjector(modules = [PasswordFragmentProvider::class])
abstract fun bindPasswordActivity(): PasswordActivity
......
......@@ -38,7 +38,6 @@ import chat.rocket.core.internal.ReactionsAdapter
import com.facebook.drawee.backends.pipeline.DraweeConfig
import com.facebook.imagepipeline.backends.okhttp3.OkHttpImagePipelineConfigFactory
import com.facebook.imagepipeline.core.ImagePipelineConfig
import com.facebook.imagepipeline.listener.RequestListener
import com.facebook.imagepipeline.listener.RequestLoggingListener
import com.squareup.moshi.Moshi
import dagger.Module
......@@ -111,12 +110,12 @@ class AppModule {
@Provides
@Singleton
fun provideOkHttpClient(logger: HttpLoggingInterceptor): OkHttpClient {
return OkHttpClient.Builder().apply {
addInterceptor(logger)
connectTimeout(15, TimeUnit.SECONDS)
readTimeout(20, TimeUnit.SECONDS)
writeTimeout(15, TimeUnit.SECONDS)
}.build()
return OkHttpClient.Builder()
.addInterceptor(logger)
.connectTimeout(15, TimeUnit.SECONDS)
.readTimeout(20, TimeUnit.SECONDS)
.writeTimeout(15, TimeUnit.SECONDS)
.build()
}
@Provides
......@@ -138,8 +137,7 @@ class AppModule {
@Provides
@Singleton
fun provideImagePipelineConfig(context: Context, @ForFresco okHttpClient: OkHttpClient): ImagePipelineConfig {
val listeners = HashSet<RequestListener>()
listeners.add(RequestLoggingListener())
val listeners = setOf(RequestLoggingListener())
return OkHttpImagePipelineConfigFactory.newBuilder(context, okHttpClient)
.setRequestListeners(listeners)
......
......@@ -6,7 +6,6 @@ import android.graphics.Canvas
import android.graphics.Paint
import android.graphics.RectF
import android.net.Uri
import android.support.customtabs.CustomTabsIntent
import android.support.v4.content.res.ResourcesCompat
import android.text.Spanned
import android.text.style.ClickableSpan
......@@ -16,6 +15,7 @@ import android.view.View
import chat.rocket.android.R
import chat.rocket.android.server.domain.PublicSettings
import chat.rocket.android.server.domain.useRealName
import chat.rocket.android.util.extensions.openTabbedUrl
import chat.rocket.android.widget.emoji.EmojiParser
import chat.rocket.android.widget.emoji.EmojiRepository
import chat.rocket.android.widget.emoji.EmojiTypefaceSpan
......@@ -151,12 +151,7 @@ class MessageParser @Inject constructor(
if (!link.startsWith("@") && link !in consumed) {
builder.setSpan(object : ClickableSpan() {
override fun onClick(view: View) {
with(view) {
val tabsbuilder = CustomTabsIntent.Builder()
tabsbuilder.setToolbarColor(ResourcesCompat.getColor(context.resources, R.color.colorPrimary, context.theme))
val customTabsIntent = tabsbuilder.build()
customTabsIntent.launchUrl(context, getUri(link))
}
view.openTabbedUrl(getUri(link))
}
}, matcher.start(0), matcher.end(0))
consumed.add(link)
......
package chat.rocket.android.chatroom.di
import android.arch.lifecycle.LifecycleOwner
import chat.rocket.android.chatroom.presentation.PinnedMessagesView
import chat.rocket.android.chatroom.ui.PinnedMessagesFragment
import chat.rocket.android.core.lifecycle.CancelStrategy
import chat.rocket.android.dagger.scope.PerFragment
import chat.rocket.android.pinnedmessages.presentation.PinnedMessagesView
import chat.rocket.android.pinnedmessages.ui.PinnedMessagesFragment
import dagger.Module
import dagger.Provides
import kotlinx.coroutines.experimental.Job
......
package chat.rocket.android.chatroom.di
import chat.rocket.android.chatroom.ui.PinnedMessagesFragment
import chat.rocket.android.pinnedmessages.ui.PinnedMessagesFragment
import dagger.Module
import dagger.android.ContributesAndroidInjector
......
package chat.rocket.android.chatroom.presentation
package chat.rocket.android.pinnedmessages.presentation
import chat.rocket.android.chatroom.viewmodel.ViewModelMapper
import chat.rocket.android.core.lifecycle.CancelStrategy
......
package chat.rocket.android.chatroom.presentation
package chat.rocket.android.pinnedmessages.presentation
import chat.rocket.android.chatroom.viewmodel.BaseViewModel
import chat.rocket.android.core.behaviours.LoadingView
......
package chat.rocket.android.chatroom.ui
package chat.rocket.android.pinnedmessages.ui
import android.os.Bundle
import android.support.v4.app.Fragment
import android.support.v7.app.AppCompatActivity
import android.support.v7.widget.DefaultItemAnimator
import android.support.v7.widget.LinearLayoutManager
import android.support.v7.widget.RecyclerView
......@@ -10,10 +11,12 @@ import android.view.View
import android.view.ViewGroup
import chat.rocket.android.R
import chat.rocket.android.chatroom.adapter.ChatRoomAdapter
import chat.rocket.android.chatroom.presentation.PinnedMessagesPresenter
import chat.rocket.android.chatroom.presentation.PinnedMessagesView
import chat.rocket.android.chatroom.ui.ChatRoomActivity
import chat.rocket.android.chatroom.viewmodel.BaseViewModel
import chat.rocket.android.helper.EndlessRecyclerViewScrollListener
import chat.rocket.android.pinnedmessages.presentation.PinnedMessagesPresenter
import chat.rocket.android.pinnedmessages.presentation.PinnedMessagesView
import chat.rocket.android.util.extensions.inflate
import chat.rocket.android.util.extensions.setVisible
import chat.rocket.android.util.extensions.showToast
import chat.rocket.android.util.extensions.ui
......@@ -21,54 +24,69 @@ import dagger.android.support.AndroidSupportInjection
import kotlinx.android.synthetic.main.fragment_pinned_messages.*
import javax.inject.Inject
private const val BUNDLE_CHAT_ROOM_ID = "chat_room_id"
private const val BUNDLE_CHAT_ROOM_NAME = "chat_room_name"
private const val BUNDLE_CHAT_ROOM_TYPE = "chat_room_type"
fun newPinnedMessagesFragment(chatRoomId: String, chatRoomType: String, chatRoomName: String): Fragment {
fun newInstance(chatRoomId: String, chatRoomType: String) : Fragment {
return PinnedMessagesFragment().apply {
arguments = Bundle(3).apply {
arguments = Bundle(1).apply {
putString(BUNDLE_CHAT_ROOM_ID, chatRoomId)
putString(BUNDLE_CHAT_ROOM_NAME, chatRoomName)
putString(BUNDLE_CHAT_ROOM_TYPE, chatRoomType)
}
}
}
private const val BUNDLE_CHAT_ROOM_ID = "chat_room_id"
private const val BUNDLE_CHAT_ROOM_TYPE = "chat_room_type"
class PinnedMessagesFragment : Fragment(), PinnedMessagesView {
@Inject lateinit var presenter: PinnedMessagesPresenter
private lateinit var chatRoomId: String
private lateinit var chatRoomName: String
private lateinit var chatRoomType: String
private lateinit var adapter: ChatRoomAdapter
@Inject
lateinit var presenter: PinnedMessagesPresenter
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
AndroidSupportInjection.inject(this)
val bundle = arguments
if (bundle != null) {
if (bundle != null){
chatRoomId = bundle.getString(BUNDLE_CHAT_ROOM_ID)
chatRoomName = bundle.getString(BUNDLE_CHAT_ROOM_NAME)
chatRoomType = bundle.getString(BUNDLE_CHAT_ROOM_TYPE)
}else{
requireNotNull(bundle) { "no arguments supplied when the fragment was instantiated" }
}
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?) =
inflater.inflate(R.layout.fragment_pinned_messages, container, false)
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? = container?.inflate(R.layout.fragment_pinned_messages)
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
setupToolbar()
presenter.loadPinnedMessages(chatRoomId)
}
override fun showLoading() {
ui { view_loading.setVisible(true) }
override fun showPinnedMessages(pinnedMessages: List<BaseViewModel<*>>) {
ui {
if (recycler_view_pinned.adapter == null){
adapter = ChatRoomAdapter(chatRoomType,"",null,false)
recycler_view_pinned.adapter = adapter
val linearLayoutManager = LinearLayoutManager(context, LinearLayoutManager.VERTICAL,false)
recycler_view_pinned.layoutManager = linearLayoutManager
recycler_view_pinned.itemAnimator = DefaultItemAnimator()
if (pinnedMessages.size > 10){
recycler_view_pinned.addOnScrollListener(object : EndlessRecyclerViewScrollListener(linearLayoutManager){
override fun onLoadMore(page: Int, totalItemsCount: Int, recyclerView: RecyclerView?) {
presenter.loadPinnedMessages(chatRoomId)
}
override fun hideLoading() {
ui { view_loading.setVisible(false) }
})
}
togglePinView(pinnedMessages.size)
}
adapter.appendData(pinnedMessages)
}
}
override fun showMessage(resId: Int) {
......@@ -85,38 +103,23 @@ class PinnedMessagesFragment : Fragment(), PinnedMessagesView {
override fun showGenericErrorMessage() = showMessage(getString(R.string.msg_generic_error))
override fun showPinnedMessages(pinnedMessages: List<BaseViewModel<*>>) {
ui {
if (recycler_view_pinned.adapter == null) {
// TODO - add a better constructor for this case...
adapter = ChatRoomAdapter(chatRoomType, chatRoomName, null, false)
recycler_view_pinned.adapter = adapter
val linearLayoutManager = LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false)
recycler_view_pinned.layoutManager = linearLayoutManager
recycler_view_pinned.itemAnimator = DefaultItemAnimator()
if (pinnedMessages.size > 10) {
recycler_view_pinned.addOnScrollListener(object : EndlessRecyclerViewScrollListener(linearLayoutManager) {
override fun onLoadMore(page: Int, totalItemsCount: Int, recyclerView: RecyclerView?) {
presenter.loadPinnedMessages(chatRoomId)
}
})
}
togglePinView(pinnedMessages.size)
override fun showLoading() {
ui{ view_loading.setVisible(true) }
}
adapter.appendData(pinnedMessages)
override fun hideLoading() {
ui { view_loading.setVisible(false) }
}
private fun setupToolbar() {
(activity as ChatRoomActivity).setupToolbarTitle(getString(R.string.title_pinned_messages))
}
private fun togglePinView(size: Int) {
private fun togglePinView(size : Int){
if (size == 0){
iv_pin_icon.setVisible(true)
tv_pin_title.setVisible(true)
tv_pin_description.setVisible(true)
pin_view.setVisible(true)
}else{
iv_pin_icon.setVisible(false)
tv_pin_title.setVisible(false)
tv_pin_description.setVisible(false)
pin_view.setVisible(false)
}
}
}
\ No newline at end of file
......@@ -25,7 +25,7 @@ class RefreshSettingsInteractor @Inject constructor(
HIDE_USER_JOIN, HIDE_USER_LEAVE,
HIDE_TYPE_AU, HIDE_MUTE_UNMUTE, HIDE_TYPE_RU, ALLOW_MESSAGE_DELETING,
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) {
withContext(CommonPool) {
......
......@@ -49,6 +49,7 @@ const val ALLOW_MESSAGE_EDITING = "Message_AllowEditing"
const val SHOW_DELETED_STATUS = "Message_ShowDeletedStatus"
const val SHOW_EDITED_STATUS = "Message_ShowEditedStatus"
const val ALLOW_MESSAGE_PINNING = "Message_AllowPinning"
const val STORE_LAST_MESSAGE = "Store_Last_Message"
/*
* Extension functions for Public Settings.
......@@ -57,6 +58,7 @@ const val ALLOW_MESSAGE_PINNING = "Message_AllowPinning"
* ServerPresenter.kt and a extension function to access it
*/
fun PublicSettings.isLdapAuthenticationEnabled(): Boolean = this[LDAP_ENABLE]?.value == true
fun PublicSettings.isCasAuthenticationEnabled(): Boolean = this[CAS_ENABLE]?.value == true
fun PublicSettings.casLoginUrl(): String = this[CAS_LOGIN_URL]?.value.toString()
fun PublicSettings.isRegistrationEnabledForNewUsers(): Boolean = this[ACCOUNT_REGISTRATION]?.value == "Public"
......@@ -84,13 +86,15 @@ fun PublicSettings.allowedMessagePinning(): Boolean = this[ALLOW_MESSAGE_PINNING
fun PublicSettings.allowedMessageEditing(): Boolean = this[ALLOW_MESSAGE_EDITING]?.value == true
fun PublicSettings.allowedMessageDeleting(): Boolean = this[ALLOW_MESSAGE_DELETING]?.value == true
fun PublicSettings.uploadMimeTypeFilter(): Array<String> {
val values = this[UPLOAD_WHITELIST_MIMETYPES]?.value
values?.let { it as String }?.split(",")?.let {
return it.mapToTypedArray { it.trim() }
}
fun PublicSettings.hasShowLastMessage(): Boolean = this[STORE_LAST_MESSAGE] != null
fun PublicSettings.showLastMessage(): Boolean = this[STORE_LAST_MESSAGE]?.value == true
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 {
......
package chat.rocket.android.util.extensions
import android.net.Uri
import android.support.customtabs.CustomTabsIntent
import android.support.v4.content.res.ResourcesCompat
import android.view.View
import chat.rocket.android.R
fun View.openTabbedUrl(url: Uri) {
with(this) {
val tabsbuilder = CustomTabsIntent.Builder()
tabsbuilder.setToolbarColor(ResourcesCompat.getColor(context.resources, R.color.colorPrimary, context.theme))
val customTabsIntent = tabsbuilder.build()
customTabsIntent.launchUrl(context, url)
}
}
\ No newline at end of file
......@@ -37,14 +37,12 @@
android:layout_width="100dp"
android:layout_height="100dp"
android:src="@drawable/ic_pin_black_24dp"
android:tint="#AFADAF"
android:tint="@color/icon_grey"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="@id/tv_pin_title"
app:layout_constraintVertical_chainStyle="packed"
android:visibility="gone"
tools:visibility="visible" />
app:layout_constraintVertical_chainStyle="packed" />
<TextView
android:id="@+id/tv_pin_title"
......@@ -58,9 +56,7 @@
android:textSize="20sp"
android:layout_marginTop="24dp"
android:textStyle="bold"
android:textColor="#8B8B8B"
android:visibility="gone"
tools:visibility="visible"/>
android:textColor="@color/colorSecondaryText"/>
<TextView
android:id="@+id/tv_pin_description"
......@@ -74,8 +70,14 @@
android:layout_marginTop="16dp"
android:textAlignment="center"
android:textSize="16sp"
android:textColor="#c1c1c1"
android:textColor="@color/colorSecondaryTextLight"/>
<android.support.constraint.Group
android:id="@+id/pin_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:constraint_referenced_ids="tv_pin_description,iv_pin_icon,tv_pin_title"
android:visibility="gone"
tools:visibility="visible"/>
tools:visibility="visible" />
</android.support.constraint.ConstraintLayout>
\ No newline at end of file
......@@ -22,46 +22,64 @@
<ImageView
android:id="@+id/image_chat_icon"
android:layout_width="12dp"
android:layout_height="12dp"
android:layout_height="0dp"
android:layout_marginStart="16dp"
app:layout_constraintBottom_toBottomOf="@+id/text_chat_name"
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" />
<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
android:id="@+id/text_chat_name"
style="@style/ChatRoom.Name.TextView"
android:layout_width="wrap_content"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:ellipsize="end"
android:lines="1"
android:maxLines="1"
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_constraintTop_toTopOf="parent"
tools:text="general" />
<TextView
android:id="@+id/text_last_message_date_time"
style="@style/Timestamp.TextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
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_height="0dp"
android:gravity="center"
android:layout_marginEnd="8dp"
app:layout_constraintBottom_toBottomOf="@+id/layout_unread_messages_badge"
android:layout_marginTop="2dp"
android:ellipsize="end"
android:maxLines="2"
android:textDirection="locale"
tools:visibility="visible"
app:layout_constraintEnd_toStartOf="@+id/layout_unread_messages_badge"
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" />
app:layout_constraintTop_toTopOf="@+id/text_chat_name"
tools:text="11:45 AM" />
<include
android:id="@+id/layout_unread_messages_badge"
......@@ -69,6 +87,6 @@
android:layout_width="18dp"
android:layout_height="18dp"
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>
\ No newline at end of file
......@@ -2,6 +2,7 @@
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/message_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?android:attr/selectableItemBackground"
......@@ -74,6 +75,16 @@
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
tools:text="11:45 PM" />
<TextView
android:id="@+id/text_edit_indicator"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/msg_edited"
android:layout_marginStart="8dp"
android:textStyle="italic"
android:visibility="gone"
tools:visibility="visible" />
</LinearLayout>
<TextView
......
......@@ -2,6 +2,7 @@
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/attachment_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?android:attr/selectableItemBackground"
......
......@@ -100,7 +100,6 @@
<string name="msg_ver_not_minimum">
Parece que la versión del servidor está por debajo de la versión mínima requerida %1$s.\nActualice su servidor para iniciar sesión!
</string>
<string name="msg_proceed">PROCEDER</string>
<string name="msg_cancel">CANCELAR</string>
<string name="msg_warning">ADVERTENCIA</string>
......@@ -111,6 +110,7 @@
<string name="msg_image_saved_failed">Error al guardar la imagen</string>
<string name="msg_no_chat_title">Sin mensajes de chat</string>
<string name="msg_no_chat_description">Comience a conversar para ver\nsus mensajes aquí.</string>
<string name="msg_edited">(editado)</string>
<!-- System messages -->
<string name="message_room_name_changed">Nombre de la sala cambiado para: %1$s por %2$s</string>
......
......@@ -110,6 +110,7 @@
<string name="msg_image_saved_failed">Échec de l\'enregistrement de l\'image</string>
<string name="msg_no_chat_title">Aucun message de discussion</string>
<string name="msg_no_chat_description">Commencez à converser pour voir\nvos messages ici.</string>
<string name="msg_edited">(édité)</string>
<!-- System messages -->
<string name="message_room_name_changed">Le nom de le salle a changé à: %1$s par %2$s</string>
......
......@@ -112,6 +112,7 @@
<string name="msg_image_saved_failed">छवि को सहेजने में विफल</string>
<string name="msg_no_chat_title">कोई चैट संदेश नहीं</string>
<string name="msg_no_chat_description">यहां अपने संदेश देखने के लिए\nबातचीत शुरू करें।</string>
<string name="msg_edited">(संपादित)</string>
<!-- System messages -->
<string name="message_room_name_changed">%2$s ने रूम का नाम बदलकर %1$s किया</string>
......
......@@ -106,6 +106,7 @@
<string name="msg_invalid_server_protocol">O protocolo selecionado não é suportado pelo servidor, por favor utilize HTTPS e tente novamente</string>
<string name="msg_image_saved_successfully">Imagem salva na galeria</string>
<string name="msg_image_saved_failed">Falha ao salvar a imagem</string>
<string name="msg_edited">(editado)</string>
<!-- System messages -->
<string name="message_room_name_changed">Nome da sala alterado para: %1$s por %2$s</string>
......
......@@ -2,7 +2,7 @@
<string name="app_name" translatable="false">Rocket.Chat</string>
<!-- Titles -->
<string name="title_sign_in_your_server">Sign in your server</string>
<string name="title_sign_in_your_server">Sign in to your server</string>
<string name="title_log_in">Log in</string>
<string name="title_register_username">Register username</string>
<string name="title_reset_password">Reset password</string>
......@@ -107,6 +107,7 @@
<string name="msg_invalid_server_protocol">The selected protocol is not accepted by this server, try using HTTPS</string>
<string name="msg_image_saved_successfully">Image has been saved to gallery</string>
<string name="msg_image_saved_failed">Failed to save image</string>
<string name="msg_edited">(edited)</string>
<!-- System messages -->
<string name="message_room_name_changed">Room name changed to: %1$s by %2$s</string>
......
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,13 +4,13 @@ ext {
compileSdk : 27,
targetSdk : 27,
buildTools : '27.0.3',
kotlin : '1.2.40',
kotlin : '1.2.41',
coroutine : '0.22.5',
dokka : '0.9.16',
// Main dependencies
support : '27.1.0',
constraintLayout : '1.0.2',
support : '27.1.1',
constraintLayout : '1.1.0',
androidKtx : '0.3',
dagger : '2.14.1',
exoPlayer : '2.6.0',
......@@ -35,7 +35,7 @@ ext {
// For testing
junit : '4.12',
truth : '0.36',
expresso : '3.0.1',
espresso : '3.0.2',
mockito : '2.10.0'
]
libraries = [
......@@ -98,7 +98,8 @@ ext {
// For testing
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}",
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