Skip to content

Commit 2a6127b

Browse files
Merge branch 'main' into fix/nearby-offline-crash-6469
2 parents e3476eb + 6e27c12 commit 2a6127b

File tree

9 files changed

+116
-67
lines changed

9 files changed

+116
-67
lines changed

app/build.gradle.kts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ plugins {
66
alias(libs.plugins.jetbrains.kotlin.android)
77
alias(libs.plugins.kotlin.kapt)
88
alias(libs.plugins.kotlin.parcelize)
9+
alias(libs.plugins.compose.compiler)
910
}
1011

1112
apply(from = "$rootDir/jacoco.gradle")
@@ -182,9 +183,6 @@ android {
182183
compose = true
183184
}
184185
buildToolsVersion = buildToolsVersion
185-
composeOptions {
186-
kotlinCompilerExtensionVersion = "1.5.8"
187-
}
188186
packaging {
189187
jniLibs {
190188
excludes += listOf("META-INF/androidx.*")

app/src/main/java/fr/free/nrw/commons/OkHttpConnectionFactory.kt

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -91,14 +91,17 @@ private class UnsuccessfulResponseInterceptor : Interceptor {
9191
if (ERRORS_PREFIX == responseBody.string()) {
9292
rsp.body.use { body ->
9393
val bodyString = body!!.string()
94-
95-
throw MwIOException(
96-
"MediaWiki API returned error: $bodyString",
97-
GsonUtil.defaultGson.fromJson(
98-
bodyString,
99-
MwErrorResponse::class.java
100-
).error!!,
94+
95+
val errorResponse = GsonUtil.defaultGson.fromJson(
96+
bodyString,
97+
MwErrorResponse::class.java
10198
)
99+
if (errorResponse?.error != null) {
100+
throw MwIOException(
101+
"MediaWiki API returned error: $bodyString",
102+
errorResponse.error
103+
)
104+
}
102105
}
103106
}
104107
}

app/src/main/java/fr/free/nrw/commons/explore/ExploreFragment.kt

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,9 @@ class ExploreFragment : CommonsDaggerSupportFragment() {
6464
override fun onPageScrollStateChanged(state: Int) = Unit
6565
override fun onPageSelected(position: Int) {
6666
binding!!.viewPager.canScroll = position != 2
67+
// based on which tab we are now recreate the options menu
68+
activity?.invalidateOptionsMenu()
69+
6770
if (position == 2) {
6871
mapRootFragment?.requestLocationIfNeeded()
6972
}
@@ -178,19 +181,6 @@ class ExploreFragment : CommonsDaggerSupportFragment() {
178181
if (binding!!.viewPager.currentItem == 2) {
179182
others.setVisible(true)
180183
}
181-
182-
// if on Map tab, show all menu options, else only show search
183-
binding!!.viewPager.addOnPageChangeListener(object : OnPageChangeListener {
184-
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) = Unit
185-
override fun onPageScrollStateChanged(state: Int) = Unit
186-
override fun onPageSelected(position: Int) {
187-
binding!!.viewPager.canScroll = position != 2
188-
others.setVisible(position == 2)
189-
if (position == 2) {
190-
mapRootFragment?.requestLocationIfNeeded()
191-
}
192-
}
193-
})
194184
} else {
195185
inflater.inflate(R.menu.menu_search, menu)
196186
}

app/src/main/java/fr/free/nrw/commons/nearby/presenter/NearbyParentFragmentPresenter.kt

Lines changed: 93 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -506,6 +506,93 @@ class NearbyParentFragmentPresenter
506506
}
507507
}
508508

509+
/**
510+
* Creates a HashMap mapping place locations (LatLng) to the associated places.
511+
*
512+
* @param places The list of Places used to create HashMap entries
513+
* @param startIndex Only Places with indices between startIndex and places.lastIndex
514+
* (inclusive) will be used to create the HashMap. This can be useful for avoiding redundant
515+
* computation when calling this method on the same places list multiple times.
516+
*
517+
* @return The HashMap containing (Place's LatLng, Place) entries.
518+
*/
519+
private fun getLocationPlaceMap(places: List<Place>, startIndex: Int): HashMap<LatLng, Place> {
520+
val map = hashMapOf<LatLng, Place>()
521+
522+
for (i in startIndex..places.lastIndex) {
523+
map[places[i].location] = places[i]
524+
}
525+
526+
return map
527+
}
528+
529+
/**
530+
* Ensures the correct bookmark boolean value for Places whose bookmarks have changed.
531+
* This bookmark information is retrieved from the bookmarkLocationDao.
532+
*
533+
* @param updatedGroups The MarkerPlaceGroups which will be displayed on the map to the user.
534+
* @param bookmarkChangedPlacesIndex Only Places at indices greater than or equal to this number
535+
* in bookmarkChangedPlaces will be handled. This can be useful for avoiding redundant
536+
* computation when calling this method multiple times.
537+
*
538+
* @return The updated bookmarkChangedPlacesIndex used in future calls to this method.
539+
*/
540+
private suspend fun handleBookmarksToggled(
541+
updatedGroups: MutableList<MarkerPlaceGroup>,
542+
bookmarkChangedPlacesIndex: Int
543+
): Int {
544+
var i = bookmarkChangedPlacesIndex
545+
if (i < bookmarkChangedPlaces.size) {
546+
val bookmarkChangedPlacesBacklog = getLocationPlaceMap(bookmarkChangedPlaces, i)
547+
548+
i += bookmarkChangedPlacesBacklog.size
549+
for ((index, group) in updatedGroups.withIndex()) {
550+
if (bookmarkChangedPlacesBacklog.containsKey(group.place.location)) {
551+
updatedGroups[index] = MarkerPlaceGroup(
552+
bookmarkLocationDao
553+
.findBookmarkLocation(updatedGroups[index].place.name),
554+
updatedGroups[index].place
555+
)
556+
}
557+
}
558+
}
559+
560+
return i
561+
}
562+
563+
/**
564+
* Ensures any clicked Places are updated using existing Place data
565+
* and not by data from regular/batched WikiData server responses.
566+
*
567+
* @param updatedGroups The MarkerPlaceGroups which will be displayed on the map to the user.
568+
* @param clickedPlacesIndex Only Places at indices greater than or equal to this number
569+
* in clickedPlaces will be handled. This can be useful for avoiding redundant computation when
570+
* calling this method multiple times.
571+
*
572+
* @return The updated clickedPlacesIndex used in future calls to this method.
573+
*/
574+
private fun handlePlacesClicked(
575+
updatedGroups: MutableList<MarkerPlaceGroup>,
576+
clickedPlacesIndex: Int
577+
): Int {
578+
var i = clickedPlacesIndex
579+
if (i < clickedPlaces.size) {
580+
val clickedPlacesBacklog = getLocationPlaceMap(clickedPlaces, i)
581+
582+
i += clickedPlacesBacklog.size
583+
for ((index, group) in updatedGroups.withIndex()) {
584+
if (clickedPlacesBacklog.containsKey(group.place.location)) {
585+
updatedGroups[index] = MarkerPlaceGroup(
586+
updatedGroups[index].isBookmarked,
587+
clickedPlacesBacklog[group.place.location]
588+
)
589+
}
590+
}
591+
}
592+
593+
return i
594+
}
595+
509596
/**
510597
* Load the places' details from cache and Wikidata query, and update these details on the map
511598
* as and when they arrive.
@@ -526,8 +613,6 @@ class NearbyParentFragmentPresenter
526613
// clear past clicks and bookmarkChanged queues
527614
clickedPlaces.clear()
528615
bookmarkChangedPlaces.clear()
529-
var clickedPlacesIndex = 0
530-
var bookmarkChangedPlacesIndex = 0
531616

532617
val updatedGroups = nearbyPlaceGroups.toMutableList()
533618
// first load cached places:
@@ -546,50 +631,17 @@ class NearbyParentFragmentPresenter
546631
updatedGroups, collectResults)
547632

548633
var collectCount = 0
634+
var clickedPlacesIndex = 0
635+
var bookmarkChangedPlacesIndex = 0
549636
while (collectCount < indicesToUpdate.size) {
550637
val resultList = collectResults.receive()
551638

552639
processResults(resultList, updatedGroups)
640+
641+
clickedPlacesIndex = handlePlacesClicked(updatedGroups, clickedPlacesIndex)
553642

554-
// handle any places clicked
555-
if (clickedPlacesIndex < clickedPlaces.size) {
556-
val clickedPlacesBacklog = hashMapOf<LatLng, Place>()
557-
while (clickedPlacesIndex < clickedPlaces.size) {
558-
clickedPlacesBacklog.put(
559-
clickedPlaces[clickedPlacesIndex].location,
560-
clickedPlaces[clickedPlacesIndex]
561-
)
562-
++clickedPlacesIndex
563-
}
564-
for ((index, group) in updatedGroups.withIndex()) {
565-
if (clickedPlacesBacklog.containsKey(group.place.location)) {
566-
updatedGroups[index] = MarkerPlaceGroup(
567-
updatedGroups[index].isBookmarked,
568-
clickedPlacesBacklog[group.place.location]
569-
)
570-
}
571-
}
572-
}
573-
// handle any bookmarks toggled
574-
if (bookmarkChangedPlacesIndex < bookmarkChangedPlaces.size) {
575-
val bookmarkChangedPlacesBacklog = hashMapOf<LatLng, Place>()
576-
while (bookmarkChangedPlacesIndex < bookmarkChangedPlaces.size) {
577-
bookmarkChangedPlacesBacklog.put(
578-
bookmarkChangedPlaces[bookmarkChangedPlacesIndex].location,
579-
bookmarkChangedPlaces[bookmarkChangedPlacesIndex]
580-
)
581-
++bookmarkChangedPlacesIndex
582-
}
583-
for ((index, group) in updatedGroups.withIndex()) {
584-
if (bookmarkChangedPlacesBacklog.containsKey(group.place.location)) {
585-
updatedGroups[index] = MarkerPlaceGroup(
586-
bookmarkLocationDao
587-
.findBookmarkLocation(updatedGroups[index].place.name),
588-
updatedGroups[index].place
589-
)
590-
}
591-
}
592-
}
643+
bookmarkChangedPlacesIndex = handleBookmarksToggled(updatedGroups,
644+
bookmarkChangedPlacesIndex)
593645
schedulePlacesUpdate(updatedGroups)
594646
collectCount += resultList.size
595647
}

app/src/main/res/values-ps/strings.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@
101101
<string name="menu_from_camera">انځور اخيستل</string>
102102
<string name="menu_nearby">نژدې</string>
103103
<string name="provider_contributions">زما پورته کېدنې</string>
104-
<string name="menu_copy_link">وېبتړ لمېسل</string>
104+
<string name="menu_copy_link">تړونی لمېسل</string>
105105
<string name="menu_link_copied">وېبتړ ټينگدړې ته لمېسل شوی دی</string>
106106
<string name="menu_share">شريکول</string>
107107
<string name="menu_view_file_page">د دوتنې مخ کتل</string>

app/src/main/res/values-se/strings.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@
116116
<string name="no_uploads_yet">It leat vel bajásluđen ovttage gova.</string>
117117
<string name="menu_retry_upload">Geahččal ođđasit</string>
118118
<string name="menu_cancel_upload">Gaskkalduhte</string>
119+
<string name="language_search_all_languages">Buot gielat</string>
119120
<string name="media_upload_policy">Go sádden dán gova sisa, de seammás julggaštan ahte lea mu bargu, mas ii leat duogášvuoigatvuohta bargui dahje selfiide, ja muđuige soahpá &lt;a href=\"https://commons.wikimedia.org/wiki/Commons:Policies_and_guidelines\"&gt;Wikimedia Commons policies&lt;/a&gt;.</string>
120121
<string name="menu_download">Viečča</string>
121122
<string name="preference_license">Dábálaš liseansa</string>

build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
plugins {
33
alias(libs.plugins.android.application) apply false
44
alias(libs.plugins.jetbrains.kotlin.android) apply false
5+
alias(libs.plugins.compose.compiler) apply false
56
alias(libs.plugins.github.triplet.play) apply false
67
alias(libs.plugins.getkeepsafe.dexcount)
78
}

gradle.properties

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,6 @@ android.enableJetifier=true
2424
android.jetifier.ignorelist=bcprov-jdk15on
2525
android.nonTransitiveRClass=false
2626
android.nonFinalResIds=false
27+
28+
# Enable K2 mode for KAPT (required for Kotlin 2.0+)
29+
kapt.use.k2=true

gradle/libs.versions.toml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ glide = "4.12.0"
3333
gson = "2.8.5"
3434
junit = "4.13.2"
3535
junitJupiter = "5.10.0"
36-
kotlin = "1.9.22"
36+
kotlin = "2.1.0"
3737
kotlinStdlib = "1.8.0"
3838
coroutines = "1.7.3"
3939
leakcanary = "2.10"
@@ -58,7 +58,7 @@ recyclerview = "1.2.0-alpha02"
5858
recyclerviewFastscroll = "2.0.1"
5959
retrofit = "2.8.1"
6060
robolectric = "4.14.1"
61-
room = "2.6.1"
61+
room = "2.7.0"
6262
rules = "1.5.0"
6363
runner = "1.5.2"
6464
rxandroid = "2.1.0"
@@ -208,5 +208,6 @@ android-application = { id = "com.android.application", version.ref = "agp" }
208208
jetbrains-kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
209209
kotlin-kapt = { id = "org.jetbrains.kotlin.kapt" }
210210
kotlin-parcelize = { id = "org.jetbrains.kotlin.plugin.parcelize" }
211+
compose-compiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" }
211212
github-triplet-play = { id = "com.github.triplet.play", version.ref = "githubTripletPlay" }
212213
getkeepsafe-dexcount = { id = "com.getkeepsafe.dexcount", version.ref = "dexcount" }

0 commit comments

Comments
 (0)