Skip to content

Commit 60b1249

Browse files
Merge branch 'main' into Serializable_extensions
# Conflicts: # app/src/main/java/org/wikipedia/descriptions/DescriptionEditActivity.kt
2 parents cb8b39f + ac6025d commit 60b1249

File tree

76 files changed

+1040
-471
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

76 files changed

+1040
-471
lines changed

app/src/main/java/org/wikipedia/bridge/JavaScriptActionHandler.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ object JavaScriptActionHandler {
7171
}
7272

7373
fun scrollToAnchor(anchorLink: String): String {
74-
val anchor = if (anchorLink.contains("#")) anchorLink.substring(anchorLink.indexOf("#") + 1) else anchorLink
74+
val anchor = anchorLink.substringAfter('#')
7575
return "var el = document.getElementById('$anchor');" +
7676
"window.scrollTo(0, el.offsetTop - (screen.height / 2));" +
7777
"setTimeout(function(){ el.style.backgroundColor='#fc3';" +

app/src/main/java/org/wikipedia/categories/CategoryActivity.kt

+3-2
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@ import org.wikipedia.page.Namespace
3333
import org.wikipedia.page.PageTitle
3434
import org.wikipedia.page.linkpreview.LinkPreviewDialog
3535
import org.wikipedia.readinglist.database.ReadingList
36-
import org.wikipedia.util.*
36+
import org.wikipedia.util.ResourceUtil
37+
import org.wikipedia.util.StringUtil
3738
import org.wikipedia.views.DrawableItemDecoration
3839
import org.wikipedia.views.PageItemView
3940
import org.wikipedia.views.WikiErrorView
@@ -138,7 +139,7 @@ class CategoryActivity : BaseActivity() {
138139
startActivity(newIntent(this, title))
139140
} else {
140141
val entry = HistoryEntry(title, HistoryEntry.SOURCE_CATEGORY)
141-
ExclusiveBottomSheetPresenter.show(supportFragmentManager, LinkPreviewDialog.newInstance(entry, null))
142+
ExclusiveBottomSheetPresenter.show(supportFragmentManager, LinkPreviewDialog.newInstance(entry))
142143
}
143144
}
144145

app/src/main/java/org/wikipedia/dataclient/Service.kt

+3-5
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,8 @@ interface Service {
4949
)
5050
suspend fun fullTextSearch(
5151
@Query("gsrsearch") searchTerm: String?,
52-
@Query("gsroffset") gsrOffset: String?,
5352
@Query("gsrlimit") gsrLimit: Int,
54-
@Query("continue") cont: String?
53+
@Query("gsroffset") gsrOffset: Int?
5554
): MwQueryResponse
5655

5756
@GET(MW_API_PREFIX + "action=query&list=allusers&auwitheditsonly=1")
@@ -65,10 +64,9 @@ interface Service {
6564
"&gsrnamespace=6&iiurlwidth=" + PREFERRED_THUMB_SIZE
6665
)
6766
suspend fun fullTextSearchCommons(
68-
@Query("gsrsearch") searchTerm: String?,
69-
@Query("gsroffset") gsrOffset: String?,
67+
@Query("gsrsearch") searchTerm: String,
7068
@Query("gsrlimit") gsrLimit: Int,
71-
@Query("continue") cont: String?
69+
@Query("gsroffset") gsrOffset: Int?,
7270
): MwQueryResponse
7371

