diff --git a/app-sample/build.gradle b/app-sample/build.gradle
index a340eeaf..afc24af7 100644
--- a/app-sample/build.gradle
+++ b/app-sample/build.gradle
@@ -18,6 +18,12 @@ android {
resConfig 'en'
setProperty("archivesBaseName", "markwon-$versionName")
+
+ final def scheme = 'markwon'
+ buildConfigField 'String', 'DEEPLINK_SCHEME', "\"$scheme\""
+ manifestPlaceholders += [
+ 'deeplink_scheme': scheme
+ ]
}
dexOptions {
diff --git a/app-sample/src/main/AndroidManifest.xml b/app-sample/src/main/AndroidManifest.xml
index ac691724..411c6a42 100644
--- a/app-sample/src/main/AndroidManifest.xml
+++ b/app-sample/src/main/AndroidManifest.xml
@@ -16,10 +16,20 @@
tools:ignore="AllowBackup,GoogleAppIndexingWarning">
+
+
+
+
+
+
+
+
+
+
-
-
+
+
diff --git a/app-sample/src/main/java/io/noties/markwon/app/sample/Deeplink.kt b/app-sample/src/main/java/io/noties/markwon/app/sample/Deeplink.kt
new file mode 100644
index 00000000..65034fa4
--- /dev/null
+++ b/app-sample/src/main/java/io/noties/markwon/app/sample/Deeplink.kt
@@ -0,0 +1,73 @@
+package io.noties.markwon.app.sample
+
+import android.net.Uri
+import io.noties.debug.Debug
+import io.noties.markwon.app.BuildConfig
+import io.noties.markwon.sample.annotations.MarkwonArtifact
+
+sealed class Deeplink {
+ data class Sample(val id: String) : Deeplink()
+ data class Search(val search: SampleSearch) : Deeplink()
+
+ companion object {
+ fun parse(data: Uri?): Deeplink? {
+ Debug.i(data)
+ @Suppress("NAME_SHADOWING")
+ val data = data ?: return null
+ if (BuildConfig.DEEPLINK_SCHEME != data.scheme) return null
+ return when (data.host) {
+ // markwon://sample/20202827
+ "sample" -> parseSample(data.lastPathSegment)
+ // markwon://search?a=ext-latex&q=text
+ "search" -> parseSearch(data.query)
+ else -> null
+ }
+ }
+
+ private fun parseSample(id: String?): Sample? {
+ if (id == null) return null
+ return Sample(id)
+ }
+
+ private fun parseSearch(query: String?): Search? {
+ Debug.i("query: '$query'")
+
+ val params = query
+ ?.split("&")
+ ?.map {
+ val (k, v) = it.split("=")
+ Pair(k, v)
+ }
+ ?.toMap()
+ ?: return null
+
+ val artifact = params["a"]
+ val tag = params["t"]
+ val search = params["q"]
+
+ Debug.i("artifact: '$artifact', tag: '$tag', search: '$search'")
+
+ val sampleSearch: SampleSearch? = if (artifact != null) {
+ val encodedArtifact = MarkwonArtifact.values()
+ .firstOrNull { it.artifactName() == artifact }
+ if (encodedArtifact != null) {
+ SampleSearch.Artifact(search, encodedArtifact)
+ } else {
+ null
+ }
+ } else if (tag != null) {
+ SampleSearch.Tag(search, tag)
+ } else if (search != null) {
+ SampleSearch.All(search)
+ } else {
+ null
+ }
+
+ if (sampleSearch == null) {
+ return null
+ }
+
+ return Search(sampleSearch)
+ }
+ }
+}
\ No newline at end of file
diff --git a/app-sample/src/main/java/io/noties/markwon/app/sample/MainActivity.kt b/app-sample/src/main/java/io/noties/markwon/app/sample/MainActivity.kt
index e60c63d7..c3405494 100644
--- a/app-sample/src/main/java/io/noties/markwon/app/sample/MainActivity.kt
+++ b/app-sample/src/main/java/io/noties/markwon/app/sample/MainActivity.kt
@@ -2,7 +2,10 @@ package io.noties.markwon.app.sample
import android.os.Bundle
import android.view.Window
+import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
+import io.noties.markwon.app.App
+import io.noties.markwon.app.sample.ui.SampleFragment
import io.noties.markwon.app.sample.ui.SampleListFragment
class MainActivity : FragmentActivity() {
@@ -11,9 +14,27 @@ class MainActivity : FragmentActivity() {
super.onCreate(savedInstanceState)
if (supportFragmentManager.findFragmentById(Window.ID_ANDROID_CONTENT) == null) {
+
supportFragmentManager.beginTransaction()
.add(Window.ID_ANDROID_CONTENT, SampleListFragment.init())
.commitNowAllowingStateLoss()
+
+ // process deeplink if we are not restored
+ val deeplink = Deeplink.parse(intent.data)
+ val deepLinkFragment: Fragment? = if (deeplink != null) {
+ when (deeplink) {
+ is Deeplink.Sample -> App.sampleManager.sample(deeplink.id)
+ ?.let { SampleFragment.init(it) }
+ is Deeplink.Search -> SampleListFragment.init(deeplink.search)
+ }
+ } else null
+
+ if (deepLinkFragment != null) {
+ supportFragmentManager.beginTransaction()
+ .replace(Window.ID_ANDROID_CONTENT, deepLinkFragment)
+ .addToBackStack(null)
+ .commit()
+ }
}
}
}
\ No newline at end of file
diff --git a/app-sample/src/main/java/io/noties/markwon/app/sample/SampleManager.kt b/app-sample/src/main/java/io/noties/markwon/app/sample/SampleManager.kt
index b45fd616..d0021d53 100644
--- a/app-sample/src/main/java/io/noties/markwon/app/sample/SampleManager.kt
+++ b/app-sample/src/main/java/io/noties/markwon/app/sample/SampleManager.kt
@@ -15,6 +15,10 @@ class SampleManager(
SampleUtils.readSamples(context)
}
+ fun sample(id: String): Sample? {
+ return samples.firstOrNull { id == it.id }
+ }
+
fun samples(search: SampleSearch?, callback: (List) -> Unit): Cancellable {
var action: ((List) -> Unit)? = callback
diff --git a/app-sample/src/main/java/io/noties/markwon/app/sample/ui/SampleListFragment.kt b/app-sample/src/main/java/io/noties/markwon/app/sample/ui/SampleListFragment.kt
index bf5154e2..16acb1aa 100644
--- a/app-sample/src/main/java/io/noties/markwon/app/sample/ui/SampleListFragment.kt
+++ b/app-sample/src/main/java/io/noties/markwon/app/sample/ui/SampleListFragment.kt
@@ -98,11 +98,20 @@ class SampleListFragment : Fragment() {
// }
val state: State? = arguments?.getParcelable(STATE)
- Debug.i(state)
+ val initialSearch = arguments?.getString(ARG_SEARCH)
+
+ // clear it anyway
+ arguments?.remove(ARG_SEARCH)
+
+ Debug.i(state, initialSearch)
pendingRecyclerScrollPosition = state?.recyclerScrollPosition
- if (state?.search != null) {
- searchBar.search(state.search)
+
+ val search = listOf(state?.search, initialSearch)
+ .firstOrNull { it != null }
+
+ if (search != null) {
+ searchBar.search(search)
} else {
fetch()
}
@@ -144,35 +153,38 @@ class SampleListFragment : Fragment() {
val appBarTitle: TextView = appBar.findViewById(R.id.app_bar_title)
val appBarIconReadme: ImageView = appBar.findViewById(R.id.app_bar_icon_readme)
- val isInitialScreen = type is Type.All
+ val isInitialScreen = fragmentManager?.backStackEntryCount == 0
appBarIcon.hidden = isInitialScreen
appBarIconReadme.hidden = !isInitialScreen
val type = this.type
- if (type is Type.All) {
+
+ val (text, background) = when (type) {
+ is Type.Artifact -> Pair(type.artifact.displayName, R.drawable.bg_artifact)
+ is Type.Tag -> Pair(type.tag.tagDisplayName, R.drawable.bg_tag)
+ is Type.All -> Pair(resources.getString(R.string.app_name), 0)
+ }
+
+ appBarTitle.text = text
+
+ if (background != 0) {
+ appBarTitle.setBackgroundResource(background)
+ }
+
+ if (isInitialScreen) {
appBarIconReadme.setOnClickListener {
context?.let {
val intent = ReadMeActivity.makeIntent(it)
it.startActivity(intent)
}
}
- return
+ } else {
+ appBarIcon.setImageResource(R.drawable.ic_arrow_back_white_24dp)
+ appBarIcon.setOnClickListener {
+ requireActivity().onBackPressed()
+ }
}
-
- appBarIcon.setImageResource(R.drawable.ic_arrow_back_white_24dp)
- appBarIcon.setOnClickListener {
- requireActivity().onBackPressed()
- }
-
- val (text, background) = when (type) {
- is Type.Artifact -> Pair(type.artifact.displayName, R.drawable.bg_artifact)
- is Type.Tag -> Pair(type.tag.tagDisplayName, R.drawable.bg_tag)
- else -> error("Unexpected type: $type")
- }
-
- appBarTitle.text = text
- appBarTitle.setBackgroundResource(background)
}
private fun bindSamples(samples: List) {
@@ -192,7 +204,6 @@ class SampleListFragment : Fragment() {
val scrollPosition = pendingRecyclerScrollPosition
Debug.i(scrollPosition)
- Debug.trace()
if (scrollPosition != null) {
pendingRecyclerScrollPosition = null
@@ -242,7 +253,6 @@ class SampleListFragment : Fragment() {
}
Debug.i(sampleSearch)
- Debug.trace()
// clear current
cancellable?.let {
@@ -259,6 +269,7 @@ class SampleListFragment : Fragment() {
companion object {
private const val ARG_ARTIFACT = "arg.Artifact"
private const val ARG_TAG = "arg.Tag"
+ private const val ARG_SEARCH = "arg.Search"
private const val STATE = "key.State"
fun init(): SampleListFragment {
@@ -283,6 +294,23 @@ class SampleListFragment : Fragment() {
return fragment
}
+ fun init(search: SampleSearch): SampleListFragment {
+ val fragment = SampleListFragment()
+ fragment.arguments = Bundle().apply {
+
+ when (search) {
+ is SampleSearch.Artifact -> putString(ARG_ARTIFACT, search.artifact.name)
+ is SampleSearch.Tag -> putString(ARG_TAG, search.tag)
+ }
+
+ val query = search.text
+ if (query != null) {
+ putString(ARG_SEARCH, query)
+ }
+ }
+ return fragment
+ }
+
fun markwon(context: Context): Markwon {
return Markwon.builder(context)
.usePlugin(MovementMethodPlugin.none())