Commit 6e14d0ea authored by Konstantin Tskhovrebov's avatar Konstantin Tskhovrebov 🤖

added simple notes list for issue

parent 5088782d
......@@ -32,7 +32,7 @@ object Screens {
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)
......
......@@ -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())
......
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
......@@ -40,7 +40,7 @@ class IssueActivity : BaseActivity() {
}
if (savedInstanceState == null) {
navigator.setLaunchScreen(Screens.ISSUE_INFO_SCREEN, null)
navigator.setLaunchScreen(Screens.ISSUE_SCREEN, null)
}
}
......@@ -53,7 +53,7 @@ class IssueActivity : BaseActivity() {
override val navigator = object : FlowNavigator(this, R.id.container) {
override fun createFragment(screenKey: String?, data: Any?) = when(screenKey) {
Screens.ISSUE_INFO_SCREEN -> IssueInfoFragment()
Screens.ISSUE_SCREEN -> IssueFragment()
else -> null
}
}
......
package ru.terrakok.gitlabclient.ui.issue
import android.os.Bundle
import android.support.v4.app.FragmentPagerAdapter
import kotlinx.android.synthetic.main.fragment_mr.*
import ru.terrakok.cicerone.Router
import ru.terrakok.gitlabclient.R
import ru.terrakok.gitlabclient.toothpick.DI
import ru.terrakok.gitlabclient.ui.global.BaseFragment
import toothpick.Toothpick
import javax.inject.Inject
/**
* Created by Konstantin Tskhovrebov (aka @terrakok) on 14.02.18.
*/
class IssueFragment : BaseFragment(), IssueInfoFragment.ToolbarConfigurator {
override val layoutRes = R.layout.fragment_issue
@Inject
lateinit var router: Router
private val adapter by lazy { IssuePagesAdapter() }
override fun onCreate(savedInstanceState: Bundle?) {
Toothpick.inject(this, Toothpick.openScope(DI.ISSUE_SCOPE))
super.onCreate(savedInstanceState)
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
toolbar.setNavigationOnClickListener { onBackPressed() }
viewPager.adapter = adapter
}
override fun onBackPressed() {
super.onBackPressed()
router.exit()
}
override fun setTitle(title: String, subTitle: String) {
toolbar.title = title
toolbar.subtitle = subTitle
}
private inner class IssuePagesAdapter : FragmentPagerAdapter(childFragmentManager) {
override fun getItem(position: Int): BaseFragment? = when (position) {
0 -> IssueInfoFragment()
1 -> IssueNotesFragment()
else -> null
}
override fun getCount() = 2
override fun getPageTitle(position: Int) = when (position) {
0 -> getString(R.string.merge_request_info_tab)
1 -> getString(R.string.merge_request_discussion_tab)
else -> null
}
}
}
\ No newline at end of file
package ru.terrakok.gitlabclient.ui.issue
import android.os.Bundle
import com.arellomobile.mvp.presenter.InjectPresenter
import com.arellomobile.mvp.presenter.ProvidePresenter
import kotlinx.android.synthetic.main.fragment_issue_info.*
......@@ -10,8 +9,8 @@ import ru.terrakok.gitlabclient.entity.issue.IssueState
import ru.terrakok.gitlabclient.extension.color
import ru.terrakok.gitlabclient.extension.humanTime
import ru.terrakok.gitlabclient.extension.loadRoundedImage
import ru.terrakok.gitlabclient.presentation.issue.IssueInfoPresenter
import ru.terrakok.gitlabclient.presentation.issue.IssueInfoView
import ru.terrakok.gitlabclient.presentation.issue.info.IssueInfoPresenter
import ru.terrakok.gitlabclient.presentation.issue.info.IssueInfoView
import ru.terrakok.gitlabclient.toothpick.DI
import ru.terrakok.gitlabclient.ui.global.BaseFragment
import toothpick.Toothpick
......@@ -30,17 +29,12 @@ class IssueInfoFragment : BaseFragment(), IssueInfoView {
Toothpick.openScope(DI.ISSUE_SCOPE)
.getInstance(IssueInfoPresenter::class.java)
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
toolbar.setNavigationOnClickListener { presenter.onBackPressed() }
}
override fun showIssue(issueInfo: IssueInfoView.IssueInfo) {
val issue = issueInfo.issue
val project = issueInfo.project
toolbar.title = "#${issue.iid}"
toolbar.subtitle = project.name
(parentFragment as? ToolbarConfigurator)
?.setTitle("#${issue.iid}", issueInfo.project.name)
titleTextView.text = issue.title
stateImageView.setImageResource(R.drawable.circle)
// TODO: issue info (Display action user name for the CLOSED states).
......@@ -72,7 +66,7 @@ class IssueInfoFragment : BaseFragment(), IssueInfoView {
showSnackMessage(message)
}
override fun onBackPressed() {
presenter.onBackPressed()
interface ToolbarConfigurator {
fun setTitle(title: String, subTitle: String)
}
}
\ No newline at end of file
package ru.terrakok.gitlabclient.ui.issue
import android.os.Bundle
import android.support.v7.widget.LinearLayoutManager
import com.arellomobile.mvp.presenter.InjectPresenter
import com.arellomobile.mvp.presenter.ProvidePresenter
import com.hannesdorfmann.adapterdelegates3.ListDelegationAdapter
import kotlinx.android.synthetic.main.layout_base_list.*
import ru.terrakok.gitlabclient.R
import ru.terrakok.gitlabclient.presentation.global.NoteWithFormattedBody
import ru.terrakok.gitlabclient.presentation.issue.notes.IssueNotesPresenter
import ru.terrakok.gitlabclient.presentation.issue.notes.IssueNotesView
import ru.terrakok.gitlabclient.toothpick.DI
import ru.terrakok.gitlabclient.ui.global.BaseFragment
import ru.terrakok.gitlabclient.ui.global.list.SimpleDividerDecorator
import ru.terrakok.gitlabclient.ui.global.list.SystemNoteAdapterDelegate
import ru.terrakok.gitlabclient.ui.global.list.UserNoteAdapterDelegate
import toothpick.Toothpick
/**
* Created by Konstantin Tskhovrebov (aka @terrakok) on 15.02.18.
*/
class IssueNotesFragment : BaseFragment(), IssueNotesView {
override val layoutRes = R.layout.fragment_issue_notes
private val adapter by lazy { NotesAdapter() }
@InjectPresenter
lateinit var presenter: IssueNotesPresenter
@ProvidePresenter
fun providePresenter() =
Toothpick.openScope(DI.ISSUE_SCOPE)
.getInstance(IssueNotesPresenter::class.java)
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
with(recyclerView) {
setHasFixedSize(true)
layoutManager = LinearLayoutManager(context)
addItemDecoration(SimpleDividerDecorator(context))
adapter = this@IssueNotesFragment.adapter
}
swipeToRefresh.setOnRefreshListener { presenter.refresh() }
}
override fun showNotes(notes: List<NoteWithFormattedBody>) {
adapter.setData(notes)
}
override fun showProgress(show: Boolean) {
swipeToRefresh.isRefreshing = show
}
override fun showMessage(message: String) {
showSnackMessage(message)
}
private inner class NotesAdapter : ListDelegationAdapter<MutableList<Any>>() {
init {
items = mutableListOf()
delegatesManager.addDelegate(UserNoteAdapterDelegate({}))
delegatesManager.addDelegate(SystemNoteAdapterDelegate({}))
}
fun setData(data: List<NoteWithFormattedBody>) {
items.clear()
items.addAll(data)
notifyDataSetChanged()
}
}
}
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
style="@style/ToolbarStyle"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:elevation="0dp"
app:navigationIcon="@drawable/ic_arrow_back_24dp"
tools:subtitle="GitFox"
tools:title="#56"/>
<android.support.v4.view.ViewPager
android:id="@+id/viewPager"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.TabLayout
style="@style/ToolbarStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</android.support.v4.view.ViewPager>
</LinearLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
style="@style/ToolbarStyle"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:navigationIcon="@drawable/ic_arrow_back_24dp"
tools:subtitle="GitFox"
tools:title="#56"/>
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true">
android:layout_height="match_parent">
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
......@@ -93,6 +78,4 @@
</android.support.constraint.ConstraintLayout>
</ScrollView>
</LinearLayout>
\ No newline at end of file
</ScrollView>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<include layout="@layout/layout_base_list"/>
</FrameLayout>
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