Some progress on Coil

Signed-off-by: Mario Danic <mario@lovelyhq.com>
This commit is contained in:
Mario Danic 2019-10-24 14:40:22 +02:00
parent 3ff922ed06
commit 82a9c1d616
6 changed files with 120 additions and 35 deletions

View File

@ -149,7 +149,7 @@ ext {
work_version = "2.3.0-alpha02"
koin_version = "2.1.0-alpha-1"
lifecycle_version = "2.2.0-beta01"
coil_version = "0.7.0"
coil_version = "0.8.0"
room_version = "2.2.0"
}

View File

@ -33,6 +33,7 @@ import android.widget.TextView;
import androidx.emoji.widget.EmojiTextView;
import butterknife.BindView;
import butterknife.ButterKnife;
import coil.ImageLoader;
import com.facebook.drawee.backends.pipeline.Fresco;
import com.facebook.drawee.interfaces.DraweeController;
import com.facebook.drawee.view.SimpleDraweeView;

View File

@ -20,9 +20,13 @@
package com.nextcloud.talk.newarch.di.module
import android.app.Application
import android.content.Context
import android.text.TextUtils
import android.util.Log
import coil.ImageLoader
import coil.decode.GifDecoder
import coil.decode.SvgDecoder
import com.github.aurae.retrofit2.LoganSquareConverterFactory
import com.nextcloud.talk.BuildConfig
import com.nextcloud.talk.R
@ -80,6 +84,7 @@ val NetworkModule = module {
single { createOkHttpClient(androidContext(), get(), get(), get(), get(), get(), get(), get()) }
factory { createApiErrorHandler() }
single { createNextcloudTalkRepository(get()) }
single { createImageLoader(androidApplication(), get()) }
}
@ -237,9 +242,9 @@ fun createDispatcher(): Dispatcher {
return dispatcher
}
fun createCache(androidApplication: NextcloudTalkApplication): Cache {
val cacheSize = 128 * 1024 * 1024 // 128 MB
return Cache(androidApplication.cacheDir, cacheSize.toLong())
fun createCache(androidApplication: Application): Cache {
//val cacheSize = 128 * 1024 * 1024 // 128 MB
return Cache(androidApplication.cacheDir, Long.MAX_VALUE)
}
fun createApiErrorHandler(): ApiErrorHandler {
@ -250,6 +255,22 @@ fun createService(retrofit: Retrofit): ApiService {
return retrofit.create(ApiService::class.java)
}
fun createImageLoader(
androidApplication: Application,
okHttpClient: OkHttpClient
): ImageLoader {
return ImageLoader(androidApplication) {
availableMemoryPercentage(0.5)
bitmapPoolPercentage(0.5)
crossfade(true)
okHttpClient(okHttpClient)
componentRegistry {
add(GifDecoder())
add(SvgDecoder(androidApplication))
}
}
}
fun createNextcloudTalkRepository(apiService: ApiService): NextcloudTalkRepository {
return NextcloudTalkRepositoryImpl(apiService)
}

View File

@ -22,6 +22,7 @@ package com.nextcloud.talk.newarch.features.conversationsList
import android.app.SearchManager
import android.content.Context
import android.graphics.drawable.Drawable
import android.os.Build
import android.os.Bundle
import android.text.InputType
@ -38,6 +39,9 @@ import androidx.core.view.MenuItemCompat
import androidx.lifecycle.Observer
import androidx.recyclerview.widget.RecyclerView.ViewHolder
import butterknife.OnClick
import coil.ImageLoader
import coil.target.Target
import coil.transform.CircleCropTransformation
import com.afollestad.materialdialogs.LayoutMode.WRAP_CONTENT
import com.afollestad.materialdialogs.MaterialDialog
import com.afollestad.materialdialogs.bottomsheets.BottomSheet
@ -53,10 +57,12 @@ import com.nextcloud.talk.controllers.SettingsController
import com.nextcloud.talk.controllers.bottomsheet.items.listItemsWithImage
import com.nextcloud.talk.newarch.conversationsList.mvp.BaseView
import com.nextcloud.talk.newarch.mvvm.ext.initRecyclerView
import com.nextcloud.talk.newarch.utils.Images
import com.nextcloud.talk.newarch.utils.ViewState.FAILED
import com.nextcloud.talk.newarch.utils.ViewState.LOADED
import com.nextcloud.talk.newarch.utils.ViewState.LOADED_EMPTY
import com.nextcloud.talk.newarch.utils.ViewState.LOADING
import com.nextcloud.talk.utils.ApiUtils
import com.nextcloud.talk.utils.ConductorRemapping
import com.nextcloud.talk.utils.DisplayUtils
import com.nextcloud.talk.utils.animations.SharedElementTransition
@ -66,6 +72,7 @@ import eu.davidea.flexibleadapter.FlexibleAdapter.OnItemClickListener
import eu.davidea.flexibleadapter.FlexibleAdapter.OnItemLongClickListener
import eu.davidea.flexibleadapter.common.SmoothScrollLinearLayoutManager
import eu.davidea.flexibleadapter.items.IFlexible
import kotlinx.android.synthetic.main.controller_conversations_rv.view.*
import kotlinx.android.synthetic.main.controller_conversations_rv.view.dataStateView
import kotlinx.android.synthetic.main.controller_conversations_rv.view.floatingActionButton
import kotlinx.android.synthetic.main.controller_conversations_rv.view.recyclerView
@ -85,6 +92,7 @@ class ConversationsListView : BaseView(), OnQueryTextListener,
lateinit var viewModel: ConversationsListViewModel
val factory: ConversationListViewModelFactory by inject()
val imageLoader: ImageLoader by inject()
private val recyclerViewAdapter = FlexibleAdapter(mutableListOf(), null, true)
@ -120,7 +128,28 @@ class ConversationsListView : BaseView(), OnQueryTextListener,
.toInt()
}
iconSize?.let { viewModel.loadAvatar(it) }
iconSize?.let {
val target = object : Target {
override fun onSuccess(result: Drawable) {
super.onSuccess(result)
settingsItem?.icon = result
}
override fun onError(error: Drawable?) {
super.onError(error)
settingsItem?.icon = context.getDrawable(R.drawable.ic_settings_white_24dp)
}
}
viewModel.currentUserLiveData.value?.let {
val avatarRequest = Images().getRequestForUrl(imageLoader, context, ApiUtils.getUrlForAvatarWithNameAndPixels(
it.baseUrl,
it.userId, iconSize), it, target, this, CircleCropTransformation()
)
imageLoader.load(avatarRequest)
}
}
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {

View File

@ -28,6 +28,8 @@ import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.Transformations
import androidx.lifecycle.viewModelScope
import coil.request.LoadRequest
import coil.target.ViewTarget
import com.facebook.common.executors.UiThreadImmediateExecutorService
import com.facebook.common.references.CloseableReference
import com.facebook.datasource.DataSource
@ -89,6 +91,7 @@ class ConversationsListViewModel constructor(
viewModelScope.launch {
setConversationUpdateStatus(conversation, true)
}
leaveConversationUseCase.invoke(viewModelScope, parametersOf(
currentUserLiveData.value,
conversation
@ -196,36 +199,6 @@ class ConversationsListViewModel constructor(
})
}
fun loadAvatar(avatarSize: Int) {
val imageRequest = DisplayUtils.getImageRequestForUrl(
ApiUtils.getUrlForAvatarWithNameAndPixels(
currentUserLiveData.value!!.baseUrl,
currentUserLiveData.value!!.userId, avatarSize
), null
)
val imagePipeline = Fresco.getImagePipeline()
val dataSource = imagePipeline.fetchDecodedImage(imageRequest, viewModelScope)
dataSource.subscribe(object : BaseBitmapDataSubscriber() {
override fun onNewResultImpl(bitmap: Bitmap?) {
if (bitmap != null) {
val roundedBitmapDrawable = RoundedBitmapDrawableFactory.create(
context.resources,
bitmap
)
roundedBitmapDrawable.isCircular = true
roundedBitmapDrawable.setAntiAlias(true)
currentUserAvatar.value = roundedBitmapDrawable
}
}
override fun onFailureImpl(dataSource: DataSource<CloseableReference<CloseableImage>>) {
currentUserAvatar.value = context.getDrawable(R.drawable.ic_settings_white_24dp)
}
}, UiThreadImmediateExecutorService.getInstance())
}
fun getShareIntentForConversation(conversation: Conversation): Intent {
val sendIntent: Intent = Intent().apply {
action = Intent.ACTION_SEND

View File

@ -0,0 +1,61 @@
/*
* Nextcloud Talk application
*
* @author Mario Danic
* Copyright (C) 2017-2019 Mario Danic <mario@lovelyhq.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.nextcloud.talk.newarch.utils
import android.content.Context
import androidx.lifecycle.LifecycleOwner
import coil.ImageLoader
import coil.request.LoadRequest
import coil.target.Target
import coil.transform.Transformation
import com.nextcloud.talk.models.database.UserEntity
class Images {
fun getRequestForUrl(
imageLoader: ImageLoader,
context: Context,
url: String,
userEntity:
UserEntity,
target: Target?,
lifecycleOwner: LifecycleOwner?,
vararg transformations: Transformation
): LoadRequest {
return LoadRequest(context, imageLoader.defaults) {
data(url)
transformations(*transformations)
lifecycleOwner?.let {
lifecycle(lifecycleOwner)
}
target?.let {
target(target)
}
if (url.startsWith(userEntity.baseUrl) && url.contains(
"index.php/core/preview?fileId="
)
) {
addHeader("Authorization", userEntity.getCredentials())
}
}
}
}