mirror of
https://github.com/k0shk0sh/FastHub.git
synced 2025-12-08 19:05:54 +00:00
display dashboard in PR and reviews & their comment
This commit is contained in:
parent
f4561d84b4
commit
73cb05f218
@ -11,6 +11,7 @@ import com.fastaccess.github.ui.adapter.base.BaseViewHolder
|
||||
import com.fastaccess.github.ui.adapter.viewholder.CommentViewHolder
|
||||
import com.fastaccess.github.ui.adapter.viewholder.IssueContentViewHolder
|
||||
import com.fastaccess.github.ui.adapter.viewholder.LoadingViewHolder
|
||||
import com.fastaccess.github.ui.adapter.viewholder.ReviewViewHolder
|
||||
import io.noties.markwon.Markwon
|
||||
|
||||
/**
|
||||
@ -34,6 +35,7 @@ class IssueTimelineAdapter(
|
||||
return getItem(position)?.let {
|
||||
when {
|
||||
it.comment != null -> COMMENT
|
||||
it.review?.comment != null -> REVIEW_THREAD
|
||||
else -> CONTENT
|
||||
}
|
||||
} ?: super.getItemViewType(position)
|
||||
@ -51,6 +53,13 @@ class IssueTimelineAdapter(
|
||||
getItemByPosition(position)?.comment?.let { commentClickListener.invoke(position, it) }
|
||||
}
|
||||
}
|
||||
REVIEW_THREAD -> ReviewViewHolder(parent, markwon, theme, notifyCallback, deleteCommentListener, editCommentListener).apply {
|
||||
itemView.setOnClickListener {
|
||||
val position = adapterPosition
|
||||
if (position == RecyclerView.NO_POSITION) return@setOnClickListener
|
||||
getItemByPosition(position)?.comment?.let { commentClickListener.invoke(position, it) }
|
||||
}
|
||||
}
|
||||
CONTENT -> IssueContentViewHolder(parent)
|
||||
else -> LoadingViewHolder<Any>(parent).apply { itemView.isVisible = false }
|
||||
}
|
||||
@ -62,6 +71,7 @@ class IssueTimelineAdapter(
|
||||
) {
|
||||
when (holder) {
|
||||
is CommentViewHolder -> holder.bind(getItem(position).comment)
|
||||
is ReviewViewHolder -> holder.bind(getItem(position).review)
|
||||
is IssueContentViewHolder -> holder.bind(getItem(position))
|
||||
}
|
||||
}
|
||||
@ -79,6 +89,7 @@ class IssueTimelineAdapter(
|
||||
private const val HEADER = 1
|
||||
private const val COMMENT = 2
|
||||
private const val CONTENT = 3
|
||||
private const val REVIEW_THREAD = 4
|
||||
|
||||
private val DIFF_CALLBACK = object : DiffUtil.ItemCallback<TimelineModel?>() {
|
||||
override fun areItemsTheSame(
|
||||
|
||||
@ -0,0 +1,111 @@
|
||||
package com.fastaccess.github.ui.adapter.viewholder
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.view.LayoutInflater
|
||||
import android.view.MotionEvent
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.view.isVisible
|
||||
import com.fastaccess.data.model.CommentAuthorAssociation
|
||||
import com.fastaccess.data.model.CommentModel
|
||||
import com.fastaccess.data.model.ReviewModel
|
||||
import com.fastaccess.github.R
|
||||
import com.fastaccess.github.extensions.getColorAttr
|
||||
import com.fastaccess.github.extensions.isTrue
|
||||
import com.fastaccess.github.extensions.showYesNoDialog
|
||||
import com.fastaccess.github.extensions.timeAgo
|
||||
import com.fastaccess.github.ui.adapter.base.BaseViewHolder
|
||||
import com.fastaccess.github.utils.extensions.popMenu
|
||||
import com.fastaccess.markdown.spans.DiffLineSpan
|
||||
import io.noties.markwon.Markwon
|
||||
import io.noties.markwon.utils.NoCopySpannableFactory
|
||||
import kotlinx.android.synthetic.main.comment_small_row_item.view.*
|
||||
import kotlinx.android.synthetic.main.commit_with_comment_row_item.view.*
|
||||
|
||||
|
||||
/**
|
||||
* Created by Kosh on 12.10.18.
|
||||
*/
|
||||
|
||||
class CommitThreadViewHolder(
|
||||
parent: ViewGroup,
|
||||
private val markwon: Markwon,
|
||||
private val theme: Int,
|
||||
private val callback: (position: Int) -> Unit,
|
||||
private val deleteCommentListener: (position: Int, comment: CommentModel) -> Unit,
|
||||
private val editCommentListener: (position: Int, comment: CommentModel) -> Unit
|
||||
) : BaseViewHolder<ReviewModel?>(
|
||||
LayoutInflater.from(parent.context)
|
||||
.inflate(R.layout.commit_with_comment_row_item, parent, false)
|
||||
) {
|
||||
|
||||
@SuppressLint("SetTextI18n", "DefaultLocale")
|
||||
override fun bind(item: ReviewModel?) {
|
||||
val review = item ?: run {
|
||||
itemView.isVisible = false
|
||||
return
|
||||
}
|
||||
itemView.apply {
|
||||
itemView.commentLayout.isVisible = review.comment != null
|
||||
review.comment?.let { model ->
|
||||
fileName.text = model.path
|
||||
if (model.diffHunk.isNullOrEmpty()) {
|
||||
diffHunk.text = DiffLineSpan.getSpannable(
|
||||
model.diffHunk,
|
||||
context.getColorAttr(R.attr.patch_addition), context.getColorAttr(R.attr.patch_deletion),
|
||||
context.getColorAttr(R.attr.patch_ref),
|
||||
truncate = true
|
||||
)
|
||||
diffHunk.isVisible = true
|
||||
} else {
|
||||
diffHunk.isVisible = false
|
||||
}
|
||||
userIcon.loadAvatar(model.author?.avatarUrl, model.author?.url ?: "")
|
||||
author.text = model.author?.login ?: ""
|
||||
association.text = if (CommentAuthorAssociation.NONE == model.authorAssociation) {
|
||||
model.updatedAt?.timeAgo()
|
||||
} else {
|
||||
com.fastaccess.markdown.widget.SpannableBuilder.builder()
|
||||
.bold(model.authorAssociation?.value?.toLowerCase()?.replace("_", "") ?: "")
|
||||
.space()
|
||||
.append(model.updatedAt?.timeAgo())
|
||||
}
|
||||
|
||||
description.post {
|
||||
description.setSpannableFactory(NoCopySpannableFactory.getInstance())
|
||||
val bodyMd = model.body
|
||||
markwon.setMarkdown(description, if (!bodyMd.isNullOrEmpty()) bodyMd else resources.getString(R.string.no_description_provided))
|
||||
}
|
||||
|
||||
description.setOnTouchListener { v, event ->
|
||||
if (event.action == MotionEvent.ACTION_UP && !description.hasSelection()) {
|
||||
itemView.callOnClick()
|
||||
}
|
||||
return@setOnTouchListener false
|
||||
}
|
||||
|
||||
val canAlter = model.viewerCanUpdate == true || model.viewerCanDelete == true
|
||||
menu.isVisible = canAlter
|
||||
if (canAlter) {
|
||||
menu.popMenu(R.menu.comment_menu, { menu ->
|
||||
menu.findItem(R.id.edit)?.isVisible = model.viewerCanUpdate == true
|
||||
menu.findItem(R.id.delete)?.isVisible = model.viewerCanDelete == true
|
||||
}) { itemId ->
|
||||
if (itemId == R.id.delete) {
|
||||
context.showYesNoDialog(R.string.delete) {
|
||||
it.isTrue {
|
||||
deleteCommentListener.invoke(adapterPosition, model)
|
||||
}
|
||||
}
|
||||
} else if (itemId == R.id.edit) {
|
||||
editCommentListener.invoke(adapterPosition, model)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
adaptiveEmoticon.init(requireNotNull(model.id), model.reactionGroups) {
|
||||
callback.invoke(adapterPosition)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -5,6 +5,7 @@ import android.graphics.Color
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.view.isVisible
|
||||
import com.fastaccess.data.model.*
|
||||
import com.fastaccess.github.R
|
||||
import com.fastaccess.github.extensions.route
|
||||
@ -12,6 +13,7 @@ import com.fastaccess.github.extensions.timeAgo
|
||||
import com.fastaccess.github.ui.adapter.base.BaseViewHolder
|
||||
import com.fastaccess.markdown.spans.LabelSpan
|
||||
import com.fastaccess.markdown.widget.SpannableBuilder
|
||||
import github.type.PullRequestReviewState
|
||||
import github.type.PullRequestState
|
||||
import github.type.StatusState
|
||||
import kotlinx.android.synthetic.main.issue_content_row_item.view.*
|
||||
@ -48,18 +50,57 @@ class IssueContentViewHolder(parent: ViewGroup) : BaseViewHolder<TimelineModel>(
|
||||
item.reviewDismissed?.let(this::presenetReviewDismissed)
|
||||
item.reviewRequestRemoved?.let(this::presenetReviewRequestRemoved)
|
||||
item.pullRequestCommit?.let(this::presentPrCommit)
|
||||
item.review?.let(this::presentReview)
|
||||
}
|
||||
|
||||
@SuppressLint("DefaultLocale")
|
||||
private fun presentReview(model: ReviewModel) {
|
||||
itemView.apply {
|
||||
val icon = when (model.state) {
|
||||
PullRequestReviewState.APPROVED.rawValue() -> R.drawable.ic_done
|
||||
PullRequestReviewState.CHANGES_REQUESTED.rawValue() -> R.drawable.ic_clear
|
||||
PullRequestReviewState.COMMENTED.rawValue() -> R.drawable.ic_comment
|
||||
else -> 0
|
||||
}
|
||||
if (icon != 0) {
|
||||
stateIcon.setImageResource(icon)
|
||||
stateIcon.isVisible = true
|
||||
} else {
|
||||
stateIcon.isVisible = false
|
||||
}
|
||||
userIcon.loadAvatar(model.author?.avatarUrl, model.author?.url)
|
||||
text.text = SpannableBuilder.builder()
|
||||
.bold(model.author?.login)
|
||||
.space()
|
||||
.apply {
|
||||
append(model.state?.replace("_", " ")?.toLowerCase() ?: "")
|
||||
val body = model.body
|
||||
if (!body.isNullOrEmpty()) {
|
||||
newline()
|
||||
append(body)
|
||||
space()
|
||||
} else {
|
||||
space()
|
||||
}
|
||||
}
|
||||
.append(model.createdAt?.timeAgo())
|
||||
}
|
||||
}
|
||||
|
||||
private fun presentPrCommit(model: PullRequestCommitModel) {
|
||||
itemView.apply {
|
||||
stateIcon.setImageResource(
|
||||
when (model.commit?.state) {
|
||||
StatusState.ERROR.rawValue(), StatusState.FAILURE.rawValue() -> R.drawable.ic_state_error
|
||||
StatusState.SUCCESS.rawValue() -> R.drawable.ic_state_success
|
||||
StatusState.PENDING.rawValue() -> R.drawable.ic_state_pending
|
||||
else -> 0
|
||||
}
|
||||
)
|
||||
val icon = when (model.commit?.state) {
|
||||
StatusState.ERROR.rawValue(), StatusState.FAILURE.rawValue() -> R.drawable.ic_state_error
|
||||
StatusState.SUCCESS.rawValue() -> R.drawable.ic_state_success
|
||||
StatusState.PENDING.rawValue() -> R.drawable.ic_state_pending
|
||||
else -> 0
|
||||
}
|
||||
if (icon == 0) {
|
||||
stateIcon.isVisible = false
|
||||
} else {
|
||||
stateIcon.setImageResource(icon)
|
||||
stateIcon.isVisible = true
|
||||
}
|
||||
userIcon.loadAvatar(model.commit?.author?.avatarUrl, model.commit?.author?.url)
|
||||
text.text = SpannableBuilder.builder()
|
||||
.bold(model.commit?.author?.login)
|
||||
@ -70,6 +111,7 @@ class IssueContentViewHolder(parent: ViewGroup) : BaseViewHolder<TimelineModel>(
|
||||
model.commit?.commitUrl?.let { view.context.route(it) }
|
||||
})
|
||||
.space()
|
||||
.append("${model.commit?.message} " ?: "")
|
||||
.append(model.commit?.authoredDate?.timeAgo())
|
||||
}
|
||||
}
|
||||
@ -95,7 +137,7 @@ class IssueContentViewHolder(parent: ViewGroup) : BaseViewHolder<TimelineModel>(
|
||||
text.text = SpannableBuilder.builder()
|
||||
.bold(model.actor?.login)
|
||||
.space()
|
||||
.append("dismissed their review (${model.previousReviewState?.toLowerCase()})")
|
||||
.append("dismissed ${model.previousReviewState?.replace("_", " ")?.toLowerCase()} review")
|
||||
.newline()
|
||||
.append(model.dismissalMessage ?: "")
|
||||
.space()
|
||||
|
||||
@ -0,0 +1,112 @@
|
||||
package com.fastaccess.github.ui.adapter.viewholder
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.view.LayoutInflater
|
||||
import android.view.MotionEvent
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.view.isVisible
|
||||
import com.fastaccess.data.model.CommentAuthorAssociation
|
||||
import com.fastaccess.data.model.CommentModel
|
||||
import com.fastaccess.data.model.ReviewModel
|
||||
import com.fastaccess.github.R
|
||||
import com.fastaccess.github.extensions.getColorAttr
|
||||
import com.fastaccess.github.extensions.isTrue
|
||||
import com.fastaccess.github.extensions.showYesNoDialog
|
||||
import com.fastaccess.github.extensions.timeAgo
|
||||
import com.fastaccess.github.ui.adapter.base.BaseViewHolder
|
||||
import com.fastaccess.github.utils.extensions.popMenu
|
||||
import com.fastaccess.markdown.spans.DiffLineSpan
|
||||
import com.fastaccess.markdown.widget.SpannableBuilder
|
||||
import io.noties.markwon.Markwon
|
||||
import io.noties.markwon.utils.NoCopySpannableFactory
|
||||
import kotlinx.android.synthetic.main.comment_small_row_item.view.*
|
||||
import kotlinx.android.synthetic.main.review_with_comment_row_item.view.*
|
||||
|
||||
|
||||
/**
|
||||
* Created by Kosh on 12.10.18.
|
||||
*/
|
||||
|
||||
class ReviewViewHolder(
|
||||
parent: ViewGroup,
|
||||
private val markwon: Markwon,
|
||||
private val theme: Int,
|
||||
private val callback: (position: Int) -> Unit,
|
||||
private val deleteCommentListener: (position: Int, comment: CommentModel) -> Unit,
|
||||
private val editCommentListener: (position: Int, comment: CommentModel) -> Unit
|
||||
) : BaseViewHolder<ReviewModel?>(
|
||||
LayoutInflater.from(parent.context)
|
||||
.inflate(R.layout.review_with_comment_row_item, parent, false)
|
||||
) {
|
||||
|
||||
@SuppressLint("SetTextI18n", "DefaultLocale")
|
||||
override fun bind(item: ReviewModel?) {
|
||||
val review = item ?: run {
|
||||
itemView.isVisible = false
|
||||
return
|
||||
}
|
||||
itemView.apply {
|
||||
itemView.commentLayout.isVisible = review.comment != null
|
||||
review.comment?.let { model ->
|
||||
fileName.text = model.path
|
||||
if (!model.diffHunk.isNullOrEmpty()) {
|
||||
diffHunk.text = DiffLineSpan.getSpannable(
|
||||
model.diffHunk,
|
||||
context.getColorAttr(R.attr.patch_addition), context.getColorAttr(R.attr.patch_deletion),
|
||||
context.getColorAttr(R.attr.patch_ref),
|
||||
truncate = true
|
||||
)
|
||||
diffHunk.isVisible = true
|
||||
} else {
|
||||
diffHunk.isVisible = false
|
||||
}
|
||||
userIcon.loadAvatar(model.author?.avatarUrl, model.author?.url ?: "")
|
||||
author.text = model.author?.login ?: ""
|
||||
association.text = if (CommentAuthorAssociation.NONE == model.authorAssociation) {
|
||||
model.updatedAt?.timeAgo()
|
||||
} else {
|
||||
SpannableBuilder.builder()
|
||||
.bold(model.authorAssociation?.value?.toLowerCase()?.replace("_", "") ?: "")
|
||||
.space()
|
||||
.append(model.updatedAt?.timeAgo())
|
||||
}
|
||||
|
||||
description.post {
|
||||
description.setSpannableFactory(NoCopySpannableFactory.getInstance())
|
||||
val bodyMd = model.body
|
||||
markwon.setMarkdown(description, if (!bodyMd.isNullOrEmpty()) bodyMd else resources.getString(R.string.no_description_provided))
|
||||
}
|
||||
|
||||
description.setOnTouchListener { v, event ->
|
||||
if (event.action == MotionEvent.ACTION_UP && !description.hasSelection()) {
|
||||
itemView.callOnClick()
|
||||
}
|
||||
return@setOnTouchListener false
|
||||
}
|
||||
|
||||
val canAlter = model.viewerCanUpdate == true || model.viewerCanDelete == true
|
||||
menu.isVisible = canAlter
|
||||
if (canAlter) {
|
||||
menu.popMenu(R.menu.comment_menu, { menu ->
|
||||
menu.findItem(R.id.edit)?.isVisible = model.viewerCanUpdate == true
|
||||
menu.findItem(R.id.delete)?.isVisible = model.viewerCanDelete == true
|
||||
}) { itemId ->
|
||||
if (itemId == R.id.delete) {
|
||||
context.showYesNoDialog(R.string.delete) {
|
||||
it.isTrue {
|
||||
deleteCommentListener.invoke(adapterPosition, model)
|
||||
}
|
||||
}
|
||||
} else if (itemId == R.id.edit) {
|
||||
editCommentListener.invoke(adapterPosition, model)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
adaptiveEmoticon.init(requireNotNull(model.id), model.reactionGroups) {
|
||||
callback.invoke(adapterPosition)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -34,8 +34,8 @@ import github.type.PullRequestState
|
||||
import io.noties.markwon.Markwon
|
||||
import io.noties.markwon.utils.NoCopySpannableFactory
|
||||
import kotlinx.android.synthetic.main.comment_box_layout.*
|
||||
import kotlinx.android.synthetic.main.issue_header_row_item.*
|
||||
import kotlinx.android.synthetic.main.issue_pr_view_layout.*
|
||||
import kotlinx.android.synthetic.main.pr_header_row_item.*
|
||||
import kotlinx.android.synthetic.main.pr_view_layout.*
|
||||
import kotlinx.android.synthetic.main.recyclerview_fastscroll_empty_state_layout.*
|
||||
import kotlinx.android.synthetic.main.title_toolbar_layout.*
|
||||
import javax.inject.Inject
|
||||
@ -55,7 +55,7 @@ class PullRequestFragment : BaseIssuePrTimelineFragment() {
|
||||
IssueTimelineAdapter(markwon, preference.theme, onCommentClicked(), onDeleteCommentClicked(), onEditCommentClicked())
|
||||
}
|
||||
|
||||
override fun layoutRes(): Int = R.layout.issue_pr_fragment_layout
|
||||
override fun layoutRes(): Int = R.layout.pr_fragment_layout
|
||||
override fun viewModel(): BaseViewModel? = viewModel
|
||||
override fun isPr(): Boolean = true
|
||||
override fun lockIssuePr(lockReason: LockReason?) = viewModel.lockUnlockIssue(login, repo, number, lockReason, true)
|
||||
@ -186,9 +186,20 @@ class PullRequestFragment : BaseIssuePrTimelineFragment() {
|
||||
initAssignees(model.assignees)
|
||||
initMilestone(model.milestone)
|
||||
initToolbarMenu(isAuthor, model.viewerCanUpdate == true, model.viewerDidAuthor, model.locked, state = model.state)
|
||||
initDashboard(model)
|
||||
recyclerView.removeEmptyView()
|
||||
}
|
||||
|
||||
private fun initDashboard(model: PullRequestModel) {
|
||||
commits.text = getString(R.string.commits_with_count, model.dashboard?.commits ?: 0)
|
||||
files.text = getString(R.string.files_with_count, model.dashboard?.changedFiles ?: 0)
|
||||
addition.text = getString(R.string.addition_with_count, model.dashboard?.additions ?: 0)
|
||||
deletion.text = getString(R.string.deletion_with_count, model.dashboard?.deletions ?: 0)
|
||||
approved.text = getString(R.string.approved_with_count, model.dashboard?.approvedReviews ?: 0)
|
||||
commented.text = getString(R.string.commented_with_count, model.dashboard?.commentedReviews ?: 0)
|
||||
changes.text = getString(R.string.changes_with_count, model.dashboard?.changeRequestedReviews ?: 0)
|
||||
}
|
||||
|
||||
override fun onEditCommentClicked(): (position: Int, comment: CommentModel) -> Unit = { position, comment ->
|
||||
routeForResult(
|
||||
EDITOR_DEEPLINK, EDIT_COMMENT_REQUEST_CODE, bundleOf(
|
||||
|
||||
@ -205,8 +205,7 @@ abstract class BaseTimelineUseCase : BaseObservableUseCase() {
|
||||
comment = CommentModel(
|
||||
node.id, node.databaseId,
|
||||
ShortUserModel(node.author?.login, node.author?.login, node.author?.url?.toString(), avatarUrl = node.author?.avatarUrl.toString()),
|
||||
node.bodyHTML.toString(), node.body, CommentAuthorAssociation.fromName(node.authorAssociation.rawValue()),
|
||||
node.viewerCannotUpdateReasons.map { reason -> CommentCannotUpdateReason.fromName(reason.rawValue()) }.toList(),
|
||||
node.body, CommentAuthorAssociation.fromName(node.authorAssociation.rawValue()),
|
||||
node.reactionGroups?.map { it.fragments.reactions.toReactionGroup() }, node.createdAt, node.updatedAt,
|
||||
node.isViewerCanReact, node.isViewerCanDelete, node.isViewerCanUpdate, node.isViewerDidAuthor, node.isViewerCanMinimize
|
||||
)
|
||||
|
||||
@ -2,7 +2,10 @@ package com.fastaccess.github.usecase.issuesprs
|
||||
|
||||
import com.apollographql.apollo.ApolloClient
|
||||
import com.apollographql.apollo.rx2.Rx2Apollo
|
||||
import com.fastaccess.data.model.*
|
||||
import com.fastaccess.data.model.CommentAuthorAssociation
|
||||
import com.fastaccess.data.model.CommentModel
|
||||
import com.fastaccess.data.model.ShortUserModel
|
||||
import com.fastaccess.data.model.TimelineModel
|
||||
import com.fastaccess.data.repository.SchedulerProvider
|
||||
import com.fastaccess.domain.repository.services.IssuePrService
|
||||
import com.fastaccess.domain.response.body.CommentRequestModel
|
||||
@ -39,8 +42,7 @@ class CreateIssueCommentUseCase @Inject constructor(
|
||||
node.id,
|
||||
node.databaseId,
|
||||
ShortUserModel(node.author?.login, node.author?.login, avatarUrl = node.author?.avatarUrl.toString()),
|
||||
node.bodyHTML.toString(), node.body, CommentAuthorAssociation.fromName(node.authorAssociation.rawValue()),
|
||||
node.viewerCannotUpdateReasons.map { reason -> CommentCannotUpdateReason.fromName(reason.rawValue()) }.toList(),
|
||||
node.body, CommentAuthorAssociation.fromName(node.authorAssociation.rawValue()),
|
||||
node.reactionGroups?.map { it.fragments.reactions.toReactionGroup() }, node.createdAt, node.updatedAt,
|
||||
node.isViewerCanReact, node.isViewerCanDelete, node.isViewerCanUpdate, node.isViewerDidAuthor, node.isViewerCanMinimize
|
||||
)
|
||||
|
||||
@ -6,6 +6,7 @@ import com.apollographql.apollo.rx2.Rx2Apollo
|
||||
import com.fastaccess.data.model.*
|
||||
import com.fastaccess.data.persistence.models.MyIssuesPullsModel
|
||||
import com.fastaccess.data.repository.SchedulerProvider
|
||||
import com.fastaccess.extension.toReactionGroup
|
||||
import com.fastaccess.extension.toUser
|
||||
import com.fastaccess.github.extensions.addIfNotNull
|
||||
import github.GetPullRequestTimelineQuery
|
||||
@ -45,11 +46,6 @@ class GetPullRequestTimelineUseCase @Inject constructor(
|
||||
timeline.pageInfo.startCursor, timeline.pageInfo.endCursor,
|
||||
timeline.pageInfo.isHasNextPage, timeline.pageInfo.isHasPreviousPage
|
||||
)
|
||||
/**
|
||||
*
|
||||
PULL_REQUEST_COMMIT, PULL_REQUEST_COMMIT_COMMENT_THREAD,
|
||||
PULL_REQUEST_REVIEW, PULL_REQUEST_REVIEW_THREAD,]
|
||||
*/
|
||||
timeline.nodes?.forEach { node ->
|
||||
when (node) {
|
||||
is AsIssueComment -> node.fragments.comment?.let { list.add(getComment(it)) }
|
||||
@ -88,7 +84,6 @@ class GetPullRequestTimelineUseCase @Inject constructor(
|
||||
is AsReviewDismissedEvent -> list.add(getDismissedReview(node))
|
||||
is AsReviewRequestRemovedEvent -> list.add(getReviewRemoved(node))
|
||||
is AsPullRequestReview -> list.add(getPullRequestReview(node))
|
||||
is AsPullRequestCommit -> list.add(getPullRequestCommit(node))
|
||||
}
|
||||
}
|
||||
return@map Pair(pageInfo, list)
|
||||
@ -108,49 +103,41 @@ class GetPullRequestTimelineUseCase @Inject constructor(
|
||||
node.state.rawValue(),
|
||||
node.createdAt,
|
||||
node.comments.nodes?.map {
|
||||
ReviewComment(
|
||||
ShortUserModel(
|
||||
it.author?.login,
|
||||
it.author?.login,
|
||||
it.author?.url?.toString(),
|
||||
avatarUrl = it.author?.avatarUrl.toString()
|
||||
),
|
||||
ShortUserModel(
|
||||
it.replyTo?.author?.login,
|
||||
it.replyTo?.author?.login,
|
||||
it.replyTo?.author?.url?.toString(),
|
||||
avatarUrl = it.replyTo?.author?.avatarUrl.toString()
|
||||
),
|
||||
it.body,
|
||||
it.path,
|
||||
it.originalPosition,
|
||||
it.isOutdated
|
||||
CommentModel(
|
||||
it.id,
|
||||
it.databaseId,
|
||||
ShortUserModel(it.author?.login, it.author?.login, it.author?.url?.toString(), avatarUrl = it.author?.avatarUrl?.toString()),
|
||||
it.body, CommentAuthorAssociation.fromName(it.authorAssociation.rawValue()),
|
||||
it.reactionGroups?.map { it.fragments.reactions.toReactionGroup() },
|
||||
it.updatedAt, it.updatedAt, it.isViewerCanReact, it.isViewerCanDelete,
|
||||
it.isViewerCanUpdate, it.isViewerDidAuthor, false,
|
||||
it.path, it.originalPosition, it.isOutdated, it.diffHunk
|
||||
)
|
||||
}?.firstOrNull()
|
||||
)
|
||||
)
|
||||
|
||||
private fun getPullRequestCommit(node: AsPullRequestCommit) = TimelineModel(
|
||||
pullRequestCommit = PullRequestCommitModel(
|
||||
node.id,
|
||||
node.url.toString(),
|
||||
CommitModel(
|
||||
node.prCommit.oid.toString(),
|
||||
ShortUserModel(
|
||||
node.prCommit.author?.name,
|
||||
node.prCommit.author?.name,
|
||||
node.prCommit.author?.user?.url.toString(),
|
||||
avatarUrl = node.prCommit.author?.avatarUrl?.toString() ?: node.prCommit.author?.user?.avatarUrl?.toString()
|
||||
),
|
||||
node.prCommit.message,
|
||||
node.prCommit.abbreviatedOid,
|
||||
node.prCommit.commitUrl.toString(),
|
||||
node.prCommit.authoredDate,
|
||||
node.prCommit.isCommittedViaWeb,
|
||||
node.prCommit.history.nodes?.lastOrNull()?.status?.state?.rawValue()
|
||||
)
|
||||
)
|
||||
)
|
||||
// private fun getPullRequestCommit(node: AsPullRequestCommit) = TimelineModel(
|
||||
// pullRequestCommit = PullRequestCommitModel(
|
||||
// node.id,
|
||||
// node.url.toString(),
|
||||
// CommitModel(
|
||||
// node.prCommit.oid.toString(),
|
||||
// ShortUserModel(
|
||||
// node.prCommit.author?.name,
|
||||
// node.prCommit.author?.name,
|
||||
// node.prCommit.author?.user?.url.toString(),
|
||||
// avatarUrl = node.prCommit.author?.avatarUrl?.toString() ?: node.prCommit.author?.user?.avatarUrl?.toString()
|
||||
// ),
|
||||
// node.prCommit.message,
|
||||
// node.prCommit.abbreviatedOid,
|
||||
// node.prCommit.commitUrl.toString(),
|
||||
// node.prCommit.authoredDate,
|
||||
// node.prCommit.isCommittedViaWeb,
|
||||
// node.prCommit.history.nodes?.lastOrNull()?.status?.state?.rawValue()
|
||||
// )
|
||||
// )
|
||||
// )
|
||||
|
||||
private fun getReviewRemoved(node: AsReviewRequestRemovedEvent) = TimelineModel(
|
||||
reviewRequestRemoved = ReviewRequestRemovedModel(
|
||||
|
||||
@ -4,6 +4,7 @@ import com.apollographql.apollo.ApolloClient
|
||||
import com.apollographql.apollo.rx2.Rx2Apollo
|
||||
import com.fastaccess.data.model.CountModel
|
||||
import com.fastaccess.data.model.EmbeddedRepoModel
|
||||
import com.fastaccess.data.model.PullRequestDashboard
|
||||
import com.fastaccess.data.model.ShortUserModel
|
||||
import com.fastaccess.data.persistence.models.PullRequestModel
|
||||
import com.fastaccess.data.repository.PullRequestRepository
|
||||
@ -44,24 +45,33 @@ class GetPullRequestUseCase @Inject constructor(
|
||||
.observeOn(schedulerProvider.uiThread())
|
||||
.map { it.data()?.repositoryOwner?.repository?.pullRequest?.fragments?.fullPullRequest }
|
||||
.map { issue ->
|
||||
repoProvider.upsert(PullRequestModel(issue.id, issue.databaseId, issue.number, issue.activeLockReason?.rawValue(),
|
||||
issue.body, issue.bodyHTML.toString(), issue.closedAt, issue.createdAt, issue.updatedAt, issue.state.rawValue(),
|
||||
issue.title, issue.viewerSubscription?.rawValue(), ShortUserModel(
|
||||
issue.author?.login, issue.author?.login,
|
||||
issue.author?.url?.toString(), avatarUrl = issue.author?.avatarUrl?.toString()
|
||||
),
|
||||
EmbeddedRepoModel(issue.repository.nameWithOwner), ShortUserModel(
|
||||
issue.mergedBy?.login, issue.mergedBy?.login,
|
||||
issue.mergedBy?.url?.toString(), avatarUrl = issue.mergedBy?.avatarUrl?.toString()
|
||||
),
|
||||
CountModel(issue.userContentEdits?.totalCount),
|
||||
issue.reactionGroups?.map { it.fragments.reactions.toReactionGroup() },
|
||||
issue.viewerCannotUpdateReasons.map { it.rawValue() }, issue.isClosed, issue.isCreatedViaEmail, issue.isLocked,
|
||||
issue.isViewerCanReact, issue.isViewerCanSubscribe, issue.isViewerCanUpdate, issue.isViewerDidAuthor,
|
||||
issue.mergeable.rawValue(), issue.isMerged, issue.mergedAt,
|
||||
issue.authorAssociation.rawValue(), issue.url.toString(), issue.labels?.nodes?.map { it.fragments.labels.toLabels() },
|
||||
issue.milestone?.toMilestone(), issue.assignees.nodes?.map { it.fragments }?.map { it.shortUserRowItem.toUser() },
|
||||
issue.headRefName, issue.baseRefName)
|
||||
repoProvider.upsert(
|
||||
PullRequestModel(
|
||||
issue.id, issue.databaseId, issue.number, issue.activeLockReason?.rawValue(),
|
||||
issue.body, issue.bodyHTML.toString(), issue.closedAt, issue.createdAt, issue.updatedAt, issue.state.rawValue(),
|
||||
issue.title, issue.viewerSubscription?.rawValue(), ShortUserModel(
|
||||
issue.author?.login, issue.author?.login,
|
||||
issue.author?.url?.toString(), avatarUrl = issue.author?.avatarUrl?.toString()
|
||||
),
|
||||
EmbeddedRepoModel(issue.repository.nameWithOwner), ShortUserModel(
|
||||
issue.mergedBy?.login, issue.mergedBy?.login,
|
||||
issue.mergedBy?.url?.toString(), avatarUrl = issue.mergedBy?.avatarUrl?.toString()
|
||||
),
|
||||
CountModel(issue.userContentEdits?.totalCount),
|
||||
issue.reactionGroups?.map { it.fragments.reactions.toReactionGroup() },
|
||||
issue.viewerCannotUpdateReasons.map { it.rawValue() }, issue.isClosed, issue.isCreatedViaEmail, issue.isLocked,
|
||||
issue.isViewerCanReact, issue.isViewerCanSubscribe, issue.isViewerCanUpdate, issue.isViewerDidAuthor,
|
||||
issue.mergeable.rawValue(), issue.isMerged, issue.mergedAt,
|
||||
issue.authorAssociation.rawValue(), issue.url.toString(), issue.labels?.nodes?.map { it.fragments.labels.toLabels() },
|
||||
issue.milestone?.toMilestone(), issue.assignees.nodes?.map { it.fragments }?.map { it.shortUserRowItem.toUser() },
|
||||
issue.headRefName, issue.baseRefName,
|
||||
PullRequestDashboard(
|
||||
issue.changedFiles, issue.additions, issue.deletions,
|
||||
issue.commits.totalCount, issue.commentedReviews?.totalCount ?: 0,
|
||||
issue.approvedReviews?.totalCount ?: 0,
|
||||
issue.changeRequestedReviews?.totalCount ?: 0
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<include layout="@layout/pr_view_layout" />
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="2dp"
|
||||
android:background="@drawable/toolbar_shadow_up" />
|
||||
|
||||
<include layout="@layout/comment_box_layout" />
|
||||
</LinearLayout>
|
||||
@ -0,0 +1,53 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<com.fastaccess.github.ui.widget.ParentSwipeRefreshLayout 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:id="@+id/swipeRefresh"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
tools:showIn="@layout/issue_pr_fragment_layout">
|
||||
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||
android:id="@+id/coordinatorLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:id="@+id/appBar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?android:windowBackground"
|
||||
android:theme="?android:toolbarStyle"
|
||||
app:elevation="0dp">
|
||||
|
||||
<com.google.android.material.appbar.CollapsingToolbarLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:contentScrim="?android:windowBackground"
|
||||
app:layout_scrollFlags="scroll|exitUntilCollapsed"
|
||||
app:scrimAnimationDuration="0"
|
||||
app:titleEnabled="false">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/issueHeaderWrapper"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="?actionBarSize"
|
||||
android:orientation="vertical"
|
||||
android:visibility="invisible"
|
||||
app:layout_collapseMode="none">
|
||||
|
||||
<include layout="@layout/pr_header_row_item" />
|
||||
</LinearLayout>
|
||||
|
||||
<include layout="@layout/title_toolbar_layout" />
|
||||
|
||||
</com.google.android.material.appbar.CollapsingToolbarLayout>
|
||||
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
<include layout="@layout/recyclerview_fastscroll_empty_state_layout" />
|
||||
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
</com.fastaccess.github.ui.widget.ParentSwipeRefreshLayout>
|
||||
@ -0,0 +1,94 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout 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:id="@+id/commentLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:foreground="?selectableItemBackground"
|
||||
android:paddingTop="@dimen/spacing_normal"
|
||||
android:paddingBottom="@dimen/spacing_normal">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="@dimen/spacing_normal"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<com.fastaccess.github.ui.widget.AvatarImageView
|
||||
android:id="@+id/userIcon"
|
||||
android:layout_width="@dimen/small_icon_zie"
|
||||
android:layout_height="@dimen/small_icon_zie"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginEnd="@dimen/spacing_xs_large"
|
||||
android:adjustViewBounds="true"
|
||||
android:scaleType="centerCrop"
|
||||
tools:src="@drawable/ic_ring" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical">
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:id="@+id/author"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:maxLines="1"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Small"
|
||||
app:autoSizeMaxTextSize="14sp"
|
||||
app:autoSizeMinTextSize="10sp"
|
||||
app:autoSizeStepGranularity="1dp"
|
||||
app:autoSizeTextType="uniform"
|
||||
tools:text="Place the truffels in an ice blender, and toss immediately with tangy lime.immediately with tangy lime" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:id="@+id/association"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:maxLines="1"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Caption"
|
||||
app:autoSizeMaxTextSize="14sp"
|
||||
app:autoSizeMinTextSize="10sp"
|
||||
app:autoSizeStepGranularity="1dp"
|
||||
app:autoSizeTextType="uniform"
|
||||
tools:text="Owner" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageButton
|
||||
android:id="@+id/menu"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:background="?selectableItemBackgroundBorderless"
|
||||
android:src="@drawable/ic_overflow" />
|
||||
</LinearLayout>
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:id="@+id/description"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:breakStrategy="simple"
|
||||
android:hyphenationFrequency="none"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Small"
|
||||
android:textIsSelectable="true"
|
||||
tools:text="Place the truffels in an ice blender, and toss immediately with tangy lime.immediately with tangy lime" />
|
||||
|
||||
<com.fastaccess.github.ui.widget.AdaptiveEmoticonLayout
|
||||
android:id="@+id/adaptiveEmoticon"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/spacing_normal" />
|
||||
</LinearLayout>
|
||||
|
||||
</FrameLayout>
|
||||
@ -0,0 +1,52 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<com.google.android.material.card.MaterialCardView 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"
|
||||
style="@style/CardViewStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/spacing_xs_large"
|
||||
android:layout_marginTop="@dimen/spacing_micro"
|
||||
android:layout_marginEnd="@dimen/spacing_xs_large"
|
||||
android:layout_marginBottom="@dimen/spacing_micro"
|
||||
app:cardBackgroundColor="?colorPrimary">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:id="@+id/fileName"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:drawableStart="@drawable/ic_push"
|
||||
android:drawablePadding="@dimen/spacing_normal"
|
||||
android:ellipsize="middle"
|
||||
android:gravity="start|center"
|
||||
android:maxLines="2"
|
||||
android:paddingTop="@dimen/spacing_normal"
|
||||
android:paddingBottom="@dimen/spacing_normal"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Small"
|
||||
tools:text="/app/src/main/java/blah/blah/blah/blah/MainActivity.kt" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:id="@+id/diffHunk"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:maxLines="5"
|
||||
android:paddingTop="@dimen/spacing_normal"
|
||||
android:paddingBottom="@dimen/spacing_normal"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Caption"
|
||||
tools:text="long text....." />
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="?dividerColor" />
|
||||
|
||||
<include layout="@layout/comment_small_row_item" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
@ -108,10 +108,10 @@
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:id="@+id/association"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Caption"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:maxLines="1"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Caption"
|
||||
android:textStyle="bold"
|
||||
app:autoSizeMaxTextSize="14sp"
|
||||
app:autoSizeMinTextSize="10sp"
|
||||
|
||||
@ -0,0 +1,366 @@
|
||||
<?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="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:paddingStart="@dimen/spacing_xs_large"
|
||||
android:paddingTop="@dimen/spacing_normal"
|
||||
android:paddingEnd="@dimen/spacing_xs_large"
|
||||
android:paddingBottom="@dimen/spacing_normal">
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:id="@+id/title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:maxLines="4"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Title"
|
||||
android:textIsSelectable="true"
|
||||
app:autoSizeMaxTextSize="20sp"
|
||||
app:autoSizeMinTextSize="12sp"
|
||||
app:autoSizeStepGranularity="1dp"
|
||||
app:autoSizeTextType="uniform"
|
||||
tools:text="Place the truffels in an ice blender, and toss immediately with tangy lime.immediately with tangy lime" />
|
||||
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/spacing_micro"
|
||||
android:layout_marginBottom="@dimen/spacing_micro"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<com.google.android.material.chip.Chip
|
||||
android:id="@+id/state"
|
||||
style="@style/ChipStyleNoElevation"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginTop="@dimen/spacing_micro"
|
||||
android:layout_marginEnd="@dimen/spacing_normal"
|
||||
android:layout_marginBottom="@dimen/spacing_micro"
|
||||
android:textAllCaps="false"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Caption"
|
||||
android:textColor="@color/white"
|
||||
tools:text="@string/open" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:id="@+id/opener"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:maxLines="3"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Small"
|
||||
app:autoSizeMaxTextSize="14sp"
|
||||
app:autoSizeMinTextSize="12sp"
|
||||
app:autoSizeStepGranularity="1dp"
|
||||
app:autoSizeTextType="uniform"
|
||||
tools:text="Place the truffels in an ice blender, and toss immediately with tangy lime.immediately with tangy lime" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/issueComment"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/spacing_micro"
|
||||
android:layout_marginBottom="@dimen/spacing_micro"
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="@dimen/spacing_normal"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<com.fastaccess.github.ui.widget.AvatarImageView
|
||||
android:id="@+id/userIcon"
|
||||
android:layout_width="@dimen/large_icon_zie"
|
||||
android:layout_height="@dimen/large_icon_zie"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginEnd="@dimen/spacing_xs_large"
|
||||
android:adjustViewBounds="true"
|
||||
android:scaleType="centerCrop"
|
||||
tools:src="@drawable/ic_ring" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical">
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:id="@+id/author"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:maxLines="1"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Small"
|
||||
app:autoSizeMaxTextSize="14sp"
|
||||
app:autoSizeMinTextSize="10sp"
|
||||
app:autoSizeStepGranularity="1dp"
|
||||
app:autoSizeTextType="uniform"
|
||||
tools:text="Place the truffels in an ice blender, and toss immediately with tangy lime.immediately with tangy lime" />
|
||||
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:id="@+id/association"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:maxLines="1"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Caption"
|
||||
android:textStyle="bold"
|
||||
app:autoSizeMaxTextSize="14sp"
|
||||
app:autoSizeMinTextSize="10sp"
|
||||
app:autoSizeStepGranularity="1dp"
|
||||
app:autoSizeTextType="uniform"
|
||||
tools:text="Owner" />
|
||||
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:id="@+id/description"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginTop="@dimen/spacing_micro"
|
||||
android:breakStrategy="simple"
|
||||
android:hyphenationFrequency="none"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Subhead"
|
||||
android:textIsSelectable="true"
|
||||
tools:targetApi="m"
|
||||
tools:text="Place the truffels in an ice blender, and toss immediately with tangy lime.immediately with tangy lime" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/labelsLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/spacing_normal"
|
||||
android:orientation="vertical"
|
||||
android:visibility="gone">
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/labels"
|
||||
android:textAllCaps="true"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Subhead"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:id="@+id/labels"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Small" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/assigneesLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/spacing_normal"
|
||||
android:orientation="vertical"
|
||||
android:visibility="gone">
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/assignees"
|
||||
android:textAllCaps="true"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Subhead"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:id="@+id/assignees"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Small" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/milestoneLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/spacing_normal"
|
||||
android:orientation="vertical"
|
||||
android:visibility="gone">
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/milestone"
|
||||
android:textAllCaps="true"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Subhead"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:id="@+id/milestone"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Small" />
|
||||
</LinearLayout>
|
||||
|
||||
<com.fastaccess.github.ui.widget.AdaptiveEmoticonLayout
|
||||
android:id="@+id/adaptiveEmoticon"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/spacing_normal" />
|
||||
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/prDashboard"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/spacing_xs_large"
|
||||
android:layout_marginBottom="@dimen/spacing_xs_large"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
style="@style/CardViewStyle"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/spacing_normal"
|
||||
android:layout_marginTop="@dimen/spacing_normal"
|
||||
android:layout_marginEnd="@dimen/spacing_normal"
|
||||
android:layout_marginBottom="@dimen/spacing_normal"
|
||||
android:layout_weight="1"
|
||||
android:minHeight="150dp"
|
||||
app:cardCornerRadius="@dimen/spacing_normal"
|
||||
app:cardElevation="@dimen/spacing_micro">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="@dimen/spacing_normal"
|
||||
android:text="@string/commits"
|
||||
android:textAllCaps="true"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Medium" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:id="@+id/commits"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:maxLines="1"
|
||||
android:padding="@dimen/spacing_normal"
|
||||
android:text="@string/commits_with_count"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Small"
|
||||
tools:text="Commits: 100,00" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:id="@+id/files"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:maxLines="1"
|
||||
android:padding="@dimen/spacing_normal"
|
||||
android:text="@string/files_with_count"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Small"
|
||||
tools:text="Files: 100,00" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:id="@+id/addition"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:maxLines="1"
|
||||
android:padding="@dimen/spacing_normal"
|
||||
android:text="@string/addition_with_count"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Small"
|
||||
tools:text="Addition 100,00" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:id="@+id/deletion"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:maxLines="1"
|
||||
android:padding="@dimen/spacing_normal"
|
||||
android:text="@string/deletion_with_count"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Small"
|
||||
tools:text="Deletion 100,00" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
<com.google.android.material.card.MaterialCardView
|
||||
style="@style/CardViewStyle"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/spacing_normal"
|
||||
android:layout_marginTop="@dimen/spacing_normal"
|
||||
android:layout_marginEnd="@dimen/spacing_normal"
|
||||
android:layout_marginBottom="@dimen/spacing_normal"
|
||||
android:layout_weight="1"
|
||||
android:minHeight="150dp"
|
||||
app:cardCornerRadius="@dimen/spacing_normal"
|
||||
app:cardElevation="@dimen/spacing_micro">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="@dimen/spacing_normal"
|
||||
android:text="@string/reviews"
|
||||
android:textAllCaps="true"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Medium" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:id="@+id/approved"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:maxLines="1"
|
||||
android:padding="@dimen/spacing_normal"
|
||||
android:text="@string/approved_with_count"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Small"
|
||||
tools:text="Approved 100,00" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:id="@+id/commented"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:maxLines="1"
|
||||
android:padding="@dimen/spacing_normal"
|
||||
android:text="@string/commented_with_count"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Small"
|
||||
tools:text="Commented 100,00" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:id="@+id/changes"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:maxLines="1"
|
||||
android:padding="@dimen/spacing_normal"
|
||||
android:text="@string/changes_with_count"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Small"
|
||||
tools:text="Changes 100,00" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:maxLines="1"
|
||||
android:padding="@dimen/spacing_normal"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Small"
|
||||
android:visibility="invisible"
|
||||
tools:text="Changes 100,00" />
|
||||
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
@ -0,0 +1,50 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
style="@style/CardViewStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/spacing_xs_large"
|
||||
android:layout_marginTop="@dimen/spacing_micro"
|
||||
android:layout_marginEnd="@dimen/spacing_xs_large"
|
||||
android:layout_marginBottom="@dimen/spacing_micro">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:id="@+id/fileName"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:drawableStart="@drawable/ic_eye"
|
||||
android:drawablePadding="@dimen/spacing_normal"
|
||||
android:ellipsize="middle"
|
||||
android:gravity="start|center"
|
||||
android:maxLines="2"
|
||||
android:paddingTop="@dimen/spacing_normal"
|
||||
android:paddingBottom="@dimen/spacing_normal"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Small"
|
||||
tools:text="/app/src/main/java/blah/blah/blah/blah/MainActivity.kt" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:id="@+id/diffHunk"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:maxLines="5"
|
||||
android:paddingTop="@dimen/spacing_normal"
|
||||
android:paddingBottom="@dimen/spacing_normal"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Caption"
|
||||
tools:text="long text....." />
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="?dividerColor" />
|
||||
|
||||
<include layout="@layout/comment_small_row_item" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</com.google.android.material.card.MaterialCardView>
|
||||
@ -171,12 +171,29 @@ fragment FullPullRequest on PullRequest {
|
||||
mergedAt
|
||||
headRefName
|
||||
baseRefName
|
||||
changedFiles
|
||||
additions
|
||||
deletions
|
||||
url
|
||||
createdViaEmail
|
||||
authorAssociation
|
||||
commits(first: 0) {
|
||||
totalCount
|
||||
}
|
||||
commentedReviews: reviews(first: 0, states: COMMENTED) {
|
||||
totalCount
|
||||
}
|
||||
approvedReviews: reviews(first: 0, states: APPROVED) {
|
||||
totalCount
|
||||
}
|
||||
changeRequestedReviews: reviews(first: 0, states: CHANGES_REQUESTED) {
|
||||
totalCount
|
||||
}
|
||||
mergedBy {
|
||||
avatarUrl
|
||||
login
|
||||
url
|
||||
}
|
||||
url
|
||||
userContentEdits(first: 0) {
|
||||
totalCount
|
||||
}
|
||||
@ -188,11 +205,9 @@ fragment FullPullRequest on PullRequest {
|
||||
reactionGroups {
|
||||
...Reactions
|
||||
}
|
||||
createdViaEmail
|
||||
repository {
|
||||
nameWithOwner
|
||||
}
|
||||
authorAssociation
|
||||
labels(first: 30) {
|
||||
nodes {
|
||||
...Labels
|
||||
|
||||
@ -161,7 +161,7 @@ query getPullRequestTimeline($login: String!, $repo: String!, $number: Int!, $pa
|
||||
state
|
||||
timelineItems(first: 30, after: $page, itemTypes: [ISSUE_COMMENT, CLOSED_EVENT, REOPENED_EVENT, REFERENCED_EVENT, ASSIGNED_EVENT,
|
||||
UNASSIGNED_EVENT, LABELED_EVENT, UNLABELED_EVENT, MILESTONED_EVENT, DEMILESTONED_EVENT, RENAMED_TITLE_EVENT,
|
||||
LOCKED_EVENT, UNLOCKED_EVENT, TRANSFERRED_EVENT, PULL_REQUEST_COMMIT, PULL_REQUEST_COMMIT_COMMENT_THREAD,
|
||||
LOCKED_EVENT, UNLOCKED_EVENT, TRANSFERRED_EVENT, PULL_REQUEST_COMMIT_COMMENT_THREAD,
|
||||
PULL_REQUEST_REVIEW, PULL_REQUEST_REVIEW_THREAD, HEAD_REF_DELETED_EVENT, HEAD_REF_FORCE_PUSHED_EVENT,
|
||||
MERGED_EVENT, MERGED_EVENT, REVIEW_DISMISSED_EVENT, REVIEW_REQUESTED_EVENT,
|
||||
REVIEW_REQUEST_REMOVED_EVENT, READY_FOR_REVIEW_EVENT]) {
|
||||
@ -225,41 +225,10 @@ query getPullRequestTimeline($login: String!, $repo: String!, $number: Int!, $pa
|
||||
... on TransferredEvent {
|
||||
... Transferred
|
||||
}
|
||||
... on PullRequestCommit {
|
||||
id
|
||||
url
|
||||
prCommit: commit {
|
||||
oid
|
||||
abbreviatedOid
|
||||
committedViaWeb
|
||||
authoredDate
|
||||
message
|
||||
commitUrl
|
||||
status {
|
||||
state
|
||||
}
|
||||
history {
|
||||
nodes {
|
||||
status {
|
||||
state
|
||||
}
|
||||
}
|
||||
}
|
||||
author {
|
||||
avatarUrl
|
||||
name
|
||||
user {
|
||||
login
|
||||
avatarUrl
|
||||
url
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
... on PullRequestCommitCommentThread {
|
||||
path
|
||||
position
|
||||
tComment: comments(first: 5) {
|
||||
tComment: comments(first: 1) {
|
||||
nodes {
|
||||
author {
|
||||
avatarUrl
|
||||
@ -433,8 +402,10 @@ query getPullRequestTimeline($login: String!, $repo: String!, $number: Int!, $pa
|
||||
createdAt
|
||||
state
|
||||
resourcePath
|
||||
comments(first: 5) {
|
||||
comments(first: 1) {
|
||||
nodes {
|
||||
id
|
||||
databaseId
|
||||
author {
|
||||
login
|
||||
avatarUrl
|
||||
@ -444,12 +415,15 @@ query getPullRequestTimeline($login: String!, $repo: String!, $number: Int!, $pa
|
||||
originalPosition
|
||||
path
|
||||
outdated
|
||||
replyTo {
|
||||
author {
|
||||
login
|
||||
avatarUrl
|
||||
url
|
||||
}
|
||||
authorAssociation
|
||||
updatedAt
|
||||
viewerCanReact
|
||||
viewerCanDelete
|
||||
viewerCanUpdate
|
||||
viewerDidAuthor
|
||||
diffHunk
|
||||
reactionGroups {
|
||||
...Reactions
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,11 @@
|
||||
package com.fastaccess.data.model
|
||||
|
||||
data class PullRequestDashboard(
|
||||
var changedFiles: Int = 0,
|
||||
var additions: Int = 0,
|
||||
var deletions: Int = 0,
|
||||
var commits: Int = 0,
|
||||
var commentedReviews: Int = 0,
|
||||
var approvedReviews: Int = 0,
|
||||
var changeRequestedReviews: Int = 0
|
||||
)
|
||||
@ -51,10 +51,8 @@ data class CommentModel(
|
||||
@SerializedName("id") var id: String? = null,
|
||||
@SerializedName("databaseId") var databaseId: Int? = null,
|
||||
@SerializedName("author") var author: ShortUserModel? = null,
|
||||
@SerializedName("bodyHTML") var bodyHTML: String? = null,
|
||||
@SerializedName("body") var body: String? = null,
|
||||
@SerializedName("authorAssociation") var authorAssociation: CommentAuthorAssociation? = null,
|
||||
@SerializedName("viewerCannotUpdateReasons") var viewerCannotUpdateReasons: List<CommentCannotUpdateReason?>? = null,
|
||||
@SerializedName("reactionGroups") var reactionGroups: List<ReactionGroupModel>? = null,
|
||||
@SerializedName("createdAt") var createdAt: Date? = null,
|
||||
@SerializedName("updatedAt") var updatedAt: Date? = null,
|
||||
@ -62,7 +60,11 @@ data class CommentModel(
|
||||
@SerializedName("viewerCanDelete") var viewerCanDelete: Boolean? = null,
|
||||
@SerializedName("viewerCanUpdate") var viewerCanUpdate: Boolean? = null,
|
||||
@SerializedName("viewerDidAuthor") var viewerDidAuthor: Boolean? = null,
|
||||
@SerializedName("viewerCanMinimize") var viewerCanMinimize: Boolean? = null
|
||||
@SerializedName("viewerCanMinimize") var viewerCanMinimize: Boolean? = null,
|
||||
@SerializedName("path") var path: String? = null,
|
||||
@SerializedName("originalPosition") var originalPosition: Int? = null,
|
||||
@SerializedName("outdated") var outdated: Boolean? = null,
|
||||
@SerializedName("diffHunk") var diffHunk: String? = null
|
||||
)
|
||||
|
||||
data class CrossReferencedEventModel(
|
||||
@ -208,19 +210,9 @@ data class ReviewModel(
|
||||
@SerializedName("authorAssociation") var authorAssociation: String? = null,
|
||||
@SerializedName("state") var state: String? = null,
|
||||
@SerializedName("createdAt") var createdAt: Date? = null,
|
||||
@SerializedName("comment") var comment: ReviewComment? = null
|
||||
@SerializedName("comment") var comment: CommentModel? = null
|
||||
)
|
||||
|
||||
data class ReviewComment(
|
||||
@SerializedName("author") var author: ShortUserModel? = null,
|
||||
@SerializedName("replyTo") var replyTo: ShortUserModel? = null,
|
||||
@SerializedName("body") var body: String? = null,
|
||||
@SerializedName("path") var path: String? = null,
|
||||
@SerializedName("originalPosition") var originalPosition: Int? = null,
|
||||
@SerializedName("outdated") var outdated: Boolean? = null
|
||||
)
|
||||
|
||||
|
||||
enum class CommentAuthorAssociation(val value: String) {
|
||||
MEMBER("MEMBER"),
|
||||
OWNER("OWNER"),
|
||||
|
||||
@ -10,7 +10,7 @@ import com.fastaccess.data.persistence.models.*
|
||||
* Created by Kosh on 11.05.18.
|
||||
*/
|
||||
|
||||
const val VERSION = 30
|
||||
const val VERSION = 31
|
||||
const val DATABASE_NAME = "FastHub-Room-DB"
|
||||
|
||||
@Database(
|
||||
|
||||
@ -3,10 +3,7 @@ package com.fastaccess.data.persistence.models
|
||||
import androidx.room.Embedded
|
||||
import androidx.room.Entity
|
||||
import androidx.room.PrimaryKey
|
||||
import com.fastaccess.data.model.CountModel
|
||||
import com.fastaccess.data.model.EmbeddedRepoModel
|
||||
import com.fastaccess.data.model.ReactionGroupModel
|
||||
import com.fastaccess.data.model.ShortUserModel
|
||||
import com.fastaccess.data.model.*
|
||||
import com.fastaccess.data.model.parcelable.LabelModel
|
||||
import com.fastaccess.data.model.parcelable.MilestoneModel
|
||||
import com.google.gson.annotations.SerializedName
|
||||
@ -52,7 +49,8 @@ data class PullRequestModel(
|
||||
@SerializedName("milestone") @Embedded(prefix = "milestone_") var milestone: MilestoneModel? = null,
|
||||
@SerializedName("assignees") var assignees: List<ShortUserModel>? = null,
|
||||
@SerializedName("headRefName") var headRefName: String? = null,
|
||||
@SerializedName("baseRefName") var baseRefName: String? = null
|
||||
@SerializedName("baseRefName") var baseRefName: String? = null,
|
||||
@SerializedName("reviewDashboard") @Embedded(prefix = "dashboard_") var dashboard: PullRequestDashboard? = null
|
||||
) {
|
||||
companion object {
|
||||
const val TABLE_NAME = "pullrequest_table"
|
||||
|
||||
@ -0,0 +1,93 @@
|
||||
package com.fastaccess.markdown.spans
|
||||
|
||||
import android.graphics.*
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.text.SpannableString
|
||||
import android.text.SpannableStringBuilder
|
||||
import android.text.Spanned
|
||||
import android.text.TextPaint
|
||||
import android.text.style.LineBackgroundSpan
|
||||
import android.text.style.MetricAffectingSpan
|
||||
import android.text.style.TypefaceSpan
|
||||
import androidx.annotation.ColorInt
|
||||
import com.fastaccess.markdown.widget.SpannableBuilder
|
||||
|
||||
class DiffLineSpan private constructor(private val color: Int) : MetricAffectingSpan(), LineBackgroundSpan {
|
||||
private val rect = Rect()
|
||||
|
||||
override fun updateMeasureState(paint: TextPaint) {
|
||||
apply(paint)
|
||||
}
|
||||
|
||||
override fun updateDrawState(paint: TextPaint) {
|
||||
apply(paint)
|
||||
}
|
||||
|
||||
private fun apply(paint: TextPaint) {
|
||||
paint.typeface = Typeface.MONOSPACE
|
||||
}
|
||||
|
||||
override fun drawBackground(
|
||||
c: Canvas, p: Paint, left: Int, right: Int, top: Int, baseline: Int, bottom: Int, text: CharSequence, start: Int,
|
||||
end: Int, lnum: Int
|
||||
) {
|
||||
val style = p.style
|
||||
val color = p.color
|
||||
p.style = Paint.Style.FILL
|
||||
p.color = this.color
|
||||
rect.set(left, top, right, bottom)
|
||||
c.drawRect(rect, p)
|
||||
p.color = color
|
||||
p.style = style
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun getSpannable(
|
||||
text: String?,
|
||||
@ColorInt patchAdditionColor: Int,
|
||||
@ColorInt patchDeletionColor: Int,
|
||||
@ColorInt patchRefColor: Int,
|
||||
newLine: Drawable? = null,
|
||||
truncate: Boolean = false
|
||||
): SpannableStringBuilder {
|
||||
val builder = SpannableStringBuilder()
|
||||
if (!text.isNullOrEmpty()) {
|
||||
val split = text.split("\\r?\\n|\\r".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
|
||||
if (split.isNotEmpty()) {
|
||||
val lines = split.size
|
||||
var index = -1
|
||||
for (i in 0 until lines) {
|
||||
if (truncate && lines - i > 2) continue
|
||||
var token = split[i]
|
||||
if (i < lines - 1) {
|
||||
token += "\n"
|
||||
}
|
||||
val firstChar = token[0]
|
||||
var color = Color.TRANSPARENT
|
||||
when {
|
||||
token.startsWith("@@") -> color = patchRefColor
|
||||
firstChar == '+' -> color = patchAdditionColor
|
||||
firstChar == '-' -> color = patchDeletionColor
|
||||
}
|
||||
index = token.indexOf("\\ No newline at end of file")
|
||||
if (index != -1) {
|
||||
token = token.replace("\\ No newline at end of file", "")
|
||||
}
|
||||
val spannableDiff = SpannableString(token)
|
||||
if (color != Color.TRANSPARENT) {
|
||||
val span = DiffLineSpan(color)
|
||||
spannableDiff.setSpan(span, 0, token.length, SpannableString.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||
}
|
||||
builder.append(spannableDiff)
|
||||
}
|
||||
if (index != -1) {
|
||||
builder.insert(builder.length - 1, SpannableBuilder.builder().append(newLine))
|
||||
}
|
||||
}
|
||||
}
|
||||
builder.setSpan(TypefaceSpan("monospace"), 0, builder.length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||
return builder
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,12 +1,30 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportHeight="24"
|
||||
android:viewportWidth="24">
|
||||
|
||||
android:height="26dp"
|
||||
android:viewportWidth="12"
|
||||
android:viewportHeight="14">
|
||||
<path
|
||||
android:fillColor="?icon_color"
|
||||
tools:fillColor="#000"
|
||||
android:pathData="M18,22A2,2 0 0,0 20,20V4C20,2.89 19.1,2 18,2H12V9L9.5,7.5L7,9V2H6A2,2 0 0,0 4,4V20A2,2 0 0,0 6,22H18Z"/>
|
||||
</vector>
|
||||
android:fillType="evenOdd"
|
||||
android:pathData="M6.455,1v4.364L4.818,4.273l-1.636,1.09V1"
|
||||
android:strokeWidth="1"
|
||||
android:strokeColor="#000"
|
||||
android:strokeLineCap="round"
|
||||
android:strokeLineJoin="round" />
|
||||
<path
|
||||
android:fillColor="?icon_color"
|
||||
android:fillType="evenOdd"
|
||||
android:pathData="M2.09,1A1.09,1.09 0,0 0,1 2.09v9.82c0,-0.604 0.488,-1.092 1.09,-1.092h7.637a1.09,1.09 0,0 0,1.091 -1.09V2.09A1.09,1.09 0,0 0,9.728 1H2.09z"
|
||||
android:strokeWidth="1"
|
||||
android:strokeColor="#000"
|
||||
android:strokeLineCap="round"
|
||||
android:strokeLineJoin="round" />
|
||||
<path
|
||||
android:fillColor="?icon_color"
|
||||
android:fillType="evenOdd"
|
||||
android:pathData="M9.727,13a1.09,1.09 0,0 0,1.091 -1.09V9.727a1.09,1.09 0,0 1,-1.09 1.09H2.09a1.09,1.09 0,1 0,0 2.182h7.636z"
|
||||
android:strokeWidth="1"
|
||||
android:strokeColor="#000"
|
||||
android:strokeLineCap="round"
|
||||
android:strokeLineJoin="round" />
|
||||
</vector>
|
||||
|
||||
@ -1,11 +1,30 @@
|
||||
<vector
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="16dp"
|
||||
android:height="16dp"
|
||||
android:viewportHeight="24"
|
||||
android:viewportWidth="24">
|
||||
|
||||
android:height="18dp"
|
||||
android:viewportWidth="12"
|
||||
android:viewportHeight="14">
|
||||
<path
|
||||
android:fillColor="?icon_color"
|
||||
android:pathData="M18,22A2,2 0 0,0 20,20V4C20,2.89 19.1,2 18,2H12V9L9.5,7.5L7,9V2H6A2,2 0 0,0 4,4V20A2,2 0 0,0 6,22H18Z"/>
|
||||
</vector>
|
||||
android:fillType="evenOdd"
|
||||
android:pathData="M6.455,1v4.364L4.818,4.273l-1.636,1.09V1"
|
||||
android:strokeWidth="1"
|
||||
android:strokeColor="#000"
|
||||
android:strokeLineCap="round"
|
||||
android:strokeLineJoin="round" />
|
||||
<path
|
||||
android:fillColor="?icon_color"
|
||||
android:fillType="evenOdd"
|
||||
android:pathData="M2.09,1A1.09,1.09 0,0 0,1 2.09v9.82c0,-0.604 0.488,-1.092 1.09,-1.092h7.637a1.09,1.09 0,0 0,1.091 -1.09V2.09A1.09,1.09 0,0 0,9.728 1H2.09z"
|
||||
android:strokeWidth="1"
|
||||
android:strokeColor="#000"
|
||||
android:strokeLineCap="round"
|
||||
android:strokeLineJoin="round" />
|
||||
<path
|
||||
android:fillColor="?icon_color"
|
||||
android:fillType="evenOdd"
|
||||
android:pathData="M9.727,13a1.09,1.09 0,0 0,1.091 -1.09V9.727a1.09,1.09 0,0 1,-1.09 1.09H2.09a1.09,1.09 0,1 0,0 2.182h7.636z"
|
||||
android:strokeWidth="1"
|
||||
android:strokeColor="#000"
|
||||
android:strokeLineCap="round"
|
||||
android:strokeLineJoin="round" />
|
||||
</vector>
|
||||
|
||||
@ -15,6 +15,7 @@
|
||||
<dimen name="fab_margin">16dp</dimen>
|
||||
<dimen name="grid_spacing">0dp</dimen>
|
||||
<dimen name="large_icon_zie">48dp</dimen>
|
||||
<dimen name="small_icon_zie">36dp</dimen>
|
||||
<dimen name="header_icon_zie">64dp</dimen>
|
||||
<dimen name="icon_size">24dp</dimen>
|
||||
<dimen name="divider_height">1px</dimen>
|
||||
|
||||
@ -610,4 +610,14 @@
|
||||
<string name="limit_by">Limit by</string>
|
||||
<string name="no_internet_connection">Not connected to Internet</string>
|
||||
<string name="lock_reason">Lock Reason</string>
|
||||
<string name="reviews">Reviews</string>
|
||||
<string name="approved">Approved</string>
|
||||
<string name="commented">Commented</string>
|
||||
<string name="files_with_count">Files: %d</string>
|
||||
<string name="addition_with_count">Addition: %d</string>
|
||||
<string name="changes_with_count">Changes: %d</string>
|
||||
<string name="deletion_with_count">Deletion: %d</string>
|
||||
<string name="approved_with_count">Approved: %d</string>
|
||||
<string name="commented_with_count">Commented: %d</string>
|
||||
<string name="commits_with_count">Commits: %d</string>
|
||||
</resources>
|
||||
Loading…
x
Reference in New Issue
Block a user