Merge pull request #174 from tylerbwong/image-coil
Add CoilImagesPlugin Module
This commit is contained in:
		
						commit
						6b9e79ce5e
					
				| @ -72,7 +72,8 @@ ext { | ||||
|             'adapt'                   : 'io.noties:adapt:2.0.0', | ||||
|             'dagger'                  : "com.google.dagger:dagger:$daggerVersion", | ||||
|             'picasso'                 : 'com.squareup.picasso:picasso:2.71828', | ||||
|             'glide'                   : 'com.github.bumptech.glide:glide:4.9.0' | ||||
|             'glide'                   : 'com.github.bumptech.glide:glide:4.9.0', | ||||
|             'coil'                    : 'io.coil-kt:coil:0.8.0' | ||||
|     ] | ||||
| 
 | ||||
|     deps['annotationProcessor'] = [ | ||||
|  | ||||
							
								
								
									
										35
									
								
								docs/docs/v4/image-coil/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								docs/docs/v4/image-coil/README.md
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,35 @@ | ||||
| # Image Coil | ||||
| 
 | ||||
| <MavenBadge4 :artifact="'image-coil'" /> | ||||
| 
 | ||||
| Image loading based on `Coil` library | ||||
| 
 | ||||
| ```kotlin | ||||
| val markwon = Markwon.builder(context) | ||||
|         // automatically create Coil instance | ||||
|         .usePlugin(CoilImagesPlugin.create(context)) | ||||
|         // use supplied ImageLoader instance | ||||
|         .usePlugin(CoilImagesPlugin.create( | ||||
|             context, | ||||
|             ImageLoader(context) { | ||||
|                 availableMemoryPercentage(0.5) | ||||
|                 bitmapPoolPercentage(0.5) | ||||
|                 crossfade(true) | ||||
|             } | ||||
|         )) | ||||
|         // if you need more control | ||||
|         .usePlugin(CoilImagesPlugin.create(object : CoilImagesPlugin.CoilStore { | ||||
|             override fun load(drawable: AsyncDrawable): LoadRequest { | ||||
|                 return LoadRequest(context, customImageLoader.defaults) { | ||||
|                     data(drawable.destination) | ||||
|                     crossfade(true) | ||||
|                     transformations(CircleCropTransformation()) | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             override cancel(disposable: RequestDisposable) { | ||||
|                 disposable.dispose() | ||||
|             } | ||||
|         }, customImageLoader)) | ||||
|         .build() | ||||
| ``` | ||||
							
								
								
									
										3
									
								
								markwon-image-coil/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								markwon-image-coil/README.md
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | ||||
| # Images (Coil) | ||||
| 
 | ||||
| https://noties.io/Markwon/docs/v4/image-coil/ | ||||
							
								
								
									
										21
									
								
								markwon-image-coil/build.gradle
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								markwon-image-coil/build.gradle
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,21 @@ | ||||
| apply plugin: 'com.android.library' | ||||
| 
 | ||||
| android { | ||||
| 
 | ||||
|     compileSdkVersion config['compile-sdk'] | ||||
|     buildToolsVersion config['build-tools'] | ||||
| 
 | ||||
|     defaultConfig { | ||||
|         minSdkVersion config['min-sdk'] | ||||
|         targetSdkVersion config['target-sdk'] | ||||
|         versionCode 1 | ||||
|         versionName version | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| dependencies { | ||||
|     api project(':markwon-core') | ||||
|     api deps['coil'] | ||||
| } | ||||
| 
 | ||||
| registerArtifact(this) | ||||
							
								
								
									
										4
									
								
								markwon-image-coil/gradle.properties
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								markwon-image-coil/gradle.properties
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,4 @@ | ||||
| POM_NAME=Image Coil | ||||
| POM_ARTIFACT_ID=image-coil | ||||
| POM_DESCRIPTION=Markwon image loading module (based on Coil library) | ||||
| POM_PACKAGING=aar | ||||
							
								
								
									
										1
									
								
								markwon-image-coil/src/main/AndroidManifest.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								markwon-image-coil/src/main/AndroidManifest.xml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1 @@ | ||||
| <manifest package="io.noties.markwon.image.coil" /> | ||||
| @ -0,0 +1,187 @@ | ||||
| package io.noties.markwon.image.coil; | ||||
| 
 | ||||
| import android.content.Context; | ||||
| import android.graphics.drawable.Drawable; | ||||
| import android.text.Spanned; | ||||
| import android.widget.TextView; | ||||
| 
 | ||||
| import androidx.annotation.NonNull; | ||||
| import androidx.annotation.Nullable; | ||||
| 
 | ||||
| import org.commonmark.node.Image; | ||||
| 
 | ||||
| import java.util.HashMap; | ||||
| import java.util.Map; | ||||
| 
 | ||||
| import coil.Coil; | ||||
| import coil.ImageLoader; | ||||
| import coil.api.ImageLoaders; | ||||
| import coil.request.LoadRequest; | ||||
| import coil.request.RequestDisposable; | ||||
| import coil.target.Target; | ||||
| import io.noties.markwon.AbstractMarkwonPlugin; | ||||
| import io.noties.markwon.MarkwonConfiguration; | ||||
| import io.noties.markwon.MarkwonSpansFactory; | ||||
| import io.noties.markwon.image.AsyncDrawable; | ||||
| import io.noties.markwon.image.AsyncDrawableLoader; | ||||
| import io.noties.markwon.image.AsyncDrawableScheduler; | ||||
| import io.noties.markwon.image.DrawableUtils; | ||||
| import io.noties.markwon.image.ImageSpanFactory; | ||||
| 
 | ||||
| /** | ||||
|  * @since 4.0.0 | ||||
|  * @author Tyler Wong | ||||
|  */ | ||||
| public class CoilImagesPlugin extends AbstractMarkwonPlugin { | ||||
| 
 | ||||
|     public interface CoilStore { | ||||
| 
 | ||||
|         @NonNull | ||||
|         LoadRequest load(@NonNull AsyncDrawable drawable); | ||||
| 
 | ||||
|         void cancel(@NonNull RequestDisposable disposable); | ||||
|     } | ||||
| 
 | ||||
|     @NonNull | ||||
|     public static CoilImagesPlugin create(@NonNull final Context context) { | ||||
|         return create(new CoilStore() { | ||||
|             @NonNull | ||||
|             @Override | ||||
|             public LoadRequest load(@NonNull AsyncDrawable drawable) { | ||||
|                 return ImageLoaders.newLoadBuilder(Coil.loader(), context) | ||||
|                         .data(drawable.getDestination()) | ||||
|                         .build(); | ||||
|             } | ||||
| 
 | ||||
|             @Override | ||||
|             public void cancel(@NonNull RequestDisposable disposable) { | ||||
|                 disposable.dispose(); | ||||
|             } | ||||
|         }, Coil.loader()); | ||||
|     } | ||||
| 
 | ||||
|     @NonNull | ||||
|     public static CoilImagesPlugin create(@NonNull final Context context, | ||||
|                                           @NonNull final ImageLoader imageLoader) { | ||||
|         return create(new CoilStore() { | ||||
|             @NonNull | ||||
|             @Override | ||||
|             public LoadRequest load(@NonNull AsyncDrawable drawable) { | ||||
|                 return ImageLoaders.newLoadBuilder(imageLoader, context) | ||||
|                         .data(drawable.getDestination()) | ||||
|                         .build(); | ||||
|             } | ||||
| 
 | ||||
|             @Override | ||||
|             public void cancel(@NonNull RequestDisposable disposable) { | ||||
|                 disposable.dispose(); | ||||
|             } | ||||
|         }, imageLoader); | ||||
|     } | ||||
| 
 | ||||
|     @NonNull | ||||
|     public static CoilImagesPlugin create(@NonNull final CoilStore coilStore, | ||||
|                                           @NonNull final ImageLoader imageLoader) { | ||||
|         return new CoilImagesPlugin(coilStore, imageLoader); | ||||
|     } | ||||
| 
 | ||||
|     private final CoilAsyncDrawableLoader coilAsyncDrawableLoader; | ||||
| 
 | ||||
|     @SuppressWarnings("WeakerAccess") | ||||
|     CoilImagesPlugin(@NonNull CoilStore coilStore, @NonNull ImageLoader imageLoader) { | ||||
|         this.coilAsyncDrawableLoader = new CoilAsyncDrawableLoader(coilStore, imageLoader); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void configureSpansFactory(@NonNull MarkwonSpansFactory.Builder builder) { | ||||
|         builder.setFactory(Image.class, new ImageSpanFactory()); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void configureConfiguration(@NonNull MarkwonConfiguration.Builder builder) { | ||||
|         builder.asyncDrawableLoader(coilAsyncDrawableLoader); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void beforeSetText(@NonNull TextView textView, @NonNull Spanned markdown) { | ||||
|         AsyncDrawableScheduler.unschedule(textView); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void afterSetText(@NonNull TextView textView) { | ||||
|         AsyncDrawableScheduler.schedule(textView); | ||||
|     } | ||||
| 
 | ||||
|     private static class CoilAsyncDrawableLoader extends AsyncDrawableLoader { | ||||
| 
 | ||||
|         private final CoilStore coilStore; | ||||
|         private final ImageLoader imageLoader; | ||||
|         private final Map<AsyncDrawable, RequestDisposable> cache = new HashMap<>(2); | ||||
| 
 | ||||
|         CoilAsyncDrawableLoader(@NonNull CoilStore coilStore, @NonNull ImageLoader imageLoader) { | ||||
|             this.coilStore = coilStore; | ||||
|             this.imageLoader = imageLoader; | ||||
|         } | ||||
| 
 | ||||
|         @Override | ||||
|         public void load(@NonNull AsyncDrawable drawable) { | ||||
|             final Target target = new AsyncDrawableTarget(drawable); | ||||
|             LoadRequest request = coilStore.load(drawable).newBuilder() | ||||
|                     .target(target) | ||||
|                     .build(); | ||||
|             RequestDisposable disposable = imageLoader.load(request); | ||||
|             cache.put(drawable, disposable); | ||||
|         } | ||||
| 
 | ||||
|         @Override | ||||
|         public void cancel(@NonNull AsyncDrawable drawable) { | ||||
|             final RequestDisposable disposable = cache.remove(drawable); | ||||
|             if (disposable != null) { | ||||
|                 coilStore.cancel(disposable); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         @Nullable | ||||
|         @Override | ||||
|         public Drawable placeholder(@NonNull AsyncDrawable drawable) { | ||||
|             return null; | ||||
|         } | ||||
| 
 | ||||
|         private class AsyncDrawableTarget implements Target { | ||||
| 
 | ||||
|             private final AsyncDrawable drawable; | ||||
| 
 | ||||
|             AsyncDrawableTarget(@NonNull AsyncDrawable drawable) { | ||||
|                 this.drawable = drawable; | ||||
|             } | ||||
| 
 | ||||
|             @Override | ||||
|             public void onSuccess(@NonNull Drawable loadedDrawable) { | ||||
|                 if (cache.remove(drawable) != null) { | ||||
|                     if (drawable.isAttached()) { | ||||
|                         DrawableUtils.applyIntrinsicBoundsIfEmpty(loadedDrawable); | ||||
|                         drawable.setResult(loadedDrawable); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             @Override | ||||
|             public void onStart(@Nullable Drawable placeholder) { | ||||
|                 if (placeholder != null && drawable.isAttached()) { | ||||
|                     DrawableUtils.applyIntrinsicBoundsIfEmpty(placeholder); | ||||
|                     drawable.setResult(placeholder); | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             @Override | ||||
|             public void onError(@Nullable Drawable errorDrawable) { | ||||
|                 if (cache.remove(drawable) != null) { | ||||
|                     if (errorDrawable != null && drawable.isAttached()) { | ||||
|                         DrawableUtils.applyIntrinsicBoundsIfEmpty(errorDrawable); | ||||
|                         drawable.setResult(errorDrawable); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -82,6 +82,7 @@ public class RecyclerActivity extends Activity { | ||||
| //                })) | ||||
|                 .usePlugin(PicassoImagesPlugin.create(context)) | ||||
| //                .usePlugin(GlideImagesPlugin.create(context)) | ||||
| //                .usePlugin(CoilImagesPlugin.create(context)) | ||||
|                 // important to use TableEntryPlugin instead of TablePlugin | ||||
|                 .usePlugin(TableEntryPlugin.create(context)) | ||||
|                 .usePlugin(HtmlPlugin.create()) | ||||
|  | ||||
| @ -8,6 +8,7 @@ include ':app', ':sample', | ||||
|         ':markwon-ext-tasklist', | ||||
|         ':markwon-html', | ||||
|         ':markwon-image', | ||||
|         ':markwon-image-coil', | ||||
|         ':markwon-image-glide', | ||||
|         ':markwon-image-picasso', | ||||
|         ':markwon-linkify', | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Dimitry
						Dimitry