Merge branch 'commons-app:main' into Nearby-When-tapping-green-pin,-show-picture-thumbnail-

This commit is contained in:
Sujal 2025-02-19 18:29:14 +05:30 committed by GitHub
commit 6f1314355e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 153 additions and 19 deletions

View file

@ -1,6 +1,11 @@
name: Android CI
on: [push, pull_request, workflow_dispatch]
on: [push, pull_request, workflow_dispatch]
permissions:
pull-requests: write
contents: read
actions: read
concurrency:
group: build-${{ github.event.pull_request.number || github.ref }}
@ -102,3 +107,64 @@ jobs:
with:
name: prodDebugAPK
path: app/build/outputs/apk/prod/debug/app-*.apk
- name: Comment on PR with APK download links
if: github.event_name == 'pull_request'
uses: actions/github-script@v6
with:
github-token: ${{secrets.GITHUB_TOKEN}}
script: |
try {
const token = process.env.GITHUB_TOKEN;
if (!token) {
throw new Error('GITHUB_TOKEN is not set. Please check workflow permissions.');
}
const { data: { artifacts } } = await github.rest.actions.listWorkflowRunArtifacts({
owner: context.repo.owner,
repo: context.repo.repo,
run_id: context.runId
});
if (!artifacts || artifacts.length === 0) {
console.log('No artifacts found for this workflow run.');
return;
}
const betaArtifact = artifacts.find(artifact => artifact.name === "betaDebugAPK");
const prodArtifact = artifacts.find(artifact => artifact.name === "prodDebugAPK");
if (!betaArtifact || !prodArtifact) {
console.log('Could not find both Beta and Prod APK artifacts.');
console.log('Available artifacts:', artifacts.map(a => a.name).join(', '));
return;
}
const betaDownloadUrl = `${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/suites/${context.runId}/artifacts/${betaArtifact.id}`;
const prodDownloadUrl = `${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/suites/${context.runId}/artifacts/${prodArtifact.id}`;
const commentBody = `
📱 **APK for pull request is ready to see the changes** 📱
- [Download Beta APK](${betaDownloadUrl})
- [Download Prod APK](${prodDownloadUrl})
`;
await github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: commentBody
});
console.log('Successfully posted comment with APK download links');
} catch (error) {
console.error('Error in PR comment creation:', error);
if (error.message.includes('GITHUB_TOKEN')) {
core.setFailed('Missing or invalid GITHUB_TOKEN. Please check repository secrets configuration.');
} else if (error.status === 403) {
core.setFailed('Permission denied. Please check workflow permissions in repository settings.');
} else {
core.setFailed(`Workflow failed: ${error.message}`);
}
}

View file

