Commit 0402669e authored by Lucio Maciel's avatar Lucio Maciel

Display attachments and other fixes

parent 6d84d280
apply plugin: 'com.android.application'
apply plugin: 'io.fabric'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt'
......@@ -63,6 +64,7 @@ dependencies {
implementation libraries.daggerSupport
kapt libraries.daggerProcessor
kapt libraries.daggerAndroidApt
implementation libraries.playServicesGcm
implementation libraries.room
......@@ -80,6 +82,7 @@ dependencies {
implementation libraries.threeTenABP
implementation libraries.fresco
api libraries.frescoOkHttp
implementation libraries.frescoAnimatedGif
implementation libraries.frescoWebP
implementation libraries.frescoAnimatedWebP
......@@ -97,6 +100,10 @@ dependencies {
implementation libraries.textDrawable
implementation('com.crashlytics.sdk.android:crashlytics:2.6.8@aar') {
transitive = true
}
testImplementation libraries.junit
androidTestImplementation(libraries.expressoCore, {
exclude group: 'com.android.support', module: 'support-annotations'
......
......@@ -75,6 +75,11 @@
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
</intent-filter>
</service>
<meta-data
android:name="io.fabric.ApiKey"
android:value="12ac6e94f850aaffcdff52001af77ca415d06a43" />
</application>
</manifest>
\ No newline at end of file
......@@ -4,13 +4,15 @@ import android.app.Activity
import android.app.Application
import android.app.Service
import chat.rocket.android.BuildConfig
import chat.rocket.android.app.utils.CustomImageFormatConfigurator
import chat.rocket.android.dagger.DaggerAppComponent
import chat.rocket.android.helper.CrashlyticsTree
import chat.rocket.android.server.domain.GetCurrentServerInteractor
import chat.rocket.android.server.domain.MultiServerTokenRepository
import chat.rocket.android.server.domain.SettingsRepository
import chat.rocket.common.model.Token
import chat.rocket.core.TokenRepository
import com.crashlytics.android.Crashlytics
import com.crashlytics.android.core.CrashlyticsCore
import com.facebook.drawee.backends.pipeline.DraweeConfig
import com.facebook.drawee.backends.pipeline.Fresco
import com.facebook.imagepipeline.core.ImagePipelineConfig
......@@ -19,9 +21,12 @@ import dagger.android.AndroidInjector
import dagger.android.DispatchingAndroidInjector
import dagger.android.HasActivityInjector
import dagger.android.HasServiceInjector
import io.fabric.sdk.android.Fabric
import timber.log.Timber
import javax.inject.Inject
class RocketChatApplication : Application(), HasActivityInjector, HasServiceInjector {
@Inject
......@@ -30,9 +35,10 @@ class RocketChatApplication : Application(), HasActivityInjector, HasServiceInje
@Inject
lateinit var serviceDispatchingAndroidInjector: DispatchingAndroidInjector<Service>
companion object {
lateinit var instance: RocketChatApplication
}
@Inject
lateinit var imagePipelineConfig: ImagePipelineConfig
@Inject
lateinit var draweeConfig: DraweeConfig
// TODO - remove this from here when we have a proper service handling the connection.
@Inject
......@@ -54,9 +60,9 @@ class RocketChatApplication : Application(), HasActivityInjector, HasServiceInje
AndroidThreeTen.init(this)
setupCrashlytics()
setupFresco()
setupTimber()
instance = this
}
// TODO - remove this when we have a proper service handling connection...
......@@ -69,21 +75,20 @@ class RocketChatApplication : Application(), HasActivityInjector, HasServiceInje
}
}
private fun setupFresco() {
val imagePipelineConfig = ImagePipelineConfig.newBuilder(this)
.setImageDecoderConfig(CustomImageFormatConfigurator.createImageDecoderConfig())
.build()
val draweeConfigBuilder = DraweeConfig.newBuilder()
CustomImageFormatConfigurator.addCustomDrawableFactories(draweeConfigBuilder)
private fun setupCrashlytics() {
val core = CrashlyticsCore.Builder().disabled(BuildConfig.DEBUG).build()
Fabric.with(this, Crashlytics.Builder().core(core).build())
}
Fresco.initialize(this, imagePipelineConfig, draweeConfigBuilder.build())
private fun setupFresco() {
Fresco.initialize(this, imagePipelineConfig, draweeConfig)
}
private fun setupTimber() {
if (BuildConfig.DEBUG) {
Timber.plant(Timber.DebugTree())
} else {
Timber.plant(CrashlyticsTree())
}
}
......
......@@ -17,7 +17,7 @@ import chat.rocket.android.helper.AnimationHelper
import chat.rocket.android.helper.KeyboardHelper
import chat.rocket.android.helper.TextHelper
import chat.rocket.android.util.inflate
import chat.rocket.android.util.setVisibility
import chat.rocket.android.util.setVisible
import chat.rocket.android.util.textContent
import dagger.android.support.AndroidSupportInjection
import kotlinx.android.synthetic.main.fragment_authentication_log_in.*
......@@ -92,8 +92,8 @@ class LoginFragment : Fragment(), LoginView {
override fun showOauthView(value: Boolean) {
if (value) {
social_accounts_container.setVisibility(true)
button_fab.setVisibility(true)
social_accounts_container.setVisible(true)
button_fab.setVisible(true)
// We need to setup the layout to hide and show the oauth interface when the soft keyboard is shown
// (means that the user touched the text_username_or_email or text_password EditText to fill that respective fields).
......@@ -102,8 +102,8 @@ class LoginFragment : Fragment(), LoginView {
isGlobalLayoutListenerSetUp = true
}
} else {
social_accounts_container.setVisibility(false)
button_fab.setVisibility(false)
social_accounts_container.setVisible(false)
button_fab.setVisible(false)
}
}
......@@ -143,7 +143,7 @@ class LoginFragment : Fragment(), LoginView {
button_gitlab.isEnabled = true
}
override fun showSignUpView(value: Boolean) = text_new_to_rocket_chat.setVisibility(value)
override fun showSignUpView(value: Boolean) = text_new_to_rocket_chat.setVisible(value)
override fun alertWrongUsernameOrEmail() {
AnimationHelper.vibrateSmartPhone(appContext)
......@@ -159,11 +159,11 @@ class LoginFragment : Fragment(), LoginView {
override fun showLoading() {
enableUserInput(false)
view_loading.setVisibility(true)
view_loading.setVisible(true)
}
override fun hideLoading() {
view_loading.setVisibility(false)
view_loading.setVisible(false)
enableUserInput(true)
}
......@@ -189,7 +189,7 @@ class LoginFragment : Fragment(), LoginView {
}
private fun showLoginButton(value: Boolean) {
button_log_in.setVisibility(value)
button_log_in.setVisible(value)
}
private fun setupSignUpListener() {
......
......@@ -48,11 +48,11 @@ class ServerFragment : Fragment(), ServerView {
override fun showLoading() {
enableUserInput(false)
view_loading.setVisibility(true)
view_loading.setVisible(true)
}
override fun hideLoading() {
view_loading.setVisibility(false)
view_loading.setVisible(false)
enableUserInput(true)
}
......
......@@ -14,7 +14,7 @@ import chat.rocket.android.authentication.signup.presentation.SignupView
import chat.rocket.android.helper.AnimationHelper
import chat.rocket.android.helper.KeyboardHelper
import chat.rocket.android.helper.TextHelper
import chat.rocket.android.util.setVisibility
import chat.rocket.android.util.setVisible
import chat.rocket.android.util.textContent
import dagger.android.support.AndroidSupportInjection
import kotlinx.android.synthetic.main.fragment_authentication_sign_up.*
......@@ -26,9 +26,9 @@ class SignupFragment : Fragment(), SignupView {
private val layoutListener = ViewTreeObserver.OnGlobalLayoutListener {
if (KeyboardHelper.isSoftKeyboardShown(constraint_layout.rootView)) {
text_new_user_agreement.setVisibility(false)
text_new_user_agreement.setVisible(false)
} else {
text_new_user_agreement.setVisibility(true)
text_new_user_agreement.setVisible(true)
}
}
......@@ -92,11 +92,11 @@ class SignupFragment : Fragment(), SignupView {
override fun showLoading() {
enableUserInput(false)
view_loading.setVisibility(true)
view_loading.setVisible(true)
}
override fun hideLoading() {
view_loading.setVisibility(false)
view_loading.setVisible(false)
enableUserInput(true)
}
......
......@@ -14,7 +14,7 @@ import chat.rocket.android.R
import chat.rocket.android.authentication.twofactor.presentation.TwoFAPresenter
import chat.rocket.android.authentication.twofactor.presentation.TwoFAView
import chat.rocket.android.helper.AnimationHelper
import chat.rocket.android.util.setVisibility
import chat.rocket.android.util.setVisible
import chat.rocket.android.util.textContent
import dagger.android.support.AndroidSupportInjection
import kotlinx.android.synthetic.main.fragment_authentication_two_fa.*
......@@ -75,11 +75,11 @@ class TwoFAFragment : Fragment(), TwoFAView {
override fun showLoading() {
enableUserInput(false)
view_loading.setVisibility(true)
view_loading.setVisible(true)
}
override fun hideLoading() {
view_loading.setVisibility(false)
view_loading.setVisible(false)
enableUserInput(true)
}
......
......@@ -26,7 +26,8 @@ class ChatRoomPresenter @Inject constructor(private val view: ChatRoomView,
private val strategy: CancelStrategy,
getSettingsInteractor: GetSettingsInteractor,
private val serverInteractor: GetCurrentServerInteractor,
factory: RocketChatClientFactory) {
factory: RocketChatClientFactory,
private val mapper: MessageViewModelMapper) {
private val client = factory.create(serverInteractor.get()!!)
private val roomMessages = ArrayList<Message>()
private var subId: String? = null
......@@ -47,7 +48,7 @@ class ChatRoomPresenter @Inject constructor(private val view: ChatRoomView,
roomMessages.addAll(messages)
}
val messagesViewModels = MessageViewModelMapper.mapToViewModelList(messages, settings)
val messagesViewModels = mapper.mapToViewModelList(messages, settings)
view.showMessages(messagesViewModels, serverInteractor.get()!!)
// Subscribe after getting the first page of messages from REST
......@@ -148,7 +149,7 @@ class ChatRoomPresenter @Inject constructor(private val view: ChatRoomView,
private fun updateMessage(streamedMessage: Message) {
launchUI(strategy) {
val viewModelStreamedMessage = MessageViewModelMapper.mapToViewModel(streamedMessage, settings)
val viewModelStreamedMessage = mapper.mapToViewModel(streamedMessage, settings)
synchronized(roomMessages) {
val index = roomMessages.indexOfFirst { msg -> msg.id == streamedMessage.id }
if (index != -1) {
......
......@@ -4,14 +4,18 @@ import android.support.v7.widget.RecyclerView
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import chat.rocket.android.R
import chat.rocket.android.chatroom.viewmodel.AttachmentType
import chat.rocket.android.chatroom.viewmodel.MessageViewModel
import chat.rocket.android.player.PlayerActivity
import chat.rocket.android.util.inflate
import chat.rocket.android.util.setVisibility
import chat.rocket.android.util.setVisible
import chat.rocket.common.util.ifNull
import com.facebook.drawee.view.SimpleDraweeView
import kotlinx.android.synthetic.main.avatar.view.*
import kotlinx.android.synthetic.main.item_message.view.*
import kotlinx.android.synthetic.main.message_attachment.view.*
class ChatRoomAdapter(private val serverUrl: String) : RecyclerView.Adapter<ChatRoomAdapter.ViewHolder>() {
......@@ -61,12 +65,54 @@ class ChatRoomAdapter(private val serverUrl: String) : RecyclerView.Adapter<Chat
text_user_name.text = message.sender
text_message_time.text = message.time
text_content.text = message.content
bindAttachment(message, attachment_container, image_attachment, audio_video_attachment,
file_name)
}
private fun bindAttachment(message: MessageViewModel,
attachment_container: View,
image_attachment: SimpleDraweeView,
audio_video_attachment: View,
file_name: TextView) {
with(message) {
if (attachmentUrl == null || attachmentType == null) {
attachment_container.setVisible(false)
}
var imageVisible = false
var videoVisible = false
attachment_container.setVisible(true)
when (message.attachmentType) {
is AttachmentType.Image -> {
imageVisible = true
image_attachment.setImageURI(message.attachmentUrl)
}
is AttachmentType.Video,
is AttachmentType.Audio -> {
videoVisible = true
audio_video_attachment.setOnClickListener { view ->
message.attachmentUrl?.let { url ->
PlayerActivity.play(view.context, url)
}
}
}
}
image_attachment.setVisible(imageVisible)
audio_video_attachment.setVisible(videoVisible)
file_name.text = message.attachmentTitle
}
}
private fun bindUserAvatar(message: MessageViewModel, drawee: SimpleDraweeView, imageUnknownAvatar: ImageView) = message.getAvatarUrl(serverUrl).let {
drawee.setImageURI(it.toString())
drawee.setVisible(true)
imageUnknownAvatar.setVisible(false)
}.ifNull {
imageUnknownAvatar.setVisibility(true)
drawee.setVisible(false)
imageUnknownAvatar.setVisible(true)
}
}
}
\ No newline at end of file
}
......@@ -15,7 +15,7 @@ import chat.rocket.android.chatroom.presentation.ChatRoomView
import chat.rocket.android.chatroom.viewmodel.MessageViewModel
import chat.rocket.android.helper.EndlessRecyclerViewScrollListener
import chat.rocket.android.util.inflate
import chat.rocket.android.util.setVisibility
import chat.rocket.android.util.setVisible
import chat.rocket.android.util.textContent
import dagger.android.support.AndroidSupportInjection
import kotlinx.android.synthetic.main.fragment_chat_room.*
......@@ -123,9 +123,9 @@ class ChatRoomFragment : Fragment(), ChatRoomView {
adapter.updateItem(index, message)
}
override fun showLoading() = view_loading.setVisibility(true)
override fun showLoading() = view_loading.setVisible(true)
override fun hideLoading() = view_loading.setVisibility(false)
override fun hideLoading() = view_loading.setVisible(false)
override fun showMessage(message: String) = Toast.makeText(activity, message, Toast.LENGTH_SHORT).show()
......@@ -133,8 +133,8 @@ class ChatRoomFragment : Fragment(), ChatRoomView {
private fun setupComposer() {
if (isChatRoomReadOnly) {
text_room_is_read_only.setVisibility(true)
top_container.setVisibility(false)
text_room_is_read_only.setVisible(true)
top_container.setVisible(false)
} else {
text_send.setOnClickListener { sendMessage(text_message.textContent) }
}
......
......@@ -8,24 +8,52 @@ import android.text.SpannableString
import android.text.style.ForegroundColorSpan
import android.text.style.StyleSpan
import chat.rocket.android.R
import chat.rocket.android.app.RocketChatApplication
import chat.rocket.android.helper.UrlHelper
import chat.rocket.android.server.domain.SITE_URL
import chat.rocket.android.server.domain.USE_REALNAME
import chat.rocket.common.model.Token
import chat.rocket.core.model.Message
import chat.rocket.core.model.MessageType.*
import chat.rocket.core.model.Value
import chat.rocket.core.model.attachment.AudioAttachment
import chat.rocket.core.model.attachment.FileAttachment
import chat.rocket.core.model.attachment.ImageAttachment
import chat.rocket.core.model.attachment.VideoAttachment
import okhttp3.HttpUrl
data class MessageViewModel(private val message: Message,
data class MessageViewModel(val context: Context,
private val token: Token?,
private val message: Message,
private val settings: Map<String, Value<Any>>?) {
val id: String = message.id
val time: CharSequence
val sender: CharSequence
val content: CharSequence
var attachmentUrl: String? = null
var attachmentTitle: CharSequence? = null
var attachmentType: AttachmentType? = null
init {
sender = getSenderName()
content = getContent(RocketChatApplication.instance)
content = getContent(context)
time = getTime()
message.attachments?.let {
if (it.isEmpty() || it[0] == null) return@let
val attachment = it[0] as FileAttachment
val baseUrl = settings?.get(SITE_URL)
baseUrl?.let {
attachmentUrl = attachmentUrl("${baseUrl.value}${attachment.url}")
attachmentTitle = attachment.title
attachmentType = when (attachment) {
is ImageAttachment -> AttachmentType.Image
is VideoAttachment -> AttachmentType.Video
is AudioAttachment -> AttachmentType.Audio
else -> null
}
}
}
}
fun getAvatarUrl(serverUrl: String): String? {
......@@ -41,7 +69,7 @@ data class MessageViewModel(private val message: Message,
val username = message.sender?.username
val realName = message.sender?.name
val senderName = if (useRealName) realName else username
return if (senderName == null) username.toString() else senderName.toString()
return senderName ?: username.toString()
}
fun getContent(context: Context): CharSequence {
......@@ -91,4 +119,23 @@ data class MessageViewModel(private val message: Message,
return spannableMsg
}
private fun attachmentUrl(url: String): String {
var response = url
val httpUrl = HttpUrl.parse(url)
httpUrl?.let {
response = it.newBuilder().apply {
addQueryParameter("rc_uid", token?.userId)
addQueryParameter("rc_token", token?.authToken)
}.build().toString()
}
return response
}
}
sealed class AttachmentType {
object Image : AttachmentType()
object Video : AttachmentType()
object Audio : AttachmentType()
}
\ No newline at end of file
package chat.rocket.android.chatroom.viewmodel
import android.content.Context
import chat.rocket.core.TokenRepository
import chat.rocket.core.model.Message
import chat.rocket.core.model.Value
import javax.inject.Inject
object MessageViewModelMapper {
class MessageViewModelMapper @Inject constructor(private val context: Context, private val tokenRepository: TokenRepository) {
suspend fun mapToViewModel(message: Message, settings: Map<String, Value<Any>>?) = MessageViewModel(message, settings)
suspend fun mapToViewModel(message: Message, settings: Map<String, Value<Any>>?) = MessageViewModel(context, tokenRepository.get(), message, settings)
suspend fun mapToViewModelList(messageList: List<Message>, settings: Map<String, Value<Any>>?): List<MessageViewModel> {
val vmList = mutableListOf<MessageViewModel>()
for (msg in messageList) {
vmList.add(MessageViewModel(msg, settings))
}
return vmList
return messageList.map { MessageViewModel(context, tokenRepository.get(), it, settings) }
}
}
\ No newline at end of file
......@@ -11,7 +11,7 @@ import android.widget.TextView
import chat.rocket.android.R
import chat.rocket.android.helper.UrlHelper
import chat.rocket.android.util.inflate
import chat.rocket.android.util.setVisibility
import chat.rocket.android.util.setVisible
import chat.rocket.android.util.textContent
import chat.rocket.common.model.BaseRoom.RoomType
import chat.rocket.core.model.ChatRoom
......@@ -52,12 +52,12 @@ class ChatRoomsAdapter(private val context: Context,
val chatRoomName = chatRoom.name
if (chatRoom.type == RoomType.ONE_TO_ONE) {
drawee.setImageURI(UrlHelper.getAvatarUrl(chatRoom.client.url, chatRoomName))
imageView.setVisibility(false)
avatarLayout.setVisibility(true)
imageView.setVisible(false)
avatarLayout.setVisible(true)
} else {
imageView.setImageDrawable(DrawableHelper.getTextDrawable(chatRoomName))
avatarLayout.setVisibility(false)
imageView.setVisibility(true)
avatarLayout.setVisible(false)
imageView.setVisible(true)
}
}
......@@ -99,11 +99,11 @@ class ChatRoomsAdapter(private val context: Context,
when {
totalUnreadMessage in 1..99 -> {
textView.textContent = totalUnreadMessage.toString()
textView.setVisibility(true)
textView.setVisible(true)
}
totalUnreadMessage > 99 -> {
textView.textContent = context.getString(R.string.msg_more_than_ninety_nine_unread_messages)
textView.setVisibility(true)
textView.setVisible(true)
}
}
}
......
......@@ -12,7 +12,7 @@ import android.widget.Toast
import chat.rocket.android.R
import chat.rocket.android.chatrooms.presentation.ChatRoomsPresenter
import chat.rocket.android.chatrooms.presentation.ChatRoomsView
import chat.rocket.android.util.setVisibility
import chat.rocket.android.util.setVisible
import chat.rocket.android.widget.DividerItemDecoration
import chat.rocket.core.model.ChatRoom
import dagger.android.support.AndroidSupportInjection
......@@ -104,9 +104,9 @@ class ChatRoomsFragment : Fragment(), ChatRoomsView {
}
}
override fun showLoading() = view_loading.setVisibility(true)
override fun showLoading() = view_loading.setVisible(true)
override fun hideLoading() = view_loading.setVisibility(false)
override fun hideLoading() = view_loading.setVisible(false)
override fun showMessage(message: String) = Toast.makeText(activity, message, Toast.LENGTH_SHORT).show()
......
......@@ -6,8 +6,11 @@ import android.content.Context
import android.content.SharedPreferences
import chat.rocket.android.BuildConfig
import chat.rocket.android.app.RocketChatDatabase
import chat.rocket.android.app.utils.CustomImageFormatConfigurator
import chat.rocket.android.authentication.infraestructure.MemoryTokenRepository
import chat.rocket.android.authentication.infraestructure.SharedPreferencesMultiServerTokenRepository
import chat.rocket.android.dagger.qualifier.ForFresco
import chat.rocket.android.helper.FrescoAuthInterceptor
import chat.rocket.android.infrastructure.LocalRepository
import chat.rocket.android.infrastructure.SharedPrefsLocalRepository
import chat.rocket.android.server.domain.ChatRoomsRepository
......@@ -23,10 +26,16 @@ import chat.rocket.android.util.TimberLogger
import chat.rocket.common.util.PlatformLogger
import chat.rocket.core.RocketChatClient
import chat.rocket.core.TokenRepository
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
import dagger.Provides
import kotlinx.coroutines.experimental.Job
import okhttp3.Interceptor
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import javax.inject.Singleton
......@@ -91,6 +100,46 @@ class AppModule {
}.build()
}
@Provides
@ForFresco
@Singleton
fun provideFrescoAuthIntercepter(tokenRepository: TokenRepository): Interceptor {
return FrescoAuthInterceptor(tokenRepository)
}
@Provides
@ForFresco
@Singleton
fun provideFrescoOkHttpClient(okHttpClient: OkHttpClient, @ForFresco authInterceptor: Interceptor): OkHttpClient {
return okHttpClient.newBuilder().apply {
//addInterceptor(authInterceptor)
}.build()
}
@Provides
@Singleton
fun provideImagePipelineConfig(context: Context, @ForFresco okHttpClient: OkHttpClient): ImagePipelineConfig {
val listeners = HashSet<RequestListener>()
listeners.add(RequestLoggingListener())
return OkHttpImagePipelineConfigFactory.newBuilder(context, okHttpClient)
.setImageDecoderConfig(CustomImageFormatConfigurator.createImageDecoderConfig())
.setRequestListeners(listeners)
.setDownsampleEnabled(true)
//.experiment().setBitmapPrepareToDraw(true).experiment()
.experiment().setPartialImageCachingEnabled(true).build()
}
@Provides
@Singleton
fun provideDraweeConfig(): DraweeConfig {
val draweeConfigBuilder = DraweeConfig.newBuilder()
CustomImageFormatConfigurator.addCustomDrawableFactories(draweeConfigBuilder)
return draweeConfigBuilder.build()
}
@Provides
@Singleton
fun provideTokenRepository(): TokenRepository {
......
package chat.rocket.android.dagger.qualifier
import javax.inject.Qualifier
@Qualifier
@Retention(AnnotationRetention.RUNTIME)
annotation class ForFresco
\ No newline at end of file
package chat.rocket.android.helper
import com.crashlytics.android.Crashlytics
import timber.log.Timber
class CrashlyticsTree : Timber.Tree() {
override fun log(priority: Int, tag: String, message: String, throwable: Throwable?) {
Crashlytics.log(priority, tag, message)
if (throwable != null) {
Crashlytics.logException(throwable)
}
}
}
\ No newline at end of file
package chat.rocket.android.helper
import chat.rocket.core.TokenRepository
import okhttp3.Interceptor
import okhttp3.Response
class FrescoAuthInterceptor(private val tokenRepository: TokenRepository) : Interceptor {
override fun intercept(chain: Interceptor.Chain): Response {
val token = tokenRepository.get()
var request = chain.request()
token?.let {
val url = request.url().newBuilder().apply {
addQueryParameter("rc_uid", token.userId)
addQueryParameter("rc_token", token.authToken)
}.build()
request = request.newBuilder().apply {
url(url)
}.build()
}
return chain.proceed(request)
}
}
\ No newline at end of file
......@@ -13,7 +13,7 @@ fun String.ifEmpty(value: String): String {
return this
}
fun View.setVisibility(value: Boolean) {
fun View.setVisible(value: Boolean) {
visibility = if (value) {
View.VISIBLE
} else {
......
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="80dp"
android:height="45dp"
android:viewportWidth="80.0"
android:viewportHeight="45.0">
<path
android:pathData="M0,0h80v45h-80z"
android:strokeColor="#00000000"
android:fillColor="#C3D1DA"
android:strokeWidth="1"/>
<path
android:pathData="M43.99,16.75C44.34,16.75 44.64,16.87 44.88,17.12C45.13,17.36 45.25,17.66 45.25,18.01L45.25,26.74C45.25,27.09 45.13,27.39 44.88,27.63C44.64,27.88 44.34,28 43.99,28L35.26,28C34.91,28 34.61,27.88 34.37,27.63C34.12,27.39 34,27.09 34,26.74L34,18.01C34,17.66 34.12,17.36 34.37,17.12C34.61,16.87 34.91,16.75 35.26,16.75L43.99,16.75ZM43.99,26.74L43.99,18.01L35.26,18.01L35.26,26.74L43.99,26.74ZM40.86,22.55L43.05,25.51L36.2,25.51L37.9,23.28L39.13,24.78L40.86,22.55Z"
android:strokeColor="#00000000"
android:fillColor="#5D8298"
android:strokeWidth="1"/>
</vector>
......@@ -55,13 +55,12 @@
app:layout_constraintTop_toBottomOf="@+id/top_container"
tools:text="This is a multiline chat message from Bertie that will take more than just one line of text. I have sure that everything is amazing!" />
<!-- TODO implement -->
<com.facebook.drawee.view.SimpleDraweeView
android:id="@+id/image_attachment"
<!-- TODO - Use separate adapter items for messages and attachments. -->
<include
layout="@layout/message_attachment"
android:layout_width="0dp"
android:layout_height="150dp"
android:layout_marginTop="5dp"
android:visibility="gone"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
app:layout_constraintLeft_toLeftOf="@id/top_container"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/text_content" />
......
<?xml version="1.0" encoding="utf-8"?>
<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"
android:id="@+id/attachment_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<com.facebook.drawee.view.SimpleDraweeView
android:id="@+id/image_attachment"
android:layout_width="match_parent"
android:layout_height="150dp"
fresco:actualImageScaleType="fitStart"
fresco:placeholderImage="@drawable/image_dummy"
tools:visibility="visible"
android:visibility="gone"/>
<FrameLayout
android:id="@+id/audio_video_attachment"
android:layout_width="match_parent"
android:layout_height="150dp"
android:background="@color/black"
android:visibility="gone"
tools:visibility="gone">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:src="@drawable/exo_controls_play"/>
</FrameLayout>
<TextView
android:id="@+id/file_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:text="Filename.png"/>
</LinearLayout>
\ No newline at end of file
......@@ -5,6 +5,7 @@ buildscript {
repositories {
google()
jcenter()
maven { url 'https://maven.fabric.io/public' }
mavenCentral()
}
......@@ -13,6 +14,7 @@ buildscript {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${versions.kotlin}"
classpath "org.jetbrains.dokka:dokka-gradle-plugin:${versions.dokka}"
classpath 'com.google.gms:google-services:3.1.2'
classpath 'io.fabric.tools:gradle:1.+'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
......
......@@ -71,6 +71,7 @@ ext {
threeTenABP : "com.jakewharton.threetenabp:threetenabp:${versions.threeTenABP}",
fresco : "com.facebook.fresco:fresco:${versions.fresco}",
frescoOkHttp : "com.facebook.fresco:imagepipeline-okhttp3:${versions.fresco}",
frescoAnimatedGif : "com.facebook.fresco:animated-gif:${versions.fresco}",
frescoWebP : "com.facebook.fresco:webpsupport:${versions.fresco}",
frescoAnimatedWebP : "com.facebook.fresco:animated-webp:${versions.fresco}",
......
package chat.rocket.android.player
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import android.util.Log
import android.view.View
import com.google.android.exoplayer2.DefaultLoadControl
import com.google.android.exoplayer2.DefaultRenderersFactory
......@@ -22,10 +25,12 @@ class PlayerActivity : AppCompatActivity() {
private var playWhenReady = true
private var currentWindow = 0
private var playbackPosition = 0L
private lateinit var videoUrl: String
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_player)
videoUrl = intent.getStringExtra(URL_KEY)
}
override fun onStart() {
......@@ -65,8 +70,9 @@ class PlayerActivity : AppCompatActivity() {
player.seekTo(currentWindow, playbackPosition)
isPlayerInitialized = true
}
val uri = Uri.parse("http://download.blender.org/peach/bigbuckbunny_movies/BigBuckBunny_320x180.mp4")
val uri = Uri.parse(videoUrl)
val mediaSource = buildMediaSource(uri)
Log.d("PlayerActivity", "Player with: " + videoUrl)
player.prepare(mediaSource, true, false)
}
......@@ -86,4 +92,13 @@ class PlayerActivity : AppCompatActivity() {
// Read the docs for detailed explanation: https://developer.android.com/training/basics/firstapp/starting-activity.html and https://developer.android.com/design/patterns/fullscreen.html
player_view.systemUiVisibility = View.SYSTEM_UI_FLAG_FULLSCREEN or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
}
companion object {
const private val URL_KEY = "URL_KEY"
fun play(context: Context, url: String) {
context.startActivity(Intent(context, PlayerActivity::class.java).apply {
putExtra(URL_KEY, url)
})
}
}
}
\ No newline at end of file
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