Skip to content

Commit

Permalink
Automatic Scroll on Search added (#988)
Browse files Browse the repository at this point in the history
  • Loading branch information
4shutosh authored May 20, 2023
1 parent 9795b67 commit aacd5ff
Show file tree
Hide file tree
Showing 12 changed files with 314 additions and 46 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ Please add your entries according to this format.
* Add support for GraphQL [#805] [#884]
* Show GraphQL OperationName header to transaction title [#69], [#116]
* Allows to filter transactions based on graphqlOperationName [#920]
* Added scroll to highlighted text search in response screen [#988]

### Fixed

Expand Down Expand Up @@ -557,3 +558,5 @@ Initial release.
[#930]: https://github.com/ChuckerTeam/chucker/pull/930
[#970]: https://github.com/ChuckerTeam/chucker/pull/970
[#975]: https://github.com/ChuckerTeam/chucker/pull/975
[#388]: https://github.com/ChuckerTeam/chucker/issues/388
[#988]: https://github.com/ChuckerTeam/chucker/pull/988
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import android.text.Spanned
import android.text.style.BackgroundColorSpan
import android.text.style.ForegroundColorSpan
import android.text.style.UnderlineSpan
import java.util.regex.Pattern

/**
* Highlight parts of the String when it matches the search.
Expand All @@ -13,21 +14,55 @@ import android.text.style.UnderlineSpan
*/
internal fun SpannableStringBuilder.highlightWithDefinedColors(
search: String,
startIndices: List<Int>,
backgroundColor: Int,
foregroundColor: Int
): SpannableStringBuilder {
val startIndexes = indexesOf(this.toString(), search)
return applyColoredSpannable(this, startIndexes, search.length, backgroundColor, foregroundColor)
return applyColoredSpannable(this, startIndices, search.length, backgroundColor, foregroundColor)
}

private fun indexesOf(text: String, search: String): List<Int> {
val startPositions = mutableListOf<Int>()
var index = text.indexOf(search, 0, true)
while (index >= 0) {
startPositions.add(index)
index = text.indexOf(search, index + 1, true)
internal fun CharSequence.indicesOf(input: String): List<Int> =
Pattern.compile(input, Pattern.CASE_INSENSITIVE).toRegex()
.findAll(this)
.map { it.range.first }
.toCollection(mutableListOf())

internal fun SpannableStringBuilder.highlightWithDefinedColorsSubstring(
search: String,
startIndex: Int,
backgroundColor: Int,
foregroundColor: Int
): SpannableStringBuilder {
return applyColoredSpannableSubstring(this, startIndex, search.length, backgroundColor, foregroundColor)
}

private fun applyColoredSpannableSubstring(
text: SpannableStringBuilder,
subStringStartPosition: Int,
subStringLength: Int,
backgroundColor: Int,
foregroundColor: Int
): SpannableStringBuilder {
return text.apply {
setSpan(
UnderlineSpan(),
subStringStartPosition,
subStringStartPosition + subStringLength,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
)
setSpan(
ForegroundColorSpan(foregroundColor),
subStringStartPosition,
subStringStartPosition + subStringLength,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
)
setSpan(
BackgroundColorSpan(backgroundColor),
subStringStartPosition,
subStringStartPosition + subStringLength,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
)
}
return startPositions
}

private fun applyColoredSpannable(
Expand All @@ -37,26 +72,9 @@ private fun applyColoredSpannable(
backgroundColor: Int,
foregroundColor: Int
): SpannableStringBuilder {
return indexes
.fold(text) { builder, position ->
builder.setSpan(
UnderlineSpan(),
position,
position + length,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
)
builder.setSpan(
ForegroundColorSpan(foregroundColor),
position,
position + length,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
)
builder.setSpan(
BackgroundColorSpan(backgroundColor),
position,
position + length,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
)
builder
return text.apply {
indexes.forEach {
applyColoredSpannableSubstring(text, it, length, backgroundColor, foregroundColor)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.chuckerteam.chucker.internal.support

import android.view.View

internal fun View.visible() {
if (this.visibility != View.VISIBLE) {
this.visibility = View.VISIBLE
}
}

internal fun View.gone() {
if (this.visibility != View.GONE) {
this.visibility = View.GONE
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,5 @@ internal class TransactionPagerAdapter(context: Context, fm: FragmentManager) :

override fun getCount(): Int = titles.size

override fun getPageTitle(position: Int): CharSequence? = titles[position]
override fun getPageTitle(position: Int): CharSequence = titles[position]
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ import com.chuckerteam.chucker.databinding.ChuckerTransactionItemImageBinding
import com.chuckerteam.chucker.internal.support.ChessboardDrawable
import com.chuckerteam.chucker.internal.support.SpanTextUtil
import com.chuckerteam.chucker.internal.support.highlightWithDefinedColors
import com.chuckerteam.chucker.internal.support.highlightWithDefinedColorsSubstring
import com.chuckerteam.chucker.internal.support.indicesOf

/**
* Adapter responsible of showing the content of the Transaction Request/Response body.
Expand Down Expand Up @@ -45,10 +47,12 @@ internal class TransactionBodyAdapter : RecyclerView.Adapter<TransactionPayloadV
val headersItemBinding = ChuckerTransactionItemHeadersBinding.inflate(inflater, parent, false)
TransactionPayloadViewHolder.HeaderViewHolder(headersItemBinding)
}

TYPE_BODY_LINE -> {
val bodyItemBinding = ChuckerTransactionItemBodyLineBinding.inflate(inflater, parent, false)
TransactionPayloadViewHolder.BodyLineViewHolder(bodyItemBinding)
}

else -> {
val imageItemBinding = ChuckerTransactionItemImageBinding.inflate(inflater, parent, false)
TransactionPayloadViewHolder.ImageViewHolder(imageItemBinding)
Expand All @@ -66,15 +70,35 @@ internal class TransactionBodyAdapter : RecyclerView.Adapter<TransactionPayloadV
}
}

internal fun highlightQueryWithColors(newText: String, backgroundColor: Int, foregroundColor: Int) {
internal fun highlightQueryWithColors(
newText: String,
backgroundColor: Int,
foregroundColor: Int
): List<SearchItemBodyLine> {
val listOfSearchItems = arrayListOf<SearchItemBodyLine>()
items.filterIsInstance<TransactionPayloadItem.BodyLineItem>()
.withIndex()
.forEach { (index, item) ->
if (item.line.contains(newText, ignoreCase = true)) {
val listOfOccurrences = item.line.indicesOf(newText)
if (listOfOccurrences.isNotEmpty()) {
// storing the occurrences and their positions
listOfOccurrences.forEach {
listOfSearchItems.add(
SearchItemBodyLine(
indexBodyLine = index + 1,
indexStartOfQuerySubString = it
)
)
}

// highlighting the occurrences
item.line.clearHighlightSpans()
item.line =
item.line
.highlightWithDefinedColors(newText, backgroundColor, foregroundColor)
item.line = item.line.highlightWithDefinedColors(
newText,
listOfOccurrences,
backgroundColor,
foregroundColor
)
notifyItemChanged(index + 1)
} else {
// Let's clear the spans if we haven't found the query string.
Expand All @@ -84,6 +108,26 @@ internal class TransactionBodyAdapter : RecyclerView.Adapter<TransactionPayloadV
}
}
}
return listOfSearchItems
}

internal fun highlightItemWithColorOnPosition(
position: Int,
queryStartPosition: Int,
queryText: String,
backgroundColor: Int,
foregroundColor: Int
) {
val item = items.getOrNull(position) as? TransactionPayloadItem.BodyLineItem
if (item != null) {
item.line = item.line.highlightWithDefinedColorsSubstring(
queryText,
queryStartPosition,
backgroundColor,
foregroundColor
)
notifyItemChanged(position)
}
}

internal fun resetHighlight() {
Expand Down Expand Up @@ -117,6 +161,11 @@ internal class TransactionBodyAdapter : RecyclerView.Adapter<TransactionPayloadV
}
return removedSpansCount
}

internal data class SearchItemBodyLine(
val indexBodyLine: Int,
val indexStartOfQuerySubString: Int
)
}

internal sealed class TransactionPayloadViewHolder(view: View) : RecyclerView.ViewHolder(view) {
Expand Down
Loading

0 comments on commit aacd5ff

Please sign in to comment.