@ -232,13 +232,23 @@ public class Place implements Parcelable {
*/
@Nullable
public String getWikiDataEntityId() {
if (this.entityID != null && !this.entityID.equals("")) {
return this.entityID;
}
if (!hasWikidataLink()) {
Timber.d("Wikidata entity ID is null for place with sitelink %s", siteLinks.toString());
return null;
}
//Determine entityID from link
String wikiDataLink = siteLinks.getWikidataLink().toString();
return wikiDataLink.replace("http://www.wikidata.org/entity/", "");
if (wikiDataLink.contains("http://www.wikidata.org/entity/")) {
this.entityID = wikiDataLink.substring("http://www.wikidata.org/entity/".length());
return this.entityID;
}
return null;
}
/**

View file

@ -11,6 +11,7 @@ import android.content.IntentFilter
import android.content.res.Configuration
import android.graphics.Color
import android.graphics.Paint
import android.graphics.drawable.Drawable
import android.location.Location
import android.location.LocationManager
import android.net.Uri
@ -241,6 +242,7 @@ class NearbyParentFragment : CommonsDaggerSupportFragment(),
@Volatile
private var stopQuery = false
private var drawableCache: MutableMap<Pair<Context, Int>, Drawable>? = null
// Explore map data (for if we came from Explore)
private var prevZoom = 0.0
@ -747,6 +749,7 @@ class NearbyParentFragment : CommonsDaggerSupportFragment(),
startMapWithoutPermission()
}
}
drawableCache = HashMap()
}
/**
@ -1527,7 +1530,7 @@ class NearbyParentFragment : CommonsDaggerSupportFragment(),
marker.showInfoWindow()
presenter!!.handlePinClicked(updatedPlace)
savePlaceToDatabase(place)
val icon = ContextCompat.getDrawable(
val icon = getDrawable(
requireContext(),
getIconFor(updatedPlace, isBookMarked)
)
@ -2077,8 +2080,35 @@ class NearbyParentFragment : CommonsDaggerSupportFragment(),
)
}
/**
* Gets the specified Drawable object. This is a wrapper method for ContextCompat.getDrawable().
* This method caches results from previous calls for faster retrieval.
*
* @param context The context to use to get the Drawable
* @param id The integer that describes the Drawable resource
* @return The Drawable object
*/
private fun getDrawable(context: Context?, id: Int?): Drawable? {
if (drawableCache == null || context == null || id == null) {
return null
}
val key = Pair(context, id)
if (!drawableCache!!.containsKey(key)) {
val drawable = ContextCompat.getDrawable(context, id)
if (drawable != null) {
drawableCache!![key] = drawable
} else {
return null
}
}
return drawableCache!![key]
}
fun convertToMarker(place: Place, isBookMarked: Boolean): Marker {
val icon = ContextCompat.getDrawable(requireContext(), getIconFor(place, isBookMarked))
val icon = getDrawable(requireContext(), getIconFor(place, isBookMarked))
val point = GeoPoint(place.location.latitude, place.location.longitude)
val marker = Marker(binding!!.map)
marker.position = point
@ -2589,7 +2619,7 @@ class NearbyParentFragment : CommonsDaggerSupportFragment(),
Marker.ANCHOR_BOTTOM
)
startMarker.icon =
ContextCompat.getDrawable(
getDrawable(
this.requireContext(),
fr.free.nrw.commons.R.drawable.current_location_marker
)
@ -2647,7 +2677,7 @@ class NearbyParentFragment : CommonsDaggerSupportFragment(),
Marker(binding?.map).apply {
position = it
setAnchor(Marker.ANCHOR_CENTER, Marker.ANCHOR_BOTTOM)
icon = ContextCompat.getDrawable(context, R.drawable.current_location_marker)
icon = getDrawable(context, R.drawable.current_location_marker)
title = "Your Location"
textLabelFontSize = 24
overlays.add(this)

View file

@ -15,7 +15,7 @@ class ResultTuple {
}
constructor() {
language = ""
language = "bug" // Basa Ugi language - TODO Respect the `Default description language` setting.
type = ""
value = ""
}

View file

@ -25,9 +25,12 @@ import kotlinx.coroutines.Job
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.delay
import kotlinx.coroutines.ensureActive
import kotlinx.coroutines.job
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import okhttp3.internal.wait
import timber.log.Timber
import java.io.IOException
import java.lang.reflect.InvocationHandler
import java.lang.reflect.Method
import java.lang.reflect.Proxy
@ -75,8 +78,8 @@ class NearbyParentFragmentPresenter
* - **connnectionCount**: number of parallel requests
*/
private object LoadPlacesAsyncOptions {
const val BATCH_SIZE = 3
const val CONNECTION_COUNT = 3
const val BATCH_SIZE = 10
const val CONNECTION_COUNT = 20
}
private var schedulePlacesUpdateJob: Job? = null
@ -91,7 +94,7 @@ class NearbyParentFragmentPresenter
private object SchedulePlacesUpdateOptions {
var skippedCount = 0
const val SKIP_LIMIT = 3
const val SKIP_DELAY_MS = 500L
const val SKIP_DELAY_MS = 100L
}
// used to tell the asynchronous place detail loading job that the places' bookmarked status
@ -379,13 +382,32 @@ class NearbyParentFragmentPresenter
)
} catch (e: Exception) {
Timber.tag("NearbyPinDetails").e(e)
collectResults.send(indices.map { Pair(it, updatedGroups[it]) })
//HTTP request failed. Try individual places
for (i in indices) {
launch {
val onePlaceBatch = mutableListOf<Pair<Int, MarkerPlaceGroup>>()
try {
val fetchedPlace = nearbyController.getPlaces(
mutableListOf(updatedGroups[i].place)
)
onePlaceBatch.add(Pair(i, MarkerPlaceGroup(
bookmarkLocationDao.findBookmarkLocation(
fetchedPlace[0]),fetchedPlace[0])))
} catch (e: Exception) {
Timber.tag("NearbyPinDetails").e(e)
onePlaceBatch.add(Pair(i, updatedGroups[i]))
}
collectResults.send(onePlaceBatch)
}
}
}
}
}
}
var collectCount = 0
for (resultList in collectResults) {
while (collectCount < indicesToUpdate.size) {
val resultList = collectResults.receive()
for ((index, fetchedPlaceGroup) in resultList) {
val existingPlace = updatedGroups[index].place
val finalPlaceGroup = MarkerPlaceGroup(
@ -442,9 +464,7 @@ class NearbyParentFragmentPresenter
}
}
schedulePlacesUpdate(updatedGroups)
if (++collectCount == totalBatches) {
break
}
collectCount += resultList.size
}
collectResults.close()
}

View file

