@@ -13,9 +13,11 @@ import android.graphics.Bitmap
1313import android.graphics.drawable.Drawable
1414import android.graphics.drawable.PictureDrawable
1515import android.widget.ImageView
16+ import androidx.activity.ComponentActivity
1617import androidx.annotation.DrawableRes
1718import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory
1819import androidx.core.net.toUri
20+ import androidx.lifecycle.lifecycleScope
1921import com.bumptech.glide.Glide
2022import com.bumptech.glide.RequestBuilder
2123import com.bumptech.glide.load.DataSource
@@ -28,43 +30,161 @@ import com.bumptech.glide.request.target.BitmapImageViewTarget
2830import com.bumptech.glide.request.target.Target
2931import com.nextcloud.common.NextcloudClient
3032import com.nextcloud.utils.LinkHelper.validateAndGetURL
33+ import com.owncloud.android.lib.common.OwnCloudAccount
34+ import com.owncloud.android.lib.common.OwnCloudClientManagerFactory
3135import com.owncloud.android.lib.common.utils.Log_OC
3236import com.owncloud.android.utils.svg.SvgSoftwareLayerSetter
37+ import kotlinx.coroutines.Dispatchers
38+ import kotlinx.coroutines.launch
39+ import kotlinx.coroutines.withContext
3340
3441/* *
3542 * Utility object for loading images (including SVGs) using Glide.
3643 *
3744 * Provides methods for loading images into `ImageView`, `Target<Drawable>`, `Target<Bitmap>` ...
3845 * from both URLs and URIs.
3946 */
40- @Suppress(" TooManyFunctions" )
47+ @Suppress(" TooManyFunctions" , " TooGenericExceptionCaught " )
4148object GlideHelper {
4249 private const val TAG = " GlideHelper"
4350
44- private class GlideLogger <T >(private val methodName : String , private val identifier : String ) : RequestListener<T> {
45- override fun onLoadFailed (p0 : GlideException ? , p1 : Any? , p2 : Target <T >, p3 : Boolean ): Boolean {
46- Log_OC .e(TAG , " $methodName : Load failed for $identifier " )
47- Log_OC .e(TAG , " $methodName : Error: ${p0?.message} " )
48- p0?.logRootCauses(TAG )
49- return false
51+ @Suppress(" TooGenericExceptionCaught" )
52+ fun getBitmap (context : Context , url : String? ): Bitmap ? {
53+ val validatedUrl = validateAndGetURL(url) ? : return null
54+
55+ return try {
56+ Glide .with (context)
57+ .asBitmap()
58+ .load(validatedUrl)
59+ .diskCacheStrategy(DiskCacheStrategy .NONE )
60+ .skipMemoryCache(true )
61+ .withLogging(" downloadImageSynchronous" , validatedUrl)
62+ .submit(Target .SIZE_ORIGINAL , Target .SIZE_ORIGINAL )
63+ .get()
64+ } catch (e: Exception ) {
65+ Log_OC .e(TAG , " exception getBitmap: $e " )
66+ null
5067 }
68+ }
5169
52- override fun onResourceReady (p0 : T & Any , p1 : Any , p2 : Target <T ?>? , p3 : DataSource , p4 : Boolean ): Boolean {
53- Log_OC .i(TAG , " Glide load completed: $p0 " )
54- return false
70+ fun loadCircularBitmapIntoImageView (context : Context , url : String? , imageView : ImageView , placeholder : Drawable ? ) {
71+ val validatedUrl = validateAndGetURL(url) ? : return
72+
73+ try {
74+ Glide .with (context)
75+ .asBitmap()
76+ .load(validatedUrl)
77+ .placeholder(placeholder)
78+ .error(placeholder)
79+ .withLogging(" loadCircularBitmapIntoImageView" , validatedUrl)
80+ .into(object : BitmapImageViewTarget (imageView) {
81+ override fun setResource (resource : Bitmap ? ) {
82+ val circularBitmapDrawable = RoundedBitmapDrawableFactory .create(context.resources, resource)
83+ circularBitmapDrawable.isCircular = true
84+ imageView.setImageDrawable(circularBitmapDrawable)
85+ }
86+ })
87+ } catch (e: Exception ) {
88+ Log_OC .e(TAG , " exception loadCircularBitmapIntoImageView: $e " )
89+ imageView.setImageDrawable(placeholder)
5590 }
5691 }
5792
58- private fun isSVG (url : String ): Boolean = (url.toUri().encodedPath?.endsWith(" .svg" ) == true )
93+ @SuppressLint(" CheckResult" )
94+ fun loadIntoImageView (
95+ context : Context ,
96+ client : NextcloudClient ? ,
97+ url : String? ,
98+ imageView : ImageView ,
99+ @DrawableRes placeholder : Int ,
100+ circleCrop : Boolean = false
101+ ) {
102+ try {
103+ createRequestBuilder<Drawable >(context, client, url)
104+ ?.placeholder(placeholder)
105+ ?.error(placeholder)
106+ ?.apply { if (circleCrop) circleCrop() }
107+ ?.withLogging(" loadIntoImageView" , url ? : " null" )
108+ ?.into(imageView) ? : imageView.setImageResource(placeholder)
109+ } catch (e: Exception ) {
110+ Log_OC .e(TAG , " exception loadIntoImageView: $e " )
111+ imageView.setImageResource(placeholder)
112+ }
113+ }
114+
115+ fun getDrawable (context : Context , client : NextcloudClient ? , urlString : String? ): Drawable ? = try {
116+ createRequestBuilder<Drawable >(context, client, urlString)?.submit()?.get()
117+ } catch (e: Exception ) {
118+ Log_OC .e(TAG , " exception getDrawable: $e " )
119+ null
120+ }
121+
122+ fun <T > loadIntoTarget (
123+ activity : ComponentActivity ,
124+ account : OwnCloudAccount ? ,
125+ url : String ,
126+ target : Target <T >,
127+ @DrawableRes placeholder : Int
128+ ) {
129+ if (account == null ) {
130+ Log_OC .e(TAG , " loadIntoTargetWithActivity: account cannot be null" )
131+ return
132+ }
133+
134+ activity.lifecycleScope.launch(Dispatchers .IO ) {
135+ val clientFactory = OwnCloudClientManagerFactory .getDefaultSingleton()
136+ val client = clientFactory.getNextcloudClientFor(account, activity)
137+ withContext(Dispatchers .Main ) {
138+ try {
139+ createRequestBuilder<T >(activity, client, url)
140+ ?.placeholder(placeholder)
141+ ?.error(placeholder)
142+ ?.withLogging(" loadIntoTarget" , url)
143+ ?.into(target)
144+ } catch (e: Exception ) {
145+ Log_OC .e(TAG , " exception loadIntoTarget: $e " )
146+ }
147+ }
148+ }
149+ }
59150
60- private fun createGlideUrl (url : String , client : NextcloudClient ) = GlideUrl (
151+ fun createGlideUrl (url : String , client : NextcloudClient ) = GlideUrl (
61152 url,
62153 LazyHeaders .Builder ()
63154 .addHeader(" Authorization" , client.credentials)
64155 .addHeader(" User-Agent" , " Mozilla/5.0 (Android) Nextcloud-android" )
65156 .build()
66157 )
67158
159+ // region private methods
160+ private class GlideLogger <T >(private val methodName : String , private val identifier : String ) : RequestListener<T> {
161+
162+ override fun onLoadFailed (
163+ e : GlideException ? ,
164+ model : Any? ,
165+ target : Target <T >,
166+ isFirstResource : Boolean
167+ ): Boolean {
168+ Log_OC .e(TAG , " $methodName : Load failed for $identifier " )
169+ Log_OC .e(TAG , " $methodName : Error: ${e?.message} " )
170+ e?.logRootCauses(TAG )
171+ return false
172+ }
173+
174+ override fun onResourceReady (
175+ resource : T & Any ,
176+ model : Any? ,
177+ target : Target <T ?>? ,
178+ dataSource : DataSource ,
179+ isFirstResource : Boolean
180+ ): Boolean {
181+ Log_OC .i(TAG , " $methodName : Successfully loaded $identifier from $dataSource " )
182+ return false
183+ }
184+ }
185+
186+ private fun isSVG (url : String ): Boolean = (url.toUri().encodedPath?.endsWith(" .svg" ) == true )
187+
68188 private fun <T > RequestBuilder<T>.withLogging (methodName : String , identifier : String ): RequestBuilder <T > =
69189 listener(GlideLogger (methodName, identifier))
70190
@@ -81,8 +201,10 @@ object GlideHelper {
81201 .`as `(PictureDrawable ::class .java)
82202 .load(glideUrl)
83203 .apply {
84- placeholder?.let { placeholder(it) }
85- placeholder?.let { error(it) }
204+ placeholder?.let {
205+ placeholder(it)
206+ error(it)
207+ }
86208 }
87209 .listener(SvgSoftwareLayerSetter ())
88210 }
@@ -94,47 +216,11 @@ object GlideHelper {
94216 ): RequestBuilder <Drawable > {
95217 val glideUrl = createGlideUrl(url, client)
96218 return Glide .with (context)
219+ .asDrawable()
97220 .load(glideUrl)
98221 .centerCrop()
99222 }
100223
101- @Suppress(" TooGenericExceptionCaught" )
102- fun getBitmap (context : Context , url : String? ): Bitmap ? {
103- val validatedUrl = validateAndGetURL(url) ? : return null
104-
105- return try {
106- Glide .with (context)
107- .asBitmap()
108- .load(validatedUrl)
109- .diskCacheStrategy(DiskCacheStrategy .NONE )
110- .skipMemoryCache(true )
111- .withLogging(" downloadImageSynchronous" , validatedUrl)
112- .submit(Target .SIZE_ORIGINAL , Target .SIZE_ORIGINAL )
113- .get()
114- } catch (e: Exception ) {
115- Log_OC .e(TAG , " Could not download image $e " )
116- null
117- }
118- }
119-
120- fun loadCircularBitmapIntoImageView (context : Context , url : String? , imageView : ImageView , placeholder : Drawable ) {
121- val validatedUrl = validateAndGetURL(url) ? : return
122-
123- Glide .with (context)
124- .asBitmap()
125- .load(validatedUrl)
126- .placeholder(placeholder)
127- .error(placeholder)
128- .withLogging(" loadCircularBitmapIntoImageView" , validatedUrl)
129- .into(object : BitmapImageViewTarget (imageView) {
130- override fun setResource (resource : Bitmap ? ) {
131- val circularBitmapDrawable = RoundedBitmapDrawableFactory .create(context.resources, resource)
132- circularBitmapDrawable.isCircular = true
133- imageView.setImageDrawable(circularBitmapDrawable)
134- }
135- })
136- }
137-
138224 @Suppress(" UNCHECKED_CAST" , " TooGenericExceptionCaught" , " ReturnCount" )
139225 private fun <T > createRequestBuilder (context : Context , client : NextcloudClient ? , url : String? ): RequestBuilder <T >? {
140226 if (client == null ) {
@@ -147,47 +233,15 @@ object GlideHelper {
147233 return try {
148234 val isSVG = isSVG(validatedUrl)
149235
150- return if (isSVG) {
236+ if (isSVG) {
151237 createSvgRequestBuilder(context, validatedUrl, client)
152238 } else {
153239 createUrlRequestBuilder(context, client, validatedUrl)
154- }
155- .withLogging(" createRequestBuilder" , validatedUrl) as RequestBuilder <T >?
240+ }.withLogging(" createRequestBuilder" , validatedUrl) as RequestBuilder <T >?
156241 } catch (e: Exception ) {
157- Log_OC .e(TAG , " Error createRequestBuilder: $e " )
242+ Log_OC .e(TAG , " exception createRequestBuilder: $e " )
158243 null
159244 }
160245 }
161-
162- @SuppressLint(" CheckResult" )
163- fun loadIntoImageView (
164- context : Context ,
165- client : NextcloudClient ? ,
166- url : String? ,
167- imageView : ImageView ,
168- @DrawableRes placeholder : Int ,
169- circleCrop : Boolean = false
170- ) {
171- createRequestBuilder<Drawable >(context, client, url)
172- ?.placeholder(placeholder)
173- ?.error(placeholder)
174- ?.apply { if (circleCrop) circleCrop() }
175- ?.into(imageView)
176- }
177-
178- fun getDrawable (context : Context , client : NextcloudClient ? , urlString : String? ): Drawable ? =
179- createRequestBuilder<Drawable >(context, client, urlString)?.submit()?.get()
180-
181- fun <T > loadIntoTarget (
182- context : Context ,
183- client : NextcloudClient ? ,
184- url : String ,
185- target : Target <T >,
186- @DrawableRes placeholder : Int
187- ) {
188- createRequestBuilder<T >(context, client, url)
189- ?.placeholder(placeholder)
190- ?.error(placeholder)
191- ?.into(target)
192- }
246+ // endregion
193247}
0 commit comments