Sample app readme functionality
This commit is contained in:
		
							parent
							
								
									860d70d6d1
								
							
						
					
					
						commit
						45d205ba8c
					
				| @ -45,19 +45,46 @@ androidExtensions { | ||||
|     features = ["parcelize"] | ||||
| } | ||||
| 
 | ||||
| configurations.all { | ||||
|     exclude group: 'org.jetbrains', module: 'annotations-java5' | ||||
| } | ||||
| 
 | ||||
| dependencies { | ||||
|     kapt project(':sample-utils:processor') | ||||
|     deps['annotationProcessor'].with { | ||||
|         kapt it['prism4j-bundler'] | ||||
|     } | ||||
| 
 | ||||
|     implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" | ||||
| 
 | ||||
|     implementation project(':markwon-core') | ||||
|     implementation project(':markwon-editor') | ||||
|     implementation project(':markwon-ext-latex') | ||||
|     implementation project(':markwon-ext-strikethrough') | ||||
|     implementation project(':markwon-ext-tables') | ||||
|     implementation project(':markwon-ext-tasklist') | ||||
|     implementation project(':markwon-html') | ||||
|     implementation project(':markwon-image') | ||||
|     implementation project(':markwon-inline-parser') | ||||
|     implementation project(':markwon-linkify') | ||||
|     implementation project(':markwon-recycler') | ||||
|     implementation project(':markwon-recycler-table') | ||||
|     implementation project(':markwon-simple-ext') | ||||
|     implementation project(':markwon-syntax-highlight') | ||||
| 
 | ||||
|     implementation project(':markwon-image-picasso') | ||||
|     implementation project(':markwon-image-glide') | ||||
| 
 | ||||
|     deps.with { | ||||
|         implementation it['x-recycler-view'] | ||||
|         implementation it['x-cardview'] | ||||
|         implementation it['x-fragment'] | ||||
|         implementation it['okhttp'] | ||||
|         implementation it['prism4j'] | ||||
|         implementation it['gson'] | ||||
|         implementation it['adapt'] | ||||
|         implementation it['debug'] | ||||
|         implementation it['android-svg'] | ||||
|         implementation it['android-gif'] | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -13,7 +13,7 @@ | ||||
|         android:layout_height="wrap_content" | ||||
|         android:text="Hey!" /> | ||||
| 
 | ||||
|     <io.noties.markwon.app.base.FlowLayout | ||||
|     <io.noties.markwon.app.widget.FlowLayout | ||||
|         android:layout_width="match_parent" | ||||
|         android:layout_height="wrap_content" | ||||
|         android:paddingTop="@dimen/content_padding" | ||||
| @ -86,9 +86,9 @@ | ||||
|             android:background="@drawable/bg_artifact" | ||||
|             android:text="core" /> | ||||
| 
 | ||||
|     </io.noties.markwon.app.base.FlowLayout> | ||||
|     </io.noties.markwon.app.widget.FlowLayout> | ||||
| 
 | ||||
|     <io.noties.markwon.app.base.FlowLayout | ||||
|     <io.noties.markwon.app.widget.FlowLayout | ||||
|         android:layout_width="match_parent" | ||||
|         android:layout_height="wrap_content" | ||||
|         android:paddingTop="@dimen/content_padding" | ||||
| @ -161,6 +161,6 @@ | ||||
|             android:background="@drawable/bg_tag" | ||||
|             android:text="core" /> | ||||
| 
 | ||||
|     </io.noties.markwon.app.base.FlowLayout> | ||||
|     </io.noties.markwon.app.widget.FlowLayout> | ||||
| 
 | ||||
| </LinearLayout> | ||||
| @ -3,6 +3,8 @@ | ||||
|     xmlns:tools="http://schemas.android.com/tools" | ||||
|     package="io.noties.markwon.app"> | ||||
| 
 | ||||
|     <uses-permission android:name="android.permission.INTERNET" /> | ||||
| 
 | ||||
|     <application | ||||
|         android:name=".App" | ||||
|         android:allowBackup="true" | ||||
| @ -13,12 +15,32 @@ | ||||
|         android:theme="@style/AppTheme" | ||||
|         tools:ignore="AllowBackup,GoogleAppIndexingWarning"> | ||||
| 
 | ||||
|         <activity android:name=".MainActivity"> | ||||
|         <activity android:name=".sample.MainActivity"> | ||||
|             <intent-filter> | ||||
|                 <action android:name="android.intent.action.MAIN" /> | ||||
|                 <category android:name="android.intent.category.LAUNCHER" /> | ||||
|             </intent-filter> | ||||
|         </activity> | ||||
| 
 | ||||
|         <activity | ||||
|             android:name=".readme.ReadMeActivity" | ||||
|             android:exported="true"> | ||||
| 
 | ||||
|             <!-- github markdown files handling --> | ||||
|             <intent-filter> | ||||
|                 <action android:name="android.intent.action.VIEW" /> | ||||
| 
 | ||||
|                 <category android:name="android.intent.category.DEFAULT" /> | ||||
|                 <category android:name="android.intent.category.BROWSABLE" /> | ||||
| 
 | ||||
|                 <data | ||||
|                     android:host="github.com" | ||||
|                     android:pathPattern=".*\\.md" | ||||
|                     android:scheme="https" /> | ||||
| 
 | ||||
|             </intent-filter> | ||||
|         </activity> | ||||
| 
 | ||||
|     </application> | ||||
| 
 | ||||
| </manifest> | ||||
							
								
								
									
										1
									
								
								app-sample/src/main/assets/README.md
									
									
									
									
									
										Symbolic link
									
								
							
							
						
						
									
										1
									
								
								app-sample/src/main/assets/README.md
									
									
									
									
									
										Symbolic link
									
								
							| @ -0,0 +1 @@ | ||||
| ../../../../README.md | ||||
| @ -3,6 +3,8 @@ package io.noties.markwon.app | ||||
| import android.app.Application | ||||
| import io.noties.debug.AndroidLogDebugOutput | ||||
| import io.noties.debug.Debug | ||||
| import io.noties.markwon.app.sample.SampleManager | ||||
| import java.util.concurrent.ExecutorService | ||||
| import java.util.concurrent.Executors | ||||
| 
 | ||||
| @Suppress("unused") | ||||
| @ -13,10 +15,12 @@ class App : Application() { | ||||
| 
 | ||||
|         Debug.init(AndroidLogDebugOutput(BuildConfig.DEBUG)) | ||||
| 
 | ||||
|         sampleManager = SampleManager(this, Executors.newCachedThreadPool()) | ||||
|         executorService = Executors.newCachedThreadPool() | ||||
|         sampleManager = SampleManager(this, executorService) | ||||
|     } | ||||
| 
 | ||||
|     companion object { | ||||
|         lateinit var executorService: ExecutorService | ||||
|         lateinit var sampleManager: SampleManager | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,25 @@ | ||||
| package io.noties.markwon.app.readme | ||||
| 
 | ||||
| import android.net.Uri | ||||
| import android.text.TextUtils | ||||
| import io.noties.markwon.image.destination.ImageDestinationProcessor | ||||
| import io.noties.markwon.image.destination.ImageDestinationProcessorRelativeToAbsolute | ||||
| 
 | ||||
| class GithubImageDestinationProcessor( | ||||
|         username: String = "noties", | ||||
|         repository: String = "Markwon", | ||||
|         branch: String = "master" | ||||
| ) : ImageDestinationProcessor() { | ||||
| 
 | ||||
|     private val processor = ImageDestinationProcessorRelativeToAbsolute("https://github.com/$username/$repository/raw/$branch/") | ||||
| 
 | ||||
|     override fun process(destination: String): String { | ||||
|         // process only images without scheme information | ||||
|         val uri = Uri.parse(destination) | ||||
|         return if (TextUtils.isEmpty(uri.scheme)) { | ||||
|             processor.process(destination) | ||||
|         } else { | ||||
|             destination | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,166 @@ | ||||
| package io.noties.markwon.app.readme | ||||
| 
 | ||||
| import android.app.Activity | ||||
| import android.content.Context | ||||
| import android.net.Uri | ||||
| import android.os.Bundle | ||||
| import android.view.View | ||||
| import android.widget.TextView | ||||
| import androidx.recyclerview.widget.DefaultItemAnimator | ||||
| import androidx.recyclerview.widget.LinearLayoutManager | ||||
| import androidx.recyclerview.widget.RecyclerView | ||||
| import io.noties.debug.Debug | ||||
| import io.noties.markwon.AbstractMarkwonPlugin | ||||
| import io.noties.markwon.Markwon | ||||
| import io.noties.markwon.MarkwonVisitor | ||||
| import io.noties.markwon.app.R | ||||
| import io.noties.markwon.app.utils.ReadMeUtils | ||||
| import io.noties.markwon.app.utils.hidden | ||||
| import io.noties.markwon.app.utils.loadReadMe | ||||
| import io.noties.markwon.app.utils.textOrHide | ||||
| import io.noties.markwon.ext.tasklist.TaskListPlugin | ||||
| import io.noties.markwon.html.HtmlPlugin | ||||
| import io.noties.markwon.image.ImagesPlugin | ||||
| import io.noties.markwon.recycler.MarkwonAdapter | ||||
| import io.noties.markwon.recycler.SimpleEntry | ||||
| import io.noties.markwon.recycler.table.TableEntry | ||||
| import io.noties.markwon.recycler.table.TableEntryPlugin | ||||
| import io.noties.markwon.syntax.Prism4jThemeDefault | ||||
| import io.noties.markwon.syntax.SyntaxHighlightPlugin | ||||
| import io.noties.prism4j.Prism4j | ||||
| import io.noties.prism4j.annotations.PrismBundle | ||||
| import okhttp3.Call | ||||
| import okhttp3.Callback | ||||
| import okhttp3.OkHttpClient | ||||
| import okhttp3.Request | ||||
| import okhttp3.Response | ||||
| import org.commonmark.ext.gfm.tables.TableBlock | ||||
| import org.commonmark.node.FencedCodeBlock | ||||
| import java.io.IOException | ||||
| 
 | ||||
| @PrismBundle(includeAll = true) | ||||
| class ReadMeActivity : Activity() { | ||||
| 
 | ||||
|     private lateinit var progressBar: View | ||||
| 
 | ||||
|     override fun onCreate(savedInstanceState: Bundle?) { | ||||
|         super.onCreate(savedInstanceState) | ||||
|         setContentView(R.layout.activity_read_me) | ||||
| 
 | ||||
|         progressBar = findViewById(R.id.progress_bar) | ||||
| 
 | ||||
|         val data = intent.data | ||||
| 
 | ||||
|         Debug.i(data) | ||||
| 
 | ||||
|         initAppBar(data) | ||||
| 
 | ||||
|         initRecyclerView(data) | ||||
|     } | ||||
| 
 | ||||
|     private val markwon: Markwon | ||||
|         get() = Markwon.builder(this) | ||||
|                 .usePlugin(ImagesPlugin.create()) | ||||
|                 .usePlugin(HtmlPlugin.create()) | ||||
|                 .usePlugin(TableEntryPlugin.create(this)) | ||||
|                 .usePlugin(SyntaxHighlightPlugin.create(Prism4j(GrammarLocatorDef()), Prism4jThemeDefault.create(0))) | ||||
|                 .usePlugin(TaskListPlugin.create(this)) | ||||
|                 .usePlugin(ReadMeImageDestinationPlugin(intent.data)) | ||||
|                 .usePlugin(object : AbstractMarkwonPlugin() { | ||||
|                     override fun configureVisitor(builder: MarkwonVisitor.Builder) { | ||||
|                         builder.on(FencedCodeBlock::class.java) { visitor, block -> | ||||
|                             // we actually won't be applying code spans here, as our custom view will | ||||
|                             // draw background and apply mono typeface | ||||
|                             // | ||||
|                             // NB the `trim` operation on literal (as code will have a new line at the end) | ||||
|                             val code = visitor.configuration() | ||||
|                                     .syntaxHighlight() | ||||
|                                     .highlight(block.info, block.literal.trim()) | ||||
|                             visitor.builder().append(code) | ||||
|                         } | ||||
|                     } | ||||
|                 }) | ||||
|                 .build() | ||||
| 
 | ||||
|     private fun initAppBar(data: Uri?) { | ||||
|         val appBar = findViewById<View>(R.id.app_bar) | ||||
|         appBar.findViewById<View>(R.id.app_bar_icon).setOnClickListener { onBackPressed() } | ||||
| 
 | ||||
|         val (title: String, subtitle: String?) = if (data == null) { | ||||
|             Pair("README.md", null) | ||||
|         } else { | ||||
|             Pair(data.lastPathSegment ?: "", data.toString()) | ||||
|         } | ||||
| 
 | ||||
|         appBar.findViewById<TextView>(R.id.title).text = title | ||||
|         appBar.findViewById<TextView>(R.id.subtitle).textOrHide(subtitle) | ||||
|     } | ||||
| 
 | ||||
|     private fun initRecyclerView(data: Uri?) { | ||||
| 
 | ||||
|         val adapter = MarkwonAdapter.builder(R.layout.adapter_node, R.id.text_view) | ||||
|                 .include(FencedCodeBlock::class.java, SimpleEntry.create(R.layout.adapter_node_code_block, R.id.text_view)) | ||||
|                 .include(TableBlock::class.java, TableEntry.create { | ||||
|                     it | ||||
|                             .tableLayout(R.layout.adapter_node_table_block, R.id.table_layout) | ||||
|                             .textLayoutIsRoot(R.layout.view_table_entry_cell) | ||||
|                 }) | ||||
|                 .build() | ||||
| 
 | ||||
|         val recyclerView: RecyclerView = findViewById(R.id.recycler_view) | ||||
|         recyclerView.layoutManager = LinearLayoutManager(this) | ||||
|         recyclerView.setHasFixedSize(true) | ||||
|         recyclerView.itemAnimator = DefaultItemAnimator() | ||||
|         recyclerView.adapter = adapter | ||||
| 
 | ||||
|         load(applicationContext, data) { result -> | ||||
| 
 | ||||
|             when (result) { | ||||
|                 is Result.Failure -> Debug.e(result.throwable) | ||||
|                 is Result.Success -> { | ||||
|                     val markwon = markwon | ||||
|                     val node = markwon.parse(result.markdown) | ||||
|                     if (window != null) { | ||||
|                         recyclerView.post { | ||||
|                             adapter.setParsedMarkdown(markwon, node) | ||||
|                             adapter.notifyDataSetChanged() | ||||
|                             progressBar.hidden = true | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private sealed class Result { | ||||
|         data class Success(val markdown: String) : Result() | ||||
|         data class Failure(val throwable: Throwable) : Result() | ||||
|     } | ||||
| 
 | ||||
|     private companion object { | ||||
|         fun load(context: Context, data: Uri?, callback: (Result) -> Unit) = try { | ||||
| 
 | ||||
|             if (data == null) { | ||||
|                 callback.invoke(Result.Success(loadReadMe(context))) | ||||
|             } else { | ||||
|                 val request = Request.Builder() | ||||
|                         .get() | ||||
|                         .url(ReadMeUtils.buildRawGithubUrl(data)) | ||||
|                         .build() | ||||
|                 OkHttpClient().newCall(request).enqueue(object : Callback { | ||||
|                     override fun onFailure(call: Call, e: IOException) { | ||||
|                         callback.invoke(Result.Failure(e)) | ||||
|                     } | ||||
| 
 | ||||
|                     override fun onResponse(call: Call, response: Response) { | ||||
|                         val md = response.body()?.string() ?: "" | ||||
|                         callback.invoke(Result.Success(md)) | ||||
|                     } | ||||
|                 }) | ||||
|             } | ||||
| 
 | ||||
|         } catch (t: Throwable) { | ||||
|             callback.invoke(Result.Failure(t)) | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,21 @@ | ||||
| package io.noties.markwon.app.readme | ||||
| 
 | ||||
| import android.net.Uri | ||||
| import io.noties.markwon.AbstractMarkwonPlugin | ||||
| import io.noties.markwon.MarkwonConfiguration | ||||
| import io.noties.markwon.app.utils.ReadMeUtils | ||||
| 
 | ||||
| class ReadMeImageDestinationPlugin(private val data: Uri?) : AbstractMarkwonPlugin() { | ||||
|     override fun configureConfiguration(builder: MarkwonConfiguration.Builder) { | ||||
|         val info = ReadMeUtils.parseInfo(data) | ||||
|         if (info == null) { | ||||
|             builder.imageDestinationProcessor(GithubImageDestinationProcessor()) | ||||
|         } else { | ||||
|             builder.imageDestinationProcessor(GithubImageDestinationProcessor( | ||||
|                     username = info.username, | ||||
|                     repository = info.repository, | ||||
|                     branch = info.branch | ||||
|             )) | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -1,9 +1,9 @@ | ||||
| package io.noties.markwon.app | ||||
| package io.noties.markwon.app.sample | ||||
| 
 | ||||
| import android.os.Bundle | ||||
| import android.view.Window | ||||
| import androidx.fragment.app.FragmentActivity | ||||
| import io.noties.markwon.app.ui.SampleListFragment | ||||
| import io.noties.markwon.app.sample.ui.SampleListFragment | ||||
| 
 | ||||
| class MainActivity : FragmentActivity() { | ||||
| 
 | ||||
| @ -1,4 +1,4 @@ | ||||
| package io.noties.markwon.app | ||||
| package io.noties.markwon.app.sample | ||||
| 
 | ||||
| import android.os.Parcelable | ||||
| import io.noties.markwon.sample.annotations.MarkwonArtifact | ||||
| @ -1,4 +1,4 @@ | ||||
| package io.noties.markwon.app.adapt | ||||
| package io.noties.markwon.app.sample | ||||
| 
 | ||||
| import android.text.Spanned | ||||
| import android.view.LayoutInflater | ||||
| @ -8,8 +8,7 @@ import android.widget.TextView | ||||
| import io.noties.adapt.Item | ||||
| import io.noties.markwon.Markwon | ||||
| import io.noties.markwon.app.R | ||||
| import io.noties.markwon.app.Sample | ||||
| import io.noties.markwon.app.base.FlowLayout | ||||
| import io.noties.markwon.app.widget.FlowLayout | ||||
| import io.noties.markwon.app.utils.displayName | ||||
| import io.noties.markwon.app.utils.hidden | ||||
| import io.noties.markwon.app.utils.tagDisplayName | ||||
| @ -1,4 +1,4 @@ | ||||
| package io.noties.markwon.app | ||||
| package io.noties.markwon.app.sample | ||||
| 
 | ||||
| import android.content.Context | ||||
| import io.noties.markwon.app.utils.Cancellable | ||||
| @ -1,4 +1,4 @@ | ||||
| package io.noties.markwon.app | ||||
| package io.noties.markwon.app.sample | ||||
| 
 | ||||
| import io.noties.markwon.sample.annotations.MarkwonArtifact | ||||
| 
 | ||||
| @ -1,4 +1,4 @@ | ||||
| package io.noties.markwon.app.ui | ||||
| package io.noties.markwon.app.sample.ui | ||||
| 
 | ||||
| import android.view.LayoutInflater | ||||
| import android.view.View | ||||
| @ -1,4 +1,4 @@ | ||||
| package io.noties.markwon.app.ui | ||||
| package io.noties.markwon.app.sample.ui | ||||
| 
 | ||||
| import android.content.Context | ||||
| import android.view.View | ||||
| @ -0,0 +1,74 @@ | ||||
| package io.noties.markwon.app.sample.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.App | ||||
| import io.noties.markwon.app.R | ||||
| import io.noties.markwon.app.sample.Sample | ||||
| import io.noties.markwon.app.utils.hidden | ||||
| import io.noties.markwon.app.utils.readCode | ||||
| import io.noties.markwon.syntax.Prism4jSyntaxHighlight | ||||
| import io.noties.markwon.syntax.Prism4jThemeDefault | ||||
| import io.noties.prism4j.Prism4j | ||||
| import io.noties.prism4j.annotations.PrismBundle | ||||
| 
 | ||||
| @PrismBundle(include = ["java", "kotlin"], grammarLocatorClassName = ".GrammarLocatorSourceCode") | ||||
| class SampleCodeFragment : Fragment() { | ||||
| 
 | ||||
|     private lateinit var progressBar: View | ||||
|     private lateinit var textView: TextView | ||||
| 
 | ||||
|     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) | ||||
| 
 | ||||
|         progressBar = view.findViewById(R.id.progress_bar) | ||||
|         textView = view.findViewById(R.id.text_view) | ||||
| 
 | ||||
|         load() | ||||
|     } | ||||
| 
 | ||||
|     private fun load() { | ||||
|         App.executorService.submit { | ||||
|             val code = sample.readCode(requireContext()) | ||||
|             val prism = Prism4j(GrammarLocatorSourceCode()) | ||||
|             val highlight = Prism4jSyntaxHighlight.create(prism, Prism4jThemeDefault.create(0)) | ||||
|             val language = when (code.language) { | ||||
|                 Sample.Language.KOTLIN -> "kotlin" | ||||
|                 Sample.Language.JAVA -> "java" | ||||
|             } | ||||
|             val text = highlight.highlight(language, code.sourceCode) | ||||
| 
 | ||||
|             textView.post { | ||||
|                 //attached | ||||
|                 if (context != null) { | ||||
|                     progressBar.hidden = true | ||||
|                     textView.text = text | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     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,4 +1,4 @@ | ||||
| package io.noties.markwon.app.ui | ||||
| package io.noties.markwon.app.sample.ui | ||||
| 
 | ||||
| import android.os.Bundle | ||||
| import android.view.LayoutInflater | ||||
| @ -8,7 +8,7 @@ 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.sample.Sample | ||||
| import io.noties.markwon.app.utils.active | ||||
| 
 | ||||
| class SampleFragment : Fragment() { | ||||
| @ -1,4 +1,4 @@ | ||||
| package io.noties.markwon.app.ui | ||||
| package io.noties.markwon.app.sample.ui | ||||
| 
 | ||||
| import android.content.Context | ||||
| import android.os.Bundle | ||||
| @ -19,11 +19,11 @@ import io.noties.debug.Debug | ||||
| import io.noties.markwon.Markwon | ||||
| import io.noties.markwon.app.App | ||||
| import io.noties.markwon.app.R | ||||
| import io.noties.markwon.app.Sample | ||||
| import io.noties.markwon.app.SampleManager | ||||
| import io.noties.markwon.app.SampleSearch | ||||
| import io.noties.markwon.app.adapt.SampleItem | ||||
| import io.noties.markwon.app.base.SearchBar | ||||
| import io.noties.markwon.app.sample.Sample | ||||
| import io.noties.markwon.app.sample.SampleManager | ||||
| import io.noties.markwon.app.sample.SampleSearch | ||||
| import io.noties.markwon.app.sample.SampleItem | ||||
| import io.noties.markwon.app.widget.SearchBar | ||||
| import io.noties.markwon.app.utils.Cancellable | ||||
| import io.noties.markwon.app.utils.displayName | ||||
| import io.noties.markwon.app.utils.onPreDraw | ||||
| @ -1,11 +1,11 @@ | ||||
| package io.noties.markwon.app.ui | ||||
| package io.noties.markwon.app.sample.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 | ||||
| import io.noties.markwon.app.sample.Sample | ||||
| 
 | ||||
| class SamplePreviewFragment : Fragment() { | ||||
| 
 | ||||
| @ -1,7 +1,7 @@ | ||||
| package io.noties.markwon.app.samples | ||||
| 
 | ||||
| import io.noties.markwon.Markwon | ||||
| import io.noties.markwon.app.ui.MarkwonTextViewSample | ||||
| import io.noties.markwon.app.sample.ui.MarkwonTextViewSample | ||||
| import io.noties.markwon.sample.annotations.MarkwonArtifact | ||||
| import io.noties.markwon.sample.annotations.MarkwonSampleInfo | ||||
| 
 | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| package io.noties.markwon.app.samples.nested | ||||
| 
 | ||||
| import io.noties.markwon.Markwon | ||||
| import io.noties.markwon.app.ui.MarkwonTextViewSample | ||||
| import io.noties.markwon.app.sample.ui.MarkwonTextViewSample | ||||
| import io.noties.markwon.sample.annotations.MarkwonArtifact | ||||
| import io.noties.markwon.sample.annotations.MarkwonSampleInfo | ||||
| 
 | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| package io.noties.markwon.app.samples.nested; | ||||
| 
 | ||||
| import io.noties.markwon.Markwon; | ||||
| import io.noties.markwon.app.ui.MarkwonTextViewSample; | ||||
| import io.noties.markwon.app.sample.ui.MarkwonTextViewSample; | ||||
| import io.noties.markwon.sample.annotations.MarkwonArtifact; | ||||
| import io.noties.markwon.sample.annotations.MarkwonSampleInfo; | ||||
| 
 | ||||
|  | ||||
| @ -1,43 +0,0 @@ | ||||
| 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) | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,21 @@ | ||||
| package io.noties.markwon.app.utils | ||||
| 
 | ||||
| import java.io.IOException | ||||
| import java.io.InputStream | ||||
| import java.util.Scanner | ||||
| 
 | ||||
| fun InputStream.readStringAndClose(): String { | ||||
|     try { | ||||
|         val scanner = Scanner(this).useDelimiter("\\A") | ||||
|         if (scanner.hasNext()) { | ||||
|             return scanner.next() | ||||
|         } | ||||
|         return "" | ||||
|     } finally { | ||||
|         try { | ||||
|             close() | ||||
|         } catch (e: IOException) { | ||||
|             // ignored | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,44 @@ | ||||
| package io.noties.markwon.app.utils | ||||
| 
 | ||||
| import android.net.Uri | ||||
| import java.util.regex.Pattern | ||||
| 
 | ||||
| object ReadMeUtils { | ||||
|     // username, repo, branch, lastPathSegment | ||||
|     private val RE = Pattern.compile("^https:\\/\\/github\\.com\\/(\\w+?)\\/(\\w+?)\\/(?:blob|raw)\\/(\\w+?)\\/(.+)") | ||||
| 
 | ||||
|     data class GithubInfo( | ||||
|             val username: String, | ||||
|             val repository: String, | ||||
|             val branch: String, | ||||
|             val fileName: String | ||||
|     ) | ||||
| 
 | ||||
|     fun parseInfo(data: Uri?): GithubInfo? { | ||||
| 
 | ||||
|         if (data == null) { | ||||
|             return null | ||||
|         } | ||||
| 
 | ||||
|         val matcher = RE.matcher(data.toString()) | ||||
|         if (!matcher.matches()) { | ||||
|             return null | ||||
|         } | ||||
| 
 | ||||
|         return GithubInfo( | ||||
|                 username = matcher.group(1), | ||||
|                 repository = matcher.group(2), | ||||
|                 branch = matcher.group(3), | ||||
|                 fileName = matcher.group(4) | ||||
|         ) | ||||
|     } | ||||
| 
 | ||||
|     fun buildRawGithubUrl(data: Uri): String { | ||||
|         val info = parseInfo(data) | ||||
|         return if (info == null) { | ||||
|             data.toString() | ||||
|         } else { | ||||
|             "https://github.com/${info.username}/${info.repository}/raw/${info.branch}/${info.fileName}" | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -12,7 +12,7 @@ import java.io.InputStream; | ||||
| import java.io.InputStreamReader; | ||||
| import java.util.List; | ||||
| 
 | ||||
| import io.noties.markwon.app.Sample; | ||||
| import io.noties.markwon.app.sample.Sample; | ||||
| 
 | ||||
| public abstract class SampleUtils { | ||||
| 
 | ||||
|  | ||||
| @ -1,10 +1,9 @@ | ||||
| package io.noties.markwon.app.utils | ||||
| 
 | ||||
| import android.content.Context | ||||
| import io.noties.markwon.app.Sample | ||||
| import io.noties.markwon.app.sample.Sample | ||||
| import io.noties.markwon.sample.annotations.MarkwonArtifact | ||||
| import java.io.InputStream | ||||
| import java.util.Scanner | ||||
| 
 | ||||
| val MarkwonArtifact.displayName: String | ||||
|     get() = "@${artifactName()}" | ||||
| @ -22,11 +21,6 @@ fun Sample.readCode(context: Context): Sample.Code { | ||||
|             .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) | ||||
| @ -35,6 +29,7 @@ fun Sample.readCode(context: Context): Sample.Code { | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     // now, we have 2 possibilities -> Kotlin or Java | ||||
|     var language: Sample.Language = Sample.Language.KOTLIN | ||||
|     var stream = obtain("$path.kt") | ||||
|     if (stream == null) { | ||||
| @ -46,13 +41,12 @@ fun Sample.readCode(context: Context): Sample.Code { | ||||
|         throw IllegalStateException("Cannot obtain sample file at path: $path") | ||||
|     } | ||||
| 
 | ||||
|     val code = read(stream) | ||||
| 
 | ||||
|     try { | ||||
|         stream.close() | ||||
|     } catch (t: Throwable) { | ||||
|         // ignore | ||||
|     } | ||||
|     val code = stream.readStringAndClose() | ||||
| 
 | ||||
|     return Sample.Code(language, code) | ||||
| } | ||||
| 
 | ||||
| fun loadReadMe(context: Context): String { | ||||
|     val stream = context.assets.open("README.md") | ||||
|     return stream.readStringAndClose() | ||||
| } | ||||
| @ -0,0 +1,9 @@ | ||||
| package io.noties.markwon.app.utils | ||||
| 
 | ||||
| import android.text.TextUtils | ||||
| import android.widget.TextView | ||||
| 
 | ||||
| fun TextView.textOrHide(text: CharSequence?) { | ||||
|     this.text = text | ||||
|     this.hidden = TextUtils.isEmpty(text) | ||||
| } | ||||
| @ -1,4 +1,4 @@ | ||||
| package io.noties.markwon.app.base | ||||
| package io.noties.markwon.app.widget | ||||
| 
 | ||||
| import android.content.Context | ||||
| import android.util.AttributeSet | ||||
| @ -1,4 +1,4 @@ | ||||
| package io.noties.markwon.app.base | ||||
| package io.noties.markwon.app.widget | ||||
| 
 | ||||
| import android.content.Context | ||||
| import android.util.AttributeSet | ||||
| @ -1,4 +1,4 @@ | ||||
| package io.noties.markwon.app.base | ||||
| package io.noties.markwon.app.widget | ||||
| 
 | ||||
| import android.content.Context | ||||
| import android.util.AttributeSet | ||||
							
								
								
									
										70
									
								
								app-sample/src/main/res/layout/activity_read_me.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								app-sample/src/main/res/layout/activity_read_me.xml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,70 @@ | ||||
| <?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" /> | ||||
| 
 | ||||
|         <LinearLayout | ||||
|             android:layout_width="match_parent" | ||||
|             android:layout_height="match_parent" | ||||
|             android:layout_marginEnd="@dimen/content_padding" | ||||
|             android:gravity="center_vertical" | ||||
|             android:orientation="vertical"> | ||||
| 
 | ||||
|             <TextView | ||||
|                 android:id="@+id/title" | ||||
|                 android:layout_width="match_parent" | ||||
|                 android:layout_height="wrap_content" | ||||
|                 android:textAppearance="?android:attr/textAppearanceMedium" | ||||
|                 android:textColor="@color/white" | ||||
|                 android:textStyle="bold" | ||||
|                 tools:text="README.md" /> | ||||
| 
 | ||||
|             <TextView | ||||
|                 android:id="@+id/subtitle" | ||||
|                 android:layout_width="match_parent" | ||||
|                 android:layout_height="wrap_content" | ||||
|                 android:ellipsize="middle" | ||||
|                 android:singleLine="true" | ||||
|                 android:textAppearance="?android:attr/textAppearanceSmall" | ||||
|                 android:textColor="@color/white" | ||||
|                 tools:text="https://blah.blah/README.md" /> | ||||
| 
 | ||||
|         </LinearLayout> | ||||
| 
 | ||||
|     </LinearLayout> | ||||
| 
 | ||||
|     <FrameLayout | ||||
|         android:layout_width="match_parent" | ||||
|         android:layout_height="match_parent"> | ||||
| 
 | ||||
|         <androidx.recyclerview.widget.RecyclerView | ||||
|             android:id="@+id/recycler_view" | ||||
|             android:layout_width="match_parent" | ||||
|             android:layout_height="match_parent" | ||||
|             android:clipChildren="false" | ||||
|             android:clipToPadding="false" | ||||
|             android:overScrollMode="never" | ||||
|             android:paddingTop="@dimen/content_padding" | ||||
|             android:paddingBottom="36dip" /> | ||||
| 
 | ||||
|         <ProgressBar | ||||
|             android:id="@+id/progress_bar" | ||||
|             android:layout_width="@dimen/progress_bar_side" | ||||
|             android:layout_height="@dimen/progress_bar_side" | ||||
|             android:layout_gravity="center" /> | ||||
| 
 | ||||
|     </FrameLayout> | ||||
| 
 | ||||
| </LinearLayout> | ||||
| @ -54,7 +54,7 @@ | ||||
|             android:textAppearance="?android:attr/textAppearance" | ||||
|             tools:text="Description goes here" /> | ||||
| 
 | ||||
|         <io.noties.markwon.app.base.FlowLayout | ||||
|         <io.noties.markwon.app.widget.FlowLayout | ||||
|             android:id="@+id/artifacts" | ||||
|             android:layout_width="match_parent" | ||||
|             android:layout_height="wrap_content" | ||||
| @ -66,9 +66,9 @@ | ||||
|             <!--    we are actually fine with pre-inflating a single view    --> | ||||
|             <include layout="@layout/view_artifact" /> | ||||
| 
 | ||||
|         </io.noties.markwon.app.base.FlowLayout> | ||||
|         </io.noties.markwon.app.widget.FlowLayout> | ||||
| 
 | ||||
|         <io.noties.markwon.app.base.FlowLayout | ||||
|         <io.noties.markwon.app.widget.FlowLayout | ||||
|             android:id="@+id/tags" | ||||
|             android:layout_width="match_parent" | ||||
|             android:layout_height="wrap_content" | ||||
| @ -80,7 +80,7 @@ | ||||
| 
 | ||||
|             <include layout="@layout/view_tag" /> | ||||
| 
 | ||||
|         </io.noties.markwon.app.base.FlowLayout> | ||||
|         </io.noties.markwon.app.widget.FlowLayout> | ||||
| 
 | ||||
|     </LinearLayout> | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										17
									
								
								app-sample/src/main/res/layout/adapter_node.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								app-sample/src/main/res/layout/adapter_node.xml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,17 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <TextView xmlns:android="http://schemas.android.com/apk/res/android" | ||||
|     xmlns:tools="http://schemas.android.com/tools" | ||||
|     android:id="@+id/text_view" | ||||
|     android:layout_width="match_parent" | ||||
|     android:layout_height="wrap_content" | ||||
|     android:layout_marginLeft="16dip" | ||||
|     android:layout_marginRight="16dip" | ||||
|     android:breakStrategy="simple" | ||||
|     android:hyphenationFrequency="none" | ||||
|     android:lineSpacingExtra="2dip" | ||||
|     android:paddingTop="8dip" | ||||
|     android:paddingBottom="8dip" | ||||
|     android:textAppearance="?android:attr/textAppearanceMedium" | ||||
|     android:textColor="#000" | ||||
|     android:textSize="16sp" | ||||
|     tools:text="Hello" /> | ||||
							
								
								
									
										26
									
								
								app-sample/src/main/res/layout/adapter_node_code_block.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								app-sample/src/main/res/layout/adapter_node_code_block.xml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,26 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <HorizontalScrollView xmlns:android="http://schemas.android.com/apk/res/android" | ||||
|     android:layout_width="match_parent" | ||||
|     android:layout_height="wrap_content" | ||||
|     android:clipChildren="false" | ||||
|     android:clipToPadding="false" | ||||
|     android:fillViewport="true" | ||||
|     android:paddingLeft="16dip" | ||||
|     android:paddingRight="16dip" | ||||
|     android:scrollbarStyle="outsideInset"> | ||||
| 
 | ||||
|     <TextView | ||||
|         android:id="@+id/text_view" | ||||
|         android:layout_width="wrap_content" | ||||
|         android:layout_height="wrap_content" | ||||
|         android:background="#0f000000" | ||||
|         android:fontFamily="monospace" | ||||
|         android:lineSpacingExtra="2dip" | ||||
|         android:paddingLeft="16dip" | ||||
|         android:paddingTop="8dip" | ||||
|         android:paddingRight="16dip" | ||||
|         android:paddingBottom="8dip" | ||||
|         android:textAppearance="?android:attr/textAppearanceMedium" | ||||
|         android:textSize="14sp" /> | ||||
| 
 | ||||
| </HorizontalScrollView> | ||||
							
								
								
									
										19
									
								
								app-sample/src/main/res/layout/adapter_node_table_block.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								app-sample/src/main/res/layout/adapter_node_table_block.xml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,19 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <HorizontalScrollView xmlns:android="http://schemas.android.com/apk/res/android" | ||||
|     android:layout_width="match_parent" | ||||
|     android:layout_height="wrap_content" | ||||
|     android:clipChildren="false" | ||||
|     android:clipToPadding="false" | ||||
|     android:paddingLeft="16dip" | ||||
|     android:paddingTop="8dip" | ||||
|     android:paddingRight="16dip" | ||||
|     android:paddingBottom="8dip" | ||||
|     android:scrollbarStyle="outsideInset"> | ||||
| 
 | ||||
|     <TableLayout | ||||
|         android:id="@+id/table_layout" | ||||
|         android:layout_width="wrap_content" | ||||
|         android:layout_height="wrap_content" | ||||
|         android:stretchColumns="*" /> | ||||
| 
 | ||||
| </HorizontalScrollView> | ||||
| @ -1,28 +1,41 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android" | ||||
| <FrameLayout 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 | ||||
|     <androidx.core.widget.NestedScrollView | ||||
|         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"> | ||||
|         android:layout_height="match_parent"> | ||||
| 
 | ||||
|         <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 | ||||
|             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"> | ||||
| 
 | ||||
|     </HorizontalScrollView> | ||||
|             <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:textColor="?android:attr/textColorPrimary" | ||||
|                 android:textSize="14sp" | ||||
|                 tools:text="package io.noties.markwon" /> | ||||
| 
 | ||||
| </androidx.core.widget.NestedScrollView> | ||||
|         </HorizontalScrollView> | ||||
| 
 | ||||
|     </androidx.core.widget.NestedScrollView> | ||||
| 
 | ||||
|     <ProgressBar | ||||
|         android:id="@+id/progress_bar" | ||||
|         android:layout_width="@dimen/progress_bar_side" | ||||
|         android:layout_height="@dimen/progress_bar_side" | ||||
|         android:layout_gravity="center" /> | ||||
| 
 | ||||
| </FrameLayout> | ||||
| @ -42,7 +42,7 @@ | ||||
|             android:paddingBottom="36dip" | ||||
|             tools:layout_marginTop="56dip" /> | ||||
| 
 | ||||
|         <io.noties.markwon.app.base.SearchBar | ||||
|         <io.noties.markwon.app.widget.SearchBar | ||||
|             android:id="@+id/search_bar" | ||||
|             android:layout_width="match_parent" | ||||
|             android:layout_height="wrap_content" | ||||
|  | ||||
| @ -51,7 +51,7 @@ | ||||
|             android:visibility="gone" | ||||
|             tools:visibility="visible" /> | ||||
| 
 | ||||
|         <io.noties.markwon.app.base.TextField | ||||
|         <io.noties.markwon.app.widget.TextField | ||||
|             android:id="@+id/text_field" | ||||
|             android:layout_width="match_parent" | ||||
|             android:layout_height="wrap_content" | ||||
|  | ||||
							
								
								
									
										9
									
								
								app-sample/src/main/res/layout/view_table_entry_cell.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								app-sample/src/main/res/layout/view_table_entry_cell.xml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,9 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <TextView xmlns:android="http://schemas.android.com/apk/res/android" | ||||
|     xmlns:tools="http://schemas.android.com/tools" | ||||
|     android:layout_width="wrap_content" | ||||
|     android:layout_height="wrap_content" | ||||
|     android:textAppearance="?android:attr/textAppearanceMedium" | ||||
|     android:textColor="#000" | ||||
|     android:textSize="16sp" | ||||
|     tools:text="Table content" /> | ||||
| @ -11,4 +11,7 @@ | ||||
| 
 | ||||
|     <dimen name="divider_height">1dip</dimen> | ||||
|     <dimen name="tab_bar_height">56dip</dimen> | ||||
| 
 | ||||
|     <dimen name="progress_bar_side">64dip</dimen> | ||||
| 
 | ||||
| </resources> | ||||
| @ -4,4 +4,5 @@ | ||||
| 
 | ||||
|     <string name="tab_bar_preview">Preview</string> | ||||
|     <string name="tab_bar_code">Code</string> | ||||
| 
 | ||||
| </resources> | ||||
| @ -60,6 +60,7 @@ dependencies { | ||||
|         implementation it['debug'] | ||||
|         implementation it['adapt'] | ||||
|         implementation it['android-svg'] | ||||
|         implementation it['android-gif'] | ||||
|     } | ||||
| 
 | ||||
|     deps['annotationProcessor'].with { | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Dimitry Ivanov
						Dimitry Ivanov