@ -469,7 +469,7 @@ class UploadWorker(
contribution: Contribution,
) {
val wikiDataPlace = contribution.wikidataPlace
if (wikiDataPlace != null && wikiDataPlace.imageValue == null) {
if (wikiDataPlace != null) {
if (!contribution.hasInvalidLocation()) {
var revisionID: Long? = null
try {

View file

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* A100Star
* Ademo
* Alefar
* Amire80
@ -27,7 +28,7 @@
<string name="commons_website">אתר ויקישיתוף</string>
<string name="exit_location_picker">יציאה מבורר המיקום</string>
<string name="submit">שליחה</string>
<string name="add_another_description">הוספת יאור אחר</string>
<string name="add_another_description">הוספת תיאור אחר</string>
<string name="add_new_contribution">הוספת תרומה חדשה</string>
<string name="add_contribution_from_camera">הוספת תרומה ממצלמה</string>
<string name="add_contribution_from_photos">הוספת תרומה מ־Photos</string>
@ -38,7 +39,7 @@
<string name="show_captions_description">תיאור</string>
<string name="nearby_row_image">תמונה</string>
<string name="nearby_all">הכול</string>
<string name="nearby_filter_toggle">להפעיל למעלה</string>
<string name="nearby_filter_toggle">הפעלה</string>
<string name="nearby_filter_search">תצוגת חיפוש</string>
<string name="nearby_filter_state">מצב המקום</string>
<string name="appwidget_img">תמונת היום</string>
@ -149,7 +150,7 @@
<string name="provider_modifications">שינויים</string>
<string name="menu_upload_single">העלאה</string>
<string name="categories_search_text_hint">חיפוש קטגוריות</string>
<string name="depicts_search_text_hint">חפשו פריטים שהמדיה שלך מציגה (הר, טאג\' מהאל, וכו\')</string>
<string name="depicts_search_text_hint">חפשו פריטים שהמדיה שלכם מציגה (הר, טאג\' מהאל, וכו\')</string>
<string name="menu_save_categories">שמירה</string>
<string name="menu_overflow_desc">תפריט גלישה</string>
<string name="refresh_button">רענון</string>
@ -846,9 +847,11 @@
<string name="usages_on_other_wikis_heading">אתרי ויקי אחרים</string>
<string name="bullet_point"></string>
<string name="file_usages_container_heading">שימושים בקובץ</string>
<string name="title_activity_single_web_view">SingleWebViewActivity</string>
<string name="account">חשבון</string>
<string name="vanish_account">העלמת חשבון</string>
<string name="account_vanish_request_confirm_title">אזהרת העלמת חשבון</string>
<string name="account_vanish_request_confirm">היעלמות היא &lt;b&gt;מוצא אחרון&lt;/b&gt; וצריך &lt;b&gt;להשתמש בו רק כאשר אתם רוצים להפסיק לערוך לנצח&lt;/b&gt; וגם כדי להסתיר כמה שיותר מהאסוציאציות שלכם בעבר.&lt;br/&gt;&lt;br/&gt;מחיקת חשבון בויקישיתוף נעשית על ידי שינוי שם החשבון שלכם כך שאחרים לא יוכלו לזהות את התרומות שלכם בתהליך שנקרא חשבון היעלמות. &lt;b&gt;היעלמות אינה מבטיחה אנונימיות מוחלטת או הסרה של תרומות לפרויקטים&lt;/b&gt;.</string>
<string name="caption">כותרת</string>
<string name="caption_copied_to_clipboard">הכותרת הועתקה ללוח</string>
<string name="congratulations_all_pictures_in_this_album_have_been_either_uploaded_or_marked_as_not_for_upload">ברכותינו, כל התמונות באלבום הזה הועלו או שסומנו לא להעלאה.</string>

View file

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Authors:
* A100Star
* Ajeje Brazorf
* Amire80
* Cabal
@ -26,6 +27,7 @@
<resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="all">
<string name="submit">{{Identical|Submit}}</string>
<string name="nearby_all">{{identical|All}}</string>
<string name="nearby_filter_toggle">יש קצת בלבול בתרגום עם להחליף למעלה, למרות שהתרגום באופן טכני נכון, המשמעות באנגלית היא החלפה בין מצבים (במקרה הזה, החלפת מצב פעיל) אז אפשר להשתמש בהפעלה כתרגום</string>
<string name="uploads_pending_notification_indicator">Status text about number of uploads left.\n* %1$d represents number of uploads left, including current one</string>
<string name="contributions_subtitle">See the current issue [https://phabricator.wikimedia.org/T267142 T267142] tracked in Phabricator about the &lt;code&gt;&lt;nowiki&gt;|zero=&lt;/nowiki&gt;&lt;/code&gt; option currently not supported on Translatewiki.net with the custom &lt;code&gt;&lt;nowiki&gt;{{PLURAL}}&lt;/nowiki&gt;&lt;/code&gt; rules used by this project for Android, using a non-MediaWiki syntax.</string>
<string name="multiple_uploads_title">{{Identical|Upload}}</string>

View file

@ -18,6 +18,7 @@
* Huajing
* Hydra
* Ken418
* Kichin
* Kuailong
* Lantianjialiang
* LittlePaw365
@ -870,4 +871,6 @@
<string name="caption">说明</string>
<string name="caption_copied_to_clipboard">已复制到剪贴板</string>
<string name="congratulations_all_pictures_in_this_album_have_been_either_uploaded_or_marked_as_not_for_upload">恭喜,专辑中的所有图片都已上传或标记为不上传。</string>
<string name="show_in_explore">在探索中显示</string>
<string name="show_in_nearby">显示在附近</string>
</resources>