Repository: square/leakcanary
File: leakcanary-android-core/src/main/java/leakcanary/internal/activity/screen/LeakScreen.kt (Kotlin)

Code before:
              onLeakTraceSelected(newSelectedHeapAnalysis, selectedHeapAnalysisId, selectedLeakTrace.leakTraceIndex)
            }
          }
        } else {
          lastSelectedLeakTraceIndex = position
          onLeakTraceSelected(lastSelectedHeapAnalysis, selectedHeapAnalysisId, selectedLeakTrace.leakTraceIndex)
        }
      }
    }
    spinner.setSelection(selectedLeakTraceIndex)
  }


private fun View.onLeakTraceSelected(analysis: HeapAnalysisSuccess, heapAnalysisId: Long, leakTraceIndex: Int) {
  val selectedLeak = analysis.allLeaks.first { it.signature == leakSignature }
  val leakTrace = selectedLeak.leakTraces[leakTraceIndex]

    val listView = findViewById<ListView>(R.id.leak_canary_list)
    listView.alpha = 0f
    listView.animate()
        .alpha(1f)

    val titleText = """
      Open <a href="open_analysis">Heap Dump</a><br><br>
      Share leak trace <a href="share">as text</a> or on <a href="share_stack_overflow">Stack Overflow</a><br><br>
      Share <a href="share_hprof">Heap Dump file</a><br><br>
      References <b><u>underlined</u></b> are the likely causes of the leak.
      Learn more at <a href="https://squ.re/leaks">https://squ.re/leaks</a>
    """.trimIndent() + if (selectedLeak is LibraryLeak) "<br><br>" +
        "A <font color='#FFCC32'>Library Leak</font> is a leak caused by a known bug in 3rd party code that you do not have control over. " +
        "(<a href=\"https://square.github.io/leakcanary/fundamentals-how-leakcanary-works/#4-categorizing-leaks\">Learn More</a>)<br><br>" +
        "<b>Leak pattern</b>: ${selectedLeak.pattern}<br><br>" +
        "<b>Description</b>: ${selectedLeak.description}" else ""

    val title = Html.fromHtml(titleText) as SpannableStringBuilder
    SquigglySpan.replaceUnderlineSpans(title, context)

    replaceUrlSpanWithAction(title) { urlSpan ->
      when (urlSpan) {
        "share" -> {
          {
            share(leakToString(leakTrace, analysis))
          }
        }
        "share_stack_overflow" -> {
          {
            shareToStackOverflow(leakToString(leakTrace, analysis))
          }
        }
        "open_analysis" -> {
          {

Review comment (suggestion):
I like the idea of this PR, however the implementation looks a bit too manual and bulky to me. I'd suggest to try Android's `Linkify` util instead to make the links automatically:
https://www.tutorialspoint.com/what-is-linkify-textview-in-android

I am not sure it will work in this case, but worth a try.

Code after:
              lastSelectedHeapAnalysis = newSelectedHeapAnalysis
              onLeakTraceSelected(newSelectedHeapAnalysis, selectedHeapAnalysisId, selectedLeakTrace.leakTraceIndex)
            }
          }
        } else {
          lastSelectedLeakTraceIndex = position
          onLeakTraceSelected(lastSelectedHeapAnalysis, selectedHeapAnalysisId, selectedLeakTrace.leakTraceIndex)
        }
      }
    }
    spinner.setSelection(selectedLeakTraceIndex)
  }

private fun parseLinks(str: String):String {
    val words = str.split(" ")
    var parsedString = ""
    for (word in words) {
      parsedString += if (Patterns.WEB_URL.matcher(word).matches()) {
        "<a href=\"${word}\">${word}</a>";
      } else {
        word
      }
      if (words.indexOf(word) != words.size - 1) parsedString += " "
    }
    return parsedString
}
private fun View.onLeakTraceSelected(analysis: HeapAnalysisSuccess, heapAnalysisId: Long, leakTraceIndex: Int) {
  val selectedLeak = analysis.allLeaks.first { it.signature == leakSignature }
  val leakTrace = selectedLeak.leakTraces[leakTraceIndex]

    val listView = findViewById<ListView>(R.id.leak_canary_list)
    listView.alpha = 0f
    listView.animate()
        .alpha(1f)

    val titleText = """
      Open <a href="open_analysis">Heap Dump</a><br><br>
      Share leak trace <a href="share">as text</a> or on <a href="share_stack_overflow">Stack Overflow</a><br><br>
      Share <a href="share_hprof">Heap Dump file</a><br><br>
      References <b><u>underlined</u></b> are the likely causes of the leak.
      Learn more at <a href="https://squ.re/leaks">https://squ.re/leaks</a>
    """.trimIndent() + if (selectedLeak is LibraryLeak) "<br><br>" +
        "A <font color='#FFCC32'>Library Leak</font> is a leak caused by a known bug in 3rd party code that you do not have control over. " +
        "(<a href=\"https://square.github.io/leakcanary/fundamentals-how-leakcanary-works/#4-categorizing-leaks\">Learn More</a>)<br><br>" +
        "<b>Leak pattern</b>: ${selectedLeak.pattern}<br><br>" +
        "<b>Description</b>: ${parseLinks(selectedLeak.description)}" else ""

    val title = Html.fromHtml(titleText) as SpannableStringBuilder
    SquigglySpan.replaceUnderlineSpans(title, context)

    replaceUrlSpanWithAction(title) { urlSpan ->