7472
@GET(

app/src/main/java/org/wikipedia/dataclient/mwapi/MwQueryResponse.kt

+3-3
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@ open class MwQueryResponse : MwResponse() {
1515

1616
@Serializable
1717
class Continuation {
18-
val sroffset = 0
19-
val gsroffset = 0
20-
val gpsoffset = 0
18+
val sroffset: Int? = null
19+
val gsroffset: Int? = null
20+
val gpsoffset: Int? = null
2121
@SerialName("continue") val continuation: String? = null
2222
@SerialName("uccontinue") val ucContinuation: String? = null
2323
@SerialName("rccontinue") val rcContinuation: String? = null

app/src/main/java/org/wikipedia/dataclient/okhttp/OfflineCacheInterceptor.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ class OfflineCacheInterceptor : Interceptor {
7878
val name = line.substring(0, pos).trim()
7979
val value = line.substring(pos + 1).trim()
8080
builder.header(name, value)
81-
if (name.lowercase(Locale.getDefault()) == "content-type") {
81+
if (name.equals("content-type", true)) {
8282
contentType = value
8383
}
8484
}

app/src/main/java/org/wikipedia/descriptions/DescriptionEditRevertHelpView.kt

+11-6
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,14 @@ package org.wikipedia.descriptions
33
import android.content.Context
44
import android.net.Uri
55
import android.text.SpannableString
6-
import android.text.Spanned
76
import android.text.TextUtils
87
import android.text.method.LinkMovementMethod
98
import android.text.style.BulletSpan
109
import android.util.AttributeSet
1110
import android.view.LayoutInflater
1211
import android.widget.ScrollView
12+
import androidx.core.text.buildSpannedString
13+
import androidx.core.text.inSpans
1314
import org.wikipedia.R
1415
import org.wikipedia.WikipediaApp
1516
import org.wikipedia.databinding.ViewDescriptionEditRevertHelpBinding
@@ -31,14 +32,18 @@ class DescriptionEditRevertHelpView constructor(context: Context, attrs: Attribu
3132
.replace(":revertSubtitle".toRegex(), context.getString(R.string.description_edit_revert_subtitle))
3233
.replace(":revertIntro".toRegex(), context.getString(R.string.description_edit_revert_intro))
3334
.replace(":revertHistory".toRegex(), context.getString(R.string.description_edit_revert_history, getHistoryUri(qNumber))))
34-
val gapWidth = DimenUtil.roundedDpToPx(8f)
35-
val revertReason1 = SpannableString(StringUtil.fromHtml(context.getString(R.string.description_edit_revert_reason1, context.getString(R.string.wikidata_description_guide_url))))
36-
val revertReason2 = SpannableString(StringUtil.fromHtml(context.getString(R.string.description_edit_revert_reason2)))
37-
revertReason1.setSpan(BulletSpan(gapWidth), 0, revertReason1.length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
38-
revertReason2.setSpan(BulletSpan(gapWidth), 0, revertReason2.length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
35+
val revertReason1 = createReason(context.getString(R.string.description_edit_revert_reason1,
36+
context.getString(R.string.wikidata_description_guide_url)))
37+
val revertReason2 = createReason(context.getString(R.string.description_edit_revert_reason2))
3938
binding.helpText.text = SpannableString(TextUtils.expandTemplate(helpStr, revertReason1, revertReason2))
4039
}
4140

41+
private fun createReason(htmlString: String) = buildSpannedString {
42+
inSpans(BulletSpan(DimenUtil.roundedDpToPx(8f))) {
43+
append(StringUtil.fromHtml(htmlString))
44+
}
45+
}
46+
4247
private fun getHistoryUri(qNumber: String): Uri {
4348
return Uri.Builder()
4449
.scheme(WikipediaApp.instance.wikiSite.scheme())

app/src/main/java/org/wikipedia/diff/ArticleEditDetailsFragment.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,7 @@ class ArticleEditDetailsFragment : Fragment(), WatchlistExpiryDialog.Callback, M
273273
startActivity(FilePageActivity.newIntent(requireContext(), viewModel.pageTitle))
274274
} else {
275275
ExclusiveBottomSheetPresenter.show(childFragmentManager, LinkPreviewDialog.newInstance(
276-
HistoryEntry(viewModel.pageTitle, HistoryEntry.SOURCE_EDIT_DIFF_DETAILS), null))
276+
HistoryEntry(viewModel.pageTitle, HistoryEntry.SOURCE_EDIT_DIFF_DETAILS)))
277277
}
278278
}
279279
binding.newerIdButton.setOnClickListener {

app/src/main/java/org/wikipedia/diff/DiffUtil.kt

+38-46
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ import android.text.style.StrikethroughSpan
99
import android.text.style.StyleSpan
1010
import android.view.ViewGroup
1111
import androidx.core.graphics.ColorUtils
12+
import androidx.core.text.buildSpannedString
13+
import androidx.core.text.inSpans
14+
import androidx.core.text.set
1215
import androidx.recyclerview.widget.RecyclerView
1316
import org.wikipedia.R
1417
import org.wikipedia.dataclient.restbase.DiffResponse
@@ -31,10 +34,10 @@ object DiffUtil {
3134
if (it.lineNumber > lastItem!!.lineEnd) {
3235
lastItem!!.lineEnd = it.lineNumber
3336
}
34-
val str = SpannableStringBuilder(lastItem!!.parsedText)
35-
str.append("\n")
36-
str.append(item.parsedText)
37-
lastItem!!.parsedText = str
37+
lastItem!!.parsedText = buildSpannedString {
38+
appendLine(lastItem!!.parsedText)
39+
append(item.parsedText)
40+
}
3841
} else {
3942
items.add(item)
4043
lastItem = item
@@ -81,54 +84,43 @@ object DiffUtil {
8184
}
8285

8386
private fun createSpannableDiffText(context: Context, diff: DiffResponse.DiffItem): CharSequence {
84-
val spannableString = SpannableStringBuilder(diff.text.ifEmpty { "\n" })
85-
if (diff.text.isEmpty()) {
86-
spannableString.setSpan(EmptyLineSpan(ResourceUtil.getThemedColor(context, android.R.attr.colorBackground),
87-
ResourceUtil.getThemedColor(context, R.attr.placeholder_color)), 0, spannableString.length, 0)
88-
return spannableString
89-
}
90-
when (diff.type) {
91-
DiffResponse.DIFF_TYPE_LINE_ADDED -> {
92-
updateDiffTextDecor(context, spannableString, true, 0, diff.text.length)
93-
}
94-
DiffResponse.DIFF_TYPE_LINE_REMOVED -> {
95-
updateDiffTextDecor(context, spannableString, false, 0, diff.text.length)
96-
}
97-
DiffResponse.DIFF_TYPE_PARAGRAPH_MOVED_FROM -> {
98-
updateDiffTextDecor(context, spannableString, false, 0, diff.text.length)
99-
}
100-
DiffResponse.DIFF_TYPE_PARAGRAPH_MOVED_TO -> {
101-
updateDiffTextDecor(context, spannableString, true, 0, diff.text.length)
102-
}
103-
}
104-
if (diff.highlightRanges.isNotEmpty()) {
105-
for (highlightRange in diff.highlightRanges) {
106-
val indices = StringUtil.utf8Indices(diff.text)
107-
val highlightRangeStart = indices[highlightRange.start].coerceIn(0, diff.text.length)
108-
val highlightRangeEnd = (indices.getOrElse(highlightRange.start + highlightRange.length) { indices.last() + 1 }).coerceIn(0, diff.text.length)
87+
return buildSpannedString {
88+
if (diff.text.isEmpty()) {
89+
inSpans(EmptyLineSpan(ResourceUtil.getThemedColor(context, android.R.attr.colorBackground),
90+
ResourceUtil.getThemedColor(context, R.attr.placeholder_color))) {
91+
appendLine()
92+
}
93+
} else {
94+
append(diff.text)
95+
96+
when (diff.type) {
97+
DiffResponse.DIFF_TYPE_LINE_ADDED, DiffResponse.DIFF_TYPE_PARAGRAPH_MOVED_TO -> {
98+
updateDiffTextDecor(context, true, 0, diff.text.length)
99+
}
100+
DiffResponse.DIFF_TYPE_LINE_REMOVED, DiffResponse.DIFF_TYPE_PARAGRAPH_MOVED_FROM -> {
101+
updateDiffTextDecor(context, false, 0, diff.text.length)
102+
}
103+
}
104+
105+
for (highlightRange in diff.highlightRanges) {
106+
val indices = StringUtil.utf8Indices(diff.text)
107+
val highlightRangeStart = indices[highlightRange.start].coerceIn(0, diff.text.length)
108+
val highlightRangeEnd = (indices.getOrElse(highlightRange.start + highlightRange.length) { indices.last() + 1 }).coerceIn(0, diff.text.length)
109+
val isAddition = highlightRange.type == DiffResponse.HIGHLIGHT_TYPE_ADD
109110

110-
if (highlightRange.type == DiffResponse.HIGHLIGHT_TYPE_ADD) {
111-
updateDiffTextDecor(context, spannableString, true, highlightRangeStart, highlightRangeEnd)
112-
} else {
113-
updateDiffTextDecor(context, spannableString, false, highlightRangeStart, highlightRangeEnd)
111+
updateDiffTextDecor(context, isAddition, highlightRangeStart, highlightRangeEnd)
114112
}
115113
}
116114
}
117-
return spannableString
118115
}
119116

120-
private fun updateDiffTextDecor(context: Context, spannableText: SpannableStringBuilder, isAddition: Boolean, start: Int, end: Int) {
121-
val boldStyle = StyleSpan(Typeface.BOLD)
122-
val foregroundAddedColor = ForegroundColorSpan(ResourceUtil.getThemedColor(context, R.attr.primary_color))
123-
val foregroundRemovedColor = ForegroundColorSpan(ResourceUtil.getThemedColor(context, R.attr.primary_color))
124-
spannableText.setSpan(BackgroundColorSpan(ColorUtils.setAlphaComponent(ResourceUtil.getThemedColor(context,
125-
if (isAddition) R.attr.success_color else R.attr.destructive_color), 48)), start, end, 0)
126-
spannableText.setSpan(boldStyle, start, end, 0)
127-
if (isAddition) {
128-
spannableText.setSpan(foregroundAddedColor, start, end, 0)
129-
} else {
130-
spannableText.setSpan(foregroundRemovedColor, start, end, 0)
131-
spannableText.setSpan(StrikethroughSpan(), start, end, 0)
117+
private fun SpannableStringBuilder.updateDiffTextDecor(context: Context, isAddition: Boolean, start: Int, end: Int) {
118+
this[start, end] = BackgroundColorSpan(ColorUtils.setAlphaComponent(ResourceUtil.getThemedColor(context,
119+
if (isAddition) R.attr.success_color else R.attr.destructive_color), 48))
120+
this[start, end] = StyleSpan(Typeface.BOLD)
121+
this[start, end] = ForegroundColorSpan(ResourceUtil.getThemedColor(context, R.attr.primary_color))
122+
if (!isAddition) {
123+
this[start, end] = StrikethroughSpan()
132124
}
133125
}
134126
}

app/src/main/java/org/wikipedia/edit/FindInEditorActionProvider.kt

+4-12
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@ import android.view.View
77
import org.wikipedia.edit.richtext.SyntaxHighlighter
88
import org.wikipedia.util.DeviceUtil
99
import org.wikipedia.util.DimenUtil
10+
import org.wikipedia.util.StringUtil
1011
import org.wikipedia.views.FindInPageActionProvider
1112
import org.wikipedia.views.FindInPageActionProvider.FindInPageListener
12-
import java.util.*
1313

1414
class FindInEditorActionProvider(private val scrollView: View,
1515
private val textView: SyntaxHighlightableEditText,
@@ -59,21 +59,13 @@ class FindInEditorActionProvider(private val scrollView: View,
5959
}
6060

6161
override fun onSearchTextChanged(text: String?) {
62-
searchQuery = if (text.isNullOrEmpty()) null else text
62+
searchQuery = text?.ifEmpty { null }
6363
currentResultIndex = 0
6464
resultPositions.clear()
6565

6666
searchQuery?.let {
67-
val searchTextLower = it.lowercase(Locale.getDefault())
68-
val textLower = textView.text.toString().lowercase(Locale.getDefault())
69-
var position = 0
70-
do {
71-
position = textLower.indexOf(searchTextLower, position)
72-
if (position >= 0) {
73-
resultPositions.add(position)
74-
position += searchTextLower.length
75-
}
76-
} while (position >= 0)
67+
resultPositions += it.toRegex(StringUtil.SEARCH_REGEX_OPTIONS).findAll(textView.text)
68+
.map { it.range.first }
7769
}
7870
scrollToCurrentResult()
7971
}

app/src/main/java/org/wikipedia/edit/SyntaxHighlightViewAdapter.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ class SyntaxHighlightViewAdapter(
6262
}
6363

6464
override fun onPreviewLink(title: String) {
65-
val dialog = LinkPreviewDialog.newInstance(HistoryEntry(PageTitle(title, pageTitle.wikiSite), HistoryEntry.SOURCE_INTERNAL_LINK), null)
65+
val dialog = LinkPreviewDialog.newInstance(HistoryEntry(PageTitle(title, pageTitle.wikiSite), HistoryEntry.SOURCE_INTERNAL_LINK))
6666
ExclusiveBottomSheetPresenter.show(activity.supportFragmentManager, dialog)
6767
editText.post {
6868
dialog.dialog?.setOnDismissListener {

app/src/main/java/org/wikipedia/edit/WikiTextKeyboardView.kt

+16-51
Original file line numberDiff line numberDiff line change
@@ -90,34 +90,27 @@ class WikiTextKeyboardView constructor(context: Context, attrs: AttributeSet?) :
9090
binding.wikitextButtonPreviewLink.setOnClickListener {
9191
editText?.inputConnection?.let { inputConnection ->
9292
var title: String? = null
93-
val selection = inputConnection.getSelectedText(0)
94-
if (!selection.isNullOrEmpty() && !selection.toString().contains("[[")) {
95-
title = trimPunctuation(selection.toString())
93+
val selection = inputConnection.getSelectedText(0)?.toString()
94+
if (!selection.isNullOrEmpty() && "[[" !in selection) {
95+
title = selection.trim('.', ',', ';', '?', '!')
9696
} else {
97-
val before: String
98-
val after: String
99-
if (selection != null && selection.length > 1) {
100-
val selectionStr = selection.toString()
101-
before = selectionStr.substring(0, selectionStr.length / 2)
102-
after = selectionStr.substring(selectionStr.length / 2)
97+
val (before, after) = if (selection != null && selection.length > 1) {
98+
selection.substring(0, selection.length / 2) to
99+
selection.substring(selection.length / 2)
103100
} else {
104101
val peekLength = 64
105-
before = inputConnection.getTextBeforeCursor(peekLength, 0).toString()
106-
after = inputConnection.getTextAfterCursor(peekLength, 0).toString()
102+
inputConnection.getTextBeforeCursor(peekLength, 0)?.toString() to
103+
inputConnection.getTextAfterCursor(peekLength, 0)?.toString()
107104
}
108105

109-
if (before.isNotEmpty() && after.isNotEmpty()) {
110-
var str = before + after
111-
val i1 = lastIndexOf(before, "[[")
112-
val i2 = after.indexOf("]]") + before.length
113-
if (i1 >= 0 && i2 > 0 && i2 > i1) {
114-
str = str.substring(i1 + 2, i2).trim()
115-
if (str.isNotEmpty()) {
116-
if (str.contains("|")) {
117-
str = str.split("\\|".toRegex()).toTypedArray()[0]
118-
}
119-
title = str
120-
}
106+
if (!before.isNullOrEmpty() && !after.isNullOrEmpty()) {
107+
val str = before + after
108+
val i1 = before.lastIndexOf("[[")
109+
if (i1 >= 0) {
110+
title = str.substring(i1 + 2).substringBefore("]]")
111+
.trim()
112+
.splitToSequence('|')
113+
.firstOrNull()?.ifEmpty { null }
121114
}
122115
}
123116
}
@@ -173,7 +166,6 @@ class WikiTextKeyboardView constructor(context: Context, attrs: AttributeSet?) :
173166
}
174167

175168
companion object {
176-
177169
fun toggleSyntaxAroundCurrentSelection(editText: EditText?, ic: InputConnection, prefix: String, suffix: String) {
178170
editText?.let {
179171
if (it.selectionStart == it.selectionEnd) {
@@ -201,32 +193,5 @@ class WikiTextKeyboardView constructor(context: Context, attrs: AttributeSet?) :
201193
}
202194
}
203195
}
204-
205-
@Suppress("SameParameterValue")
206-
fun lastIndexOf(str: String, subStr: String): Int {
207-
var index = -1
208-
var a = 0
209-
while (a < str.length) {
210-
val i = str.indexOf(subStr, a)
211-
if (i >= 0) {
212-
index = i
213-
a = i + 1
214-
} else {
215-
break
216-
}
217-
}
218-
return index
219-
}
220-
221-
fun trimPunctuation(str: String): String {
222-
var newStr = str
223-
while (newStr.startsWith(".") || newStr.startsWith(",") || newStr.startsWith(";") || newStr.startsWith("?") || newStr.startsWith("!")) {
224-
newStr = newStr.substring(1)
225-
}
226-
while (newStr.endsWith(".") || newStr.endsWith(",") || newStr.endsWith(";") || newStr.endsWith("?") || newStr.endsWith("!")) {
227-
newStr = newStr.substring(0, newStr.length - 1)
228-
}
229-
return newStr
230-
}
231196
}
232197
}

0 commit comments

Comments
 (0)