Sample app, adding and reading samples
This commit is contained in:
		
							parent
							
								
									66f77f35fe
								
							
						
					
					
						commit
						860d70d6d1
					
				| @ -1,4 +1,35 @@ | ||||
| [ | ||||
|   { | ||||
|     "javaClassName": "io.noties.markwon.app.samples.nested.ThirdSample", | ||||
|     "id": "202006177155827", | ||||
|     "title": "Third sample", | ||||
|     "description": "\u003e yo! \n\n```\nfinal int i \u003d 0;\n```", | ||||
|     "artifacts": [ | ||||
|       "EDITOR", | ||||
|       "SIMPLE_EXT" | ||||
|     ], | ||||
|     "tags": [ | ||||
|       "a", | ||||
|       "c", | ||||
|       "test" | ||||
|     ] | ||||
|   }, | ||||
|   { | ||||
|     "javaClassName": "io.noties.markwon.app.samples.nested.SecondSample", | ||||
|     "id": "202006177155656", | ||||
|     "title": "Second sample", | ||||
|     "description": "# Hey hey hey", | ||||
|     "artifacts": [ | ||||
|       "CORE", | ||||
|       "RECYCLER" | ||||
|     ], | ||||
|     "tags": [ | ||||
|       "a", | ||||
|       "b", | ||||
|       "c", | ||||
|       "test" | ||||
|     ] | ||||
|   }, | ||||
|   { | ||||
|     "javaClassName": "io.noties.markwon.app.samples.FirstSample", | ||||
|     "id": "202006164150023", | ||||
|  | ||||
							
								
								
									
										1
									
								
								app-sample/src/main/assets/samples
									
									
									
									
									
										Symbolic link
									
								
							
							
						
						
									
										1
									
								
								app-sample/src/main/assets/samples
									
									
									
									
									
										Symbolic link
									
								
							| @ -0,0 +1 @@ | ||||
| ../../main/java/io/noties/markwon/app/samples/ | ||||
| @ -12,4 +12,11 @@ data class Sample( | ||||
|         val description: String, | ||||
|         val artifacts: List<MarkwonArtifact>, | ||||
|         val tags: List<String> | ||||
| ) : Parcelable | ||||
| ) : Parcelable { | ||||
| 
 | ||||
|     enum class Language { | ||||
|         JAVA, KOTLIN | ||||
|     } | ||||
| 
 | ||||
|     data class Code(val language: Language, val sourceCode: String) | ||||
| } | ||||
| @ -81,6 +81,21 @@ class SampleItem( | ||||
|         val artifacts: FlowLayout = requireView(R.id.artifacts) | ||||
|         val tags: FlowLayout = requireView(R.id.tags) | ||||
|     } | ||||
| 
 | ||||
|     override fun equals(other: Any?): Boolean { | ||||
|         if (this === other) return true | ||||
|         if (javaClass != other?.javaClass) return false | ||||
| 
 | ||||
|         other as SampleItem | ||||
| 
 | ||||
|         if (sample != other.sample) return false | ||||
| 
 | ||||
|         return true | ||||
|     } | ||||
| 
 | ||||
|     override fun hashCode(): Int { | ||||
|         return sample.hashCode() | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| private fun FlowLayout.ensure(viewsCount: Int, layoutResId: Int): List<View> { | ||||
|  | ||||
| @ -0,0 +1,3 @@ | ||||
| [{*.java, *.kt}] | ||||
| indent_style = space | ||||
| indent_size = 2 | ||||
| @ -1,15 +1,30 @@ | ||||
| package io.noties.markwon.app.samples | ||||
| 
 | ||||
| import io.noties.markwon.app.ui.MarkwonSample | ||||
| import io.noties.markwon.Markwon | ||||
| import io.noties.markwon.app.ui.MarkwonTextViewSample | ||||
| import io.noties.markwon.sample.annotations.MarkwonArtifact | ||||
| import io.noties.markwon.sample.annotations.MarkwonSampleInfo | ||||
| 
 | ||||
| @MarkwonSampleInfo( | ||||
|         id = "202006164150023", | ||||
|         title = "First Sample", | ||||
|         description = "This **is** _the first_ sample", | ||||
|         artifacts = [MarkwonArtifact.CORE], | ||||
|         tags = ["test"] | ||||
|   id = "202006164150023", | ||||
|   title = "First Sample", | ||||
|   description = "This **is** _the first_ sample", | ||||
|   artifacts = [MarkwonArtifact.CORE], | ||||
|   tags = ["test"] | ||||
| ) | ||||
| class FirstSample : MarkwonSample() { | ||||
| class FirstSample : MarkwonTextViewSample() { | ||||
| 
 | ||||
|   override fun render() { | ||||
| 
 | ||||
|     val md = """ | ||||
|             # Hello there! | ||||
|             > How are you? | ||||
|              | ||||
|             **bold** and _italic_ and **bold _italic bold_ just bold** | ||||
|         """.trimIndent() | ||||
| 
 | ||||
|     val markwon: Markwon = Markwon.create(context) | ||||
| 
 | ||||
|     markwon.setMarkdown(textView, md) | ||||
|   } | ||||
| } | ||||
| @ -0,0 +1,65 @@ | ||||
| package io.noties.markwon.app.samples.nested | ||||
| 
 | ||||
| import io.noties.markwon.Markwon | ||||
| import io.noties.markwon.app.ui.MarkwonTextViewSample | ||||
| import io.noties.markwon.sample.annotations.MarkwonArtifact | ||||
| import io.noties.markwon.sample.annotations.MarkwonSampleInfo | ||||
| 
 | ||||
| @MarkwonSampleInfo( | ||||
|   id = "202006177155656", | ||||
|   title = "Second sample", | ||||
|   description = "# Hey hey hey", | ||||
|   artifacts = [MarkwonArtifact.CORE, MarkwonArtifact.RECYCLER], | ||||
|   tags = ["b", "c", "a", "test"] | ||||
| ) | ||||
| class SecondSample : MarkwonTextViewSample() { | ||||
|   override fun render() { | ||||
|     val md = """ | ||||
|       # Hello second | ||||
|        | ||||
|       ```java | ||||
|       final int i = 0; | ||||
|       ``` | ||||
|     """.trimIndent() | ||||
| 
 | ||||
|     val markwon = Markwon.create(context) | ||||
|     markwon.setMarkdown(textView, md) | ||||
|   } | ||||
| 
 | ||||
|   val _mock: String | ||||
|   get() = """ | ||||
|     a | ||||
|     b | ||||
|     d | ||||
|     s | ||||
|     as | ||||
|     sd | ||||
|     ds | ||||
|     sd | ||||
|     s | ||||
|     sd | ||||
|     sd | ||||
|     ds | ||||
|     sd | ||||
|     sd | ||||
|     sd | ||||
|     sd | ||||
|     sd | ||||
|     sd | ||||
|     ds | ||||
|     sd | ||||
|     sd | ||||
|      | ||||
|     s | ||||
|     sd | ||||
|     sd | ||||
|     sd | ||||
|     sd | ||||
|     sd | ||||
|      | ||||
|     ds | ||||
|     sd | ||||
|     sd | ||||
|     sd | ||||
|   """.trimIndent() | ||||
| } | ||||
| @ -0,0 +1,22 @@ | ||||
| package io.noties.markwon.app.samples.nested; | ||||
| 
 | ||||
| import io.noties.markwon.Markwon; | ||||
| import io.noties.markwon.app.ui.MarkwonTextViewSample; | ||||
| import io.noties.markwon.sample.annotations.MarkwonArtifact; | ||||
| import io.noties.markwon.sample.annotations.MarkwonSampleInfo; | ||||
| 
 | ||||
| @MarkwonSampleInfo( | ||||
|   id = "202006177155827", | ||||
|   title = "Third sample", | ||||
|   description = "> yo! \n\n```\nfinal int i = 0;\n```", | ||||
|   artifacts = {MarkwonArtifact.SIMPLE_EXT, MarkwonArtifact.EDITOR}, | ||||
|   tags = {"a", "c", "test"} | ||||
| ) | ||||
| public class ThirdSample extends MarkwonTextViewSample { | ||||
|   @Override | ||||
|   public void render() { | ||||
|     final String md = "# Hello!"; | ||||
|     final Markwon markwon = Markwon.create(context); | ||||
|     markwon.setMarkdown(textView, md); | ||||
|   } | ||||
| } | ||||
| @ -1,5 +1,16 @@ | ||||
| package io.noties.markwon.app.ui | ||||
| 
 | ||||
| import android.view.LayoutInflater | ||||
| import android.view.View | ||||
| import android.view.ViewGroup | ||||
| 
 | ||||
| abstract class MarkwonSample { | ||||
| 
 | ||||
|     fun createView(inflater: LayoutInflater, container: ViewGroup?): View { | ||||
|         return inflater.inflate(layoutResId, container, false) | ||||
|     } | ||||
| 
 | ||||
|     abstract fun onViewCreated(view: View) | ||||
| 
 | ||||
|     protected abstract val layoutResId: Int | ||||
| } | ||||
| @ -0,0 +1,23 @@ | ||||
| package io.noties.markwon.app.ui | ||||
| 
 | ||||
| import android.content.Context | ||||
| import android.view.View | ||||
| import android.widget.TextView | ||||
| 
 | ||||
| import io.noties.markwon.app.R | ||||
| 
 | ||||
| abstract class MarkwonTextViewSample : MarkwonSample() { | ||||
| 
 | ||||
|     protected lateinit var context: Context | ||||
|     protected lateinit var textView: TextView | ||||
| 
 | ||||
|     override val layoutResId: Int = R.layout.sample_text_view | ||||
| 
 | ||||
|     final override fun onViewCreated(view: View) { | ||||
|         context = view.context | ||||
|         textView = view.findViewById(R.id.text_view) | ||||
|         render() | ||||
|     } | ||||
| 
 | ||||
|     abstract fun render() | ||||
| } | ||||
| @ -0,0 +1,43 @@ | ||||
| package io.noties.markwon.app.ui | ||||
| 
 | ||||
| import android.os.Bundle | ||||
| import android.view.LayoutInflater | ||||
| import android.view.View | ||||
| import android.view.ViewGroup | ||||
| import android.widget.TextView | ||||
| import androidx.fragment.app.Fragment | ||||
| import io.noties.markwon.app.R | ||||
| import io.noties.markwon.app.Sample | ||||
| import io.noties.markwon.app.utils.readCode | ||||
| 
 | ||||
| class SampleCodeFragment : Fragment() { | ||||
| 
 | ||||
|     override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { | ||||
|         return inflater.inflate(R.layout.fragment_sample_code, container, false) | ||||
|     } | ||||
| 
 | ||||
|     override fun onViewCreated(view: View, savedInstanceState: Bundle?) { | ||||
|         super.onViewCreated(view, savedInstanceState) | ||||
| 
 | ||||
|         val textView: TextView = view.findViewById(R.id.text_view) | ||||
|         val code = sample.readCode(requireContext()) | ||||
| 
 | ||||
|         textView.text = code.sourceCode | ||||
|     } | ||||
| 
 | ||||
|     private val sample: Sample by lazy(LazyThreadSafetyMode.NONE) { | ||||
|         arguments!!.getParcelable<Sample>(ARG_SAMPLE) | ||||
|     } | ||||
| 
 | ||||
|     companion object { | ||||
|         private const val ARG_SAMPLE = "arg.Sample" | ||||
| 
 | ||||
|         fun init(sample: Sample): SampleCodeFragment { | ||||
|             return SampleCodeFragment().apply { | ||||
|                 arguments = Bundle().apply { | ||||
|                     putParcelable(ARG_SAMPLE, sample) | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -1,13 +1,127 @@ | ||||
| package io.noties.markwon.app.ui | ||||
| 
 | ||||
| import android.os.Bundle | ||||
| import android.view.LayoutInflater | ||||
| import android.view.View | ||||
| import android.view.ViewGroup | ||||
| import android.widget.TextView | ||||
| import androidx.fragment.app.Fragment | ||||
| import androidx.fragment.app.FragmentTransaction | ||||
| import io.noties.markwon.app.R | ||||
| import io.noties.markwon.app.Sample | ||||
| import io.noties.markwon.app.utils.active | ||||
| 
 | ||||
| class SampleFragment : Fragment() { | ||||
| 
 | ||||
|     private lateinit var container: ViewGroup | ||||
| 
 | ||||
|     private var isCodeSelected = false | ||||
| 
 | ||||
|     override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { | ||||
|         return inflater.inflate(R.layout.fragment_sample, container, false) | ||||
|     } | ||||
| 
 | ||||
|     override fun onViewCreated(view: View, savedInstanceState: Bundle?) { | ||||
|         super.onViewCreated(view, savedInstanceState) | ||||
| 
 | ||||
|         container = view.findViewById(R.id.container) | ||||
|         isCodeSelected = savedInstanceState?.getBoolean(KEY_CODE_SELECTED) ?: false | ||||
| 
 | ||||
|         initAppBar(view) | ||||
|         initTabBar(view) | ||||
|     } | ||||
| 
 | ||||
|     private fun initAppBar(view: View) { | ||||
|         val appBar: View = view.findViewById(R.id.app_bar) | ||||
|         val icon: View = appBar.findViewById(R.id.app_bar_icon) | ||||
|         val title: TextView = appBar.findViewById(R.id.app_bar_title) | ||||
| 
 | ||||
|         icon.setOnClickListener { | ||||
|             activity?.onBackPressed() | ||||
|         } | ||||
| 
 | ||||
|         title.text = sample.title | ||||
|     } | ||||
| 
 | ||||
|     private fun initTabBar(view: View) { | ||||
|         val tabBar: View = view.findViewById(R.id.tab_bar) | ||||
|         val preview: View = tabBar.findViewById(R.id.tab_bar_preview) | ||||
|         val code: View = tabBar.findViewById(R.id.tab_bar_code) | ||||
| 
 | ||||
|         preview.setOnClickListener { | ||||
|             if (!it.active) { | ||||
|                 it.active = true | ||||
|                 code.active = false | ||||
|                 showPreview() | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         code.setOnClickListener { | ||||
|             if (!it.active) { | ||||
|                 it.active = true | ||||
|                 preview.active = false | ||||
|                 showCode() | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         // maybe check state (in case of restoration) | ||||
| 
 | ||||
|         // initial values | ||||
|         preview.active = !isCodeSelected | ||||
|         code.active = isCodeSelected | ||||
| 
 | ||||
|         if (isCodeSelected) { | ||||
|             showCode() | ||||
|         } else { | ||||
|             showPreview() | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private fun showPreview() { | ||||
|         isCodeSelected = false | ||||
|         showFragment(TAG_PREVIEW, TAG_CODE) { SamplePreviewFragment.init(sample) } | ||||
|     } | ||||
| 
 | ||||
|     private fun showCode() { | ||||
|         isCodeSelected = true | ||||
|         showFragment(TAG_CODE, TAG_PREVIEW) { SampleCodeFragment.init(sample) } | ||||
|     } | ||||
| 
 | ||||
|     private fun showFragment(showTag: String, hideTag: String, provider: () -> Fragment) { | ||||
|         val manager = childFragmentManager | ||||
|         manager.beginTransaction().apply { | ||||
|             setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN) | ||||
| 
 | ||||
|             val existing = manager.findFragmentByTag(showTag) | ||||
|             if (existing != null) { | ||||
|                 show(existing) | ||||
|             } else { | ||||
|                 add(container.id, provider(), showTag) | ||||
|             } | ||||
| 
 | ||||
|             manager.findFragmentByTag(hideTag)?.also { | ||||
|                 hide(it) | ||||
|             } | ||||
| 
 | ||||
|             commitAllowingStateLoss() | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     override fun onSaveInstanceState(outState: Bundle) { | ||||
|         super.onSaveInstanceState(outState) | ||||
| 
 | ||||
|         outState.putBoolean(KEY_CODE_SELECTED, isCodeSelected) | ||||
|     } | ||||
| 
 | ||||
|     private val sample: Sample by lazy(LazyThreadSafetyMode.NONE) { | ||||
|         (arguments!!.getParcelable<Sample>(ARG_SAMPLE)) | ||||
|     } | ||||
| 
 | ||||
|     companion object { | ||||
|         private const val ARG_SAMPLE = "arg.Sample" | ||||
|         private const val TAG_PREVIEW = "tag.Preview" | ||||
|         private const val TAG_CODE = "tag.Code" | ||||
|         private const val KEY_CODE_SELECTED = "key.Selected" | ||||
| 
 | ||||
|         fun init(sample: Sample): SampleFragment { | ||||
|             val fragment = SampleFragment() | ||||
|  | ||||
| @ -0,0 +1,38 @@ | ||||
| package io.noties.markwon.app.ui | ||||
| 
 | ||||
| import android.os.Bundle | ||||
| import android.view.LayoutInflater | ||||
| import android.view.View | ||||
| import android.view.ViewGroup | ||||
| import androidx.fragment.app.Fragment | ||||
| import io.noties.markwon.app.Sample | ||||
| 
 | ||||
| class SamplePreviewFragment : Fragment() { | ||||
| 
 | ||||
|     override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { | ||||
|         return markwonSample.createView(inflater, container) | ||||
|     } | ||||
| 
 | ||||
|     override fun onViewCreated(view: View, savedInstanceState: Bundle?) { | ||||
|         super.onViewCreated(view, savedInstanceState) | ||||
| 
 | ||||
|         markwonSample.onViewCreated(view) | ||||
|     } | ||||
| 
 | ||||
|     private val markwonSample: MarkwonSample by lazy(LazyThreadSafetyMode.NONE) { | ||||
|         val sample: Sample = arguments!!.getParcelable<Sample>(ARG_SAMPLE)!! | ||||
|         Class.forName(sample.javaClassName).newInstance() as MarkwonSample | ||||
|     } | ||||
| 
 | ||||
|     companion object { | ||||
|         private const val ARG_SAMPLE = "arg.Sample" | ||||
| 
 | ||||
|         fun init(sample: Sample): SamplePreviewFragment { | ||||
|             return SamplePreviewFragment().apply { | ||||
|                 arguments = Bundle().apply { | ||||
|                     putParcelable(ARG_SAMPLE, sample) | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -1,9 +1,58 @@ | ||||
| package io.noties.markwon.app.utils | ||||
| 
 | ||||
| import android.content.Context | ||||
| import io.noties.markwon.app.Sample | ||||
| import io.noties.markwon.sample.annotations.MarkwonArtifact | ||||
| import java.io.InputStream | ||||
| import java.util.Scanner | ||||
| 
 | ||||
| val MarkwonArtifact.displayName: String | ||||
|     get() = "@${artifactName()}" | ||||
| 
 | ||||
| val String.tagDisplayName: String | ||||
|     get() = "#$this" | ||||
|     get() = "#$this" | ||||
| 
 | ||||
| private const val SAMPLE_PREFIX = "io.noties.markwon.app." | ||||
| 
 | ||||
| fun Sample.readCode(context: Context): Sample.Code { | ||||
|     val assets = context.assets | ||||
| 
 | ||||
|     // keep sample and nested directories | ||||
|     val path = javaClassName | ||||
|             .removePrefix(SAMPLE_PREFIX) | ||||
|             .replace('.', '/') | ||||
| 
 | ||||
|     // now, we have 2 possibilities -> Kotlin or Java | ||||
|     fun read(stream: InputStream): String { | ||||
|         return Scanner(stream).useDelimiter("\\A").next() | ||||
|     } | ||||
| 
 | ||||
|     fun obtain(path: String): InputStream? { | ||||
|         return try { | ||||
|             assets.open(path) | ||||
|         } catch (t: Throwable) { | ||||
|             null | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     var language: Sample.Language = Sample.Language.KOTLIN | ||||
|     var stream = obtain("$path.kt") | ||||
|     if (stream == null) { | ||||
|         language = Sample.Language.JAVA | ||||
|         stream = obtain("$path.java") | ||||
|     } | ||||
| 
 | ||||
|     if (stream == null) { | ||||
|         throw IllegalStateException("Cannot obtain sample file at path: $path") | ||||
|     } | ||||
| 
 | ||||
|     val code = read(stream) | ||||
| 
 | ||||
|     try { | ||||
|         stream.close() | ||||
|     } catch (t: Throwable) { | ||||
|         // ignore | ||||
|     } | ||||
| 
 | ||||
|     return Sample.Code(language, code) | ||||
| } | ||||
| @ -0,0 +1,7 @@ | ||||
| package io.noties.markwon.app.utils | ||||
| 
 | ||||
| import android.view.View | ||||
| import android.view.ViewGroup | ||||
| 
 | ||||
| val ViewGroup.children: List<View> | ||||
|     get() = (0 until childCount).map { getChildAt(it) } | ||||
| @ -3,6 +3,7 @@ package io.noties.markwon.app.utils | ||||
| import android.view.View | ||||
| import android.view.View.GONE | ||||
| import android.view.View.VISIBLE | ||||
| import android.view.ViewGroup | ||||
| import android.view.ViewTreeObserver | ||||
| 
 | ||||
| var View.hidden: Boolean | ||||
| @ -23,4 +24,12 @@ fun View.onPreDraw(action: () -> Unit) { | ||||
|             return true | ||||
|         } | ||||
|     }) | ||||
| } | ||||
| } | ||||
| 
 | ||||
| var View.active: Boolean | ||||
|     get() = isActivated | ||||
|     set(newValue) { | ||||
|         isActivated = newValue | ||||
| 
 | ||||
|         (this as? ViewGroup)?.children?.forEach { it.active = newValue } | ||||
|     } | ||||
							
								
								
									
										5
									
								
								app-sample/src/main/res/color/tab_bar_item.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								app-sample/src/main/res/color/tab_bar_item.xml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,5 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <selector xmlns:android="http://schemas.android.com/apk/res/android"> | ||||
|     <item android:color="@color/accent" android:state_activated="true" /> | ||||
|     <item android:color="@color/gray" /> | ||||
| </selector> | ||||
| @ -1,5 +1,10 @@ | ||||
| <vector android:height="24dp" android:tint="#FFFFFF" | ||||
|     android:viewportHeight="24" android:viewportWidth="24" | ||||
|     android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android"> | ||||
|     <path android:fillColor="@android:color/white" android:pathData="M20,11H7.83l5.59,-5.59L12,4l-8,8 8,8 1.41,-1.41L7.83,13H20v-2z"/> | ||||
| <vector xmlns:android="http://schemas.android.com/apk/res/android" | ||||
|     android:width="24dp" | ||||
|     android:height="24dp" | ||||
|     android:tint="#FFFFFF" | ||||
|     android:viewportWidth="24" | ||||
|     android:viewportHeight="24"> | ||||
|     <path | ||||
|         android:fillColor="#FF000000" | ||||
|         android:pathData="M20,11H7.83l5.59,-5.59L12,4l-8,8 8,8 1.41,-1.41L7.83,13H20v-2z" /> | ||||
| </vector> | ||||
|  | ||||
| @ -2,8 +2,8 @@ | ||||
|     android:width="24dp" | ||||
|     android:height="24dp" | ||||
|     android:tint="#FFFFFF" | ||||
|     android:viewportWidth="24.0" | ||||
|     android:viewportHeight="24.0"> | ||||
|     android:viewportWidth="24" | ||||
|     android:viewportHeight="24"> | ||||
|     <path | ||||
|         android:fillColor="#FF000000" | ||||
|         android:pathData="M19,6.41L17.59,5 12,10.59 6.41,5 5,6.41 10.59,12 5,17.59 6.41,19 12,13.41 17.59,19 19,17.59 13.41,12z" /> | ||||
|  | ||||
							
								
								
									
										10
									
								
								app-sample/src/main/res/drawable/ic_code_white_24dp.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								app-sample/src/main/res/drawable/ic_code_white_24dp.xml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,10 @@ | ||||
| <vector xmlns:android="http://schemas.android.com/apk/res/android" | ||||
|     android:width="24dp" | ||||
|     android:height="24dp" | ||||
|     android:tint="#FFFFFF" | ||||
|     android:viewportWidth="24" | ||||
|     android:viewportHeight="24"> | ||||
|     <path | ||||
|         android:fillColor="#FF000000" | ||||
|         android:pathData="M9.4,16.6L4.8,12l4.6,-4.6L8,6l-6,6 6,6 1.4,-1.4zM14.6,16.6l4.6,-4.6 -4.6,-4.6L16,6l6,6 -6,6 -1.4,-1.4z" /> | ||||
| </vector> | ||||
| @ -0,0 +1,10 @@ | ||||
| <vector xmlns:android="http://schemas.android.com/apk/res/android" | ||||
|     android:width="24dp" | ||||
|     android:height="24dp" | ||||
|     android:tint="#FFFFFF" | ||||
|     android:viewportWidth="24" | ||||
|     android:viewportHeight="24"> | ||||
|     <path | ||||
|         android:fillColor="#FF000000" | ||||
|         android:pathData="M12,4.5C7,4.5 2.73,7.61 1,12c1.73,4.39 6,7.5 11,7.5s9.27,-3.11 11,-7.5c-1.73,-4.39 -6,-7.5 -11,-7.5zM12,17c-2.76,0 -5,-2.24 -5,-5s2.24,-5 5,-5 5,2.24 5,5 -2.24,5 -5,5zM12,9c-1.66,0 -3,1.34 -3,3s1.34,3 3,3 3,-1.34 3,-3 -1.34,-3 -3,-3z" /> | ||||
| </vector> | ||||
| @ -2,8 +2,8 @@ | ||||
|     android:width="24dp" | ||||
|     android:height="24dp" | ||||
|     android:tint="#FFFFFF" | ||||
|     android:viewportWidth="24.0" | ||||
|     android:viewportHeight="24.0"> | ||||
|     android:viewportWidth="24" | ||||
|     android:viewportHeight="24"> | ||||
|     <path | ||||
|         android:fillColor="#FF000000" | ||||
|         android:pathData="M15.5,14h-0.79l-0.28,-0.27C15.41,12.59 16,11.11 16,9.5 16,5.91 13.09,3 9.5,3S3,5.91 3,9.5 5.91,16 9.5,16c1.61,0 3.09,-0.59 4.23,-1.57l0.27,0.28v0.79l5,4.99L20.49,19l-4.99,-5zM9.5,14C7.01,14 5,11.99 5,9.5S7.01,5 9.5,5 14,7.01 14,9.5 11.99,14 9.5,14z" /> | ||||
|  | ||||
							
								
								
									
										80
									
								
								app-sample/src/main/res/layout/fragment_sample.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										80
									
								
								app-sample/src/main/res/layout/fragment_sample.xml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,80 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" | ||||
|     xmlns:tools="http://schemas.android.com/tools" | ||||
|     android:layout_width="match_parent" | ||||
|     android:layout_height="match_parent" | ||||
|     android:clipChildren="false" | ||||
|     android:orientation="vertical"> | ||||
| 
 | ||||
|     <LinearLayout | ||||
|         style="@style/AppBarContainer" | ||||
|         android:orientation="horizontal"> | ||||
| 
 | ||||
|         <ImageView | ||||
|             style="@style/AppBarIcon" | ||||
|             android:src="@drawable/ic_arrow_back_white_24dp" | ||||
|             tools:ignore="ContentDescription" /> | ||||
| 
 | ||||
|         <FrameLayout | ||||
|             android:layout_width="match_parent" | ||||
|             android:layout_height="match_parent" | ||||
|             android:layout_marginEnd="@dimen/app_bar_height"> | ||||
| 
 | ||||
|             <TextView | ||||
|                 style="@style/AppBarTitle" | ||||
|                 tools:text="Sample title with a lot of content, can it fit here?" /> | ||||
| 
 | ||||
|         </FrameLayout> | ||||
| 
 | ||||
|     </LinearLayout> | ||||
| 
 | ||||
|     <FrameLayout | ||||
|         android:id="@+id/container" | ||||
|         android:layout_width="match_parent" | ||||
|         android:layout_height="0px" | ||||
|         android:layout_weight="1" /> | ||||
| 
 | ||||
|     <View | ||||
|         android:layout_width="match_parent" | ||||
|         android:layout_height="@dimen/divider_height" | ||||
|         android:background="@color/divider" /> | ||||
| 
 | ||||
|     <LinearLayout | ||||
|         style="@style/TabBarContainer" | ||||
|         tools:ignore="DisableBaselineAlignment"> | ||||
| 
 | ||||
|         <LinearLayout | ||||
|             android:id="@id/tab_bar_preview" | ||||
|             style="@style/TabBarItem" | ||||
|             tools:ignore="UseCompoundDrawables"> | ||||
| 
 | ||||
|             <ImageView | ||||
|                 style="@style/TabBarItemIcon" | ||||
|                 android:src="@drawable/ic_remove_red_eye_white_24dp" | ||||
|                 tools:ignore="ContentDescription" /> | ||||
| 
 | ||||
|             <TextView | ||||
|                 style="@style/TabBarItemText" | ||||
|                 android:text="@string/tab_bar_preview" /> | ||||
| 
 | ||||
|         </LinearLayout> | ||||
| 
 | ||||
|         <LinearLayout | ||||
|             android:id="@id/tab_bar_code" | ||||
|             style="@style/TabBarItem" | ||||
|             tools:ignore="UseCompoundDrawables"> | ||||
| 
 | ||||
|             <ImageView | ||||
|                 style="@style/TabBarItemIcon" | ||||
|                 android:src="@drawable/ic_code_white_24dp" | ||||
|                 tools:ignore="ContentDescription" /> | ||||
| 
 | ||||
|             <TextView | ||||
|                 style="@style/TabBarItemText" | ||||
|                 android:text="@string/tab_bar_code" /> | ||||
| 
 | ||||
|         </LinearLayout> | ||||
| 
 | ||||
|     </LinearLayout> | ||||
| 
 | ||||
| </LinearLayout> | ||||
							
								
								
									
										28
									
								
								app-sample/src/main/res/layout/fragment_sample_code.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								app-sample/src/main/res/layout/fragment_sample_code.xml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,28 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android" | ||||
|     xmlns:tools="http://schemas.android.com/tools" | ||||
|     android:layout_width="match_parent" | ||||
|     android:layout_height="match_parent"> | ||||
| 
 | ||||
|     <HorizontalScrollView | ||||
|         android:layout_width="match_parent" | ||||
|         android:layout_height="match_parent" | ||||
|         android:clipChildren="false" | ||||
|         android:clipToPadding="false" | ||||
|         android:fillViewport="true" | ||||
|         android:padding="@dimen/content_padding_double" | ||||
|         android:scrollbarStyle="outsideInset"> | ||||
| 
 | ||||
|         <TextView | ||||
|             android:id="@+id/text_view" | ||||
|             android:layout_width="wrap_content" | ||||
|             android:layout_height="wrap_content" | ||||
|             android:fontFamily="monospace" | ||||
|             android:lineSpacingExtra="2dip" | ||||
|             android:textAppearance="?android:attr/textAppearanceMedium" | ||||
|             android:textSize="14sp" | ||||
|             tools:text="package io.noties.markwon" /> | ||||
| 
 | ||||
|     </HorizontalScrollView> | ||||
| 
 | ||||
| </androidx.core.widget.NestedScrollView> | ||||
| @ -7,18 +7,13 @@ | ||||
|     android:orientation="vertical"> | ||||
| 
 | ||||
|     <LinearLayout | ||||
|         android:id="@+id/app_bar" | ||||
|         style="@style/AppBarContainer" | ||||
|         android:elevation="4dip" | ||||
|         android:orientation="horizontal" | ||||
|         tools:ignore="UseCompoundDrawables"> | ||||
|         android:orientation="horizontal"> | ||||
| 
 | ||||
|         <ImageView | ||||
|             android:id="@+id/app_bar_icon" | ||||
|             style="@style/AppBarIcon" | ||||
|             android:contentDescription="@null" | ||||
|             android:padding="8dip" | ||||
|             android:src="@mipmap/ic_launcher" /> | ||||
|             android:src="@mipmap/ic_launcher" | ||||
|             tools:ignore="ContentDescription" /> | ||||
| 
 | ||||
|         <FrameLayout | ||||
|             android:layout_width="match_parent" | ||||
| @ -26,18 +21,8 @@ | ||||
|             android:layout_marginEnd="@dimen/app_bar_height"> | ||||
| 
 | ||||
|             <TextView | ||||
|                 android:id="@+id/app_bar_title" | ||||
|                 android:layout_width="wrap_content" | ||||
|                 android:layout_height="wrap_content" | ||||
|                 android:layout_gravity="center" | ||||
|                 android:paddingLeft="@dimen/content_padding_double" | ||||
|                 android:paddingTop="@dimen/content_padding_half" | ||||
|                 android:paddingRight="@dimen/content_padding_double" | ||||
|                 android:paddingBottom="@dimen/content_padding_half" | ||||
|                 android:text="@string/app_name" | ||||
|                 android:textAppearance="?android:attr/textAppearanceLarge" | ||||
|                 android:textColor="@color/white" | ||||
|                 android:textStyle="bold" /> | ||||
|                 style="@style/AppBarTitle" | ||||
|                 android:text="@string/app_name" /> | ||||
| 
 | ||||
|         </FrameLayout> | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										13
									
								
								app-sample/src/main/res/layout/fragment_sample_preview.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								app-sample/src/main/res/layout/fragment_sample_preview.xml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,13 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" | ||||
|     android:layout_width="match_parent" | ||||
|     android:layout_height="match_parent" | ||||
|     android:background="#efe"> | ||||
| 
 | ||||
|     <TextView | ||||
|         android:layout_width="wrap_content" | ||||
|         android:layout_height="wrap_content" | ||||
|         android:layout_gravity="center" | ||||
|         android:text="PREVUEW" /> | ||||
| 
 | ||||
| </FrameLayout> | ||||
| @ -13,7 +13,7 @@ | ||||
|             android:id="@+id/text_view" | ||||
|             android:layout_width="match_parent" | ||||
|             android:layout_height="wrap_content" | ||||
|             android:padding="@dimen/content_padding" | ||||
|             android:padding="@dimen/content_padding_double" | ||||
|             android:textAppearance="?android:attr/textAppearanceMedium" | ||||
|             android:textColor="?android:attr/textColorPrimary" | ||||
|             tools:text="Hello there" /> | ||||
|  | ||||
| @ -12,4 +12,7 @@ | ||||
|     <color name="search_bar_background">#eee</color> | ||||
|     <color name="search_bar_background_full">#BFFFFFFF</color> | ||||
| 
 | ||||
|     <color name="divider">#eee</color> | ||||
|     <color name="tab_bar_background">#fafafa</color> | ||||
| 
 | ||||
| </resources> | ||||
| @ -8,4 +8,7 @@ | ||||
| 
 | ||||
|     <dimen name="search_bar_icon_side">36dip</dimen> | ||||
|     <dimen name="adapt_sample_hash_width">36dip</dimen> | ||||
| 
 | ||||
|     <dimen name="divider_height">1dip</dimen> | ||||
|     <dimen name="tab_bar_height">56dip</dimen> | ||||
| </resources> | ||||
| @ -1,4 +1,12 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <resources> | ||||
|     <item name="text" type="id" /> | ||||
| 
 | ||||
|     <item name="app_bar" type="id" /> | ||||
|     <item name="app_bar_icon" type="id" /> | ||||
|     <item name="app_bar_title" type="id" /> | ||||
| 
 | ||||
|     <item name="tab_bar" type="id" /> | ||||
|     <item name="tab_bar_preview" type="id" /> | ||||
|     <item name="tab_bar_code" type="id" /> | ||||
| </resources> | ||||
| @ -1,4 +1,7 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <resources> | ||||
|     <string name="app_name">Markwon</string> | ||||
| 
 | ||||
|     <string name="tab_bar_preview">Preview</string> | ||||
|     <string name="tab_bar_code">Code</string> | ||||
| </resources> | ||||
| @ -6,22 +6,46 @@ | ||||
|         <item name="android:colorPrimary">@color/gray_light</item> | ||||
|         <item name="android:colorPrimaryDark">@color/gray</item> | ||||
|         <item name="android:windowBackground">@color/window_background</item> | ||||
|         <item name="android:windowSplashscreenContent" tools:ignore="NewApi">@drawable/bg_splash</item> | ||||
|         <item name="android:windowSplashscreenContent" tools:ignore="NewApi">@drawable/bg_splash | ||||
|         </item> | ||||
|     </style> | ||||
| 
 | ||||
|     <style name="AppTheme" parent="AppThemeBase" /> | ||||
| 
 | ||||
|     <style name="AppBarContainer"> | ||||
|         <item name="android:id">@id/app_bar</item> | ||||
|         <item name="android:layout_width">match_parent</item> | ||||
|         <item name="android:layout_height">@dimen/app_bar_height</item> | ||||
|         <item name="android:background">@color/gray_light</item> | ||||
|         <item name="android:elevation">4dip</item> | ||||
|     </style> | ||||
| 
 | ||||
|     <style name="AppBarIcon"> | ||||
|         <item name="android:id">@id/app_bar_icon</item> | ||||
|         <item name="android:layout_width">@dimen/app_bar_height</item> | ||||
|         <item name="android:layout_height">@dimen/app_bar_height</item> | ||||
|         <item name="android:scaleType">centerInside</item> | ||||
|         <item name="android:background">?android:attr/selectableItemBackgroundBorderless</item> | ||||
|         <item name="android:contentDescription">@null</item> | ||||
|         <item name="android:padding">8dip</item> | ||||
|     </style> | ||||
| 
 | ||||
|     <style name="AppBarTitle"> | ||||
|         <item name="android:id">@id/app_bar_title</item> | ||||
|         <item name="android:layout_width">wrap_content</item> | ||||
|         <item name="android:layout_height">wrap_content</item> | ||||
|         <item name="android:layout_gravity">center</item> | ||||
|         <item name="android:paddingLeft">@dimen/content_padding_double</item> | ||||
|         <item name="android:paddingRight">@dimen/content_padding_double</item> | ||||
|         <item name="android:paddingTop">@dimen/content_padding_half</item> | ||||
|         <item name="android:paddingBottom">@dimen/content_padding_half</item> | ||||
|         <item name="android:textAppearance">?android:attr/textAppearanceLarge</item> | ||||
|         <item name="android:textColor">@color/white</item> | ||||
|         <item name="android:textStyle">bold</item> | ||||
|         <item name="android:lines">1</item> | ||||
|         <item name="android:singleLine">true</item> | ||||
|         <item name="android:maxLines">1</item> | ||||
|         <item name="android:ellipsize">end</item> | ||||
|     </style> | ||||
| 
 | ||||
|     <style name="ArtifactTagText"> | ||||
| @ -39,4 +63,35 @@ | ||||
|         <item name="android:textColor">@color/white</item> | ||||
|     </style> | ||||
| 
 | ||||
|     <style name="TabBarContainer"> | ||||
|         <item name="android:id">@id/tab_bar</item> | ||||
|         <item name="android:layout_width">match_parent</item> | ||||
|         <item name="android:layout_height">@dimen/tab_bar_height</item> | ||||
|         <item name="android:background">@color/tab_bar_background</item> | ||||
|         <item name="android:baselineAligned">false</item> | ||||
|         <item name="android:orientation">horizontal</item> | ||||
|     </style> | ||||
| 
 | ||||
|     <style name="TabBarItem"> | ||||
|         <item name="android:layout_width">0px</item> | ||||
|         <item name="android:layout_height">match_parent</item> | ||||
|         <item name="android:layout_weight">1</item> | ||||
|         <item name="android:background">?android:attr/selectableItemBackgroundBorderless</item> | ||||
|         <item name="android:gravity">center</item> | ||||
|         <item name="android:orientation">vertical</item> | ||||
|     </style> | ||||
| 
 | ||||
|     <style name="TabBarItemIcon"> | ||||
|         <item name="android:layout_width">wrap_content</item> | ||||
|         <item name="android:layout_height">wrap_content</item> | ||||
|         <item name="android:tint">@color/tab_bar_item</item> | ||||
|     </style> | ||||
| 
 | ||||
|     <style name="TabBarItemText"> | ||||
|         <item name="android:layout_width">wrap_content</item> | ||||
|         <item name="android:layout_height">wrap_content</item> | ||||
|         <item name="android:textAppearance">?android:attr/textAppearanceSmall</item> | ||||
|         <item name="android:textColor">@color/tab_bar_item</item> | ||||
|     </style> | ||||
| 
 | ||||
| </resources> | ||||
										
											Binary file not shown.
										
									
								
							| @ -20,11 +20,14 @@ import java.text.SimpleDateFormat; | ||||
| import java.util.ArrayList; | ||||
| import java.util.Arrays; | ||||
| import java.util.Collections; | ||||
| import java.util.HashSet; | ||||
| import java.util.Comparator; | ||||
| import java.util.List; | ||||
| import java.util.ListIterator; | ||||
| import java.util.Locale; | ||||
| import java.util.Set; | ||||
| import java.util.TreeSet; | ||||
| import java.util.stream.Collectors; | ||||
| import java.util.stream.Stream; | ||||
| 
 | ||||
| import javax.annotation.processing.AbstractProcessor; | ||||
| import javax.annotation.processing.ProcessingEnvironment; | ||||
| @ -33,6 +36,7 @@ import javax.lang.model.SourceVersion; | ||||
| import javax.lang.model.element.Element; | ||||
| import javax.lang.model.element.TypeElement; | ||||
| 
 | ||||
| import io.noties.markwon.sample.annotations.MarkwonArtifact; | ||||
| import io.noties.markwon.sample.annotations.MarkwonSampleInfo; | ||||
| 
 | ||||
| public class MarkwonSampleProcessor extends AbstractProcessor { | ||||
| @ -159,6 +163,8 @@ public class MarkwonSampleProcessor extends AbstractProcessor { | ||||
|         // new items come first (DESC order) | ||||
|         Collections.sort(samples, (lhs, rhs) -> rhs.id.compareTo(lhs.id)); | ||||
| 
 | ||||
|         // sort each sample artifacts (alphabet) and tags (alphabet) | ||||
| 
 | ||||
|         final String json = new GsonBuilder() | ||||
|                 .setPrettyPrinting() | ||||
|                 .create() | ||||
| @ -176,13 +182,17 @@ public class MarkwonSampleProcessor extends AbstractProcessor { | ||||
| 
 | ||||
|         final String id = info.id(); | ||||
| 
 | ||||
|         // NB! sorted artifacts (by name) and tags | ||||
|         final Set<MarkwonArtifact> artifacts = Stream.of(info.artifacts()) | ||||
|                 .collect(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(MarkwonArtifact::name)))); | ||||
| 
 | ||||
|         final MarkwonSample sample = new MarkwonSample( | ||||
|                 element.getQualifiedName().toString(), | ||||
|                 id, | ||||
|                 info.title(), | ||||
|                 info.description(), | ||||
|                 new HashSet<>(Arrays.asList(info.artifacts())), | ||||
|                 new HashSet<>(Arrays.asList(info.tags())) | ||||
|                 artifacts, | ||||
|                 new TreeSet<>(Arrays.asList(info.tags())) | ||||
|         ); | ||||
| 
 | ||||
|         try { | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Dimitry Ivanov
						Dimitry Ivanov