Commit 39152b27 authored by Eugene Shapovalov's avatar Eugene Shapovalov 💬

Implemented image url logic for markdown.

parent 94851cfc
......@@ -57,7 +57,7 @@ ext {
moxyVersion = "1.4.6"
toothpickVersion = "1.0.6"
retrofitVersion = "2.2.0"
markwonVersion = "1.0.3"
markwonVersion = "1.1.1"
}
dependencies {
......
......@@ -7,13 +7,13 @@ import ru.terrakok.gitlabclient.entity.Author
* Created by Konstantin Tskhovrebov (aka @terrakok) on 24.12.17.
*/
data class TargetHeader(
val author: Author,
val icon: TargetHeaderIcon,
val title: TargetHeaderTitle,
val body: CharSequence,
val date: LocalDateTime,
val target: AppTarget,
val targetId: Long,
val internal: TargetInternal?,
val badges: List<TargetBadge>
val author: Author,
val icon: TargetHeaderIcon,
val title: TargetHeaderTitle,
val body: CharSequence,
val date: LocalDateTime,
val target: AppTarget,
val targetId: Long,
val internal: TargetInternal?,
val badges: List<TargetBadge>
)
\ No newline at end of file
......@@ -15,6 +15,7 @@ import ru.terrakok.gitlabclient.entity.event.EventTarget
import ru.terrakok.gitlabclient.entity.event.EventTargetType
import ru.terrakok.gitlabclient.model.data.server.GitlabApi
import ru.terrakok.gitlabclient.model.system.SchedulersProvider
import ru.terrakok.gitlabclient.presentation.global.MarkDownUrlResolver
import ru.terrakok.gitlabclient.toothpick.PrimitiveWrapper
import ru.terrakok.gitlabclient.toothpick.qualifier.DefaultPageSize
import javax.inject.Inject
......@@ -25,7 +26,8 @@ import javax.inject.Inject
class EventRepository @Inject constructor(
private val api: GitlabApi,
private val schedulers: SchedulersProvider,
@DefaultPageSize private val defaultPageSizeWrapper: PrimitiveWrapper<Int>
@DefaultPageSize private val defaultPageSizeWrapper: PrimitiveWrapper<Int>,
private val markDownUrlResolver: MarkDownUrlResolver
) {
private val defaultPageSize = defaultPageSizeWrapper.value
......@@ -86,7 +88,7 @@ class EventRepository @Inject constructor(
targetData.name,
project?.name ?: ""
),
getBody(event) ?: "",
getBody(event, project) ?: "",
event.createdAt,
targetData.target,
targetData.id,
......@@ -209,9 +211,15 @@ class EventRepository @Inject constructor(
}
}
private fun getBody(event: Event) = when (event.targetType) {
private fun getBody(event: Event, project: Project?) = when (event.targetType) {
EventTargetType.NOTE,
EventTargetType.DIFF_NOTE -> event.note?.body
EventTargetType.DIFF_NOTE -> {
if (event.note != null && project != null) {
markDownUrlResolver.resolve(event.note.body, project)
} else {
null
}
}
EventTargetType.ISSUE,
EventTargetType.MERGE_REQUEST,
EventTargetType.MILESTONE -> event.targetTitle
......
......@@ -3,6 +3,7 @@ package ru.terrakok.gitlabclient.model.repository.issue
import io.reactivex.Observable
import io.reactivex.Single
import io.reactivex.functions.BiFunction
import ru.terrakok.gitlabclient.entity.Note
import ru.terrakok.gitlabclient.entity.OrderBy
import ru.terrakok.gitlabclient.entity.Project
import ru.terrakok.gitlabclient.entity.Sort
......@@ -13,6 +14,7 @@ import ru.terrakok.gitlabclient.entity.issue.IssueScope
import ru.terrakok.gitlabclient.entity.issue.IssueState
import ru.terrakok.gitlabclient.model.data.server.GitlabApi
import ru.terrakok.gitlabclient.model.system.SchedulersProvider
import ru.terrakok.gitlabclient.presentation.global.MarkDownUrlResolver
import ru.terrakok.gitlabclient.toothpick.PrimitiveWrapper
import ru.terrakok.gitlabclient.toothpick.qualifier.DefaultPageSize
import javax.inject.Inject
......@@ -23,7 +25,8 @@ import javax.inject.Inject
class IssueRepository @Inject constructor(
private val api: GitlabApi,
private val schedulers: SchedulersProvider,
@DefaultPageSize private val defaultPageSizeWrapper: PrimitiveWrapper<Int>
@DefaultPageSize private val defaultPageSizeWrapper: PrimitiveWrapper<Int>,
private val markDownUrlResolver: MarkDownUrlResolver
) {
private val defaultPageSize = defaultPageSizeWrapper.value
......@@ -107,8 +110,25 @@ class IssueRepository @Inject constructor(
issueId: Long,
orderBy: OrderBy? = null,
sort: Sort? = Sort.ASC
) = api
.getIssueNotes(projectId, issueId, orderBy, sort)
.subscribeOn(schedulers.io())
.observeOn(schedulers.ui())
) =
Single
.zip(
api.getProject(projectId),
api.getIssueNotes(projectId, issueId, orderBy, sort),
BiFunction<Project, List<Note>, List<Note>> { project, notes ->
ArrayList(notes).apply {
val iterator = listIterator()
while (iterator.hasNext()) {
val note = iterator.next()
val resolved = markDownUrlResolver.resolve(note.body, project)
if (resolved != note.body) {
iterator.set(note.copy(body = resolved))
}
}
}
}
)
.subscribeOn(schedulers.io())
.observeOn(schedulers.ui())
}
\ No newline at end of file
......@@ -4,6 +4,7 @@ import io.reactivex.Observable
import io.reactivex.Single
import io.reactivex.functions.BiFunction
import org.threeten.bp.LocalDateTime
import ru.terrakok.gitlabclient.entity.Note
import ru.terrakok.gitlabclient.entity.OrderBy
import ru.terrakok.gitlabclient.entity.Project
import ru.terrakok.gitlabclient.entity.Sort
......@@ -15,6 +16,7 @@ import ru.terrakok.gitlabclient.entity.mergerequest.MergeRequestState
import ru.terrakok.gitlabclient.entity.mergerequest.MergeRequestViewType
import ru.terrakok.gitlabclient.model.data.server.GitlabApi
import ru.terrakok.gitlabclient.model.system.SchedulersProvider
import ru.terrakok.gitlabclient.presentation.global.MarkDownUrlResolver
import ru.terrakok.gitlabclient.toothpick.PrimitiveWrapper
import ru.terrakok.gitlabclient.toothpick.qualifier.DefaultPageSize
import javax.inject.Inject
......@@ -22,7 +24,8 @@ import javax.inject.Inject
class MergeRequestRepository @Inject constructor(
private val api: GitlabApi,
private val schedulers: SchedulersProvider,
@DefaultPageSize private val defaultPageSizeWrapper: PrimitiveWrapper<Int>
@DefaultPageSize private val defaultPageSizeWrapper: PrimitiveWrapper<Int>,
private val markDownUrlResolver: MarkDownUrlResolver
) {
private val defaultPageSize = defaultPageSizeWrapper.value
......@@ -114,8 +117,25 @@ class MergeRequestRepository @Inject constructor(
mergeRequestId: Long,
orderBy: OrderBy? = null,
sort: Sort? = Sort.ASC
) = api
.getMergeRequestNotes(projectId, mergeRequestId, orderBy, sort)
.subscribeOn(schedulers.io())
.observeOn(schedulers.ui())
) =
Single
.zip(
api.getProject(projectId),
api.getMergeRequestNotes(projectId, mergeRequestId, orderBy, sort),
BiFunction<Project, List<Note>, List<Note>> { project, notes ->
ArrayList(notes).apply {
val iterator = listIterator()
while (iterator.hasNext()) {
val note = iterator.next()
val resolved = markDownUrlResolver.resolve(note.body, project)
if (resolved != note.body) {
iterator.set(note.copy(body = resolved))
}
}
}
}
)
.subscribeOn(schedulers.io())
.observeOn(schedulers.ui())
}
\ No newline at end of file
......@@ -10,16 +10,12 @@ import ru.terrakok.gitlabclient.model.system.SchedulersProvider
*/
class MarkDownConverter(
private val config: SpannableConfiguration,
private val imageHostHolder: ImageHostHolder,
private val schedulers: SchedulersProvider
) {
class ImageHostHolder(var url: String)
fun markdownToSpannable(raw: String): Single<CharSequence> = Single
.fromCallable {
// imageHostHolder.url = "" todo resolve image urls
Markwon.markdown(config, raw)
}
.subscribeOn(schedulers.computation())
.observeOn(schedulers.ui())
fun markdownToSpannable(raw: String): Single<CharSequence> =
Single
.fromCallable { Markwon.markdown(config, raw) }
.subscribeOn(schedulers.computation())
.observeOn(schedulers.ui())
}
\ No newline at end of file
package ru.terrakok.gitlabclient.presentation.global
import ru.terrakok.gitlabclient.entity.Project
import javax.inject.Inject
class MarkDownUrlResolver @Inject constructor() {
private val regex = Regex("^!\\[\\w+]\\(/uploads/\\w+/\\w+\\.\\w+\\)$")
// ![CragHag](/uploads/69c4ef83b86c66eb3f147915d26c427e/CragHag.png) - before attach
// https://gitlab.com/terrakok/gitlab-client/uploads/b4048510da2ba117cdc793007066bc25/CragHag.png link to download
// https://gitlab.com/CraggyHaggy/GandastBot/uploads/9475c799f5e9ad5cd1a8ce28ce652ff9/citadel.jpg
fun resolve(body: String, project: Project): String {
return if (regex.matches(body)) {
StringBuilder(body)
.insert(body.indexOf("/uploads/"), project.pathWithNamespace)
.toString()
} else {
body
}
}
}
\ No newline at end of file
......@@ -22,6 +22,7 @@ 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.presentation.global.MarkDownUrlResolver
import ru.terrakok.gitlabclient.toothpick.provider.ApiProvider
import ru.terrakok.gitlabclient.toothpick.provider.GsonProvider
import ru.terrakok.gitlabclient.toothpick.provider.MarkDownConverterProvider
......@@ -40,6 +41,7 @@ class ServerModule(serverUrl: String) : Module() {
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()
bind(MarkDownUrlResolver::class.java).singletonInScope()
//Auth
//todo: before release change and move to private config
......
......@@ -3,14 +3,13 @@ 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.UrlProcessorRelativeToAbsolute
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
......@@ -29,6 +28,7 @@ class MarkDownConverterProvider @Inject constructor(
.builderWithDefaults(context)
.codeBackgroundColor(context.color(R.color.beige))
.build()
private val asyncDrawableLoader
get() = AsyncDrawableLoader.builder()
.client(httpClient)
......@@ -36,14 +36,7 @@ class MarkDownConverterProvider @Inject constructor(
.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 urlProcessor = UrlProcessorRelativeToAbsolute("https://gitlab.com/")
private val spannableConfig
get() = SpannableConfiguration.builder(context)
......@@ -54,7 +47,6 @@ class MarkDownConverterProvider @Inject constructor(
override fun get() = MarkDownConverter(
spannableConfig,
hostHolder,
schedulers
)
}
\ 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