Commit 115611b7 authored by Eugene Shapovalov's avatar Eugene Shapovalov 💬

Merge remote-tracking branch 'remotes/origin/develop' into bug/project_info_loading_readme

# Conflicts:
#	app/src/main/java/ru/terrakok/gitlabclient/ui/global/BaseActivity.kt
parents 4c15e3be 583c1d9a
......@@ -6,7 +6,7 @@ apply from: '../ci.gradle'
android {
compileSdkVersion 27
buildToolsVersion '27.0.1'
buildToolsVersion '27.0.3'
defaultConfig {
applicationId "ru.terrakok.gitlabclient"
......@@ -112,6 +112,7 @@ dependencies {
testCompile "org.mockito:mockito-core:2.8.9"
//Mockito Kotlin
testCompile "com.nhaarman:mockito-kotlin-kt1.1:1.5.0"
implementation 'com.android.support:cardview-v7:27.0.2'
}
configurations.all {
......
package ru.terrakok.gitlabclient
import android.content.Context
import android.content.Intent
import ru.terrakok.gitlabclient.ui.auth.AuthActivity
import ru.terrakok.gitlabclient.ui.issue.IssueActivity
import ru.terrakok.gitlabclient.ui.launch.MainActivity
import ru.terrakok.gitlabclient.ui.mergerequest.MergeRequestActivity
import ru.terrakok.gitlabclient.ui.project.ProjectActivity
import ru.terrakok.gitlabclient.ui.user.UserActivity
/**
* @author Konstantin Tskhovrebov (aka terrakok) on 26.03.17.
*/
......@@ -20,8 +29,24 @@ object Screens {
const val USER_INFO_SCREEN = "user info screen"
const val MR_FLOW = "mr flow"
const val MR_INFO_SCREEN = "mr info screen"
const val MR_SCREEN = "mr screen"
const val ISSUE_FLOW = "issue flow"
const val ISSUE_INFO_SCREEN = "issue info screen"
const val ISSUE_SCREEN = "issue screen"
fun getFlowIntent(context: Context, flowKey: String, data: Any?): Intent? = when (flowKey) {
Screens.AUTH_FLOW -> AuthActivity.getStartIntent(context)
Screens.MAIN_FLOW -> MainActivity.getStartIntent(context)
Screens.PROJECT_FLOW -> ProjectActivity.getStartIntent(data as Long, context)
Screens.USER_FLOW -> UserActivity.getStartIntent(data as Long, context)
Screens.MR_FLOW -> {
val (projectId, mrId) = data as Pair<Long, Long>
MergeRequestActivity.getStartIntent(projectId, mrId, context)
}
Screens.ISSUE_FLOW -> {
val (projectId, issueId) = data as Pair<Long, Long>
IssueActivity.getStartIntent(projectId, issueId, context)
}
else -> null
}
}
\ No newline at end of file
......@@ -2,11 +2,9 @@ package ru.terrakok.gitlabclient.extension
import android.content.Context
import android.content.Intent
import android.content.res.Resources
import android.graphics.Bitmap
import android.graphics.drawable.Drawable
import android.net.Uri
import android.support.annotation.DrawableRes
import android.support.annotation.LayoutRes
import android.support.v4.app.Fragment
import android.support.v4.content.ContextCompat
......@@ -19,26 +17,20 @@ import android.widget.ImageView
import android.widget.TextView
import com.bumptech.glide.Glide
import com.bumptech.glide.request.target.BitmapImageViewTarget
import org.joda.time.DateTimeZone
import org.joda.time.format.DateTimeFormat
import retrofit2.HttpException
import ru.terrakok.gitlabclient.R
import ru.terrakok.gitlabclient.Screens
import ru.terrakok.gitlabclient.entity.app.develop.LicenseType
import ru.terrakok.gitlabclient.entity.app.target.*
import ru.terrakok.gitlabclient.entity.event.EventAction
import ru.terrakok.gitlabclient.entity.todo.TodoAction
import ru.terrakok.gitlabclient.model.system.ResourceManager
import ru.terrakok.gitlabclient.entity.app.target.AppTarget
import ru.terrakok.gitlabclient.entity.app.target.TargetHeader
import ru.terrakok.gitlabclient.model.system.flow.FlowRouter
import timber.log.Timber
import java.io.IOException
import java.util.*
/**
* @author Konstantin Tskhovrebov (aka terrakok). Date: 03.03.17
*/
fun Context.color(colorRes: Int) = ContextCompat.getColor(this, colorRes)
fun ImageView.tint(colorRes: Int) = this.setColorFilter(this.context.color(colorRes))
fun ViewGroup.inflate(@LayoutRes layoutRes: Int, attachToRoot: Boolean = false): View {
return LayoutInflater.from(context).inflate(layoutRes, this, attachToRoot)
}
......@@ -47,43 +39,6 @@ fun View.visible(visible: Boolean) {
this.visibility = if (visible) View.VISIBLE else View.GONE
}
fun Throwable.userMessage(resourceManager: ResourceManager) = when (this) {
is HttpException -> when (this.code()) {
304 -> resourceManager.getString(R.string.not_modified_error)
400 -> resourceManager.getString(R.string.bad_request_error)
401 -> resourceManager.getString(R.string.unauthorized_error)
403 -> resourceManager.getString(R.string.forbidden_error)
404 -> resourceManager.getString(R.string.not_found_error)
405 -> resourceManager.getString(R.string.method_not_allowed_error)
409 -> resourceManager.getString(R.string.conflict_error)
422 -> resourceManager.getString(R.string.unprocessable_error)
500 -> resourceManager.getString(R.string.server_error_error)
else -> resourceManager.getString(R.string.unknown_error)
}
is IOException -> resourceManager.getString(R.string.network_error)
else -> resourceManager.getString(R.string.unknown_error)
}
private val DATE_FORMAT = DateTimeFormat.forPattern("dd.MM.yyyy")
fun Date.humanTime(resources: Resources): String {
val localMillis = DateTimeZone.getDefault().convertUTCToLocal(this.time)
val timeDelta = (System.currentTimeMillis() - localMillis) / 1000L
val timeStr =
if (timeDelta < 60) {
resources.getString(R.string.time_sec, timeDelta)
} else if (timeDelta < 60 * 60) {
resources.getString(R.string.time_min, timeDelta / 60)
} else if (timeDelta < 60 * 60 * 24) {
resources.getString(R.string.time_hour, timeDelta / (60 * 60))
} else if (timeDelta < 60 * 60 * 24 * 7) {
resources.getString(R.string.time_day, timeDelta / (60 * 60 * 24))
} else {
return DATE_FORMAT.print(localMillis)
}
return resources.getString(R.string.time_ago, timeStr)
}
fun TextView.showTextOrHide(str: String?) {
this.text = str
this.visible(!str.isNullOrBlank())
......@@ -121,110 +76,6 @@ fun Fragment.shareText(text: String?) {
}
}
fun EventAction.getHumanName(resources: Resources) = when (this) {
EventAction.UPDATED -> resources.getString(R.string.event_action_updated)
EventAction.REOPENED -> resources.getString(R.string.event_action_reopened)
EventAction.PUSHED_TO -> resources.getString(R.string.event_action_pushed_to)
EventAction.PUSHED_NEW -> resources.getString(R.string.event_action_pushed_new)
EventAction.PUSHED -> resources.getString(R.string.event_action_pushed)
EventAction.LEFT -> resources.getString(R.string.event_action_left)
EventAction.OPENED -> resources.getString(R.string.event_action_opened)
EventAction.DESTROYED -> resources.getString(R.string.event_action_destroyed)
EventAction.DELETED -> resources.getString(R.string.event_action_deleted)
EventAction.EXPIRED -> resources.getString(R.string.event_action_expired)
EventAction.MERGED -> resources.getString(R.string.event_action_merged)
EventAction.CLOSED -> resources.getString(R.string.event_action_closed)
EventAction.ACCEPTED -> resources.getString(R.string.event_action_accepted)
EventAction.COMMENTED -> resources.getString(R.string.event_action_commented)
EventAction.COMMENTED_ON -> resources.getString(R.string.event_action_commented_on)
EventAction.JOINED -> resources.getString(R.string.event_action_joined)
EventAction.CREATED -> resources.getString(R.string.event_action_created)
}
@DrawableRes
fun TargetHeaderIcon.getIcon() = when (this) {
TargetHeaderIcon.CREATED -> R.drawable.ic_event_created_24dp
TargetHeaderIcon.JOINED -> R.drawable.ic_event_joined_24dp
TargetHeaderIcon.COMMENTED -> R.drawable.ic_event_commented_24dp
TargetHeaderIcon.MERGED -> R.drawable.ic_event_merged_24dp
TargetHeaderIcon.CLOSED -> R.drawable.ic_event_closed_24dp
TargetHeaderIcon.DESTROYED -> R.drawable.ic_event_destroyed_24dp
TargetHeaderIcon.EXPIRED -> R.drawable.ic_event_expired_24dp
TargetHeaderIcon.LEFT -> R.drawable.ic_event_left_24dp
TargetHeaderIcon.REOPENED -> R.drawable.ic_event_reopened_24dp
TargetHeaderIcon.PUSHED -> R.drawable.ic_event_pushed_24dp
TargetHeaderIcon.UPDATED -> R.drawable.ic_event_updated_24dp
TargetHeaderIcon.NONE -> R.drawable.ic_event_created_24dp
}
fun TodoAction.getHumanName(resources: Resources): String = when (this) {
TodoAction.APPROVAL_REQUIRED -> resources.getString(R.string.todo_action_approval_required)
TodoAction.ASSIGNED -> resources.getString(R.string.todo_action_assigned)
TodoAction.BUILD_FAILED -> resources.getString(R.string.todo_action_build_failed)
TodoAction.DIRECTLY_ADDRESSED -> resources.getString(R.string.todo_action_directly_addressed)
TodoAction.MARKED -> resources.getString(R.string.todo_action_marked)
TodoAction.MENTIONED -> resources.getString(R.string.todo_action_mentioned)
}
fun TargetHeaderTitle.getHumanName(resources: Resources) = when (this) {
is TargetHeaderTitle.Event -> {
"$userName ${action.getHumanName(resources)} $targetName ${resources.getString(R.string.at)} $projectName"
}
is TargetHeaderTitle.Todo -> {
val actionName = action.getHumanName(resources)
val author = if (isAuthorCurrentUser) {
resources.getString(R.string.you).capitalize()
} else {
authorUserName
}
val assignee = if (isAssigneeCurrentUser) {
if (isAuthorCurrentUser) {
resources.getString(R.string.yourself)
} else {
resources.getString(R.string.you)
}
} else {
assigneeUserName
}
when (action) {
TodoAction.ASSIGNED -> {
"$author $actionName $targetName ${resources.getString(R.string.at)} $projectName ${resources.getString(R.string.to)} $assignee"
}
TodoAction.DIRECTLY_ADDRESSED,
TodoAction.MENTIONED -> {
"$author $actionName $assignee ${resources.getString(R.string.on)} $targetName ${resources.getString(R.string.at)} $projectName"
}
TodoAction.MARKED -> {
"$author $actionName ${resources.getString(R.string.for_str)} $targetName ${resources.getString(R.string.at)} $projectName"
}
else -> {
Timber.e("Unsupported template for todo action=$actionName.")
"$author $actionName $targetName $assignee ${resources.getString(R.string.at)}"
}
}
}
}
fun LicenseType.getHumanName(resources: Resources) = when (this) {
LicenseType.MIT -> resources.getString(R.string.library_license_MIT)
LicenseType.APACHE_2 -> resources.getString(R.string.library_license_APACHE_2)
LicenseType.CUSTOM -> resources.getString(R.string.library_license_CUSTOM)
LicenseType.NONE -> resources.getString(R.string.library_license_NONE)
}
fun TargetBadgeStatus.getHumanName(resources: Resources) = when (this) {
TargetBadgeStatus.OPENED -> resources.getString(R.string.target_status_opened)
TargetBadgeStatus.CLOSED -> resources.getString(R.string.target_status_closed)
TargetBadgeStatus.MERGED -> resources.getString(R.string.target_status_merged)
}
fun TargetBadgeStatus.getBadgeColors(context: Context) = when (this) {
TargetBadgeStatus.OPENED -> Pair(context.color(R.color.green), context.color(R.color.lightGreen))
TargetBadgeStatus.CLOSED -> Pair(context.color(R.color.red), context.color(R.color.lightRed))
TargetBadgeStatus.MERGED -> Pair(context.color(R.color.blue), context.color(R.color.lightBlue))
}
fun Fragment.sendEmail(email: String?) {
if (email != null) {
startActivity(Intent.createChooser(
......
package ru.terrakok.gitlabclient.extension
import android.content.Context
import android.content.res.Resources
import android.support.annotation.DrawableRes
import org.joda.time.DateTimeZone
import org.joda.time.format.DateTimeFormat
import retrofit2.HttpException
import ru.terrakok.gitlabclient.R
import ru.terrakok.gitlabclient.entity.app.develop.LicenseType
import ru.terrakok.gitlabclient.entity.app.target.TargetBadgeStatus
import ru.terrakok.gitlabclient.entity.app.target.TargetHeaderIcon
import ru.terrakok.gitlabclient.entity.app.target.TargetHeaderTitle
import ru.terrakok.gitlabclient.entity.event.EventAction
import ru.terrakok.gitlabclient.entity.todo.TodoAction
import ru.terrakok.gitlabclient.model.system.ResourceManager
import timber.log.Timber
import java.io.IOException
import java.util.*
/**
* Created by Konstantin Tskhovrebov (aka @terrakok) on 14.02.18.
*/
fun Throwable.userMessage(resourceManager: ResourceManager) = when (this) {
is HttpException -> when (this.code()) {
304 -> resourceManager.getString(R.string.not_modified_error)
400 -> resourceManager.getString(R.string.bad_request_error)
401 -> resourceManager.getString(R.string.unauthorized_error)
403 -> resourceManager.getString(R.string.forbidden_error)
404 -> resourceManager.getString(R.string.not_found_error)
405 -> resourceManager.getString(R.string.method_not_allowed_error)
409 -> resourceManager.getString(R.string.conflict_error)
422 -> resourceManager.getString(R.string.unprocessable_error)
500 -> resourceManager.getString(R.string.server_error_error)
else -> resourceManager.getString(R.string.unknown_error)
}
is IOException -> resourceManager.getString(R.string.network_error)
else -> resourceManager.getString(R.string.unknown_error)
}
private val DATE_FORMAT = DateTimeFormat.forPattern("dd.MM.yyyy")
fun Date.humanTime(resources: Resources): String {
val localMillis = DateTimeZone.getDefault().convertUTCToLocal(this.time)
val timeDelta = (System.currentTimeMillis() - localMillis) / 1000L
val timeStr =
if (timeDelta < 60) {
resources.getString(R.string.time_sec, timeDelta)
} else if (timeDelta < 60 * 60) {
resources.getString(R.string.time_min, timeDelta / 60)
} else if (timeDelta < 60 * 60 * 24) {
resources.getString(R.string.time_hour, timeDelta / (60 * 60))
} else if (timeDelta < 60 * 60 * 24 * 7) {
resources.getString(R.string.time_day, timeDelta / (60 * 60 * 24))
} else {
return DATE_FORMAT.print(localMillis)
}
return resources.getString(R.string.time_ago, timeStr)
}
fun EventAction.getHumanName(resources: Resources) = when (this) {
EventAction.UPDATED -> resources.getString(R.string.event_action_updated)
EventAction.REOPENED -> resources.getString(R.string.event_action_reopened)
EventAction.PUSHED_TO -> resources.getString(R.string.event_action_pushed_to)
EventAction.PUSHED_NEW -> resources.getString(R.string.event_action_pushed_new)
EventAction.PUSHED -> resources.getString(R.string.event_action_pushed)
EventAction.LEFT -> resources.getString(R.string.event_action_left)
EventAction.OPENED -> resources.getString(R.string.event_action_opened)
EventAction.DESTROYED -> resources.getString(R.string.event_action_destroyed)
EventAction.DELETED -> resources.getString(R.string.event_action_deleted)
EventAction.EXPIRED -> resources.getString(R.string.event_action_expired)
EventAction.MERGED -> resources.getString(R.string.event_action_merged)
EventAction.CLOSED -> resources.getString(R.string.event_action_closed)
EventAction.ACCEPTED -> resources.getString(R.string.event_action_accepted)
EventAction.COMMENTED -> resources.getString(R.string.event_action_commented)
EventAction.COMMENTED_ON -> resources.getString(R.string.event_action_commented_on)
EventAction.JOINED -> resources.getString(R.string.event_action_joined)
EventAction.CREATED -> resources.getString(R.string.event_action_created)
}
@DrawableRes
fun TargetHeaderIcon.getIcon() = when (this) {
TargetHeaderIcon.CREATED -> R.drawable.ic_event_created_24dp
TargetHeaderIcon.JOINED -> R.drawable.ic_event_joined_24dp
TargetHeaderIcon.COMMENTED -> R.drawable.ic_event_commented_24dp
TargetHeaderIcon.MERGED -> R.drawable.ic_event_merged_24dp
TargetHeaderIcon.CLOSED -> R.drawable.ic_event_closed_24dp
TargetHeaderIcon.DESTROYED -> R.drawable.ic_event_destroyed_24dp
TargetHeaderIcon.EXPIRED -> R.drawable.ic_event_expired_24dp
TargetHeaderIcon.LEFT -> R.drawable.ic_event_left_24dp
TargetHeaderIcon.REOPENED -> R.drawable.ic_event_reopened_24dp
TargetHeaderIcon.PUSHED -> R.drawable.ic_event_pushed_24dp
TargetHeaderIcon.UPDATED -> R.drawable.ic_event_updated_24dp
TargetHeaderIcon.NONE -> R.drawable.ic_event_created_24dp
}
fun TodoAction.getHumanName(resources: Resources): String = when (this) {
TodoAction.APPROVAL_REQUIRED -> resources.getString(R.string.todo_action_approval_required)
TodoAction.ASSIGNED -> resources.getString(R.string.todo_action_assigned)
TodoAction.BUILD_FAILED -> resources.getString(R.string.todo_action_build_failed)
TodoAction.DIRECTLY_ADDRESSED -> resources.getString(R.string.todo_action_directly_addressed)
TodoAction.MARKED -> resources.getString(R.string.todo_action_marked)
TodoAction.MENTIONED -> resources.getString(R.string.todo_action_mentioned)
}
fun TargetHeaderTitle.getHumanName(resources: Resources) = when (this) {
is TargetHeaderTitle.Event -> {
"$userName ${action.getHumanName(resources)} $targetName ${resources.getString(R.string.at)} $projectName"
}
is TargetHeaderTitle.Todo -> {
val actionName = action.getHumanName(resources)
val author = if (isAuthorCurrentUser) {
resources.getString(R.string.you).capitalize()
} else {
authorUserName
}
val assignee = if (isAssigneeCurrentUser) {
if (isAuthorCurrentUser) {
resources.getString(R.string.yourself)
} else {
resources.getString(R.string.you)
}
} else {
assigneeUserName
}
when (action) {
TodoAction.ASSIGNED -> {
"$author $actionName $targetName ${resources.getString(R.string.at)} $projectName ${resources.getString(R.string.to)} $assignee"
}
TodoAction.DIRECTLY_ADDRESSED,
TodoAction.MENTIONED -> {
"$author $actionName $assignee ${resources.getString(R.string.on)} $targetName ${resources.getString(R.string.at)} $projectName"
}
TodoAction.MARKED -> {
"$author $actionName ${resources.getString(R.string.for_str)} $targetName ${resources.getString(R.string.at)} $projectName"
}
else -> {
Timber.e("Unsupported template for todo action=$actionName.")
"$author $actionName $targetName $assignee ${resources.getString(R.string.at)}"
}
}
}
}
fun LicenseType.getHumanName(resources: Resources) = when (this) {
LicenseType.MIT -> resources.getString(R.string.library_license_MIT)
LicenseType.APACHE_2 -> resources.getString(R.string.library_license_APACHE_2)
LicenseType.CUSTOM -> resources.getString(R.string.library_license_CUSTOM)
LicenseType.NONE -> resources.getString(R.string.library_license_NONE)
}
fun TargetBadgeStatus.getHumanName(resources: Resources) = when (this) {
TargetBadgeStatus.OPENED -> resources.getString(R.string.target_status_opened)
TargetBadgeStatus.CLOSED -> resources.getString(R.string.target_status_closed)
TargetBadgeStatus.MERGED -> resources.getString(R.string.target_status_merged)
}
fun TargetBadgeStatus.getBadgeColors(context: Context) = when (this) {
TargetBadgeStatus.OPENED -> Pair(context.color(R.color.green), context.color(R.color.lightGreen))
TargetBadgeStatus.CLOSED -> Pair(context.color(R.color.red), context.color(R.color.lightRed))
TargetBadgeStatus.MERGED -> Pair(context.color(R.color.blue), context.color(R.color.lightBlue))
}
\ No newline at end of file
......@@ -102,7 +102,7 @@ class IssueRepository @Inject constructor(
projectId: Long,
issueId: Long,
orderBy: OrderBy? = null,
sort: Sort? = null
sort: Sort? = Sort.ASC
) = api
.getIssueNotes(projectId, issueId, orderBy, sort)
.subscribeOn(schedulers.io())
......
......@@ -109,7 +109,7 @@ class MergeRequestRepository @Inject constructor(
projectId: Long,
mergeRequestId: Long,
orderBy: OrderBy? = null,
sort: Sort? = null
sort: Sort? = Sort.ASC
) = api
.getMergeRequestNotes(projectId, mergeRequestId, orderBy, sort)
.subscribeOn(schedulers.io())
......
package ru.terrakok.gitlabclient.presentation.global
import ru.terrakok.gitlabclient.entity.Note
data class NoteWithFormattedBody(val note: Note, val body: CharSequence)
\ No newline at end of file
package ru.terrakok.gitlabclient.presentation.issue
package ru.terrakok.gitlabclient.presentation.issue.info
import com.arellomobile.mvp.InjectViewState
import io.reactivex.Single
import io.reactivex.functions.BiFunction
import ru.terrakok.cicerone.Router
import ru.terrakok.gitlabclient.entity.Project
import ru.terrakok.gitlabclient.entity.issue.Issue
import ru.terrakok.gitlabclient.model.interactor.issue.IssueInteractor
......@@ -25,7 +24,6 @@ private typealias IssueLinker = BiFunction<Pair<Issue, CharSequence>, Project, I
class IssueInfoPresenter @Inject constructor(
@ProjectId private val projectIdWrapper: PrimitiveWrapper<Long>,
@IssueId private val issueIdWrapper: PrimitiveWrapper<Long>,
private val router: Router,
private val issueInteractor: IssueInteractor,
private val projectInteractor: ProjectInteractor,
private val mdConverter: MarkDownConverter,
......@@ -58,6 +56,4 @@ class IssueInfoPresenter @Inject constructor(
)
.connect()
}
fun onBackPressed() = router.exit()
}
\ No newline at end of file
package ru.terrakok.gitlabclient.presentation.issue
package ru.terrakok.gitlabclient.presentation.issue.info
import com.arellomobile.mvp.MvpView
import com.arellomobile.mvp.viewstate.strategy.AddToEndSingleStrategy
......
package ru.terrakok.gitlabclient.presentation.issue.notes
import com.arellomobile.mvp.InjectViewState
import ru.terrakok.gitlabclient.model.interactor.issue.IssueInteractor
import ru.terrakok.gitlabclient.presentation.global.BasePresenter
import ru.terrakok.gitlabclient.presentation.global.ErrorHandler
import ru.terrakok.gitlabclient.presentation.global.MarkDownConverter
import ru.terrakok.gitlabclient.presentation.global.NoteWithFormattedBody
import ru.terrakok.gitlabclient.toothpick.PrimitiveWrapper
import ru.terrakok.gitlabclient.toothpick.qualifier.IssueId
import ru.terrakok.gitlabclient.toothpick.qualifier.ProjectId
import javax.inject.Inject
/**
* Created by Konstantin Tskhovrebov (aka @terrakok) on 12.02.18.
*/
@InjectViewState
class IssueNotesPresenter @Inject constructor(
@ProjectId projectIdWrapper: PrimitiveWrapper<Long>,
@IssueId issueIdWrapper: PrimitiveWrapper<Long>,
private val issueInteractor: IssueInteractor,
private val mdConverter: MarkDownConverter,
private val errorHandler: ErrorHandler
) : BasePresenter<IssueNotesView>() {
private val projectId = projectIdWrapper.value
private val issueId = issueIdWrapper.value
override fun onFirstViewAttach() {
super.onFirstViewAttach()
requestNotes()
}
private fun requestNotes() {
issueInteractor.getIssueNotes(projectId, issueId)
.toObservable()
.flatMapIterable { it }
.flatMap { note ->
mdConverter.markdownToSpannable(note.body)
.map { NoteWithFormattedBody(note, it) }
.toObservable()
}
.toList()
.doOnSubscribe { viewState.showProgress(true) }
.doAfterTerminate { viewState.showProgress(false) }
.subscribe(
{ viewState.showNotes(it) },
{ errorHandler.proceed(it, { viewState.showMessage(it) }) }
)
.connect()
}
fun refresh() = requestNotes()
}
\ No newline at end of file
package ru.terrakok.gitlabclient.presentation.issue.notes
import com.arellomobile.mvp.MvpView
import com.arellomobile.mvp.viewstate.strategy.AddToEndSingleStrategy
import com.arellomobile.mvp.viewstate.strategy.OneExecutionStateStrategy
import com.arellomobile.mvp.viewstate.strategy.StateStrategyType
import ru.terrakok.gitlabclient.presentation.global.NoteWithFormattedBody
/**
* Created by Konstantin Tskhovrebov (aka @terrakok) on 12.02.18.
*/
@StateStrategyType(AddToEndSingleStrategy::class)
interface IssueNotesView : MvpView {
fun showNotes(notes: List<NoteWithFormattedBody>)
fun showProgress(show: Boolean)
@StateStrategyType(OneExecutionStateStrategy::class)
fun showMessage(message: String)
}
\ No newline at end of file
package ru.terrakok.gitlabclient.presentation.mergerequest
package ru.terrakok.gitlabclient.presentation.mergerequest.info
import com.arellomobile.mvp.InjectViewState
import io.reactivex.Single
import io.reactivex.functions.BiFunction
import ru.terrakok.cicerone.Router
import ru.terrakok.gitlabclient.entity.Project
import ru.terrakok.gitlabclient.entity.mergerequest.MergeRequest
import ru.terrakok.gitlabclient.model.interactor.mergerequest.MergeRequestInteractor
......@@ -23,9 +22,8 @@ private typealias MergeRequestLinker = BiFunction<Pair<MergeRequest, CharSequenc
*/
@InjectViewState
class MergeRequestInfoPresenter @Inject constructor(
@ProjectId private val projectIdWrapper: PrimitiveWrapper<Long>,
@MergeRequestId private val mrIdWrapper: PrimitiveWrapper<Long>,
private val router: Router,
@ProjectId projectIdWrapper: PrimitiveWrapper<Long>,
@MergeRequestId mrIdWrapper: PrimitiveWrapper<Long>,
private val mrInteractor: MergeRequestInteractor,
private val projectInteractor: ProjectInteractor,
private val mdConverter: MarkDownConverter,
......@@ -53,11 +51,9 @@ class MergeRequestInfoPresenter @Inject constructor(
.doOnSubscribe { viewState.showProgress(true) }
.doAfterTerminate { viewState.showProgress(false) }
.subscribe(
{ viewState.showMergeRequest(it) },
{ viewState.showInfo(it) },
{ errorHandler.proceed(it, { viewState.showMessage(it) }) }
)
.connect()
}
fun onBackPressed() = router.exit()
}
\ No newline at end of file
package ru.terrakok.gitlabclient.presentation.mergerequest
package ru.terrakok.gitlabclient.presentation.mergerequest.info
import com.arellomobile.mvp.MvpView
import com.arellomobile.mvp.viewstate.strategy.AddToEndSingleStrategy
......@@ -14,7 +14,7 @@ import ru.terrakok.gitlabclient.entity.mergerequest.MergeRequest
interface MergeRequestInfoView : MvpView {
data class MergeRequestInfo(val mr: MergeRequest, val project: Project, val mdDescription: CharSequence)
fun showMergeRequest(mrInfo: MergeRequestInfo)
fun showInfo(mrInfo: MergeRequestInfo)
fun showProgress(show: Boolean)
@StateStrategyType(OneExecutionStateStrategy::class)
......
package ru.terrakok.gitlabclient.presentation.mergerequest.notes
import com.arellomobile.mvp.InjectViewState
import ru.terrakok.gitlabclient.model.interactor.mergerequest.MergeRequestInteractor
import ru.terrakok.gitlabclient.presentation.global.BasePresenter
import ru.terrakok.gitlabclient.presentation.global.ErrorHandler
import ru.terrakok.gitlabclient.presentation.global.MarkDownConverter
import ru.terrakok.gitlabclient.presentation.global.NoteWithFormattedBody
import ru.terrakok.gitlabclient.toothpick.PrimitiveWrapper
import ru.terrakok.gitlabclient.toothpick.qualifier.MergeRequestId
import ru.terrakok.gitlabclient.toothpick.qualifier.ProjectId
import javax.inject.Inject
/**
* Created by Konstantin Tskhovrebov (aka @terrakok) on 12.02.18.
*/
@InjectViewState
class MergeRequestNotesPresenter @Inject constructor(
@ProjectId projectIdWrapper: PrimitiveWrapper<Long>,
@MergeRequestId mrIdWrapper: PrimitiveWrapper<Long>,
private val mrInteractor: MergeRequestInteractor,
private val mdConverter: MarkDownConverter,
private val errorHandler: ErrorHandler
) : BasePresenter<MergeRequestNotesView>() {
private val projectId = projectIdWrapper.value
private val mrId = mrIdWrapper.value
override fun onFirstViewAttach() {