Commit 50bb8b9c authored by Konstantin Tskhovrebov's avatar Konstantin Tskhovrebov 🤖

added markdown image loader but without image url resolver

parent 1117fae5
......@@ -57,6 +57,7 @@ ext {
moxyVersion = "1.4.6"
toothpickVersion = "1.0.6"
retrofitVersion = "2.2.0"
markwonVersion = "1.0.3"
}
dependencies {
......@@ -93,7 +94,8 @@ dependencies {
//Image load and cache
implementation "com.github.bumptech.glide:glide:3.8.0"
//Markdown to HTML converter
implementation 'ru.noties:markwon:1.0.3'
implementation "ru.noties:markwon:$markwonVersion"
implementation "ru.noties:markwon-image-loader:$markwonVersion"
//Bottom navigation bar
implementation 'com.aurelhubert:ahbottomnavigation:2.1.0'
//Lottie
......
package ru.terrakok.gitlabclient.presentation.global
import io.reactivex.Single
import org.commonmark.parser.Parser
import org.commonmark.renderer.html.HtmlRenderer
import ru.noties.markwon.Markwon
import ru.noties.markwon.SpannableConfiguration
import ru.terrakok.gitlabclient.model.system.SchedulersProvider
import javax.inject.Inject
/**
* @author Konstantin Tskhovrebov (aka terrakok). Date: 28.05.17
*/
class MarkDownConverter @Inject constructor(
config: Config,
class MarkDownConverter(
private val config: SpannableConfiguration,
private val imageHostHolder: ImageHostHolder,
private val schedulers: SchedulersProvider
) {
data class Config(
val parser: Parser,
val htmlRenderer: HtmlRenderer,
val spannableConfiguration: SpannableConfiguration
)
private val parser = config.parser
private val renderer = config.htmlRenderer
private val mdConfig = config.spannableConfiguration
fun markdownToHtml(raw: String): Single<String> = Single
.fromCallable {
renderer.render(parser.parse(raw))
}
.subscribeOn(schedulers.computation())
.observeOn(schedulers.ui())
class ImageHostHolder(var url: String)
fun markdownToSpannable(raw: String): Single<CharSequence> = Single
.fromCallable {
Markwon.markdown(mdConfig, raw)
// imageHostHolder.url = "" todo resolve image urls
Markwon.markdown(config, raw)
}
.subscribeOn(schedulers.computation())
.observeOn(schedulers.ui())
......
......@@ -2,17 +2,11 @@ package ru.terrakok.gitlabclient.toothpick.module
import android.content.Context
import android.content.res.AssetManager
import org.commonmark.parser.Parser
import org.commonmark.renderer.html.HtmlRenderer
import ru.noties.markwon.SpannableConfiguration
import ru.noties.markwon.spans.SpannableTheme
import ru.terrakok.cicerone.Cicerone
import ru.terrakok.cicerone.NavigatorHolder
import ru.terrakok.cicerone.Router
import ru.terrakok.gitlabclient.BuildConfig
import ru.terrakok.gitlabclient.R
import ru.terrakok.gitlabclient.entity.app.develop.AppInfo
import ru.terrakok.gitlabclient.extension.color
import ru.terrakok.gitlabclient.model.data.auth.AuthHolder
import ru.terrakok.gitlabclient.model.data.storage.Prefs
import ru.terrakok.gitlabclient.model.data.storage.RawAppData
......@@ -23,7 +17,6 @@ import ru.terrakok.gitlabclient.model.system.AppSchedulers
import ru.terrakok.gitlabclient.model.system.ResourceManager
import ru.terrakok.gitlabclient.model.system.SchedulersProvider
import ru.terrakok.gitlabclient.model.system.flow.FlowRouter
import ru.terrakok.gitlabclient.presentation.global.MarkDownConverter
import ru.terrakok.gitlabclient.toothpick.PrimitiveWrapper
import ru.terrakok.gitlabclient.toothpick.qualifier.DefaultPageSize
import ru.terrakok.gitlabclient.toothpick.qualifier.DefaultServerPath
......@@ -44,17 +37,6 @@ class AppModule(context: Context) : Module() {
bind(AssetManager::class.java).toInstance(context.assets)
bind(RawAppData::class.java)
bind(MarkDownConverter.Config::class.java).toInstance(MarkDownConverter.Config(
Parser.builder().build(),
HtmlRenderer.builder().build(),
SpannableConfiguration.builder(context)
.theme(SpannableTheme.builderWithDefaults(context)
.codeBackgroundColor(context.color(R.color.beige))
.build())
.build()
))
bind(MarkDownConverter::class.java).singletonInScope()
//Navigation
val cicerone = Cicerone.create(FlowRouter())
bind(Router::class.java).toInstance(cicerone.router)
......
......@@ -21,8 +21,10 @@ import ru.terrakok.gitlabclient.model.repository.project.ProjectRepository
import ru.terrakok.gitlabclient.model.repository.todo.TodoRepository
import ru.terrakok.gitlabclient.model.repository.user.UserRepository
import ru.terrakok.gitlabclient.presentation.global.ErrorHandler
import ru.terrakok.gitlabclient.presentation.global.MarkDownConverter
import ru.terrakok.gitlabclient.toothpick.provider.ApiProvider
import ru.terrakok.gitlabclient.toothpick.provider.GsonProvider
import ru.terrakok.gitlabclient.toothpick.provider.MarkDownConverterProvider
import ru.terrakok.gitlabclient.toothpick.provider.OkHttpClientProvider
import ru.terrakok.gitlabclient.toothpick.qualifier.ServerPath
import toothpick.config.Module
......@@ -34,9 +36,10 @@ class ServerModule(serverUrl: String) : Module() {
init {
//Network
bind(String::class.java).withName(ServerPath::class.java).toInstance(serverUrl)
bind(Gson::class.java).toProvider(GsonProvider::class.java).singletonInScope()
bind(OkHttpClient::class.java).toProvider(OkHttpClientProvider::class.java).singletonInScope()
bind(GitlabApi::class.java).toProvider(ApiProvider::class.java).singletonInScope()
bind(Gson::class.java).toProvider(GsonProvider::class.java).providesSingletonInScope()
bind(OkHttpClient::class.java).toProvider(OkHttpClientProvider::class.java).providesSingletonInScope()
bind(GitlabApi::class.java).toProvider(ApiProvider::class.java).providesSingletonInScope()
bind(MarkDownConverter::class.java).toProvider(MarkDownConverterProvider::class.java).providesSingletonInScope()
//Auth
//todo: before release change and move to private config
......
package ru.terrakok.gitlabclient.toothpick.provider
import android.content.Context
import okhttp3.OkHttpClient
import ru.noties.markwon.SpannableConfiguration
import ru.noties.markwon.UrlProcessor
import ru.noties.markwon.il.AsyncDrawableLoader
import ru.noties.markwon.spans.SpannableTheme
import ru.terrakok.gitlabclient.R
import ru.terrakok.gitlabclient.extension.color
import ru.terrakok.gitlabclient.model.system.SchedulersProvider
import ru.terrakok.gitlabclient.presentation.global.MarkDownConverter
import java.net.URI
import java.util.concurrent.Executors
import javax.inject.Inject
import javax.inject.Provider
/**
* Created by Konstantin Tskhovrebov (aka @terrakok) on 28.02.18.
*/
class MarkDownConverterProvider @Inject constructor(
private val context: Context,
private val httpClient: OkHttpClient,
private val schedulers: SchedulersProvider
) : Provider<MarkDownConverter> {
private val spannableTheme
get() = SpannableTheme
.builderWithDefaults(context)
.codeBackgroundColor(context.color(R.color.beige))
.build()
private val asyncDrawableLoader
get() = AsyncDrawableLoader.builder()
.client(httpClient)
.executorService(Executors.newCachedThreadPool())
.resources(context.resources)
.build()
private val hostHolder = MarkDownConverter.ImageHostHolder("")
private val urlProcessor = UrlProcessor { destination ->
try {
if (URI(destination).scheme.isNotEmpty()) return@UrlProcessor destination
} catch (e: Exception) {
}
return@UrlProcessor hostHolder.url + destination
}
private val spannableConfig
get() = SpannableConfiguration.builder(context)
.asyncDrawableLoader(asyncDrawableLoader)
.urlProcessor(urlProcessor)
.theme(spannableTheme)
.build()
override fun get() = MarkDownConverter(
spannableConfig,
hostHolder,
schedulers
)
}
\ No newline at end of file
package ru.terrakok.gitlabclient.toothpick.provider
import android.content.Context
import okhttp3.Cache
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import ru.terrakok.gitlabclient.BuildConfig
......@@ -14,22 +16,24 @@ import javax.inject.Provider
/**
* @author Konstantin Tskhovrebov (aka terrakok) on 20.06.17.
*/
class OkHttpClientProvider @Inject constructor(authData: AuthHolder) : Provider<OkHttpClient> {
private val httpClient: OkHttpClient
class OkHttpClientProvider @Inject constructor(
private val authData: AuthHolder,
private val context: Context
) : Provider<OkHttpClient> {
init {
val httpClientBuilder = OkHttpClient.Builder()
httpClientBuilder.addNetworkInterceptor(AuthHeaderInterceptor(authData))
httpClientBuilder.addNetworkInterceptor(ErrorResponseInterceptor())
httpClientBuilder.readTimeout(30, TimeUnit.SECONDS)
override fun get() = with(OkHttpClient.Builder()) {
cache(Cache(context.cacheDir, 20 * 1024))
connectTimeout(30, TimeUnit.SECONDS)
readTimeout(30, TimeUnit.SECONDS)
addNetworkInterceptor(AuthHeaderInterceptor(authData))
addNetworkInterceptor(ErrorResponseInterceptor())
if (BuildConfig.DEBUG) {
val httpLoggingInterceptor = HttpLoggingInterceptor()
httpLoggingInterceptor.level = HttpLoggingInterceptor.Level.BODY
httpClientBuilder.addNetworkInterceptor(httpLoggingInterceptor)
httpClientBuilder.addNetworkInterceptor(CurlLoggingInterceptor())
addNetworkInterceptor(
HttpLoggingInterceptor().apply { level = HttpLoggingInterceptor.Level.BODY }
)
addNetworkInterceptor(CurlLoggingInterceptor())
}
httpClient = httpClientBuilder.build()
build()
}
override fun get() = httpClient
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment