mirror of
https://github.com/commons-app/apps-android-commons.git
synced 2025-10-26 20:33:53 +01:00
Merge branch 'commons-app:main' into Nearby-When-tapping-green-pin,-show-picture-thumbnail-
This commit is contained in:
commit
6f1314355e
9 changed files with 153 additions and 19 deletions
66
.github/workflows/android.yml
vendored
66
.github/workflows/android.yml
vendored
|
|
@ -2,6 +2,11 @@ name: Android CI
|
|||
|
||||
on: [push, pull_request, workflow_dispatch]
|
||||
|
||||
permissions:
|
||||
pull-requests: write
|
||||
contents: read
|
||||
actions: read
|
||||
|
||||
concurrency:
|
||||
group: build-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
|
@ -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}`);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ class ResultTuple {
|
|||
}
|
||||
|
||||
constructor() {
|
||||
language = ""
|
||||
language = "bug" // Basa Ugi language - TODO Respect the `Default description language` setting.
|
||||
type = ""
|
||||
value = ""
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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">היעלמות היא <b>מוצא אחרון</b> וצריך <b>להשתמש בו רק כאשר אתם רוצים להפסיק לערוך לנצח</b> וגם כדי להסתיר כמה שיותר מהאסוציאציות שלכם בעבר.<br/><br/>מחיקת חשבון בויקישיתוף נעשית על ידי שינוי שם החשבון שלכם כך שאחרים לא יוכלו לזהות את התרומות שלכם בתהליך שנקרא חשבון היעלמות. <b>היעלמות אינה מבטיחה אנונימיות מוחלטת או הסרה של תרומות לפרויקטים</b>.</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>
|
||||
|
|
|
|||
|
|
@ -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 <code><nowiki>|zero=</nowiki></code> option currently not supported on Translatewiki.net with the custom <code><nowiki>{{PLURAL}}</nowiki></code> rules used by this project for Android, using a non-MediaWiki syntax.</string>
|
||||
<string name="multiple_uploads_title">{{Identical|Upload}}</string>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue