Sample app, adding and reading samples

This commit is contained in:
Dimitry Ivanov 2020-06-25 19:04:47 +03:00
parent 66f77f35fe
commit 860d70d6d1
34 changed files with 714 additions and 43 deletions

View File

@ -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", "javaClassName": "io.noties.markwon.app.samples.FirstSample",
"id": "202006164150023", "id": "202006164150023",

View File

@ -0,0 +1 @@
../../main/java/io/noties/markwon/app/samples/

View File

@ -12,4 +12,11 @@ data class Sample(
val description: String, val description: String,
val artifacts: List<MarkwonArtifact>, val artifacts: List<MarkwonArtifact>,
val tags: List<String> val tags: List<String>
) : Parcelable ) : Parcelable {
enum class Language {
JAVA, KOTLIN
}
data class Code(val language: Language, val sourceCode: String)
}

View File

@ -81,6 +81,21 @@ class SampleItem(
val artifacts: FlowLayout = requireView(R.id.artifacts) val artifacts: FlowLayout = requireView(R.id.artifacts)
val tags: FlowLayout = requireView(R.id.tags) 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> { private fun FlowLayout.ensure(viewsCount: Int, layoutResId: Int): List<View> {

View File

@ -0,0 +1,3 @@
[{*.java, *.kt}]
indent_style = space
indent_size = 2

View File

@ -1,15 +1,30 @@
package io.noties.markwon.app.samples 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.MarkwonArtifact
import io.noties.markwon.sample.annotations.MarkwonSampleInfo import io.noties.markwon.sample.annotations.MarkwonSampleInfo
@MarkwonSampleInfo( @MarkwonSampleInfo(
id = "202006164150023", id = "202006164150023",
title = "First Sample", title = "First Sample",
description = "This **is** _the first_ sample", description = "This **is** _the first_ sample",
artifacts = [MarkwonArtifact.CORE], artifacts = [MarkwonArtifact.CORE],
tags = ["test"] 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)
}
} }

View File

@ -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()
}

View File

@ -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);
}
}

View File

@ -1,5 +1,16 @@
package io.noties.markwon.app.ui package io.noties.markwon.app.ui
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
abstract class MarkwonSample { 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
} }

View File

@ -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()
}

View File

@ -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)
}
}
}
}
}

View File

@ -1,13 +1,127 @@
package io.noties.markwon.app.ui package io.noties.markwon.app.ui
import android.os.Bundle 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.Fragment
import androidx.fragment.app.FragmentTransaction
import io.noties.markwon.app.R
import io.noties.markwon.app.Sample import io.noties.markwon.app.Sample
import io.noties.markwon.app.utils.active
class SampleFragment : Fragment() { 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 { companion object {
private const val ARG_SAMPLE = "arg.Sample" 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 { fun init(sample: Sample): SampleFragment {
val fragment = SampleFragment() val fragment = SampleFragment()

View File

@ -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)
}
}
}
}
}

View File

@ -1,9 +1,58 @@
package io.noties.markwon.app.utils package io.noties.markwon.app.utils
import android.content.Context
import io.noties.markwon.app.Sample
import io.noties.markwon.sample.annotations.MarkwonArtifact import io.noties.markwon.sample.annotations.MarkwonArtifact
import java.io.InputStream
import java.util.Scanner
val MarkwonArtifact.displayName: String val MarkwonArtifact.displayName: String
get() = "@${artifactName()}" get() = "@${artifactName()}"
val String.tagDisplayName: String 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)
}

View File

@ -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) }

View File

@ -3,6 +3,7 @@ package io.noties.markwon.app.utils
import android.view.View import android.view.View
import android.view.View.GONE import android.view.View.GONE
import android.view.View.VISIBLE import android.view.View.VISIBLE
import android.view.ViewGroup
import android.view.ViewTreeObserver import android.view.ViewTreeObserver
var View.hidden: Boolean var View.hidden: Boolean
@ -23,4 +24,12 @@ fun View.onPreDraw(action: () -> Unit) {
return true return true
} }
}) })
} }
var View.active: Boolean
get() = isActivated
set(newValue) {
isActivated = newValue
(this as? ViewGroup)?.children?.forEach { it.active = newValue }
}

View 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>

View File

@ -1,5 +1,10 @@
<vector android:height="24dp" android:tint="#FFFFFF" <vector xmlns:android="http://schemas.android.com/apk/res/android"
android:viewportHeight="24" android:viewportWidth="24" android:width="24dp"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android"> android:height="24dp"
<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"/> 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> </vector>

View File

@ -2,8 +2,8 @@
android:width="24dp" android:width="24dp"
android:height="24dp" android:height="24dp"
android:tint="#FFFFFF" android:tint="#FFFFFF"
android:viewportWidth="24.0" android:viewportWidth="24"
android:viewportHeight="24.0"> android:viewportHeight="24">
<path <path
android:fillColor="#FF000000" 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" /> 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" />

View 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>

View 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="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>

View File

@ -2,8 +2,8 @@
android:width="24dp" android:width="24dp"
android:height="24dp" android:height="24dp"
android:tint="#FFFFFF" android:tint="#FFFFFF"
android:viewportWidth="24.0" android:viewportWidth="24"
android:viewportHeight="24.0"> android:viewportHeight="24">
<path <path
android:fillColor="#FF000000" 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" /> 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" />

View 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>

View 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>

View File

@ -7,18 +7,13 @@
android:orientation="vertical"> android:orientation="vertical">
<LinearLayout <LinearLayout
android:id="@+id/app_bar"
style="@style/AppBarContainer" style="@style/AppBarContainer"
android:elevation="4dip" android:orientation="horizontal">
android:orientation="horizontal"
tools:ignore="UseCompoundDrawables">
<ImageView <ImageView
android:id="@+id/app_bar_icon"
style="@style/AppBarIcon" style="@style/AppBarIcon"
android:contentDescription="@null" android:src="@mipmap/ic_launcher"
android:padding="8dip" tools:ignore="ContentDescription" />
android:src="@mipmap/ic_launcher" />
<FrameLayout <FrameLayout
android:layout_width="match_parent" android:layout_width="match_parent"
@ -26,18 +21,8 @@
android:layout_marginEnd="@dimen/app_bar_height"> android:layout_marginEnd="@dimen/app_bar_height">
<TextView <TextView
android:id="@+id/app_bar_title" style="@style/AppBarTitle"
android:layout_width="wrap_content" android:text="@string/app_name" />
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" />
</FrameLayout> </FrameLayout>

View 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>

View File

@ -13,7 +13,7 @@
android:id="@+id/text_view" android:id="@+id/text_view"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:padding="@dimen/content_padding" android:padding="@dimen/content_padding_double"
android:textAppearance="?android:attr/textAppearanceMedium" android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="?android:attr/textColorPrimary" android:textColor="?android:attr/textColorPrimary"
tools:text="Hello there" /> tools:text="Hello there" />

View File

@ -12,4 +12,7 @@
<color name="search_bar_background">#eee</color> <color name="search_bar_background">#eee</color>
<color name="search_bar_background_full">#BFFFFFFF</color> <color name="search_bar_background_full">#BFFFFFFF</color>
<color name="divider">#eee</color>
<color name="tab_bar_background">#fafafa</color>
</resources> </resources>

View File

@ -8,4 +8,7 @@
<dimen name="search_bar_icon_side">36dip</dimen> <dimen name="search_bar_icon_side">36dip</dimen>
<dimen name="adapt_sample_hash_width">36dip</dimen> <dimen name="adapt_sample_hash_width">36dip</dimen>
<dimen name="divider_height">1dip</dimen>
<dimen name="tab_bar_height">56dip</dimen>
</resources> </resources>

View File

@ -1,4 +1,12 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<item name="text" type="id" /> <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> </resources>

View File

@ -1,4 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<string name="app_name">Markwon</string> <string name="app_name">Markwon</string>
<string name="tab_bar_preview">Preview</string>
<string name="tab_bar_code">Code</string>
</resources> </resources>

View File

@ -6,22 +6,46 @@
<item name="android:colorPrimary">@color/gray_light</item> <item name="android:colorPrimary">@color/gray_light</item>
<item name="android:colorPrimaryDark">@color/gray</item> <item name="android:colorPrimaryDark">@color/gray</item>
<item name="android:windowBackground">@color/window_background</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>
<style name="AppTheme" parent="AppThemeBase" /> <style name="AppTheme" parent="AppThemeBase" />
<style name="AppBarContainer"> <style name="AppBarContainer">
<item name="android:id">@id/app_bar</item>
<item name="android:layout_width">match_parent</item> <item name="android:layout_width">match_parent</item>
<item name="android:layout_height">@dimen/app_bar_height</item> <item name="android:layout_height">@dimen/app_bar_height</item>
<item name="android:background">@color/gray_light</item> <item name="android:background">@color/gray_light</item>
<item name="android:elevation">4dip</item>
</style> </style>
<style name="AppBarIcon"> <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_width">@dimen/app_bar_height</item>
<item name="android:layout_height">@dimen/app_bar_height</item> <item name="android:layout_height">@dimen/app_bar_height</item>
<item name="android:scaleType">centerInside</item> <item name="android:scaleType">centerInside</item>
<item name="android:background">?android:attr/selectableItemBackgroundBorderless</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>
<style name="ArtifactTagText"> <style name="ArtifactTagText">
@ -39,4 +63,35 @@
<item name="android:textColor">@color/white</item> <item name="android:textColor">@color/white</item>
</style> </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> </resources>

Binary file not shown.

View File

@ -20,11 +20,14 @@ import java.text.SimpleDateFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet; import java.util.Comparator;
import java.util.List; import java.util.List;
import java.util.ListIterator; import java.util.ListIterator;
import java.util.Locale; import java.util.Locale;
import java.util.Set; 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.AbstractProcessor;
import javax.annotation.processing.ProcessingEnvironment; 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.Element;
import javax.lang.model.element.TypeElement; import javax.lang.model.element.TypeElement;
import io.noties.markwon.sample.annotations.MarkwonArtifact;
import io.noties.markwon.sample.annotations.MarkwonSampleInfo; import io.noties.markwon.sample.annotations.MarkwonSampleInfo;
public class MarkwonSampleProcessor extends AbstractProcessor { public class MarkwonSampleProcessor extends AbstractProcessor {
@ -159,6 +163,8 @@ public class MarkwonSampleProcessor extends AbstractProcessor {
// new items come first (DESC order) // new items come first (DESC order)
Collections.sort(samples, (lhs, rhs) -> rhs.id.compareTo(lhs.id)); Collections.sort(samples, (lhs, rhs) -> rhs.id.compareTo(lhs.id));
// sort each sample artifacts (alphabet) and tags (alphabet)
final String json = new GsonBuilder() final String json = new GsonBuilder()
.setPrettyPrinting() .setPrettyPrinting()
.create() .create()
@ -176,13 +182,17 @@ public class MarkwonSampleProcessor extends AbstractProcessor {
final String id = info.id(); 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( final MarkwonSample sample = new MarkwonSample(
element.getQualifiedName().toString(), element.getQualifiedName().toString(),
id, id,
info.title(), info.title(),
info.description(), info.description(),
new HashSet<>(Arrays.asList(info.artifacts())), artifacts,
new HashSet<>(Arrays.asList(info.tags())) new TreeSet<>(Arrays.asList(info.tags()))
); );
try { try {