From b3c1474b31ec4cdd96b7d3db789897541e4ce532 Mon Sep 17 00:00:00 2001 From: "translatewiki.net" Date: Mon, 19 May 2025 14:01:55 +0200 Subject: [PATCH 001/162] Localisation updates from https://translatewiki.net. --- app/src/main/res/values-io/strings.xml | 9 +++ app/src/main/res/values-pl/strings.xml | 88 +++++++++++++++++++++++--- app/src/main/res/values-uz/strings.xml | 2 + 3 files changed, 90 insertions(+), 9 deletions(-) diff --git a/app/src/main/res/values-io/strings.xml b/app/src/main/res/values-io/strings.xml index ec976840e..42184a763 100644 --- a/app/src/main/res/values-io/strings.xml +++ b/app/src/main/res/values-io/strings.xml @@ -436,8 +436,11 @@ Permisar Eskartar Voluntez kapabligar registrago di lokizo en \'\'Settings\'\', e probez itere.\n\nNoto: l\'arkivo sendanta povas ne havar informo pri lokizo, se l\'\'\'app\'\' ne povas rekuperar l\'informo pri lokizo en kurta intervalo. + La programo \'\'app\'\' ne enrejistros informo pri lokizo en la fotografuri pro manko di permisi Sen kapabligar GPS, l\'enrejistro di la lokizo en la fotografuri ne facesas. Uzez selektilo di fotografuri segun dokumenti + La nova funciono \'\'Android photo picker\'\' povas perdar informo pri lokizo. Kapabligez ol, se vu semblas uzar ol. + Deskapabliganta ol povos deskuplar la nova funciono \'\'Android photo picker\'\'. Posible perdos informo pri lokizo. Kaptanta \'\'token\'\' por redaktar. Adjuntanta shablono por verifikar kategorio Demandanta verifiko di kategorio por %1$s @@ -497,8 +500,10 @@ Serio-nombro Software Aceso ad enmagazinigo-moyeno ne permisita + Partigar utensilo \'\'app\'\' per... Informo pri imajo Nula kategorio trovesis + Nula reprezenturi trovita Kargajo di arkivo cesis Pro quo %1$s devas efacesar? %1$s sendesis da: %2$s @@ -578,6 +583,9 @@ Por plu bona rezulti, selektez modo \"granda exakteso\" (\'\'High Accuracy\'\'). Kad montrar lokizo? Charjez pluse + Plubonigi propozata: + - Adjuntez kategorii a ca imajo, por faciligar lua uzado. + - Adjuntez ca imajo ad artiklo asociita de Wikipedio, qua havas nula imajo. Adjuntar imajo a Wikipedio Ka vu deziras adjuntar ca imajo al artiklo de Wikipedio en idiomo %1$s? Konfirmez @@ -612,6 +620,7 @@ Uzita Mea rango Kapabligesis por uzar kun limitizita konekti! + Modo por limitizita retoligilo Imaji di qualeso Duriganta sendajo... Pauzanta sendajo... diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index 11485b473..699c60857 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -150,6 +150,7 @@ Zbyt wiele nieudanych prób zalogowania. Spróbuj ponownie za kilka minut. Przepraszamy, ten użytkownik został zablokowany na Commons Wprowadź swój kod dla dwuetapowej autoryzacji. + Kod weryfikacyjny logowania został wysłany na Twój adres e-mail. Podaj kod, aby się zalogować. Logowanie nie powiodło się Prześlij Nazwij ten zestaw @@ -255,6 +256,7 @@ Zostań beta-testerem Dołącz do kanału bety w Google Play i dostań wczesny dostęp do nowych funkcji i łatek Kod 2FA + Kod weryfikacyjny z e-mail Czy na pewno wylogować? Błąd obrazu multimedialnego Nie znaleziono podkategorii @@ -437,6 +439,7 @@ W twoim urządzeniu nie znaleziono kompatybilnej aplikacji mapowej. Zainstaluj aplikację mapową, aby korzystać z tej funkcji. Zdjęcia Lokalizacja + Kategorie Dodaj/Usuń do zakładek Zakładki Nie dodałeś żadnych zakładek @@ -474,9 +477,13 @@ Odrzuć Zezwól na dostęp do lokalizacji w Ustawieniach, a następnie spróbuj ponownie.\n\nUwaga: Jeśli aplikacja nie będzie w stanie uzyskać danych o lokalizacji z urządzenia w krótkim czasie, przesłany plik może nie zawierać tych informacji. Aparat w aplikacji potrzebuje uprawnień na dostęp do lokalizacji, aby dołączyć ją do zdjęć, jeśli nie jest dostępna w danych EXIF. Zezwól aplikacji na dostęp do lokalizacji, a następnie spróbuj ponownie.\n\nUwaga: Jeśli aplikacja nie będzie w stanie uzyskać danych o lokalizacji z urządzenia w krótkim czasie, przesłany plik może nie zawierać tych informacji. - Upewnij się, że ten nowy selektor Androida nie usuwa lokalizacji ze zdjęć. + Aplikacja nie rejestrowała lokalizacji i ujęć z powodu braku uprawnień do korzystania z lokalizacji + Aplikacja nie rejestruje lokalizacji i ujęć, ponieważ GPS jest wyłączony + Użyj selektora zdjęć na podstawie dokumentu + Nowy selektor zdjęć Androida ryzykuje utratą informacji o lokalizacji. Włącz, jeśli wydaje się, że go używasz. + Wyłączenie tego może spowodować uruchomienie nowego selektora zdjęć Androida. Grozi utratą informacji o lokalizacji.\n\nAby uzyskać więcej informacji, kliknij „Czytaj więcej”. Kampanie już nie będą widoczne. Jednak w razie potrzeby możesz ponownie włączyć to powiadomienie w ustawieniach. - Ta funkcja wymaga połączenia sieciowego, sprawdź ustawienia połączenia. + Ta funkcja wymaga połączenia sieciowego. Sprawdź swoje ustawienia połączenia. Wystąpił błąd podczas przetwarzania obrazu. Spróbuj ponownie! Pobieranie tokenu do edycji Dodawanie szablonu do sprawdzania kategorii @@ -514,6 +521,7 @@ Nie masz nieprzeczytanych powiadomień Nie masz powiadomień o przeczytaniu Udostępniaj dzienniki za pomocą + Sprawdź skrzynkę odbiorczą e-mail Zobacz przeczytane Wyświetl nieprzeczytane Wystąpił błąd podczas pobierania zdjęć @@ -592,7 +600,7 @@ Nie można dodać koordynatów. Nie można dodać opisów. Nie można dodać przypisu. - Nie można uzyskać koordynatów. + Współrzędne obrazu nie zostały zaktualizowane Nie można uzyskać opisów. Edycja opisów i przypisów Udostępnij obraz przez @@ -607,12 +615,13 @@ Potrzebne Zdjęcia Typ miejsca: Most, muzeum, hotel itp. - Coś poszło nie tak podczas logowania, musisz zresetować hasło! + Coś poszło nie tak z logowaniem. Musisz zresetować hasło! MEDIA KLASY POTOMNE KLASY NADRZĘDNE Znaleziono miejsce w pobliżu - Czy to zdjęcie %1$s? + Czy to są zdjęcia %1$s? + Czy to jest zdjęcie %1$s? Zakładki Ustawienia Usunięto z zakładek @@ -626,8 +635,10 @@ Nie można otworzyć ustawień lokalizacji. Włącz lokalizację ręcznie Aby uzyskać najlepsze wyniki, wybierz tryb wysokiej dokładności. Włączyć lokalizację? + Włącz usługi lokalizacyjne, aby aplikacja pokazywała Twoją bieżącą lokalizację Lokalizacja W pobliżu wymaga włączonej lokalizacji, aby działać poprawnie - Aby ustawić lokalizację automatycznie, musisz przyznać dostęp do swojej bieżącej lokalizacji. + Aby wyświetlić pobliskie obrazy, mapa Eksploruj wymaga zezwolenia na ustalanie lokalizacji + Aby automatycznie ustawić lokalizację, musisz udzielić uprawnień do jej określania. Czy zrobiłeś te dwa zdjęcia w tym samym miejscu? Czy chcesz użyć szerokości/długości geograficznej obrazu po prawej stronie? Wczytaj więcej Nie znaleziono miejsc, spróbuj zmienić kryteria wyszukiwania. @@ -715,6 +726,7 @@ W przeciwieństwie do zdjęcia po lewej, zdjęcie po prawej ma logo Commons wskazujące, że zostało już przesłane.\n Dotknij i przytrzymaj, aby wyświetlić podgląd obrazu. Niesamowite Tez plik został już przesłany do Commons. + Ze względów technicznych aplikacja nie może niezawodnie przesyłać więcej niż %1$d zdjęć na raz. Limit przesyłania %1$d został przekroczony przez %2$d. Odrzuć Maks.: %1$d Błąd: przekroczono limit przesyłania @@ -727,7 +739,7 @@ Mapy znajdujące się w pobliżu muszą odczytywać STAN TELEFONU, aby działały poprawnie Wkład użytkownika: %s Osiągnięcia użytkownika: %s - Wyświetl stronę użytkownika + Wyświetl profil użytkownika Edycja przedstawień Edycja kategorii Opcje zaawansowane @@ -740,8 +752,8 @@ Dodaj położenie Usuń z tego e-maila wszelkie informacje, których nie chcesz udostępniać publicznie. Pamiętaj również, że Twój adres e-mail, z którego publikujesz, oraz powiązane imię i nazwisko i zdjęcie profilowe będą widoczne publicznie. Szczegóły - Osiągnięcia są dostępne tylko w wersji prod, sprawdź dokumentację dla programistów. - Tablica wyników jest dostępna tylko w wersji prod. Zapoznaj się z dokumentacją dla programistów. + Osiągnięcia są dostępne tylko w wersji prod. Sprawdź dokumentację programistyczną. + Tabela liderów jest dostępna tylko w wersji prod. Sprawdź dokumentację dla programistów. Przesyłaj tylko zdjęcia zrobione przez siebie. Przesyłający obrazy chronione prawami autorskimi zostaną zablokowani. Dotyczy to również wersji beta. Dziękujemy za przetestowanie aplikacji! Usuń zaznaczenie wszelkich informacji, których nie chcesz udostępniać publicznie. Poziom API @@ -777,19 +789,77 @@ Przesuń szybko i długo, aby wykonać następujące czynności: \n- Lewo/Prawo: Przejdź do poprzedniego/następnego \n- Góra: Wybierz\n- Dół: Oznacz jako nieprzeznaczone do przesłania. Aby skonfigurować swojego awatara rankingu, dotknij \'Ustaw jako awatar\' w menu z trzema kropkami dowolnego obrazu. Współrzędne nie są dokładnymi współrzędnymi, ale osoba, która przesłała to zdjęcie, uważa, że są wystarczająco blisko. + Odmowa dostępu do pamięci masowej Nie można udostępnić tego elementu + Do działania tej funkcji wymagane są uprawnienia Przeczytaj jak napisać użyteczny opis Przeczytaj jak napisać użyteczny podpis + Zobacz swoje osiągnięcia Edytuj obraz Edytuj lokalizację Lokalizacja zaktualizowana! + Usuń lokalizację + Ostrzeżenie o usuwaniu lokalizacji + Lokalizacja sprawia, że zdjęcia są bardziej przydatne i łatwiejsze do znalezienia. Czy naprawdę chcesz usunąć lokalizację z tego zdjęcia? + Lokalizacja usunięta! Dziękuję autorowi Błąd wysyłania podziękowań do autora. + Twoje logowanie wygasło. Zaloguj się ponownie. + Brak dostępnej aplikacji do otwierania plików GPX Pomyślnie zapisano Chcesz otworzyć plik GPX? Chcesz otworzyć plik KML? Nie udało się zapisać pliku KML. Nie udało się zapisać pliku GPX. + Zapisywanie pliku KML + Zapisywanie pliku GPX + + %d wybrany obraz + %d wybrane obrazy + %d wybranych obrazów + + + Pamiętaj, że wszystkie obrazy w wielokrotnym przesłaniu mają te same kategorie i przedstawienia. Jeśli obrazy nie mają wspólnych przedstawień i kategorii, wykonaj kilka oddzielnych przesłań. + Uwaga dotycząca przesyłania wielu obrazów na raz + Zgłoś problem dotyczący tego elementu do Wikidata + Wprowadź komentarz poniżej Dyskusja + Napisz coś o elemencie \' %1$s\'. Będzie to publicznie widoczne. + \'%1$s\' już nie istnieje, nie da się zrobić dla niego zdjęcia. + \'%1$s\' jest w innym miejscu. Proszę podać poniżej prawidłowe miejsce i jeśli to możliwe, wpisać jego prawidłową szerokość i długość geograficzną. + Inny problem lub informacja (proszę wyjaśnić poniżej). + Twoja opinia zostanie opublikowana na następującej stronie wiki: <a href=\"https://commons.wikimedia.org/wiki/Commons:Mobile_app/Feedback\">Commons:Aplikacja mobilna/Opinie</a> + Czy na pewno chcesz anulować wszystkie przesyłania? + Anulowanie wszystkich operacji przesyłania... + Przesłania + Oczekujące + Nieudane + Nie można wczytać danych o miejscu + Usuń folder + Potwierdź usunięcie + Czy na pewno chcesz usunąć folder %1$s zawierający %2$d elementów? Usuń + Anuluj + Folder %1$s został pomyślnie usunięty + Nie udało się usunąć folderu %1$s + Błąd podczas usuwania zawartości folderu: %1$s + Nie udało się pobrać ścieżki folderu dla identyfikatora kontenera: %1$d + To miejsce nie ma jeszcze zdjęcia. Zrób je! + To miejsce już ma zdjęcie. + Sprawdzam teraz, czy to miejsce ma zdjęcie. + Błąd podczas wczytywania + Nie odnaleziono zastosowań + Commons + Inne wiki + Wykorzystanie pliku + Konto + Wymaż konto + Ostrzeżenie o wymazaniu konta + Podpis + Podpis skopiowano do schowka + Gratulacje, wszystkie zdjęcia w tym albumie zostały przesłane lub zostały oznaczone jako nie do przesłania. + Pokaż w Eksploruj + Pokaż w Pobliżu + Utworzone i przesłane przez: %1$s + Utworzone przez %1$s i przesłane przez %2$s diff --git a/app/src/main/res/values-uz/strings.xml b/app/src/main/res/values-uz/strings.xml index 14ca6f7f4..a6f19b60a 100644 --- a/app/src/main/res/values-uz/strings.xml +++ b/app/src/main/res/values-uz/strings.xml @@ -1,6 +1,7 @@ @@ -8,6 +9,8 @@ Tangalt aɣbalu Github n Commons Alugu Commons Asmel wen n Commons + Aglam + Akk %1$d n ufaylu yezga yettali %1$d n ifuyla zgan ttalin @@ -49,6 +52,7 @@ Jerred Tuqqna... Rǧu... + Txil, rǧu… Tuqqna tedda! Tqqna ur teddi ara! Ulac afaylu. Ɛreḍ wayeḍ ma ulac aɣilif. @@ -85,12 +89,14 @@ Nadi taggayin Sekles Smiren + Tabdart Usla ayen yulin Ulac taggayin imenṭaḍen akked %1$s i yettwafen Rnu taggayin akken ad terreḍ tugniwin-ik sehlent i tifin di Wikimedia Commons.\n\nBdu timerna n taggayin. Taggayin Iɣewwaṛen Jerred + Taggayt Ɣef Asnas Wikipedia Commons d asnas n uɣbalu yeldin i d-yennulfan udiɣ yettwarfed sɣur iwiziwen d wid i t-iḍemnen n tmezdagnut Wikimedia. Tasbeddit Wikimedia ur tetteka ara deg usnulfu-is, tanfelit-is, neɣ aseggem n usnas. Rnu <a href=\"%1$s\">tummla tamaynut GitHub</a> akken ad temmleḍ ibugen neɣ ad d-mudded isumar. @@ -129,6 +135,7 @@ Zgel axedddim yettwaḥerzen ara tafeḍ di Internet akked tugniwin n inazalen, tiduliwin n yidlisen, atg. Tɣileḍ igarrez? Ih! + Ugar n telɣut Taggayin Asali... Ula d yiwet ur tettwafren @@ -139,10 +146,12 @@ Ysera tasiregt: Aru deg usekles azɣaray. Asnas ur yezmir ara ad yeddu s war aya. IH Ɣur-k + Sali Ih Uhu Azwel Aglam + Ameskar Azemz n usali Turagt imsidag @@ -180,6 +189,16 @@ Qqen ar umiḍan-ik Azen afaylu n uɣmis Azen afaylu n uɣmis i yinermisen s yimayl + Qqen Ulac adeg Ilaq usireg i uskan tabdart n wadigen iqerben + Wikidata + Wikipedia + Isteqsiyen FAQ + Suqel + Tutlayin + Semmet + Nadi + Nadi + Taggayin diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml index 873417bdb..0d368b91d 100644 --- a/app/src/main/res/values-ko/strings.xml +++ b/app/src/main/res/values-ko/strings.xml @@ -227,6 +227,7 @@ 베타 테스터가 되세요 구글 플레이 베타 채널에서 메일 발송을 허가해서 새로운 기능이나 버그 수정에 대한 정보를 빨리 얻어보세요 2FA 코드 + 이메일 인증 코드 정말 로그아웃하시겠습니까? 미디어 그림 실패 하위 분류가 없습니다 @@ -429,7 +430,7 @@ 위치 권한 없이 사진이 필요한 주변 장소를 표시할 수 없습니다 다시는 묻지 않음 위치 권한 요청 - 무언가가 잘못되어, 저희는 당신의 업적을 가져올 수 없었습니다 + 오류가 발생하여, 업적을 가져올 수 없습니다. 캠페인 표시 진행되고 있는 캠페인 보기 허용 @@ -450,6 +451,7 @@ 감사 표현 보내기: 실패 이것이 저작권 규정을 준수하고 있습니까? 알맞게 분류됐습니까? + 이것이 범위에 포함되나요? 기여자에게 감사를 표하시겠습니까? 앗, 분류가 달리지 않은 것 같습니다! 이 이미지는 %1$s 분류에 속해 있습니다. @@ -487,6 +489,7 @@ 분류가 없습니다 서술이 발견되지 않았습니다 업로드 취소됨 + %1$s을(를) 삭제해야 하는 이유는 무엇인가요? 기본 설명 언어 삭제 신청 성공 @@ -689,6 +692,7 @@ 의견을 입력해 주십시오 토론 기타 문제 또는 정보 (아래에 설명해 주십시오) + 모든 업로드를 취소하시겠습니까? 모든 업로드를 취소하는 중... 업로드 보류 중 diff --git a/app/src/main/res/values-sl/strings.xml b/app/src/main/res/values-sl/strings.xml index 614f460be..d81d5ba73 100644 --- a/app/src/main/res/values-sl/strings.xml +++ b/app/src/main/res/values-sl/strings.xml @@ -90,13 +90,13 @@ Prosimo, počakajte ... Posodabljam napise in opise Prosimo, počakajte ... - Uspešno ste se prijavili! - Prijava ni uspela! + Uspešna prijava! + Prijava ni uspela! Datoteka ni bila najdena. Prosimo, poskusite z drugo datoteko. Dosežena je največja omejitev ponovnih poskusov! Prekličite nalaganje in poskusite znova. Ali želite izklopiti optimizacijo baterije? Nalaganje več kot 3 slik deluje bolj zanesljivo, ko je optimizacija baterije izklopljena. Za nemoteno nalaganje v nastavitvah izklopite optimizacijo baterije za aplikacijo Commons. \n\nMožni koraki za izklop optimizacije baterije:\n\n1. korak: Dotaknite se spodnjega gumba »Nastavitve«.\n\n 2. korak: Preklopite z »Ni optimizirano« na »Vse aplikacije«.\n\n3. korak: Poiščite »Commons« ali »fr.free.nrw.commons«.\n\n 4. korak: tapnite ga in izberite »Ne optimiziraj«.\n\n\n5. korak: Pritisnite »Končano«. - Avtentikacija ni uspela; prosimo, prijavite se znova + Avtentikacija ni uspela. Prosimo, prijavite se znova. Nalaganje se je začelo! Nalaganje na čakanju (vklopljen je način omejene povezanosti) Datoteka »%1$s« je naložena! @@ -117,17 +117,20 @@ Posnemi fotografijo Bližnje Moje naložitve + Kopiraj povezavo + Povezava je kopirana v odložišče Deli Ogled opisne strani Napis (obvezen) Prosimo, dodajte sliki napis Opis Napis - Prijava ni uspela – omrežna napaka + Prijava ni mogoča – omrežna napaka Preveč neuspešnih nalaganj. Prosimo, poskusite znova čez nekaj minut. Ta uporabnik je v Zbirki žal blokiran Navesti morate svojo dvofaktorsko avtentikacijsko kodo. - Prijava ni uspela + Na vaš e-poštni naslov je bila poslana potrditvena koda za prijavo. Prosimo, vnesite kodo za prijavo. + Prijava ni uspela Naloži Poimenuj skupino Spremembe @@ -135,6 +138,7 @@ Poišči kategorije Poiščite predmete, ki jih vaša predstavnostna datoteka prikazuje (gora, Tadž Mahal, ...) Shrani + Prelivni meni Osveži Seznam (Ni še naložitev) @@ -231,6 +235,7 @@ Postanite beta preizkuševalec Prijavite se na naš beta kanal v trgovini Google Play in pridobite zgodnji dostop do novih možnosti in popravkov hroščev Koda 2FA + Koda za preverjanje e-pošte Ali se res želite odjaviti? Nalaganje datoteke ni uspelo Najdena ni bila nobena podkategorija @@ -251,6 +256,7 @@ O orodju Nastavitve Odziv + Povratne informacije prek GitHuba Odjava Vadnica Obvestila @@ -284,14 +290,16 @@ Za podrobnosti glejte spletno stran Preskoči Prijava - Ali res želite preskočiti prijavo? - V prihodnosti se boste morali za nalaganje slik prijaviti. + Ali res želite preskočiti prijavo? + V prihodnosti se boste morali za nalaganje slik prijaviti. Za uporabo te možnosti se prijavite Kopiraj vikibesedilo v odložišče Vikibesedilo je skopirano v odložišče Bližnje mogoče ne bo pravilno delovalo. Kraj ni na voljo. + Internet ni na voljo. Prikazani so samo predpomnjeni kraji. Dostop do lokacije je bil zavrnjen. Za uporabo te možnosti ročno nastavite svojo lokacijo. Za prikaz seznama bložnjih krajev je potrebno dovoljenje + Za prikaz seznama bložnjih slik je potrebno dovoljenje Smeri Wikipodatki Wikipedija @@ -351,7 +359,7 @@ V Wikimedijini zbirki so zelo dobrodošle slike, ki prikazujejo tehniko ali kulturo. Pravilno ste odgovorili na %1$s vprašanj. Čestitamo! Za odgovor na vprašanje izberite eno od dveh možnosti. - Seja prijave je potekla. Poskusite se prijaviti znova. + Prijava je potekla. Prijavite se znova. Delite kviz s prijatelji! Nadaljuj Pravilen odgovor @@ -359,7 +367,8 @@ Ali je ta zaslonski posnetek primeren za naložitev? Delite aplikacijo Zasukaj - Napaka pri pridobivanju bližnjih krajev. + Ni bilo mogoče naložiti bližnjih krajev. + Na tem območju ni slik Tu okoli ni bližnjih krajev Napaka pri pridobivanju bližnjih spomenikov. Ni nedavnih iskanj @@ -371,11 +380,13 @@ Izbriši Dosežki Profil + Značke Statistika Prejete zahvale Izbrane slike Slike iz »Bližnji kraji« - Raven + Raven %d + %s (raven %s) Naložene slike Nevrnjene slike Uporabljene slike @@ -407,6 +418,7 @@ V vaši napravi ni mogoče najti nobene združljive aplikacije z zemljevidom. Za uporabo te možnosti namestite ustrezno aplikacijo z zemljevidom. Slike Kraji + Kategorije Dodaj/odstrani zaznamek Zaznamki Dodali niste nobenega zaznamka @@ -434,7 +446,7 @@ Nikoli več ne vprašaj Vprašaj za dovoljenje za lokacijo Vprašaj za dovoljenje za uporabo lokacije, ko je to potrebno za ogled obvestila o bližnjih krajih. - Nekaj je šlo narobe. Vaših dosežkov nismo mogli pridobiti. + Nekaj je šlo narobe. Dosežkov ni bilo mogoče pridobiti. Opravili ste toliko prispevkov, da jih naš sistem izračunavanja ne more razčleniti. To je vrhunski dosežek. Konec: Prikaži akcije @@ -450,7 +462,7 @@ Novi izbirnik fotografij Android lahko izgubi podatke o lokaciji. Omogočite ga, če ga želite uporabljati. Izklop te možnosti lahko aktivira novi izbirnik fotografij za Android. S tem tvegate izgubo podatkov o informacijah.\n\nZa več informacij kliknite »Preberi več«. Kampanj ne boste več videli. Če želite, lahko tovrstno obveščanje znova vklopite v nastavitvah. - Ta možnost zahteva omrežno povezavo. Prosimo, preverite vaše nastavitve povezave. + Ta funkcija zahteva omrežno povezavo. Prosimo, preverite vaše povezavne nastavitve. Pri obdelavi slike je prišlo do napake. Prosimo, poskusite znova! Pridobivam žeton za urejanje Dodajam predlogo za preverjanje kategorije @@ -488,6 +500,7 @@ Nimate neprebranih obvestil Ninate prebranih obvestil Delite dnevniške zapise z + Preverite svoj e-poštni nabiralnik Ogled prebranih Ogled neprebranih Pri izbiri slik je prišlo do napake @@ -566,7 +579,7 @@ Ni bilo mogoče dodati koordinat. Ni bilo mogoče dodati opisov. Napisa ni bilo mogoče dodati. - Koordinat ni bilo mogoče pridobiti. + Koordinat slike ni bilo mogoče posodobiti. Ni bilo mogoče pridobiti opisov. Uredi opise in napise Deli slike prek ... @@ -581,12 +594,13 @@ Potrebuje fotografijo Vrsta kraja: Most, muzej, hotel idr. - Pri prijavi je šlo nekaj narobe; ponastaviti morate geslo!! + Pri prijavi je šlo nekaj narobe. Ponastaviti morate geslo!! MEDIJ PODREJENI RAZREDI NADREJENI RAZREDI Najden bližnji kraj - Ali je to fotografija kraja %1$s? + So to slike %1$s? + Ali je to slika %1$s? Zaznamki Nastavitve Odstranjeno iz zaznamkov @@ -600,8 +614,10 @@ Nastavitev kraja ni bilo mogoče odpreti. Kraj vklopite ročno. Za najboljše zadetke izberite način Visoka natančnost. Vklopim kraj? + Vljudno vklopite lokacijske storitve, da bo aplikacija prikazovala vašo trenutno lokacijo. Za Bližnje je trebs vklopiti kraj - Za samodejno nastavitev lokacije morate omogočiti dostop do vaše trenutne lokacije. + Raziskovanje zemljevida potrebuje dovoljenje za lokacijo za prikaz bližnjih slik + Za samodejno nastavitev lokacije morate dodeliti dovoljenje za lokacijo. Ali ste sliki posneli na istem kraju? Ali želite uporabiti geografsko širino/dolžino desne slike? Naloži več Najden ni noben kraj. Poskusite spremeniti iskalne parametre. @@ -704,7 +720,7 @@ Bližnji zemljevidi morajo za pravilno delovanje prebrati STANJE TELEFONA Prispevki uporabnika: %s Dosežki uporabnika: %s - Ogled uporabniške strani + Ogled uporabniškega profila Uredi slike Uredi kategorije Napredne možnosti @@ -717,8 +733,8 @@ Dodaj lokacijo Iz te e-pošte odstranite vse podatke, ki jih ne želite javno deliti. Upoštevajte, da bodo vaš e-poštni naslov ter povezano ime in profilna slika javno vidni. Podrobnosti - Dosežki so na voljo samo v stabilni različici (preverite dokumentacijo razvijalcev). - Lestvica uvrstitev je na voljo samo v stabilni različici (glejte dokumentacijo razvijalcev). + Dosežki so na voljo samo v produkcijski različici. Preverite dokumentacijo razvijalcev. + Lestvica uvrstitev je na voljo samo v produkcijski različici. Glejte dokumentacijo razvijalcev. Prosimo, nalagajte samo slike, ki ste jih ustvarili sami. Naložnike avtorsko varovanega gradiva bomo blokirali. To velja tudi za betarazličico. Hvala za preizkušanje aplikacije! Prosimo, odizberite vse podatke, ki jih ne želite deliti javno. Raven API @@ -762,13 +778,72 @@ Oglejte si svoje dosežke Uredi sliko Uredi lokacijo + Lokacija posodobljena! + Odstrani lokacijo + Opozorilo o odstranitvi lokacije + Lokacija naredi slike bolj uporabne in jih je lažje najti. Ali res želite odstraniti lokacijo te slike? + Lokacija odstranjena! Zahvala avtorju Napaka pri pošiljanju zahvale avtorju. + Vaša prijava je potekla. Prosimo, prijavite se znova. + Na voljo ni nobena aplikacija za odpiranje datotek GPX + Datoteka je uspešno shranjena + Ali želite odpreti datoteko GPX? + Ali želite odpreti datoteko KML? + Shranjevanje datoteke KML ni uspelo. + Shranjevanje datoteke GPX ni uspelo. + Shranjevanje datoteke KML + Shranjevanje datoteke GPX %d izbrana slika %d izbrani sliki %d izbranih slik %d izbranih slik + Upoštevajte, da imajo vse slike v večkratnem nalaganju enake kategorije in upodobitve. Če slike nimajo skupnih upodobitev in kategorij, izvedite več ločenih nalaganj. + Opomba o večkratnih nalaganjih + Sporočite problem s tem predmetom v Wikipodatke + Prosimo, vnesite nekaj komentarjev + Pogovor + Napišite nekaj o predmetu »%1$s«. To bo javno vidno. + »%1$s« ne obstaja več. Slike tega ni več mogoče posneti. »%1$s« je na drugem kraju. Spodaj navedite pravi kraj in, če je mogoče, napišite pravilno zemljepisno širino in dolžino. + Drug problem ali informacija (razložite spodaj). + Vaše povratne informacije bodo objavljene na naslednji strani vikija: <a href=\"https://commons.wikimedia.org/wiki/Commons:Mobile_app/Feedback\">Commons:Mobilna aplikacija/Povratne informacije</a> + Ste prepričani, da želite preklicati vse nalaganja? + Preklic vseh nalaganj ... + Naložitve + Čakajoče + Neuspešno + Podatkov o kraju ni bilo mogoče naložiti + Izbriši mapo + Potrdi izbris + Ali ste prepričani, da želite izbrisati mapo %1$s, ki vsebuje %2$d predmetov? + Izbriši + Prekliči + Mapa %1$s je uspešno izbrisana + Izbris mape %1$s ni uspel + Napaka pri brisanju vsebine mape: %1$s + Pridobitev poti mape za bucket ID ni uspela: %1$d + Ta kraj še nima slike; posnamite jo! + Ta kraj že ima sliko. + Preverjam, ali ta kraj že ima sliko. + Napaka pri nalaganju + Ni najdenih uporab + Zbirka + Drugi vikiji + + Uporabe datotek + SingleWebViewActivity + Račun + Izgini račun + Opozorilo o izginjenju računa + Izginotje je <b>skrajni ukrep</b> in ga <b>uporabite samo, če želite za vedno prenehati z urejanjem</b>, in tudi, da skrijete čim več svojih preteklih povezav.\n\nIzbris računa v Wikimedijini zbirki se opravi tako, da spremenite ime svojega računa, da drugi ne morejo prepoznati vaših prispevkov. <b>Izbris ne zagotavlja popolne anonimnosti ali odstranitve prispevkov k projektom</b>. + Napis + Napis je kopiran v odložišče + Čestitamo, vse slike v tem albumu so naložene ali označene kot neprimerne za nalaganje. + Prikaži v Raziskuj + Prikaži v Bližnje + Ustvaril_a in naložil_a: %1$s + Ustvaril_a %1$s in naložil_a %2$s From 8849f8984be482c411cf2e6fd80ab273df42aeb8 Mon Sep 17 00:00:00 2001 From: Sonal Yadav Date: Sun, 25 May 2025 18:47:04 +0530 Subject: [PATCH 004/162] Fix: Use concise Wikidata feedback message while keeping full UI text (#6318) --- .../main/java/fr/free/nrw/commons/nearby/WikidataFeedback.kt | 5 ++++- app/src/main/res/values/strings.xml | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/fr/free/nrw/commons/nearby/WikidataFeedback.kt b/app/src/main/java/fr/free/nrw/commons/nearby/WikidataFeedback.kt index a1bad1f26..1775401dd 100644 --- a/app/src/main/java/fr/free/nrw/commons/nearby/WikidataFeedback.kt +++ b/app/src/main/java/fr/free/nrw/commons/nearby/WikidataFeedback.kt @@ -63,7 +63,10 @@ class WikidataFeedback : BaseActivity() { supportActionBar!!.setDisplayHomeAsUpEnabled(true) binding.appCompatButton.setOnClickListener { - var desc = findViewById(binding.radioGroup.checkedRadioButtonId).text + var desc = when (binding.radioGroup.checkedRadioButtonId) { + R.id.radioButton2 -> getString(R.string.is_at_a_different_place_wikidata, place) + else -> findViewById(binding.radioGroup.checkedRadioButtonId).text + } var det = binding.detailsEditText.text.toString() if (binding.radioGroup.checkedRadioButtonId == R.id.radioButton3 && binding.detailsEditText.text.isNullOrEmpty()) { Toast diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index bb1450e0f..68dba88be 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -832,6 +832,7 @@ Upload your first media by tapping on the add button. Talk Write something about the \'%1$s\' item. It will be publicly visible. \'%1$s\' does not exist anymore, no picture can ever be taken of it. + \'%1$s\' is at a different place. \'%1$s\' is at a different place. Please specify the correct place below, and if possible, write the correct latitude and longitude. Other problem or information (please explain below). Your feedback gets posted to the following wiki page: Commons:Mobile app/Feedback ]]> From 91ca2e6672a38c667dbd29ecd6503dece00eecc5 Mon Sep 17 00:00:00 2001 From: "translatewiki.net" Date: Mon, 26 May 2025 14:01:50 +0200 Subject: [PATCH 005/162] Localisation updates from https://translatewiki.net. --- app/src/main/res/values-ar/strings.xml | 2 ++ app/src/main/res/values-da/strings.xml | 1 + app/src/main/res/values-fr/strings.xml | 1 + app/src/main/res/values-ja/strings.xml | 6 +++--- app/src/main/res/values-ps/strings.xml | 27 +++++++++++++++++++++++++- 5 files changed, 33 insertions(+), 4 deletions(-) diff --git a/app/src/main/res/values-ar/strings.xml b/app/src/main/res/values-ar/strings.xml index 9122f4767..5025b94cb 100644 --- a/app/src/main/res/values-ar/strings.xml +++ b/app/src/main/res/values-ar/strings.xml @@ -13,6 +13,7 @@ * Hhaboh162002 * Kassem7899 * LaMagiaaa +* Lolekek * Meno25 * Mido * Monrokhoury @@ -853,6 +854,7 @@ نقاش اكتب شيئًا عن العنصر \'%1$s\'. سيكون مرئيًا للعامة. \'%1$s\' لم يعد موجودًا، ولا يمكن التقاط صورة له أبدًا. + \'%1$s\' في مكان آخر. \'%1$s\' موجود في مكان مختلف. يرجى تحديد المكان الصحيح أدناه، وإذا أمكن، اكتب خط العرض وخط الطول الصحيحين. مشكلة أو معلومات أخرى (يرجى التوضيح أدناه). سيتم نشر تعليقاتك على صفحة الويكي التالية: <a href=\"https://commons.wikimedia.org/wiki/Commons:Mobile_app/Feedback\">Commons:Mobile app/Feedback</a> diff --git a/app/src/main/res/values-da/strings.xml b/app/src/main/res/values-da/strings.xml index 106959d04..bc2b23dbf 100644 --- a/app/src/main/res/values-da/strings.xml +++ b/app/src/main/res/values-da/strings.xml @@ -789,6 +789,7 @@ Tal Skriv noget om elementet \'%1$s\'. Det vil være offentligt synligt. \'%1$s\' eksisterer ikke længere, der vil aldrig kunne tages et billede af det. + \'%1$s\' ligger et andet sted. \'%1$s\' ligger et andet sted. Angiv venligst det korrekte sted nedenfor, og skriv om muligt den korrekte bredde- og længdegrad. Andet problem eller anden information (forklar venligst nedenfor). Din feedback bliver slået op på følgende wiki-side: <a href=\"https://commons.wikimedia.org/wiki/Commons:Mobile_app/Feedback\">Commons:Mobile app/Feedback</a> diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index d8854df10..9603f1806 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -829,6 +829,7 @@ Discussion Écrivez quelque chose à propos de l’élément « %1$s ». Il sera visible publiquement. \'%1$s\' n\'existe plus, aucune photo ne pourra jamais en être prise. + \'%1$s\' est à un endroit différent. \'%1$s\' se trouve à un endroit différent. Veuillez indiquer l\'endroit correct ci-dessous et, si possible, indiquez la latitude et la longitude correctes. Autre problème ou information (merci d\'expliquer ci-dessous). Vos commentaires sont publiés sur la page wiki suivante : <a href=\"https://commons.wikimedia.org/wiki/Commons:Mobile_app/Feedback\">Commons:Mobile app/Feedback</a> diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index 967b49e8d..662ddcd23 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -303,7 +303,7 @@ やり直す 以下のとおり、近くにウィキペディアの記事に使う写真が足りない場所があります。\n\n\'この近くを検索\' ボタンを押すと、地図をロックしてその地点周辺の検索結果を表示します。 この場所の写真を募集中です。 - この場所の写真はすでにあります。 + この場所の写真は既にあります。 この場所はもうありません 画像がありません 画像の読み込み中にエラーが発生しました @@ -393,7 +393,7 @@ 全部で%2$d件のうち%1$d件目の手順:%3$s 次へ 前へ - %1$s という題名のファイルはすでに保存されています。処理をほんとうに続けますか?\n\n注記:ファイル名には適切な接頭辞が自動的に付与されます。 + %1$s という名前のファイルは既に存在します。本当に処理を続行してよろしいですか?\n\n注: ファイル名には適切な接尾辞が自動的に付加されます。 お使いの機器に適したアプリが見つかりませんでした。この機能を使用できる地図アプリをインストールしてください。 画像 位置 @@ -668,7 +668,7 @@ あなたのフィードバック アップロード不可としてマーク これ以上画像が見つかりません - この画像はすでにアップロードされています + この画像は既にアップロードされています この画像をアップロード用に選択できません 画像が選択されました 報告 diff --git a/app/src/main/res/values-ps/strings.xml b/app/src/main/res/values-ps/strings.xml index 83d30e8b7..a9ecd54f9 100644 --- a/app/src/main/res/values-ps/strings.xml +++ b/app/src/main/res/values-ps/strings.xml @@ -143,7 +143,9 @@ وېشنيزه ملگرو بياکتنه په اړه - <a href=\"https://wikimediafoundation.org/wiki/Privacy_policy\">د پټنتيا تگلاره</a> + د ويکي‌رسنۍ خونديځ کاريال يو پرانيستې سرچينې کاريال دی چې د ويکي‌رسنۍ ټولنې د بسپنه ورکوونکو او خپل‌خوښو کارنانو له خوا جوړ شوی او ساتل کېږي. د ويکي‌رسنۍ بنسټ د دې کاريال په جوړولو، پراختيا او ساتنه کې ښکېل نه دی. + د بگ راپور او وړانديزونو لپاره يوه <a href=\"%1$s\">گيټ هاب ستونزه</a> جوړه کړئ. + د پټنتيا تگلار په اړه غبرگون لېږنه (برېښليک له لارې) هيڅ برېښليک سرچينه نه ده ځای پرځای شوې @@ -161,13 +163,36 @@ ځانگړي کونگ-ورته وېشنه ۳.۰ ځانگړي کونگ ۳.۰ CC BY 3.0 + ستاسو انځورونه د نړۍ په گوټ گوټ کې خلکو ته زده کړه ورکوي! + مهرباني وکړئ هغه انځورونه راپورته کړئ چې په بشپړ ډول تاسو اخيستي يا جوړ کړې وي: + طبيعي څيزونه (گلان، څاروي، غرونه) + گټور څيزونه (بايسيکلونه، اورگډو تمځايونه) + نوميالي وگړي (ستاسو ښاروال، اولمپيک لوبغاړی چې تاسو ورسره وليدل) + مهرباني وکړئ مه يې راپورته کوئ: + د خپلو ملگرو ځان‌انځورنه او انځورونه + هغه انځورنه چې تاسو له اينټرنېټ څخه راکښته کړې وي + د ملکيتي کاريالونو سکرين‌شاټونه + د پورته کولو بېلگه: + سرليک: سيډني اوپېرا هاوس + څرگنداوی: د خليج له خوا د سيډني اوپېرا هاوس ليدنه + وېشنيزې: له لوېديځ څخه د سېډني اوپېرا هاوس ، د سېډني اوپېرا هاوس لرليد + خپل انځورونه شريک کړئ. د ويکيپېډيا ليکنو ته ژوند ورکولو کې مرسته وکړئ! + په ويکيپېډيا کې دا انځورونه له ويکيمېډيا خونديځ نه اخيستل شوي دي. + ستاسو انځورونه د نړۍ په گوټ گوټ کې خلکو ته زده کړه ورکوي! + له اينټرنېته د لمېس رېښتو لرونکو موادو او د پوسټرونو، کتاب پوښونو او نورو انځورنو د خپرلو څخه ډډه وکړئ. + ستا په اند ته پوه شوې؟ هو + نور مالومات وېشنيزې رابرسېرېږي... هېڅ هم نه دی ټاکل شوی + هيڅ نيونگ نشته څرگندونه نشته + هيڅ شننه نشته نامعلوم جواز تازه کول + د زېرمه کولو د پرېښولي غوښتنه کول + اړينه پرېښولی: بهرنۍ زېرمه ولولئ. کاريال ستاسو انځورتونه ته پرته له دې لاسرسی نشي موندلی. ښه گواښنه هو From c49c85e68bed7c73efde41728bf6c39cac9be558 Mon Sep 17 00:00:00 2001 From: Sonal Yadav Date: Wed, 28 May 2025 14:23:28 +0530 Subject: [PATCH 006/162] Fix : UninitializedPropertyAccessException (#6248) * Fix crash when uploading a duplicate file * Fix: app crash * added Kdoc * remove line b/w kdoc and function --------- Co-authored-by: Nicolas Raoul --- .../free/nrw/commons/upload/UploadActivity.kt | 4 ++- .../nrw/commons/upload/UploadPresenter.kt | 29 +++++++++++++++++-- 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/fr/free/nrw/commons/upload/UploadActivity.kt b/app/src/main/java/fr/free/nrw/commons/upload/UploadActivity.kt index ee0b21210..38e7dace8 100644 --- a/app/src/main/java/fr/free/nrw/commons/upload/UploadActivity.kt +++ b/app/src/main/java/fr/free/nrw/commons/upload/UploadActivity.kt @@ -173,6 +173,9 @@ class UploadActivity : BaseActivity(), UploadContract.View, UploadBaseFragment.C override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + // Ensure basicKvStoreFactory is always initialized before use + presenter?.setupBasicKvStoreFactory { BasicKvStore(this@UploadActivity, it) } + _binding = ActivityUploadBinding.inflate(layoutInflater) setContentView(binding.root) @@ -903,7 +906,6 @@ class UploadActivity : BaseActivity(), UploadContract.View, UploadBaseFragment.C // Save the user's choice to not show the dialog again defaultKvStore.putBoolean("hasAlreadyLaunchedCategoriesDialog", true) } - presenter!!.setupBasicKvStoreFactory { BasicKvStore(this@UploadActivity, it) } presenter!!.checkImageQuality(0) UploadMediaPresenter.isCategoriesDialogShowing = false } diff --git a/app/src/main/java/fr/free/nrw/commons/upload/UploadPresenter.kt b/app/src/main/java/fr/free/nrw/commons/upload/UploadPresenter.kt index 5d721f408..251f868ad 100644 --- a/app/src/main/java/fr/free/nrw/commons/upload/UploadPresenter.kt +++ b/app/src/main/java/fr/free/nrw/commons/upload/UploadPresenter.kt @@ -34,8 +34,7 @@ class UploadPresenter @Inject internal constructor( private val compositeDisposable = CompositeDisposable() - lateinit var basicKvStoreFactory: (String) -> BasicKvStore - + private var basicKvStoreFactory: ((String) -> BasicKvStore)? = null /** * Called by the submit button in [UploadActivity] */ @@ -132,14 +131,38 @@ class UploadPresenter @Inject internal constructor( basicKvStoreFactory = factory } + /** + * Returns the current BasicKvStore factory or throws if not initialized. + * + * @throws IllegalStateException if basicKvStoreFactory has not been initialized. + */ + private fun getBasicKvStoreFactory(): (String) -> BasicKvStore { + return basicKvStoreFactory ?: throw IllegalStateException("basicKvStoreFactory has not been initialized") + } + + /** + * Ensures that the BasicKvStore factory has been initialized before use. + * + * @throws IllegalStateException if the factory is null. + */ + private fun requireFactoryInitialized() { + val field = this::class.java.getDeclaredField("basicKvStoreFactory") + field.isAccessible = true + val value = field.get(this) + if (value == null) { + throw IllegalStateException("basicKvStoreFactory must be initialized before use. Please call setupBasicKvStoreFactory() before using presenter methods that require it.") + } + } + /** * Calls checkImageQuality of UploadMediaPresenter to check image quality of next image * * @param uploadItemIndex Index of next image, whose quality is to be checked */ override fun checkImageQuality(uploadItemIndex: Int) { + requireFactoryInitialized() repository.getUploadItem(uploadItemIndex)?.let { - presenter.setupBasicKvStoreFactory(basicKvStoreFactory) + presenter.setupBasicKvStoreFactory(getBasicKvStoreFactory()) presenter.checkImageQuality(it, uploadItemIndex) } } From ed1485ca2223a4e5859e29e83860e9cd99b2cb7a Mon Sep 17 00:00:00 2001 From: Rohit Verma <101377978+rohit9625@users.noreply.github.com> Date: Wed, 28 May 2025 17:13:13 +0530 Subject: [PATCH 007/162] Migrated from Groovy to Kotlin DSL and upgrade AGP version (#6322) * chore: migrate groovy build files to Kotlin DSL and upgrade AGP chore: use version catalog to manage dependencies chore: move plugins to version catalog remove deprecated way of enabling build-config and redundant code chore: setup triplet-play plugin configuration refactor: move dependency block and tasks to the end of build file refactor: move dependency block and mark redundant dependencies * cleanup: remove redundant dependencies from build file * cleanup: remove git utils file as the functions moved to build file --------- Co-authored-by: Nicolas Raoul --- app/build.gradle | 431 ---------------------- app/build.gradle.kts | 445 +++++++++++++++++++++++ build.gradle | 29 -- build.gradle.kts | 13 + gitutils.gradle | 26 -- gradle.properties | 14 - gradle/libs.versions.toml | 209 +++++++++++ gradle/wrapper/gradle-wrapper.properties | 2 +- settings.gradle | 1 - settings.gradle.kts | 17 + 10 files changed, 685 insertions(+), 502 deletions(-) delete mode 100644 app/build.gradle create mode 100644 app/build.gradle.kts delete mode 100644 build.gradle create mode 100644 build.gradle.kts delete mode 100644 gitutils.gradle create mode 100644 gradle/libs.versions.toml delete mode 100644 settings.gradle create mode 100644 settings.gradle.kts diff --git a/app/build.gradle b/app/build.gradle deleted file mode 100644 index 34dd7f008..000000000 --- a/app/build.gradle +++ /dev/null @@ -1,431 +0,0 @@ -plugins { - id 'com.github.triplet.play' version '2.7.2' apply false -} -apply from: '../gitutils.gradle' -apply plugin: 'com.android.application' -apply plugin: 'kotlin-android' -apply plugin: 'kotlin-kapt' -apply plugin: 'kotlin-parcelize' -apply from: "$rootDir/jacoco.gradle" - -def isRunningOnTravisAndIsNotPRBuild = System.getenv("CI") == "true" && file('../play.p12').exists() - -if (isRunningOnTravisAndIsNotPRBuild) { - apply plugin: 'com.github.triplet.play' -} - -dependencies { - - // Utils - implementation 'in.yuvi:http.fluent:1.3' - implementation 'com.google.code.gson:gson:2.8.5' - implementation ("com.squareup.okhttp3:okhttp:$OKHTTP_VERSION!!"){ - // Forcing dependency versions using force = true on a first-level dependency has been deprecated. - // Ref: https://docs.gradle.org/7.5/userguide/upgrading_version_5.html#forced_dependencies - //force = true //API 19 support - } - implementation 'com.squareup.retrofit2:retrofit:2.8.1' - implementation "com.squareup.retrofit2:converter-gson:2.8.1" - implementation "com.squareup.retrofit2:adapter-rxjava2:2.8.1" - implementation 'com.squareup.okio:okio:2.2.2' - implementation 'io.reactivex.rxjava2:rxandroid:2.1.0' - implementation 'io.reactivex.rxjava2:rxjava:2.2.3' - implementation 'com.jakewharton.rxbinding2:rxbinding:2.1.1' - implementation 'com.jakewharton.rxbinding3:rxbinding-appcompat:3.0.0' - implementation 'com.jakewharton.rxbinding2:rxbinding-support-v4:2.1.1' - implementation 'com.jakewharton.rxbinding2:rxbinding-appcompat-v7:2.1.1' - implementation 'com.jakewharton.rxbinding2:rxbinding-design:2.1.1' - implementation 'com.facebook.fresco:fresco:1.13.0' - implementation 'org.apache.commons:commons-lang3:3.8.1' - - // UI - implementation 'fr.avianey.com.viewpagerindicator:library:2.4.1.1@aar' - implementation 'com.github.chrisbanes:PhotoView:2.0.0' - implementation 'com.github.pedrovgs:renderers:3.3.3' - implementation "org.maplibre.gl:android-sdk:$MAPLIBRE_VERSION" - implementation 'org.maplibre.gl:android-plugin-scalebar-v9:1.0.0' - - implementation 'com.jakewharton.timber:timber:4.7.1' - implementation 'com.github.deano2390:MaterialShowcaseView:1.2.0' - implementation "com.google.android.material:material:1.12.0" - implementation 'com.karumi:dexter:5.0.0' - implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0' - implementation 'androidx.compose.ui:ui-tooling-preview' - androidTestImplementation 'androidx.compose.ui:ui-test-junit4' - - // Jetpack Compose - def composeBom = platform('androidx.compose:compose-bom:2024.11.00') - - implementation "androidx.activity:activity-compose:1.9.3" - implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.8.4" - implementation (composeBom) - implementation "androidx.compose.runtime:runtime" - implementation "androidx.compose.ui:ui" - implementation "androidx.compose.ui:ui-viewbinding" - implementation "androidx.compose.ui:ui-graphics" - implementation "androidx.compose.ui:ui-tooling" - implementation "androidx.compose.foundation:foundation" - implementation "androidx.compose.foundation:foundation-layout" - implementation "androidx.compose.material3:material3" - androidTestImplementation(composeBom) - - implementation "com.hannesdorfmann:adapterdelegates4-kotlin-dsl-viewbinding:$ADAPTER_DELEGATES_VERSION" - implementation "com.hannesdorfmann:adapterdelegates4-pagination:$ADAPTER_DELEGATES_VERSION" - implementation "androidx.paging:paging-runtime-ktx:$PAGING_VERSION" - testImplementation "androidx.paging:paging-common-ktx:$PAGING_VERSION" - implementation "androidx.paging:paging-rxjava2-ktx:$PAGING_VERSION" - implementation "androidx.recyclerview:recyclerview:1.2.0-alpha02" - implementation "com.squareup.okhttp3:okhttp-ws:$OKHTTP_VERSION" - - // Logging - implementation 'ch.acra:acra-dialog:5.8.4' - implementation 'ch.acra:acra-mail:5.8.4' - implementation 'org.slf4j:slf4j-api:1.7.25' - api('com.github.tony19:logback-android-classic:1.1.1-6') { - exclude group: 'com.google.android', module: 'android' - } - implementation "com.squareup.okhttp3:logging-interceptor:$OKHTTP_VERSION" - - // Dependency injector - implementation "com.google.dagger:dagger-android:$DAGGER_VERSION" - implementation "com.google.dagger:dagger-android-support:$DAGGER_VERSION" - debugImplementation 'androidx.compose.ui:ui-tooling' - debugImplementation 'androidx.compose.ui:ui-test-manifest' - kapt "com.google.dagger:dagger-android-processor:$DAGGER_VERSION" - kapt "com.google.dagger:dagger-compiler:$DAGGER_VERSION" - annotationProcessor "com.google.dagger:dagger-android-processor:$DAGGER_VERSION" - - implementation "org.jetbrains.kotlin:kotlin-reflect:$KOTLIN_VERSION" - - //Mocking - testImplementation 'com.nhaarman.mockitokotlin2:mockito-kotlin:2.2.0' - testImplementation 'org.mockito:mockito-inline:5.2.0' - testImplementation 'org.mockito:mockito-core:5.6.0' - testImplementation "org.powermock:powermock-module-junit4:2.0.9" - testImplementation "org.powermock:powermock-api-mockito2:2.0.9" - testImplementation("io.mockk:mockk:1.13.5") - - // Unit testing - testImplementation 'junit:junit:4.13.2' - testImplementation 'org.robolectric:robolectric:4.11.1' - testImplementation 'androidx.test:core:1.5.0' - testImplementation "androidx.test:runner:1.5.2" - testImplementation 'androidx.test.ext:junit:1.1.5' - testImplementation "androidx.test:rules:1.5.0" - testImplementation "com.squareup.okhttp3:mockwebserver:$OKHTTP_VERSION" - testImplementation "com.jraska.livedata:testing-ktx:1.2.0" - testImplementation "androidx.arch.core:core-testing:2.2.0" - testImplementation "org.junit.jupiter:junit-jupiter-api:5.10.0" - testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:5.10.0" - testImplementation 'com.facebook.soloader:soloader:0.10.5' - testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:1.7.3" - debugImplementation("androidx.fragment:fragment-testing-manifest:1.6.2") - androidTestImplementation("androidx.fragment:fragment-testing:1.6.2") - testImplementation "commons-io:commons-io:2.6" - - // Android testing - androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.0-alpha04' - androidTestImplementation 'androidx.test.espresso:espresso-intents:3.4.0' - androidTestImplementation 'androidx.test.espresso:espresso-contrib:3.5.0-alpha04' - androidTestImplementation 'androidx.test:runner:1.4.0' - androidTestImplementation 'androidx.test:rules:1.4.1-alpha04' - androidTestImplementation 'androidx.test:core:1.4.0' - androidTestImplementation 'androidx.test.ext:junit:1.1.3' - androidTestImplementation 'androidx.annotation:annotation:1.3.0' - androidTestImplementation 'com.squareup.okhttp3:mockwebserver:4.8.0' - androidTestImplementation "androidx.test.uiautomator:uiautomator:2.2.0" - androidTestUtil 'androidx.test:orchestrator:1.4.1' - - // Debugging - debugImplementation "com.squareup.leakcanary:leakcanary-android:$LEAK_CANARY_VERSION" - - // Support libraries - implementation "com.google.android.material:material:1.1.0-alpha04" - implementation "androidx.browser:browser:1.3.0" - implementation "androidx.cardview:cardview:1.0.0" - implementation 'androidx.constraintlayout:constraintlayout:1.1.3' - implementation 'androidx.exifinterface:exifinterface:1.3.7' - implementation "androidx.core:core-ktx:$CORE_KTX_VERSION" - implementation 'com.simplecityapps:recyclerview-fastscroll:2.0.1' - - //swipe_layout - implementation 'com.daimajia.swipelayout:library:1.2.0@aar' - - //Room - implementation "androidx.room:room-runtime:$ROOM_VERSION" - implementation "androidx.room:room-ktx:$ROOM_VERSION" - implementation "androidx.room:room-rxjava2:$ROOM_VERSION" - kapt "androidx.room:room-compiler:$ROOM_VERSION" - // For Kotlin use kapt instead of annotationProcessor - testImplementation "androidx.arch.core:core-testing:2.1.0" - - // Pref - // Java language implementation - implementation "androidx.preference:preference:$PREFERENCE_VERSION" - // Kotlin - implementation "androidx.preference:preference-ktx:$PREFERENCE_VERSION" - //Android Media - implementation 'com.github.juanitobananas:AndroidMediaUtil:v1.0-1' - - implementation "androidx.multidex:multidex:$MULTIDEX_VERSION" - - def work_version = "2.8.1" - // Kotlin + coroutines - implementation "androidx.work:work-runtime-ktx:$work_version" - implementation("androidx.work:work-runtime:$work_version") - testImplementation "androidx.work:work-testing:$work_version" - - //Glide - implementation 'com.github.bumptech.glide:glide:4.16.0' - annotationProcessor 'com.github.bumptech.glide:compiler:4.16.0' - kaptTest "androidx.databinding:databinding-compiler:8.0.2" - kaptAndroidTest "androidx.databinding:databinding-compiler:8.0.2" - - implementation("io.github.coordinates2country:coordinates2country-android:1.8") { exclude group: 'com.google.android', module: 'android' } - - //OSMDroid - implementation ("org.osmdroid:osmdroid-android:$OSMDROID_VERSION") - constraints { - implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.8.0") { - because("kotlin-stdlib-jdk7 is now a part of kotlin-stdlib") - } - implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.8.0") { - because("kotlin-stdlib-jdk8 is now a part of kotlin-stdlib") - } - } -} - -task disableAnimations(type: Exec) { - def adb = "$System.env.ANDROID_HOME/platform-tools/adb" - commandLine "$adb", 'shell', 'settings', 'put', 'global', 'window_animation_scale', '0' - commandLine "$adb", 'shell', 'settings', 'put', 'global', 'transition_animation_scale', '0' - commandLine "$adb", 'shell', 'settings', 'put', 'global', 'animator_duration_scale', '0' -} - -project.gradle.taskGraph.whenReady { - connectedBetaDebugAndroidTest.dependsOn disableAnimations - connectedProdDebugAndroidTest.dependsOn disableAnimations -} - -android { - compileSdkVersion 34 - - defaultConfig { - //applicationId 'fr.free.nrw.commons' - - versionCode 1051 - versionName '5.4.0' - setProperty("archivesBaseName", "app-commons-v$versionName-" + getBranchName()) - - minSdkVersion 21 - targetSdkVersion 34 - testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" - testInstrumentationRunnerArguments clearPackageData: 'true' - - multiDexEnabled true - - testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" - - vectorDrawables.useSupportLibrary = true - } - packagingOptions { - jniLibs { - excludes += ['META-INF/androidx.*'] - } - resources { - excludes += ['META-INF/androidx.*', 'META-INF/proguard/androidx-annotations.pro', '/META-INF/LICENSE.md', '/META-INF/LICENSE-notice.md'] - } - } - - - testOptions { - animationsDisabled true - - unitTests { - returnDefaultValues = true - includeAndroidResources = true - } - - unitTests.all { - jvmArgs '-noverify' - } - } - - sourceSets { - // use kotlin only in tests (for now) - test.java.srcDirs += 'src/test/kotlin' - - // use main assets and resources in test - test.assets.srcDirs += 'src/main/assets' - test.resources.srcDirs += 'src/main/resoures' - } - - signingConfigs { - release - } - - buildTypes { - release { - minifyEnabled true - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt' - testProguardFile 'test-proguard-rules.txt' - signingConfig signingConfigs.debug - if (isRunningOnTravisAndIsNotPRBuild) { - signingConfig signingConfigs.release - } - } - debug { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt' - testProguardFile 'test-proguard-rules.txt' - versionNameSuffix "-debug-" + getBranchName() - enableUnitTestCoverage true - enableAndroidTestCoverage true - } - } - - if (isRunningOnTravisAndIsNotPRBuild) { - // configure keystore based on env vars in Travis for automated alpha builds - signingConfigs.release.storeFile = file("../nr-commons.keystore") - signingConfigs.release.storePassword = System.getenv("keystore_password") - signingConfigs.release.keyAlias = System.getenv("key_alias") - signingConfigs.release.keyPassword = System.getenv("key_password") - } - - configurations.all { - resolutionStrategy.force 'androidx.annotation:annotation:1.1.0' - resolutionStrategy.force 'com.jakewharton.timber:timber:4.7.1' - resolutionStrategy.force 'androidx.fragment:fragment:1.3.6' - exclude module: 'okhttp-ws' - } - flavorDimensions 'tier' - productFlavors { - prod { - - applicationId 'fr.free.nrw.commons' - - buildConfigField "String", "WIKIMEDIA_API_POTD", "\"https://commons.wikimedia.org/w/api.php?action=featuredfeed&feed=potd&feedformat=rss&language=en\"" - buildConfigField "String", "WIKIMEDIA_API_HOST", "\"https://commons.wikimedia.org/w/api.php\"" - buildConfigField "String", "WIKIDATA_API_HOST", "\"https://www.wikidata.org/w/api.php\"" - buildConfigField "String", "WIKIDATA_URL", "\"https://www.wikidata.org\"" - buildConfigField "String", "WIKIMEDIA_FORGE_API_HOST", "\"https://tools.wmflabs.org/\"" - buildConfigField "String", "WIKIMEDIA_CAMPAIGNS_URL", "\"https://raw.githubusercontent.com/commons-app/campaigns/master/campaigns.json\"" - buildConfigField "String", "IMAGE_URL_BASE", "\"https://upload.wikimedia.org/wikipedia/commons\"" - buildConfigField "String", "HOME_URL", "\"https://commons.wikimedia.org/wiki/\"" - buildConfigField "String", "COMMONS_URL", "\"https://commons.wikimedia.org\"" - buildConfigField "String", "WIKIDATA_URL", "\"https://www.wikidata.org\"" - buildConfigField "String", "MOBILE_HOME_URL", "\"https://commons.m.wikimedia.org/wiki/\"" - buildConfigField "String", "MOBILE_META_URL", "\"https://meta.m.wikimedia.org/wiki/\"" - buildConfigField "String", "SIGNUP_LANDING_URL", "\"https://commons.m.wikimedia.org/w/index.php?title=Special:CreateAccount&returnto=Main+Page&returntoquery=welcome%3Dyes\"" - buildConfigField "String", "SIGNUP_SUCCESS_REDIRECTION_URL", "\"https://commons.m.wikimedia.org/w/index.php?title=Main_Page&welcome=yes\"" - buildConfigField "String", "FORGOT_PASSWORD_URL", "\"https://commons.wikimedia.org/wiki/Special:PasswordReset\"" - buildConfigField "String", "PRIVACY_POLICY_URL", "\"https://commons-app.github.io/privacy-policy\"" - buildConfigField "String", "FILE_USAGES_BASE_URL", "\"https://commons.wikimedia.org/w/api.php?action=query&format=json&formatversion=2\"" - buildConfigField "String", "ACCOUNT_TYPE", "\"fr.free.nrw.commons\"" - buildConfigField "String", "CONTRIBUTION_AUTHORITY", "\"fr.free.nrw.commons.contributions.contentprovider\"" - buildConfigField "String", "MODIFICATION_AUTHORITY", "\"fr.free.nrw.commons.modifications.contentprovider\"" - buildConfigField "String", "CATEGORY_AUTHORITY", "\"fr.free.nrw.commons.categories.contentprovider\"" - buildConfigField "String", "RECENT_SEARCH_AUTHORITY", "\"fr.free.nrw.commons.explore.recentsearches.contentprovider\"" - buildConfigField "String", "RECENT_LANGUAGE_AUTHORITY", "\"fr.free.nrw.commons.recentlanguages.contentprovider\"" - buildConfigField "String", "BOOKMARK_AUTHORITY", "\"fr.free.nrw.commons.bookmarks.contentprovider\"" - buildConfigField "String", "BOOKMARK_LOCATIONS_AUTHORITY", "\"fr.free.nrw.commons.bookmarks.locations.contentprovider\"" - buildConfigField "String", "BOOKMARK_ITEMS_AUTHORITY", "\"fr.free.nrw.commons.bookmarks.items.contentprovider\"" - buildConfigField "String", "COMMIT_SHA", "\"" + getBuildVersion().toString() + "\"" - buildConfigField "String", "TEST_USERNAME", "\"" + getTestUserName() + "\"" - buildConfigField "String", "TEST_PASSWORD", "\"" + getTestPassword() + "\"" - buildConfigField "String", "DEPICTS_PROPERTY", "\"P180\"" - buildConfigField "String", "CREATOR_PROPERTY", "\"P170\"" - dimension 'tier' - } - - beta { - applicationId 'fr.free.nrw.commons.beta' - - // What values do we need to hit the BETA versions of the site / api ? - buildConfigField "String", "WIKIMEDIA_API_POTD", "\"https://commons.wikimedia.org/w/api.php?action=featuredfeed&feed=potd&feedformat=rss&language=en\"" - buildConfigField "String", "WIKIMEDIA_API_HOST", "\"https://commons.wikimedia.beta.wmflabs.org/w/api.php\"" - buildConfigField "String", "WIKIDATA_API_HOST", "\"https://www.wikidata.org/w/api.php\"" - buildConfigField "String", "WIKIDATA_URL", "\"https://www.wikidata.org\"" - buildConfigField "String", "WIKIMEDIA_FORGE_API_HOST", "\"https://tools.wmflabs.org/\"" - buildConfigField "String", "WIKIMEDIA_CAMPAIGNS_URL", "\"https://raw.githubusercontent.com/commons-app/campaigns/master/campaigns_beta_active.json\"" - buildConfigField "String", "IMAGE_URL_BASE", "\"https://upload.beta.wmflabs.org/wikipedia/commons\"" - buildConfigField "String", "HOME_URL", "\"https://commons.wikimedia.beta.wmflabs.org/wiki/\"" - buildConfigField "String", "COMMONS_URL", "\"https://commons.wikimedia.beta.wmflabs.org\"" - buildConfigField "String", "WIKIDATA_URL", "\"https://www.wikidata.org\"" - buildConfigField "String", "MOBILE_HOME_URL", "\"https://commons.m.wikimedia.beta.wmflabs.org/wiki/\"" - buildConfigField "String", "MOBILE_META_URL", "\"https://meta.m.wikimedia.beta.wmflabs.org/wiki/\"" - buildConfigField "String", "SIGNUP_LANDING_URL", "\"https://commons.m.wikimedia.beta.wmflabs.org/w/index.php?title=Special:CreateAccount&returnto=Main+Page&returntoquery=welcome%3Dyes\"" - buildConfigField "String", "SIGNUP_SUCCESS_REDIRECTION_URL", "\"https://commons.m.wikimedia.beta.wmflabs.org/w/index.php?title=Main_Page&welcome=yes\"" - buildConfigField "String", "FORGOT_PASSWORD_URL", "\"https://commons.wikimedia.beta.wmflabs.org/wiki/Special:PasswordReset\"" - buildConfigField "String", "PRIVACY_POLICY_URL", "\"https://commons-app.github.io/privacy-policy\"" - buildConfigField "String", "FILE_USAGES_BASE_URL", "\"https://commons.wikimedia.org/w/api.php?action=query&format=json&formatversion=2\"" - buildConfigField "String", "ACCOUNT_TYPE", "\"fr.free.nrw.commons.beta\"" - buildConfigField "String", "CONTRIBUTION_AUTHORITY", "\"fr.free.nrw.commons.beta.contributions.contentprovider\"" - buildConfigField "String", "MODIFICATION_AUTHORITY", "\"fr.free.nrw.commons.beta.modifications.contentprovider\"" - buildConfigField "String", "CATEGORY_AUTHORITY", "\"fr.free.nrw.commons.beta.categories.contentprovider\"" - buildConfigField "String", "RECENT_SEARCH_AUTHORITY", "\"fr.free.nrw.commons.beta.explore.recentsearches.contentprovider\"" - buildConfigField "String", "RECENT_LANGUAGE_AUTHORITY", "\"fr.free.nrw.commons.beta.recentlanguages.contentprovider\"" - buildConfigField "String", "BOOKMARK_AUTHORITY", "\"fr.free.nrw.commons.beta.bookmarks.contentprovider\"" - buildConfigField "String", "BOOKMARK_LOCATIONS_AUTHORITY", "\"fr.free.nrw.commons.beta.bookmarks.locations.contentprovider\"" - buildConfigField "String", "BOOKMARK_ITEMS_AUTHORITY", "\"fr.free.nrw.commons.beta.bookmarks.items.contentprovider\"" - buildConfigField "String", "COMMIT_SHA", "\"" + getBuildVersion().toString() + "\"" - buildConfigField "String", "TEST_USERNAME", "\"" + getTestUserName() + "\"" - buildConfigField "String", "TEST_PASSWORD", "\"" + getTestPassword() + "\"" - buildConfigField "String", "DEPICTS_PROPERTY", "\"P245962\"" - buildConfigField "String", "CREATOR_PROPERTY", "\"P253075\"" - dimension 'tier' - } - } - - - compileOptions { - sourceCompatibility JavaVersion.VERSION_17 - targetCompatibility JavaVersion.VERSION_17 - } - kotlinOptions { - jvmTarget = "17" - } - - buildToolsVersion buildToolsVersion - - buildFeatures { - viewBinding true - compose true - } - composeOptions { - kotlinCompilerExtensionVersion '1.5.8' - } - namespace 'fr.free.nrw.commons' - lint { - abortOnError false - disable 'MissingTranslation', 'ExtraTranslation' - } -} - -String getTestUserName() { - def propFile = rootProject.file("./local.properties") - def properties = new Properties() - properties.load(new FileInputStream(propFile)) - return properties['TEST_USER_NAME'] -} - -String getTestPassword() { - def propFile = rootProject.file("./local.properties") - def properties = new Properties() - properties.load(new FileInputStream(propFile)) - return properties['TEST_USER_PASSWORD'] -} - -if (isRunningOnTravisAndIsNotPRBuild) { - play { - track = "alpha" - userFraction = 1 - serviceAccountEmail = System.getenv("SERVICE_ACCOUNT_NAME") - serviceAccountCredentials = file("../play.p12") - - resolutionStrategy = "auto" - outputProcessor { // this: ApkVariantOutput - versionNameOverride = "$versionNameOverride.$versionCode" - } - } -} diff --git a/app/build.gradle.kts b/app/build.gradle.kts new file mode 100644 index 000000000..c74f95fb4 --- /dev/null +++ b/app/build.gradle.kts @@ -0,0 +1,445 @@ +import java.util.Properties +import java.io.ByteArrayOutputStream + +plugins { + alias(libs.plugins.android.application) + alias(libs.plugins.jetbrains.kotlin.android) + alias(libs.plugins.kotlin.kapt) + alias(libs.plugins.kotlin.parcelize) +} + +apply(from = "$rootDir/jacoco.gradle") + +val isRunningOnTravisAndIsNotPRBuild = System.getenv("CI") == "true" && file("../play.p12").exists() + +if (isRunningOnTravisAndIsNotPRBuild) { + apply(plugin = "com.github.triplet.play") +} + +android { + namespace = "fr.free.nrw.commons" + compileSdk = 34 + + defaultConfig { + applicationId = "fr.free.nrw.commons" + minSdk = 21 + targetSdk = 34 + versionCode = 1043 + versionName = "5.1.2" + + setProperty("archivesBaseName", "app-commons-v$versionName-" + getBranchName()) + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + testInstrumentationRunnerArguments["clearPackageData"] = "true" + + multiDexEnabled = true + + vectorDrawables { + useSupportLibrary = true + } + } + + sourceSets { + getByName("test") { + // Use kotlin only in tests (for now) + java.srcDirs("src/test/kotlin") + + // Use main assets and resources in test + assets.srcDirs("src/main/assets") + resources.srcDirs("src/main/resources") + } + } + + signingConfigs { + create("release") { + // Configure keystore based on env vars in Travis for automated alpha builds + if(isRunningOnTravisAndIsNotPRBuild) { + storeFile = file("../nr-commons.keystore") + storePassword = System.getenv("keystore_password") + keyAlias = System.getenv("key_alias") + keyPassword = System.getenv("key_password") + } + } + } + + buildTypes { + release { + isMinifyEnabled = true + proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.txt") + testProguardFile("test-proguard-rules.txt") + + signingConfig = signingConfigs.getByName("debug") + if (isRunningOnTravisAndIsNotPRBuild) { + signingConfig = signingConfigs.getByName("release") + } + } + debug { + isMinifyEnabled = false + proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.txt") + testProguardFile("test-proguard-rules.txt") + + versionNameSuffix = "-debug-" + getBranchName() + enableUnitTestCoverage = true + enableAndroidTestCoverage = true + } + } + + configurations.all { + resolutionStrategy { + force("androidx.annotation:annotation:1.1.0") + force("com.jakewharton.timber:timber:4.7.1") + force("androidx.fragment:fragment:1.3.6") + } + exclude(module = "okhttp-ws") + } + + flavorDimensions += "tier" + productFlavors { + create("prod") { + dimension = "tier" + applicationId = "fr.free.nrw.commons" + + buildConfigField("String", "WIKIMEDIA_API_POTD", "\"https://commons.wikimedia.org/w/api.php?action=featuredfeed&feed=potd&feedformat=rss&language=en\"") + buildConfigField("String", "WIKIMEDIA_API_HOST", "\"https://commons.wikimedia.org/w/api.php\"") + buildConfigField("String", "WIKIDATA_API_HOST", "\"https://www.wikidata.org/w/api.php\"") + buildConfigField("String", "WIKIDATA_URL", "\"https://www.wikidata.org\"") + buildConfigField("String", "WIKIMEDIA_FORGE_API_HOST", "\"https://tools.wmflabs.org/\"") + buildConfigField("String", "WIKIMEDIA_CAMPAIGNS_URL", "\"https://raw.githubusercontent.com/commons-app/campaigns/master/campaigns.json\"") + buildConfigField("String", "IMAGE_URL_BASE", "\"https://upload.wikimedia.org/wikipedia/commons\"") + buildConfigField("String", "HOME_URL", "\"https://commons.wikimedia.org/wiki/\"") + buildConfigField("String", "COMMONS_URL", "\"https://commons.wikimedia.org\"") + buildConfigField("String", "WIKIDATA_URL", "\"https://www.wikidata.org\"") + buildConfigField("String", "MOBILE_HOME_URL", "\"https://commons.m.wikimedia.org/wiki/\"") + buildConfigField("String", "MOBILE_META_URL", "\"https://meta.m.wikimedia.org/wiki/\"") + buildConfigField("String", "SIGNUP_LANDING_URL", "\"https://commons.m.wikimedia.org/w/index.php?title=Special:CreateAccount&returnto=Main+Page&returntoquery=welcome%3Dyes\"") + buildConfigField("String", "SIGNUP_SUCCESS_REDIRECTION_URL", "\"https://commons.m.wikimedia.org/w/index.php?title=Main_Page&welcome=yes\"") + buildConfigField("String", "FORGOT_PASSWORD_URL", "\"https://commons.wikimedia.org/wiki/Special:PasswordReset\"") + buildConfigField("String", "PRIVACY_POLICY_URL", "\"https://github.com/commons-app/commons-app-documentation/blob/master/android/Privacy-policy.md\"") + buildConfigField("String", "FILE_USAGES_BASE_URL", "\"https://commons.wikimedia.org/w/api.php?action=query&format=json&formatversion=2\"") + buildConfigField("String", "ACCOUNT_TYPE", "\"fr.free.nrw.commons\"") + buildConfigField("String", "CONTRIBUTION_AUTHORITY", "\"fr.free.nrw.commons.contributions.contentprovider\"") + buildConfigField("String", "MODIFICATION_AUTHORITY", "\"fr.free.nrw.commons.modifications.contentprovider\"") + buildConfigField("String", "CATEGORY_AUTHORITY", "\"fr.free.nrw.commons.categories.contentprovider\"") + buildConfigField("String", "RECENT_SEARCH_AUTHORITY", "\"fr.free.nrw.commons.explore.recentsearches.contentprovider\"") + buildConfigField("String", "RECENT_LANGUAGE_AUTHORITY", "\"fr.free.nrw.commons.recentlanguages.contentprovider\"") + buildConfigField("String", "BOOKMARK_AUTHORITY", "\"fr.free.nrw.commons.bookmarks.contentprovider\"") + buildConfigField("String", "BOOKMARK_LOCATIONS_AUTHORITY", "\"fr.free.nrw.commons.bookmarks.locations.contentprovider\"") + buildConfigField("String", "BOOKMARK_ITEMS_AUTHORITY", "\"fr.free.nrw.commons.bookmarks.items.contentprovider\"") + buildConfigField("String", "COMMIT_SHA", "\"" + getBuildVersion().toString() + "\"") + buildConfigField("String", "TEST_USERNAME", "\"" + getTestUserName() + "\"") + buildConfigField("String", "TEST_PASSWORD", "\"" + getTestPassword() + "\"") + buildConfigField("String", "DEPICTS_PROPERTY", "\"P180\"") + buildConfigField("String", "CREATOR_PROPERTY", "\"P170\"") + } + + create("beta") { + dimension = "tier" + applicationId = "fr.free.nrw.commons.beta" + + // What values do we need to hit the BETA versions of the site / api ? + buildConfigField("String", "WIKIMEDIA_API_POTD", "\"https://commons.wikimedia.org/w/api.php?action=featuredfeed&feed=potd&feedformat=rss&language=en\"") + buildConfigField("String", "WIKIMEDIA_API_HOST", "\"https://commons.wikimedia.beta.wmflabs.org/w/api.php\"") + buildConfigField("String", "WIKIDATA_API_HOST", "\"https://www.wikidata.org/w/api.php\"") + buildConfigField("String", "WIKIDATA_URL", "\"https://www.wikidata.org\"") + buildConfigField("String", "WIKIMEDIA_FORGE_API_HOST", "\"https://tools.wmflabs.org/\"") + buildConfigField("String", "WIKIMEDIA_CAMPAIGNS_URL", "\"https://raw.githubusercontent.com/commons-app/campaigns/master/campaigns_beta_active.json\"") + buildConfigField("String", "IMAGE_URL_BASE", "\"https://upload.beta.wmflabs.org/wikipedia/commons\"") + buildConfigField("String", "HOME_URL", "\"https://commons.wikimedia.beta.wmflabs.org/wiki/\"") + buildConfigField("String", "COMMONS_URL", "\"https://commons.wikimedia.beta.wmflabs.org\"") + buildConfigField("String", "WIKIDATA_URL", "\"https://www.wikidata.org\"") + buildConfigField("String", "MOBILE_HOME_URL", "\"https://commons.m.wikimedia.beta.wmflabs.org/wiki/\"") + buildConfigField("String", "MOBILE_META_URL", "\"https://meta.m.wikimedia.beta.wmflabs.org/wiki/\"") + buildConfigField("String", "SIGNUP_LANDING_URL", "\"https://commons.m.wikimedia.beta.wmflabs.org/w/index.php?title=Special:CreateAccount&returnto=Main+Page&returntoquery=welcome%3Dyes\"") + buildConfigField("String", "SIGNUP_SUCCESS_REDIRECTION_URL", "\"https://commons.m.wikimedia.beta.wmflabs.org/w/index.php?title=Main_Page&welcome=yes\"") + buildConfigField("String", "FORGOT_PASSWORD_URL", "\"https://commons.wikimedia.beta.wmflabs.org/wiki/Special:PasswordReset\"") + buildConfigField("String", "PRIVACY_POLICY_URL", "\"https://github.com/commons-app/commons-app-documentation/blob/master/android/Privacy-policy.md\"") + buildConfigField("String", "FILE_USAGES_BASE_URL", "\"https://commons.wikimedia.org/w/api.php?action=query&format=json&formatversion=2\"") + buildConfigField("String", "ACCOUNT_TYPE", "\"fr.free.nrw.commons.beta\"") + buildConfigField("String", "CONTRIBUTION_AUTHORITY", "\"fr.free.nrw.commons.beta.contributions.contentprovider\"") + buildConfigField("String", "MODIFICATION_AUTHORITY", "\"fr.free.nrw.commons.beta.modifications.contentprovider\"") + buildConfigField("String", "CATEGORY_AUTHORITY", "\"fr.free.nrw.commons.beta.categories.contentprovider\"") + buildConfigField("String", "RECENT_SEARCH_AUTHORITY", "\"fr.free.nrw.commons.beta.explore.recentsearches.contentprovider\"") + buildConfigField("String", "RECENT_LANGUAGE_AUTHORITY", "\"fr.free.nrw.commons.beta.recentlanguages.contentprovider\"") + buildConfigField("String", "BOOKMARK_AUTHORITY", "\"fr.free.nrw.commons.beta.bookmarks.contentprovider\"") + buildConfigField("String", "BOOKMARK_LOCATIONS_AUTHORITY", "\"fr.free.nrw.commons.beta.bookmarks.locations.contentprovider\"") + buildConfigField("String", "BOOKMARK_ITEMS_AUTHORITY", "\"fr.free.nrw.commons.beta.bookmarks.items.contentprovider\"") + buildConfigField("String", "COMMIT_SHA", "\"" + getBuildVersion().toString() + "\"") + buildConfigField("String", "TEST_USERNAME", "\"" + getTestUserName() + "\"") + buildConfigField("String", "TEST_PASSWORD", "\"" + getTestPassword() + "\"") + buildConfigField("String", "DEPICTS_PROPERTY", "\"P245962\"") + buildConfigField("String", "CREATOR_PROPERTY", "\"P253075\"") + } + } + compileOptions { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 + } + kotlinOptions { + jvmTarget = "17" + } + buildFeatures { + buildConfig = true + viewBinding = true + compose = true + } + buildToolsVersion = buildToolsVersion + composeOptions { + kotlinCompilerExtensionVersion = "1.5.8" + } + packaging { + jniLibs { + excludes += listOf("META-INF/androidx.*") + } + resources { + excludes += listOf( + "META-INF/androidx.*", + "META-INF/proguard/androidx-annotations.pro", + "/META-INF/LICENSE.md", + "/META-INF/LICENSE-notice.md" + ) + } + } + testOptions { + animationsDisabled = true + unitTests { + isReturnDefaultValues = true + isIncludeAndroidResources = true + } + unitTests.all { + it.jvmArgs("-noverify") + } + } + lint { + abortOnError = false + disable += listOf("MissingTranslation", "ExtraTranslation") + } +} + +dependencies { + // Utils + implementation(libs.gson) + implementation(libs.okhttp) + implementation(libs.retrofit) + implementation(libs.retrofit.converter.gson) + implementation(libs.retrofit.adapter.rxjava) + implementation(libs.rxandroid) + implementation(libs.rxjava) + implementation(libs.rxbinding) + implementation(libs.rxbinding.appcompat) + implementation(libs.facebook.fresco) + implementation(libs.apache.commons.lang3) + + // UI + implementation("${libs.viewpagerindicator.library.get()}@aar") + implementation(libs.photoview) + implementation(libs.android.sdk) + implementation(libs.android.plugin.scalebar) + + implementation(libs.timber) + implementation(libs.android.material) + implementation(libs.dexter) + + // Jetpack Compose + implementation(libs.androidx.core.ktx) + implementation(libs.androidx.lifecycle.runtime.ktx) + implementation(libs.androidx.activity.compose) + implementation(platform(libs.androidx.compose.bom)) + implementation(libs.androidx.compose.runtime) + implementation(libs.androidx.ui) + implementation(libs.androidx.ui.graphics) + implementation(libs.androidx.ui.tooling.preview) + implementation(libs.androidx.ui.viewbinding) + implementation(libs.androidx.material3) + implementation(libs.androidx.foundation) + implementation(libs.androidx.foundation.layout) + androidTestImplementation(platform(libs.androidx.compose.bom)) + androidTestImplementation(libs.androidx.ui.test.junit4) + debugImplementation(libs.androidx.ui.tooling) + debugImplementation(libs.androidx.ui.test.manifest) + + implementation(libs.adapterdelegates4.kotlin.dsl.viewbinding) + implementation(libs.adapterdelegates4.pagination) + implementation(libs.androidx.paging.runtime.ktx) + testImplementation(libs.androidx.paging.common.ktx) + implementation(libs.androidx.paging.rxjava2.ktx) + implementation(libs.androidx.recyclerview) + + // Logging + implementation(libs.acra.dialog) + implementation(libs.acra.mail) + implementation(libs.slf4j.api) + implementation(libs.logback.android.classic) { + exclude(group = "com.google.android", module = "android") + } + implementation(libs.logging.interceptor) + + // Dependency injector + implementation(libs.dagger.android) + implementation(libs.dagger.android.support) + kapt(libs.dagger.android.processor) + kapt(libs.dagger.compiler) + annotationProcessor(libs.dagger.android.processor) + + implementation(libs.kotlin.reflect) + + //Mocking + testImplementation(libs.mockito.kotlin) + testImplementation(libs.mockito.core) + testImplementation(libs.powermock.module.junit) + testImplementation(libs.powermock.api.mockito) + testImplementation(libs.mockk) + + // Unit testing + testImplementation(libs.junit) + testImplementation(libs.robolectric) + testImplementation(libs.androidx.test.core) + testImplementation(libs.androidx.runner) + testImplementation(libs.androidx.test.ext.junit) + testImplementation(libs.androidx.test.rules) + testImplementation(libs.mockwebserver) + testImplementation(libs.livedata.testing.ktx) + testImplementation(libs.androidx.core.testing) + testImplementation(libs.junit.jupiter.api) + testRuntimeOnly(libs.junit.jupiter.engine) + testImplementation(libs.soloader) + testImplementation(libs.kotlinx.coroutines.test) + debugImplementation(libs.androidx.fragment.testing) + testImplementation(libs.commons.io) + + // Android testing + androidTestImplementation(libs.androidx.espresso.core) + androidTestImplementation(libs.androidx.espresso.intents) + androidTestImplementation(libs.androidx.espresso.contrib) + androidTestImplementation(libs.androidx.runner) + androidTestImplementation(libs.androidx.test.rules) + androidTestImplementation(libs.androidx.test.core) + androidTestImplementation(libs.androidx.test.ext.junit) + androidTestImplementation(libs.androidx.annotation) + androidTestImplementation(libs.mockwebserver) + androidTestImplementation(libs.androidx.uiautomator) + + // Debugging + debugImplementation(libs.leakcanary.android) + + // Support libraries + implementation(libs.androidx.browser) + implementation(libs.androidx.cardview) + implementation(libs.androidx.constraintlayout) + implementation(libs.androidx.exifinterface) + implementation(libs.recyclerview.fastscroll) + + //swipe_layout + implementation(libs.swipelayout.library) + + //Room + implementation(libs.androidx.room.runtime) + implementation(libs.androidx.room.ktx) + implementation(libs.androidx.room.rxjava) + kapt(libs.androidx.room.compiler) + + // Preferences + implementation(libs.androidx.preference) + implementation(libs.androidx.preference.ktx) + + //Android Media + implementation(libs.juanitobananas.androidDmediaUtil) + implementation(libs.androidx.multidex) + + // Kotlin + coroutines + implementation(libs.androidx.work.runtime.ktx) + implementation(libs.androidx.work.runtime) + testImplementation(libs.androidx.work.testing) + + //Glide + implementation(libs.glide) + annotationProcessor(libs.glide.compiler) + kaptTest(libs.androidx.databinding.compiler) + kaptAndroidTest(libs.androidx.databinding.compiler) + + implementation(libs.coordinates2country.android) { + exclude(group = "com.google.android", module = "android") + } + + //OSMDroid + implementation(libs.osmdroid.android) + constraints { + implementation(libs.kotlin.stdlib.jdk7) { + because("kotlin-stdlib-jdk7 is now a part of kotlin-stdlib") + } + implementation(libs.kotlin.stdlib.jdk8) { + because("kotlin-stdlib-jdk8 is now a part of kotlin-stdlib") + } + } +} + +tasks.register("disableAnimations") { + val adb = "${System.getenv("ANDROID_HOME")}/platform-tools/adb" + commandLine(adb, "shell", "settings", "put", "global", "window_animation_scale", "0") + commandLine(adb, "shell", "settings", "put", "global", "transition_animation_scale", "0") + commandLine(adb, "shell", "settings", "put", "global", "animator_duration_scale", "0") +} + +project.gradle.taskGraph.whenReady { + val connectedBetaDebugAndroidTest = tasks.named("connectedBetaDebugAndroidTest") + val connectedProdDebugAndroidTest = tasks.named("connectedProdDebugAndroidTest") + + connectedBetaDebugAndroidTest.configure { + dependsOn("disableAnimations") + } + connectedProdDebugAndroidTest.configure { + dependsOn("disableAnimations") + } +} + +fun getTestUserName(): String? { + val propFile = rootProject.file("./local.properties") + val properties = Properties() + propFile.inputStream().use { properties.load(it) } + return properties.getProperty("TEST_USER_NAME") +} + +fun getTestPassword(): String? { + val propFile = rootProject.file("./local.properties") + val properties = Properties() + propFile.inputStream().use { properties.load(it) } + return properties.getProperty("TEST_USER_PASSWORD") +} + +if (isRunningOnTravisAndIsNotPRBuild) { + configure { + track = "alpha" + userFraction = 1.0 + serviceAccountEmail = System.getenv("SERVICE_ACCOUNT_NAME") + serviceAccountCredentials = file("../play.p12") + + resolutionStrategy = "auto" + outputProcessor { // this: ApkVariantOutput + versionNameOverride = "$versionNameOverride.$versionCode" + } + } +} + +fun getBuildVersion(): String? { + return try { + val stdout = ByteArrayOutputStream() + exec { + commandLine("git", "rev-parse", "--short", "HEAD") + standardOutput = stdout + } + stdout.toString().trim() + } catch (e: Exception) { + null + } +} + +fun getBranchName(): String? { + return try { + val stdout = ByteArrayOutputStream() + exec { + commandLine("git", "rev-parse", "--abbrev-ref", "HEAD") + standardOutput = stdout + } + stdout.toString().trim() + } catch (e: Exception) { + null + } +} \ No newline at end of file diff --git a/build.gradle b/build.gradle deleted file mode 100644 index b0bad89a5..000000000 --- a/build.gradle +++ /dev/null @@ -1,29 +0,0 @@ -// Top-level build file where you can add configuration options common to all sub-projects/modules. -buildscript { - repositories { - google() - mavenCentral() - maven { url "https://plugins.gradle.org/m2/" } - } - dependencies { - classpath 'com.android.tools.build:gradle:8.7.0' - classpath 'com.getkeepsafe.dexcount:dexcount-gradle-plugin:0.8.2' - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$KOTLIN_VERSION" - classpath 'org.codehaus.groovy:groovy-all:2.4.15' - } -} - -allprojects { - repositories { - google() - mavenCentral() - gradlePluginPortal() // potential jcenter() replacement - maven { url "https://jitpack.io" } - maven { url "https://maven.google.com" } - } -} -subprojects{ - tasks.withType(Test).configureEach{ - jvmArgs = jvmArgs + ['--add-opens=java.base/java.lang=ALL-UNNAMED'] - } -} diff --git a/build.gradle.kts b/build.gradle.kts new file mode 100644 index 000000000..d3860805e --- /dev/null +++ b/build.gradle.kts @@ -0,0 +1,13 @@ +// Top-level build file where you can add configuration options common to all sub-projects/modules. +plugins { + alias(libs.plugins.android.application) apply false + alias(libs.plugins.jetbrains.kotlin.android) apply false + alias(libs.plugins.github.triplet.play) apply false + alias(libs.plugins.getkeepsafe.dexcount) +} + +subprojects{ + tasks.withType().configureEach { + jvmArgs = (jvmArgs ?: emptyList()) + listOf("--add-opens=java.base/java.lang=ALL-UNNAMED") + } +} \ No newline at end of file diff --git a/gitutils.gradle b/gitutils.gradle deleted file mode 100644 index ffcc8e520..000000000 --- a/gitutils.gradle +++ /dev/null @@ -1,26 +0,0 @@ -ext.getBuildVersion = { -> - // Short-term fix for #1157. Should ideally look into why method is failing. - try { - def stdout = new ByteArrayOutputStream() - exec { - commandLine 'git' , 'rev-parse' , '--short' , 'HEAD' - standardOutput = stdout - } - return stdout.toString().trim() - } catch (ignored) { - return null - } -} - -ext.getBranchName = { -> - try { - def stdOut = new ByteArrayOutputStream() - exec { - commandLine 'git', 'rev-parse', '--abbrev-ref', 'HEAD' - standardOutput = stdOut - } - return stdOut.toString().trim() - } catch (ignored) { - return null - } -} diff --git a/gradle.properties b/gradle.properties index 090289fa6..61c3584e5 100644 --- a/gradle.properties +++ b/gradle.properties @@ -17,24 +17,10 @@ org.gradle.jvmargs=-Xmx1536M org.gradle.caching=true android.enableR8.fullMode=false -KOTLIN_VERSION=1.9.22 -LEAK_CANARY_VERSION=2.10 -DAGGER_VERSION=2.23 -ROOM_VERSION=2.6.1 -PREFERENCE_VERSION=1.2.1 -CORE_KTX_VERSION=1.9.0 -ADAPTER_DELEGATES_VERSION=4.3.0 -PAGING_VERSION=2.1.2 -MULTIDEX_VERSION=2.0.1 -OKHTTP_VERSION=4.10.0 -MAPLIBRE_VERSION=10.0.1 -OSMDROID_VERSION=6.1.17 - #systemProp.http.proxyPort=0 #systemProp.http.proxyHost= android.useAndroidX=true android.enableJetifier=true android.jetifier.ignorelist=bcprov-jdk15on -android.defaults.buildfeatures.buildconfig=true android.nonTransitiveRClass=false android.nonFinalResIds=false diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml new file mode 100644 index 000000000..afb3615d2 --- /dev/null +++ b/gradle/libs.versions.toml @@ -0,0 +1,209 @@ +[versions] +agp = "8.9.1" +acra = "5.8.4" +activityCompose = "1.9.3" +adapterdelegates = "4.3.0" +androidmediautil = "v1.0-1" +androidSdkVersion = "10.0.1" +androidPluginScalebar = "1.0.0" +androidxJunitVersion = "1.1.5" +annotation = "1.3.0" +browser = "1.3.0" +cardview = "1.0.0" +commonsIo = "2.6" +composeBom = "2024.11.00" +constraintlayout = "1.1.3" +coordinates2country = "1.8" +dexcount = "4.0.0" +githubTripletPlay = "2.7.2" +osmdroidAndroid = "6.1.17" +testCore = "1.4.0" +coreKtx = "1.9.0" +coreTesting = "2.2.0" +dagger = "2.23" +databindingCompiler = "8.0.2" +dexterVersion = "5.0.0" +espresso = "3.6.1" +exifinterface = "1.3.7" +fragmentTesting = "1.6.2" +frescoVersion = "1.13.0" +commonsLang3Version = "3.8.1" +glide = "4.12.0" +gson = "2.8.5" +junit = "4.13.2" +junitJupiter = "5.10.0" +kotlin = "1.9.22" +kotlinStdlib = "1.8.0" +coroutines = "1.7.3" +leakcanary = "2.10" +livedataTesting = "1.2.0" +swipelayout = "1.2.0" +viewpagerIndicator = "2.4.1.1" +lifecycleRuntimeKtx = "2.8.4" +loggingInterceptor = "4.10.0" +logbackAndroidClassic = "1.1.1-6" +material = "1.12.0" +mockitoCore = "5.6.0" +mockitoKotlin = "2.2.0" +mockk = "1.13.5" +mockwebserver = "4.10.0" +multidex = "2.0.1" +okHttp = "4.10.0" +paging = "2.1.2" +photoviewVersion = "2.0.0" +powermock = "2.0.9" +preference = "1.2.1" +recyclerview = "1.2.0-alpha02" +recyclerviewFastscroll = "2.0.1" +retrofit = "2.8.1" +robolectric = "4.11.1" +room = "2.6.1" +rules = "1.5.0" +runner = "1.5.2" +rxandroid = "2.1.0" +rxjava = "2.2.3" +rxbinding = "2.1.1" +rxbindingAppcompat = "3.0.0" +slf4jApi = "1.7.25" +soloader = "0.10.5" +timber = "4.7.1" +uiautomator = "2.2.0" +workManager = "2.8.1" + +[libraries] +# AndroidX Core Dependencies +androidx-activity-compose = { group = "androidx.activity", name = "activity-compose", version.ref = "activityCompose" } +androidx-annotation = { module = "androidx.annotation:annotation", version.ref = "annotation" } +androidx-compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "composeBom" } +androidx-compose-runtime = { group = "androidx.compose.runtime", name = "runtime" } +androidx-constraintlayout = { module = "androidx.constraintlayout:constraintlayout", version.ref = "constraintlayout" } +androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" } +androidx-test-core = { module = "androidx.test:core", version.ref = "testCore" } +androidx-databinding-compiler = { module = "androidx.databinding:databinding-compiler", version.ref = "databindingCompiler" } +androidx-exifinterface = { module = "androidx.exifinterface:exifinterface", version.ref = "exifinterface" } +androidx-foundation = { module = "androidx.compose.foundation:foundation" } +androidx-foundation-layout = { module = "androidx.compose.foundation:foundation-layout" } +androidx-lifecycle-runtime-ktx = { group = "androidx.lifecycle", name = "lifecycle-runtime-ktx", version.ref = "lifecycleRuntimeKtx" } +androidx-material3 = { group = "androidx.compose.material3", name = "material3" } +androidx-runner = { module = "androidx.test:runner", version.ref = "runner" } +androidx-test-ext-junit = { module = "androidx.test.ext:junit", version.ref = "androidxJunitVersion" } +androidx-test-rules = { module = "androidx.test:rules", version.ref = "rules" } +androidx-ui = { group = "androidx.compose.ui", name = "ui" } +androidx-ui-graphics = { group = "androidx.compose.ui", name = "ui-graphics" } +androidx-ui-tooling = { group = "androidx.compose.ui", name = "ui-tooling" } +androidx-ui-tooling-preview = { group = "androidx.compose.ui", name = "ui-tooling-preview" } +androidx-ui-test-manifest = { group = "androidx.compose.ui", name = "ui-test-manifest" } +androidx-ui-test-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit4" } +androidx-ui-viewbinding = { group = "androidx.compose.ui", name = "ui-viewbinding" } + +# AndroidX Room +androidx-room-compiler = { module = "androidx.room:room-compiler", version.ref = "room" } +androidx-room-rxjava = { module = "androidx.room:room-rxjava2", version.ref = "room" } +androidx-room-ktx = { module = "androidx.room:room-ktx", version.ref = "room" } +androidx-room-runtime = { module = "androidx.room:room-runtime", version.ref = "room" } + +# AndroidX Preferences +androidx-preference = { module = "androidx.preference:preference", version.ref = "preference" } +androidx-preference-ktx = { module = "androidx.preference:preference-ktx", version.ref = "preference" } + +# AndroidX Paging +androidx-recyclerview = { module = "androidx.recyclerview:recyclerview", version.ref = "recyclerview" } +androidx-paging-common-ktx = { module = "androidx.paging:paging-common-ktx", version.ref = "paging" } +androidx-paging-runtime-ktx = { module = "androidx.paging:paging-runtime-ktx", version.ref = "paging" } +androidx-paging-rxjava2-ktx = { module = "androidx.paging:paging-rxjava2-ktx", version.ref = "paging" } + +# AndroidX Work Manager +androidx-work-testing = { module = "androidx.work:work-testing", version.ref = "workManager" } +androidx-work-runtime = { module = "androidx.work:work-runtime", version.ref = "workManager" } +androidx-work-runtime-ktx = { module = "androidx.work:work-runtime-ktx", version.ref = "workManager" } + +# Dependency injection (DI) +dagger-android-processor = { module = "com.google.dagger:dagger-android-processor", version.ref = "dagger" } +dagger-android-support = { module = "com.google.dagger:dagger-android-support", version.ref = "dagger" } +dagger-android = { module = "com.google.dagger:dagger-android", version.ref = "dagger" } +dagger-compiler = { module = "com.google.dagger:dagger-compiler", version.ref = "dagger" } + +# Image loading +facebook-fresco = { module = "com.facebook.fresco:fresco", version.ref = "frescoVersion" } +glide-compiler = { module = "com.github.bumptech.glide:compiler", version.ref = "glide" } +glide = { module = "com.github.bumptech.glide:glide", version.ref = "glide" } +photoview = { module = "com.github.chrisbanes:PhotoView", version.ref = "photoviewVersion" } + +# RxJava and Reactive Programming +rxandroid = { module = "io.reactivex.rxjava2:rxandroid", version.ref = "rxandroid" } +rxjava = { module = "io.reactivex.rxjava2:rxjava", version.ref = "rxjava" } +rxbinding = { module = "com.jakewharton.rxbinding2:rxbinding", version.ref = "rxbinding" } +rxbinding-appcompat = { module = "com.jakewharton.rxbinding3:rxbinding-appcompat", version.ref = "rxbindingAppcompat" } + +# Testing +androidx-core-testing = { module = "androidx.arch.core:core-testing", version.ref = "coreTesting" } +androidx-espresso-contrib = { module = "androidx.test.espresso:espresso-contrib", version.ref = "espresso" } +androidx-espresso-intents = { module = "androidx.test.espresso:espresso-intents", version.ref = "espresso" } +androidx-espresso-core = { module = "androidx.test.espresso:espresso-core", version.ref = "espresso" } +androidx-fragment-testing = { module = "androidx.fragment:fragment-testing", version.ref = "fragmentTesting" } +androidx-uiautomator = { module = "androidx.test.uiautomator:uiautomator", version.ref = "uiautomator" } +commons-io = { module = "commons-io:commons-io", version.ref = "commonsIo" } +junit = { module = "junit:junit", version.ref = "junit" } +junit-jupiter-engine = { module = "org.junit.jupiter:junit-jupiter-engine", version.ref = "junitJupiter" } +junit-jupiter-api = { module = "org.junit.jupiter:junit-jupiter-api", version.ref = "junitJupiter" } +kotlinx-coroutines-test = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-test", version.ref = "coroutines" } +livedata-testing-ktx = { module = "com.jraska.livedata:testing-ktx", version.ref = "livedataTesting" } +robolectric = { module = "org.robolectric:robolectric", version.ref = "robolectric" } +soloader = { module = "com.facebook.soloader:soloader", version.ref = "soloader" } + +# Mocking +mockk = { module = "io.mockk:mockk", version.ref = "mockk" } +mockwebserver = { module = "com.squareup.okhttp3:mockwebserver", version.ref = "mockwebserver" } +mockito-core = { module = "org.mockito:mockito-core", version.ref = "mockitoCore" } +mockito-kotlin = { module = "com.nhaarman.mockitokotlin2:mockito-kotlin", version.ref = "mockitoKotlin" } +powermock-api-mockito = { module = "org.powermock:powermock-api-mockito2", version.ref = "powermock" } +powermock-module-junit = { module = "org.powermock:powermock-module-junit4", version.ref = "powermock" } + +# UI components & layouts +androidx-cardview = { module = "androidx.cardview:cardview", version.ref = "cardview" } +android-material = { group = "com.google.android.material", name = "material", version.ref = "material" } +adapterdelegates4-kotlin-dsl-viewbinding = { module = "com.hannesdorfmann:adapterdelegates4-kotlin-dsl-viewbinding", version.ref = "adapterdelegates" } +adapterdelegates4-pagination = { module = "com.hannesdorfmann:adapterdelegates4-pagination", version.ref = "adapterdelegates" } +dexter = { module = "com.karumi:dexter", version.ref = "dexterVersion" } +recyclerview-fastscroll = { module = "com.simplecityapps:recyclerview-fastscroll", version.ref = "recyclerviewFastscroll" } +swipelayout-library = { module = "com.daimajia.swipelayout:library", version.ref = "swipelayout" } +viewpagerindicator-library = { module = "fr.avianey.com.viewpagerindicator:library", version.ref = "viewpagerIndicator" } + +# Networking libraries +logging-interceptor = { module = "com.squareup.okhttp3:logging-interceptor", version.ref = "loggingInterceptor" } +okhttp = { module = "com.squareup.okhttp3:okhttp", version.ref = "okHttp" } +retrofit = { module = "com.squareup.retrofit2:retrofit", version.ref = "retrofit" } +retrofit-adapter-rxjava = { module = "com.squareup.retrofit2:adapter-rxjava2", version.ref = "retrofit" } +retrofit-converter-gson = { module = "com.squareup.retrofit2:converter-gson", version.ref = "retrofit" } + +# Utility libraries +androidx-browser = { module = "androidx.browser:browser", version.ref = "browser" } +apache-commons-lang3 = { module = "org.apache.commons:commons-lang3", version.ref = "commonsLang3Version" } +gson = { group = "com.google.code.gson", name = "gson", version.ref = "gson" } +juanitobananas-androidDmediaUtil = { module = "com.github.juanitobananas:AndroidMediaUtil", version.ref = "androidmediautil" } +androidx-multidex = { module = "androidx.multidex:multidex", version.ref = "multidex" } +kotlin-reflect = { module = "org.jetbrains.kotlin:kotlin-reflect", version.ref = "kotlin" } +leakcanary-android = { module = "com.squareup.leakcanary:leakcanary-android", version.ref = "leakcanary" } + +# Logging & Crash Reporting +acra-mail = { module = "ch.acra:acra-mail", version.ref = "acra" } +acra-dialog = { module = "ch.acra:acra-dialog", version.ref = "acra" } +logback-android-classic = { module = "com.github.tony19:logback-android-classic", version.ref = "logbackAndroidClassic" } +slf4j-api = { module = "org.slf4j:slf4j-api", version.ref = "slf4jApi" } +timber = { module = "com.jakewharton.timber:timber", version.ref = "timber" } + +# Map & location services +android-sdk = { module = "org.maplibre.gl:android-sdk", version.ref = "androidSdkVersion" } +android-plugin-scalebar = { module = "org.maplibre.gl:android-plugin-scalebar-v9", version.ref = "androidPluginScalebar" } +coordinates2country-android = { module = "io.github.coordinates2country:coordinates2country-android", version.ref = "coordinates2country" } +osmdroid-android = { module = "org.osmdroid:osmdroid-android", version.ref = "osmdroidAndroid" } +kotlin-stdlib-jdk7 = { group = "org.jetbrains.kotlin", name = "kotlin-stdlib-jdk7", version.ref = "kotlinStdlib" } +kotlin-stdlib-jdk8 = { group = "org.jetbrains.kotlin", name = "kotlin-stdlib-jdk8", version.ref = "kotlinStdlib" } + +[plugins] +android-application = { id = "com.android.application", version.ref = "agp" } +jetbrains-kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } +kotlin-kapt = { id = "org.jetbrains.kotlin.kapt" } +kotlin-parcelize = { id = "org.jetbrains.kotlin.plugin.parcelize" } +github-triplet-play = { id = "com.github.triplet.play", version.ref = "githubTripletPlay" } +getkeepsafe-dexcount = { id = "com.getkeepsafe.dexcount", version.ref = "dexcount" } \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index fd53d45f9..26f6c44a2 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ #Sun Apr 23 18:22:54 IST 2023 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists \ No newline at end of file diff --git a/settings.gradle b/settings.gradle deleted file mode 100644 index e7b4def49..000000000 --- a/settings.gradle +++ /dev/null @@ -1 +0,0 @@ -include ':app' diff --git a/settings.gradle.kts b/settings.gradle.kts new file mode 100644 index 000000000..1f3c89749 --- /dev/null +++ b/settings.gradle.kts @@ -0,0 +1,17 @@ +pluginManagement { + repositories { + google() + mavenCentral() + gradlePluginPortal() + } +} +dependencyResolutionManagement { + repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) + repositories { + google() + mavenCentral() + maven("https://jitpack.io") + } +} + +include(":app") From cfc2cfcca120a9db1130116e3ee513b871f1b8d9 Mon Sep 17 00:00:00 2001 From: rayane <91428886+Rsedp8@users.noreply.github.com> Date: Thu, 29 May 2025 13:25:00 +0200 Subject: [PATCH 008/162] Fix Kotlin warnings (related to issue #5996) (#6320) * refactor: replace unused exception variable with underscore * refactor: code style fix * fix: remove unnecessary latLng variable and return null directly * fix: use explicit true/false instead of isFABsExpanded * refactor: simplify marker update logic by reducing redundant conditions * refactor: use data object instead of object * fix: check placeBindings for null instead of checking each destructured value * fix: check placeBindings for null instead of checking each destructured value * docs: fix KDoc for contentUri property by removing incorrect @param tag * docs: correct @see link in KDoc for showBadgesWithCount * docs: fix KDoc tag from @property to @param for context in BottomSheetAdapter * docs: comment out KDoc for disabled method to avoid unresolved @param warning * docs: fix KDoc for onLongPress by removing invalid @param imageUri * docs: clean up invalid KDoc tags on property and add docs to isEmpty * docs: remove invalid @param originalImageCoordinates from findOtherImages KDoc * docs: fix incorrect @param tag in checkDuplicateImage KDoc * docs: fix incorrect @param in onLongPress KDoc * docs: fix invalid @param and @return tags on author property * docs: fix incorrect @param in provideWikidataMediaInterface KDoc * docs: fix incorrect @param name in getWikiText KDoc * docs: escape wikilinks with [[ ]] to avoid KDoc resolution warnings * docs: fix KDoc by adding missing param descriptions to startActivityWithFlags * docs: fix KDoc by replacing @param with @property for contentUri * docs: fix malformed KDoc in startYourself, remove invalid @param line * docs: remove invalid @param tag in createDialogsAndHandleLocationPermissions * docs: remove invalid @param tags to @property * @docs: remove invalid @property tags * docs: clean up KDoc by removing invalid @param and @return tags * docs: fix incorrect @param name in removeBlocklisted KDoc * docs: fix incorrect @param name in checkDuplicateImage KDoc * docs: fix incorrect @param tag --------- Co-authored-by: Nicolas Raoul --- .../free/nrw/commons/UploadCancelledTest.kt | 4 +- .../java/fr/free/nrw/commons/UploadTest.kt | 2 +- .../main/java/fr/free/nrw/commons/Media.kt | 21 ++-- .../nrw/commons/actions/PageEditInterface.kt | 7 +- .../nrw/commons/bookmarks/models/Bookmark.kt | 2 +- .../ExceptionAwareThreadPoolExecutor.kt | 4 +- .../contributions/ContributionsFragment.kt | 9 +- .../listeners/ImageSelectListener.kt | 7 +- .../customselector/model/CallbackStatus.kt | 6 +- .../ui/selector/CustomSelectorActivity.kt | 7 +- .../ui/selector/ImageFileLoader.kt | 3 +- .../free/nrw/commons/di/NetworkingModule.kt | 8 +- .../commons/explore/models/RecentSearch.kt | 4 +- .../nrw/commons/mwapi/OkHttpJsonApiClient.kt | 114 +++++++++--------- .../nrw/commons/nearby/BottomSheetAdapter.kt | 2 +- .../nearby/fragments/NearbyParentFragment.kt | 11 +- .../achievements/AchievementsFragment.kt | 2 +- .../nrw/commons/quiz/QuizResultActivity.kt | 9 +- .../commons/repository/UploadRepository.kt | 7 +- .../free/nrw/commons/review/ReviewActivity.kt | 6 +- .../nrw/commons/settings/SettingsFragment.kt | 4 +- .../fr/free/nrw/commons/upload/Description.kt | 12 +- .../free/nrw/commons/upload/FileProcessor.kt | 13 +- .../commons/upload/ImageProcessingService.kt | 6 +- .../nrw/commons/upload/UploadMediaDetail.kt | 11 +- .../upload/UploadMediaDetailInputFilter.kt | 7 +- .../fr/free/nrw/commons/upload/UploadModel.kt | 7 +- .../free/nrw/commons/utils/LocationUtils.kt | 4 +- .../commons/wikidata/model/page/PageTitle.kt | 4 +- 29 files changed, 153 insertions(+), 150 deletions(-) diff --git a/app/src/androidTest/java/fr/free/nrw/commons/UploadCancelledTest.kt b/app/src/androidTest/java/fr/free/nrw/commons/UploadCancelledTest.kt index c3d3dc3c3..ed57709fc 100644 --- a/app/src/androidTest/java/fr/free/nrw/commons/UploadCancelledTest.kt +++ b/app/src/androidTest/java/fr/free/nrw/commons/UploadCancelledTest.kt @@ -49,7 +49,7 @@ class UploadCancelledTest { fun setup() { try { Intents.init() - } catch (ex: IllegalStateException) { + } catch (_: IllegalStateException) { } device.unfreezeRotation() device.setOrientationNatural() @@ -65,7 +65,7 @@ class UploadCancelledTest { fun teardown() { try { Intents.release() - } catch (ex: IllegalStateException) { + } catch (_: IllegalStateException) { } } diff --git a/app/src/androidTest/java/fr/free/nrw/commons/UploadTest.kt b/app/src/androidTest/java/fr/free/nrw/commons/UploadTest.kt index 88c7e5d3d..048d540b7 100644 --- a/app/src/androidTest/java/fr/free/nrw/commons/UploadTest.kt +++ b/app/src/androidTest/java/fr/free/nrw/commons/UploadTest.kt @@ -71,7 +71,7 @@ class UploadTest { fun setup() { try { Intents.init() - } catch (ex: IllegalStateException) { + } catch (_: IllegalStateException) { } UITestHelper.loginUser() UITestHelper.skipWelcome() diff --git a/app/src/main/java/fr/free/nrw/commons/Media.kt b/app/src/main/java/fr/free/nrw/commons/Media.kt index d07bc0265..7bd8e95fd 100644 --- a/app/src/main/java/fr/free/nrw/commons/Media.kt +++ b/app/src/main/java/fr/free/nrw/commons/Media.kt @@ -28,9 +28,7 @@ class Media constructor( */ var filename: String? = null, /** - * Gets or sets the file description. - * @return file description as a string - * @param fallbackDescription the new description of the file + * The fallback description of the file, used if no other description is provided. */ var fallbackDescription: String? = null, /** @@ -40,19 +38,24 @@ class Media constructor( */ var dateUploaded: Date? = null, /** - * Gets or sets the license name of the file. - * @return license as a String - * @param license license name as a String + * The license name of the file. */ var license: String? = null, + /** + * The URL corresponding to the license. + */ var licenseUrl: String? = null, /** - * Gets or sets the name of the creator of the file. - * @return author name as a String - * @param author creator name as a string + * The name of the creator of the file. */ var author: String? = null, + /** + * The username of the uploader. + */ var user: String? = null, + /** + * The full name of the file's creator, if different from username. + */ var creatorName: String? = null, /** * Gets the categories the file falls under. diff --git a/app/src/main/java/fr/free/nrw/commons/actions/PageEditInterface.kt b/app/src/main/java/fr/free/nrw/commons/actions/PageEditInterface.kt index db43bb620..5e2651039 100644 --- a/app/src/main/java/fr/free/nrw/commons/actions/PageEditInterface.kt +++ b/app/src/main/java/fr/free/nrw/commons/actions/PageEditInterface.kt @@ -129,9 +129,10 @@ interface PageEditInterface { ): Observable /** - * Get wiki text for provided file names - * @param titles : Name of the file - * @return Single + * Gets the wiki text for the provided file name. + * + * @param title The title (name) of the file to fetch wiki text for. + * @return A Single emitting the wiki query response. */ @GET(MW_API_PREFIX + "action=query&prop=revisions&rvprop=content|timestamp&rvlimit=1&converttitles=") fun getWikiText( diff --git a/app/src/main/java/fr/free/nrw/commons/bookmarks/models/Bookmark.kt b/app/src/main/java/fr/free/nrw/commons/bookmarks/models/Bookmark.kt index a33638e72..630889c01 100644 --- a/app/src/main/java/fr/free/nrw/commons/bookmarks/models/Bookmark.kt +++ b/app/src/main/java/fr/free/nrw/commons/bookmarks/models/Bookmark.kt @@ -8,7 +8,7 @@ class Bookmark( /** * Gets or Sets the content URI - marking this bookmark as already saved in the database * @return content URI - * @param contentUri the content URI + * contentUri the content URI */ var contentUri: Uri?, ) { diff --git a/app/src/main/java/fr/free/nrw/commons/concurrency/ExceptionAwareThreadPoolExecutor.kt b/app/src/main/java/fr/free/nrw/commons/concurrency/ExceptionAwareThreadPoolExecutor.kt index 0efe057f2..7605964bd 100644 --- a/app/src/main/java/fr/free/nrw/commons/concurrency/ExceptionAwareThreadPoolExecutor.kt +++ b/app/src/main/java/fr/free/nrw/commons/concurrency/ExceptionAwareThreadPoolExecutor.kt @@ -22,9 +22,9 @@ class ExceptionAwareThreadPoolExecutor( if (r.isDone) { r.get() } - } catch (e: CancellationException) { + } catch (_: CancellationException) { // ignore - } catch (e: InterruptedException) { + } catch (_: InterruptedException) { // ignore } catch (e: ExecutionException) { throwable = e.cause ?: e diff --git a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsFragment.kt b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsFragment.kt index f293ccc44..f50df13ff 100644 --- a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsFragment.kt +++ b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsFragment.kt @@ -808,10 +808,11 @@ class ContributionsFragment : CommonsDaggerSupportFragment(), FragmentManager.On } } - /** - * Temporarily disabled, see issue [https://github.com/commons-app/apps-android-commons/issues/5847] - * @param count The number of pending uploads. - */ + // /** + // * Temporarily disabled. See issue [#5847](https://github.com/commons-app/apps-android-commons/issues/5847) + // * @param count The number of pending uploads. + // */ + // public void updateUploadIcon(int count) { // public void updateUploadIcon(int count) { // if (pendingUploadsImageView != null) { // if (count != 0) { diff --git a/app/src/main/java/fr/free/nrw/commons/customselector/listeners/ImageSelectListener.kt b/app/src/main/java/fr/free/nrw/commons/customselector/listeners/ImageSelectListener.kt index 24565963b..88f90d2e9 100644 --- a/app/src/main/java/fr/free/nrw/commons/customselector/listeners/ImageSelectListener.kt +++ b/app/src/main/java/fr/free/nrw/commons/customselector/listeners/ImageSelectListener.kt @@ -17,8 +17,11 @@ interface ImageSelectListener { ) /** - * onLongPress - * @param imageUri : uri of image + * Called when the user performs a long press on an image. + * + * @param position The index of the pressed image in the list. + * @param images The list of all available images. + * @param selectedImages The currently selected images. */ fun onLongPress( position: Int, diff --git a/app/src/main/java/fr/free/nrw/commons/customselector/model/CallbackStatus.kt b/app/src/main/java/fr/free/nrw/commons/customselector/model/CallbackStatus.kt index c47806f16..856c8de88 100644 --- a/app/src/main/java/fr/free/nrw/commons/customselector/model/CallbackStatus.kt +++ b/app/src/main/java/fr/free/nrw/commons/customselector/model/CallbackStatus.kt @@ -8,15 +8,15 @@ sealed class CallbackStatus { /** IDLE : The callback is idle , doing nothing. */ - object IDLE : CallbackStatus() + data object IDLE : CallbackStatus() /** FETCHING : Fetching images. */ - object FETCHING : CallbackStatus() + data object FETCHING : CallbackStatus() /** SUCCESS : Success fetching images. */ - object SUCCESS : CallbackStatus() + data object SUCCESS : CallbackStatus() } diff --git a/app/src/main/java/fr/free/nrw/commons/customselector/ui/selector/CustomSelectorActivity.kt b/app/src/main/java/fr/free/nrw/commons/customselector/ui/selector/CustomSelectorActivity.kt index 6b78dfd41..f872d3044 100644 --- a/app/src/main/java/fr/free/nrw/commons/customselector/ui/selector/CustomSelectorActivity.kt +++ b/app/src/main/java/fr/free/nrw/commons/customselector/ui/selector/CustomSelectorActivity.kt @@ -610,8 +610,11 @@ class CustomSelectorActivity : } /** - * onLongPress - * @param imageUri : uri of image + * Triggered when the user performs a long press on an image. + * + * @param position The index of the selected image. + * @param images The list of all available images. + * @param selectedImages The list of images currently selected. */ override fun onLongPress( position: Int, diff --git a/app/src/main/java/fr/free/nrw/commons/customselector/ui/selector/ImageFileLoader.kt b/app/src/main/java/fr/free/nrw/commons/customselector/ui/selector/ImageFileLoader.kt index f079dee50..05eb117a3 100644 --- a/app/src/main/java/fr/free/nrw/commons/customselector/ui/selector/ImageFileLoader.kt +++ b/app/src/main/java/fr/free/nrw/commons/customselector/ui/selector/ImageFileLoader.kt @@ -104,7 +104,8 @@ class ImageFileLoader( if (file != null && file.exists() && name != null && path != null && bucketName != null) { val extension = path.substringAfterLast(".", "") // Check if the extension is one of the allowed types - if (extension.lowercase(Locale.ROOT) !in arrayOf("jpg", "jpeg", "png", "svg", "gif", "tiff", "webp", "xcf")) { + if (extension.lowercase(Locale.ROOT) !in arrayOf("jpg", "jpeg", "png", "svg", + "gif", "tiff", "webp", "xcf")) { continue } diff --git a/app/src/main/java/fr/free/nrw/commons/di/NetworkingModule.kt b/app/src/main/java/fr/free/nrw/commons/di/NetworkingModule.kt index 0e9d83478..2539db312 100644 --- a/app/src/main/java/fr/free/nrw/commons/di/NetworkingModule.kt +++ b/app/src/main/java/fr/free/nrw/commons/di/NetworkingModule.kt @@ -238,10 +238,10 @@ class NetworkingModule { factory.create(BuildConfig.COMMONS_URL) /** - * Add provider for WikidataMediaInterface - * It creates a retrofit service for the commons wiki site - * @param commonsWikiSite commonsWikiSite - * @return WikidataMediaInterface + * Provides a Retrofit service for accessing the commons wiki site via [WikidataMediaInterface]. + * + * @param factory The CommonsServiceFactory used to create the Retrofit service. + * @return An instance of [WikidataMediaInterface]. */ @Provides @Singleton diff --git a/app/src/main/java/fr/free/nrw/commons/explore/models/RecentSearch.kt b/app/src/main/java/fr/free/nrw/commons/explore/models/RecentSearch.kt index 2340865a6..0f72cac29 100644 --- a/app/src/main/java/fr/free/nrw/commons/explore/models/RecentSearch.kt +++ b/app/src/main/java/fr/free/nrw/commons/explore/models/RecentSearch.kt @@ -9,9 +9,9 @@ import java.util.Date */ class RecentSearch( /** - * Modifies the content URI - marking this query as already saved in the database + * The content URI that marks this query as already saved in the database. * - * @param contentUri the content URI + * @property contentUri the content URI */ var contentUri: Uri?, /** diff --git a/app/src/main/java/fr/free/nrw/commons/mwapi/OkHttpJsonApiClient.kt b/app/src/main/java/fr/free/nrw/commons/mwapi/OkHttpJsonApiClient.kt index 291c834bd..4fa7979d2 100644 --- a/app/src/main/java/fr/free/nrw/commons/mwapi/OkHttpJsonApiClient.kt +++ b/app/src/main/java/fr/free/nrw/commons/mwapi/OkHttpJsonApiClient.kt @@ -531,40 +531,38 @@ ${"wd:" + place.wikiDataEntityId}""" ) if (placeBindings != null) { for ((item1, label, location, clas) in placeBindings) { - if (item1 != null && label != null && clas != null) { - val input = location.value - val pattern = Pattern.compile( - "Point\\(([-+]?[0-9]*\\.?[0-9]+) ([-+]?[0-9]*\\.?[0-9]+)\\)" - ) - val matcher = pattern.matcher(input) + val input = location.value + val pattern = Pattern.compile( + "Point\\(([-+]?[0-9]*\\.?[0-9]+) ([-+]?[0-9]*\\.?[0-9]+)\\)" + ) + val matcher = pattern.matcher(input) - if (matcher.find()) { - val longStr = matcher.group(1) - val latStr = matcher.group(2) - val itemUrl = item1.value - val itemName = label.value.replace("&", "&") - val itemLatitude = latStr - val itemLongitude = longStr - val itemClass = clas.value + if (matcher.find()) { + val longStr = matcher.group(1) + val latStr = matcher.group(2) + val itemUrl = item1.value + val itemName = label.value.replace("&", "&") + val itemLatitude = latStr + val itemLongitude = longStr + val itemClass = clas.value - val formattedItemName = - if (!itemClass.isEmpty()) - "$itemName ($itemClass)" - else - itemName + val formattedItemName = + if (!itemClass.isEmpty()) + "$itemName ($itemClass)" + else + itemName - val kmlEntry = (""" - - $formattedItemName - $itemUrl - - $itemLongitude,$itemLatitude - - """) - kmlString = kmlString + kmlEntry - } else { - Timber.e("No match found") - } + val kmlEntry = (""" + + $formattedItemName + $itemUrl + + $itemLongitude,$itemLatitude + + """) + kmlString = kmlString + kmlEntry + } else { + Timber.e("No match found") } } } @@ -589,37 +587,35 @@ ${"wd:" + place.wikiDataEntityId}""" val placeBindings = runQuery(leftLatLng, rightLatLng) if (placeBindings != null) { for ((item1, label, location, clas) in placeBindings) { - if (item1 != null && label != null && clas != null) { - val input = location.value - val pattern = Pattern.compile( - "Point\\(([-+]?[0-9]*\\.?[0-9]+) ([-+]?[0-9]*\\.?[0-9]+)\\)" - ) - val matcher = pattern.matcher(input) + val input = location.value + val pattern = Pattern.compile( + "Point\\(([-+]?[0-9]*\\.?[0-9]+) ([-+]?[0-9]*\\.?[0-9]+)\\)" + ) + val matcher = pattern.matcher(input) - if (matcher.find()) { - val longStr = matcher.group(1) - val latStr = matcher.group(2) - val itemUrl = item1.value - val itemName = label.value.replace("&", "&") - val itemLatitude = latStr - val itemLongitude = longStr - val itemClass = clas.value + if (matcher.find()) { + val longStr = matcher.group(1) + val latStr = matcher.group(2) + val itemUrl = item1.value + val itemName = label.value.replace("&", "&") + val itemLatitude = latStr + val itemLongitude = longStr + val itemClass = clas.value - val formattedItemName = if (!itemClass.isEmpty()) - "$itemName ($itemClass)" - else - itemName + val formattedItemName = if (!itemClass.isEmpty()) + "$itemName ($itemClass)" + else + itemName - val gpxEntry = - (""" - - $itemName - $itemUrl - """) - gpxString = gpxString + gpxEntry - } else { - Timber.e("No match found") - } + val gpxEntry = + (""" + + $itemName + $itemUrl +""") + gpxString = gpxString + gpxEntry + } else { + Timber.e("No match found") } } } diff --git a/app/src/main/java/fr/free/nrw/commons/nearby/BottomSheetAdapter.kt b/app/src/main/java/fr/free/nrw/commons/nearby/BottomSheetAdapter.kt index a83d49f75..714cd388f 100644 --- a/app/src/main/java/fr/free/nrw/commons/nearby/BottomSheetAdapter.kt +++ b/app/src/main/java/fr/free/nrw/commons/nearby/BottomSheetAdapter.kt @@ -16,7 +16,7 @@ import fr.free.nrw.commons.nearby.model.BottomSheetItem /** * RecyclerView Adapter for displaying items in a bottom sheet. * - * @property context The context used for inflating layout resources. + * @param context The context used for inflating layout resources. * @property itemList The list of BottomSheetItem objects to display. * @constructor Creates an instance of BottomSheetAdapter. */ diff --git a/app/src/main/java/fr/free/nrw/commons/nearby/fragments/NearbyParentFragment.kt b/app/src/main/java/fr/free/nrw/commons/nearby/fragments/NearbyParentFragment.kt index 7445a6526..56af614d7 100644 --- a/app/src/main/java/fr/free/nrw/commons/nearby/fragments/NearbyParentFragment.kt +++ b/app/src/main/java/fr/free/nrw/commons/nearby/fragments/NearbyParentFragment.kt @@ -63,6 +63,7 @@ import fr.free.nrw.commons.bookmarks.locations.BookmarkLocationsDao import fr.free.nrw.commons.contributions.ContributionController import fr.free.nrw.commons.contributions.MainActivity import fr.free.nrw.commons.contributions.MainActivity.ActiveFragment +import fr.free.nrw.commons.customselector.ui.selector.ImageLoader import fr.free.nrw.commons.databinding.FragmentNearbyParentBinding import fr.free.nrw.commons.di.CommonsDaggerSupportFragment import fr.free.nrw.commons.filepicker.FilePicker @@ -1756,9 +1757,9 @@ class NearbyParentFragment : CommonsDaggerSupportFragment(), override fun animateFABs() { if (binding!!.fabPlus.isShown) { if (isFABsExpanded) { - collapseFABs(isFABsExpanded) + collapseFABs(true) } else { - expandFABs(isFABsExpanded) + expandFABs(false) } } } @@ -2013,17 +2014,17 @@ class NearbyParentFragment : CommonsDaggerSupportFragment(), if (place.exists && place.pic.trim { it <= ' ' }.isEmpty()) { shouldUpdateMarker = true } - } else if (displayExists && !displayNeedsPhoto) { + } else if (displayExists) { // Exists and all included needs and doesn't needs photo if (place.exists) { shouldUpdateMarker = true } - } else if (!displayExists && displayNeedsPhoto) { + } else if (displayNeedsPhoto) { // All and only needs photo if (place.pic.trim { it <= ' ' }.isEmpty()) { shouldUpdateMarker = true } - } else if (!displayExists && !displayNeedsPhoto) { + } else { // all shouldUpdateMarker = true } diff --git a/app/src/main/java/fr/free/nrw/commons/profile/achievements/AchievementsFragment.kt b/app/src/main/java/fr/free/nrw/commons/profile/achievements/AchievementsFragment.kt index af07423eb..f967b8619 100644 --- a/app/src/main/java/fr/free/nrw/commons/profile/achievements/AchievementsFragment.kt +++ b/app/src/main/java/fr/free/nrw/commons/profile/achievements/AchievementsFragment.kt @@ -389,7 +389,7 @@ class AchievementsFragment : CommonsDaggerSupportFragment(){ * @param badgeTextColor The badge text color. Default is R.attr.colorPrimary * @param badgeGravity The position of the badge [TOP_END,TOP_START,BOTTOM_END,BOTTOM_START]. Default is TOP_END * @return if the number is 0, then it will not create badge for it and hide the view - * @see https://developer.android.com/reference/com/google/android/material/badge/BadgeDrawable + * @see BadgeDrawable (Android Developer) */ private fun showBadgesWithCount( diff --git a/app/src/main/java/fr/free/nrw/commons/quiz/QuizResultActivity.kt b/app/src/main/java/fr/free/nrw/commons/quiz/QuizResultActivity.kt index 0282da190..81372b4a6 100644 --- a/app/src/main/java/fr/free/nrw/commons/quiz/QuizResultActivity.kt +++ b/app/src/main/java/fr/free/nrw/commons/quiz/QuizResultActivity.kt @@ -93,10 +93,11 @@ class QuizResultActivity : AppCompatActivity() { } /** - * Function to call intent to an activity - * @param context - * @param cls - * @param flags + * Starts an activity using the provided context, target class, and intent flags. + * + * @param context The context used to start the activity. + * @param cls The target activity class. + * @param flags A variable number of intent flags to apply to the Intent. */ companion object { fun startActivityWithFlags(context: Context, cls: Class, vararg flags: Int) { diff --git a/app/src/main/java/fr/free/nrw/commons/repository/UploadRepository.kt b/app/src/main/java/fr/free/nrw/commons/repository/UploadRepository.kt index 443a112dd..19f526906 100644 --- a/app/src/main/java/fr/free/nrw/commons/repository/UploadRepository.kt +++ b/app/src/main/java/fr/free/nrw/commons/repository/UploadRepository.kt @@ -199,10 +199,11 @@ class UploadRepository @Inject constructor( } /** - * Query the RemoteDataSource for image duplicity check + * Queries the RemoteDataSource to check if the image is a duplicate. * - * @param filePath file to be checked - * @return IMAGE_DUPLICATE or IMAGE_OK + * @param originalFilePath The original file to be checked. + * @param modifiedFilePath The modified version of the file (if any). + * @return IMAGE_DUPLICATE if the image already exists, otherwise IMAGE_OK. */ fun checkDuplicateImage(originalFilePath: Uri?, modifiedFilePath: Uri?): Single { return uploadModel.checkDuplicateImage(originalFilePath, modifiedFilePath) diff --git a/app/src/main/java/fr/free/nrw/commons/review/ReviewActivity.kt b/app/src/main/java/fr/free/nrw/commons/review/ReviewActivity.kt index 01a1005fe..20f289f8f 100644 --- a/app/src/main/java/fr/free/nrw/commons/review/ReviewActivity.kt +++ b/app/src/main/java/fr/free/nrw/commons/review/ReviewActivity.kt @@ -55,10 +55,10 @@ class ReviewActivity : BaseActivity() { } /** - * Consumers should be simply using this method to use this activity. + * Starts the ReviewActivity. * - * @param context - * @param title Page title + * @param context The context used to start the activity. + * @param title The page title (currently unused). */ companion object { fun startYourself(context: Context, title: String) { diff --git a/app/src/main/java/fr/free/nrw/commons/settings/SettingsFragment.kt b/app/src/main/java/fr/free/nrw/commons/settings/SettingsFragment.kt index 161927d03..092f057e9 100644 --- a/app/src/main/java/fr/free/nrw/commons/settings/SettingsFragment.kt +++ b/app/src/main/java/fr/free/nrw/commons/settings/SettingsFragment.kt @@ -276,9 +276,7 @@ class SettingsFragment : PreferenceFragmentCompat() { } /** - * Asks users to provide location access - * - * @param activity + * Asks users to provide location access. */ private fun createDialogsAndHandleLocationPermissions() { inAppCameraLocationPermissionLauncher.launch(arrayOf(permission.ACCESS_FINE_LOCATION)) diff --git a/app/src/main/java/fr/free/nrw/commons/upload/Description.kt b/app/src/main/java/fr/free/nrw/commons/upload/Description.kt index 83902aae4..cb2a85362 100644 --- a/app/src/main/java/fr/free/nrw/commons/upload/Description.kt +++ b/app/src/main/java/fr/free/nrw/commons/upload/Description.kt @@ -6,29 +6,29 @@ package fr.free.nrw.commons.upload class Description { /** * The language code, e.g., "en" or "fr". - * @param languageCode The language code. + * @property languageCode The language code. */ var languageCode: String? = null /** * The description text for the item being uploaded. - * @param descriptionText The description text. + * @property descriptionText The description text. */ var descriptionText: String? = null /** * The index of the language selected in a spinner with [SpinnerLanguagesAdapter]. - * @param selectedLanguageIndex The index of the selected language. + * @property selectedLanguageIndex The index of the selected language. */ var selectedLanguageIndex = -1 /** * Indicates if the description was added manually (by the user or programmatically). - * @param manuallyAdded Sets to true if the description was manually added by the user. - * @return True if the description was manually added. */ var isManuallyAdded = false - + /** + * Returns true if the description text is null or empty. + */ val isEmpty: Boolean get() = descriptionText == null || descriptionText!!.isEmpty() diff --git a/app/src/main/java/fr/free/nrw/commons/upload/FileProcessor.kt b/app/src/main/java/fr/free/nrw/commons/upload/FileProcessor.kt index 617da88a0..ed1867472 100644 --- a/app/src/main/java/fr/free/nrw/commons/upload/FileProcessor.kt +++ b/app/src/main/java/fr/free/nrw/commons/upload/FileProcessor.kt @@ -137,13 +137,12 @@ class FileProcessor } } - /** - * Find other images around the same location that were taken within the last 20 sec - * - * @param originalImageCoordinates - * @param fileBeingProcessed - * @param similarImageInterface - */ + /** + * Finds other images around the same location that were taken within a ±120 sec window. + * + * @param fileBeingProcessed The file currently being checked. + * @param similarImageInterface Callback to display similar images if any are found. + */ private fun findOtherImages( fileBeingProcessed: File, similarImageInterface: SimilarImageInterface?, diff --git a/app/src/main/java/fr/free/nrw/commons/upload/ImageProcessingService.kt b/app/src/main/java/fr/free/nrw/commons/upload/ImageProcessingService.kt index 3acd13c65..cbec7559f 100644 --- a/app/src/main/java/fr/free/nrw/commons/upload/ImageProcessingService.kt +++ b/app/src/main/java/fr/free/nrw/commons/upload/ImageProcessingService.kt @@ -138,10 +138,10 @@ class ImageProcessingService @Inject constructor( } /** - * Checks for duplicate image + * Checks for duplicate image by calculating its SHA1 hash and querying the media client. * - * @param filePath file to be checked - * @return IMAGE_DUPLICATE or IMAGE_OK + * @param inputStream The input stream of the file to check. + * @return IMAGE_DUPLICATE if the file exists, or IMAGE_OK otherwise. */ private fun checkDuplicateImage(inputStream: InputStream): Single { return Single.fromCallable { fileUtilsWrapper.getSHA1(inputStream) } diff --git a/app/src/main/java/fr/free/nrw/commons/upload/UploadMediaDetail.kt b/app/src/main/java/fr/free/nrw/commons/upload/UploadMediaDetail.kt index 351e53124..446d1f0cf 100644 --- a/app/src/main/java/fr/free/nrw/commons/upload/UploadMediaDetail.kt +++ b/app/src/main/java/fr/free/nrw/commons/upload/UploadMediaDetail.kt @@ -10,18 +10,15 @@ import kotlinx.parcelize.Parcelize @Parcelize data class UploadMediaDetail( /** - * The language code ie. "en" or "fr". - * @param languageCode The language code ie. "en" or "fr". + * The language code, e.g., "en" or "fr". */ var languageCode: String? = null, /** * The description text for the item being uploaded. - * @param descriptionText The description text. */ var descriptionText: String? = "", /** * The caption text for the item being uploaded. - * @param captionText The caption text. */ var captionText: String = "", ) : Parcelable { @@ -35,15 +32,11 @@ data class UploadMediaDetail( /** * The index of the language selected in a spinner with [SpinnerLanguagesAdapter]. - * @return The index of the selected language. - * @param selectedLanguageIndex The index of the language selected. */ var selectedLanguageIndex: Int = -1 /** - * Returns if the description was added manually (by the user, or programmatically). - * @return True if the description was manually added. - * @param manuallyAdded Sets to true if the description was manually added. + * Indicates whether the description was added manually (by the user or programmatically). */ var isManuallyAdded: Boolean = false } diff --git a/app/src/main/java/fr/free/nrw/commons/upload/UploadMediaDetailInputFilter.kt b/app/src/main/java/fr/free/nrw/commons/upload/UploadMediaDetailInputFilter.kt index d4baf21c8..1d5e59468 100644 --- a/app/src/main/java/fr/free/nrw/commons/upload/UploadMediaDetailInputFilter.kt +++ b/app/src/main/java/fr/free/nrw/commons/upload/UploadMediaDetailInputFilter.kt @@ -30,9 +30,10 @@ class UploadMediaDetailInputFilter : InputFilter { patterns.any { it.matcher(source).find() } /** - * Removes any blocklisted characters from the source text. - * @param source input text - * @return a cleaned character sequence + * Removes any blocklisted characters from the input text. + * + * @param input The input text to be cleaned. + * @return A cleaned character sequence with blocklisted patterns removed. */ private fun removeBlocklisted(input: CharSequence): CharSequence { var source = input diff --git a/app/src/main/java/fr/free/nrw/commons/upload/UploadModel.kt b/app/src/main/java/fr/free/nrw/commons/upload/UploadModel.kt index 2cda7a890..954079a45 100644 --- a/app/src/main/java/fr/free/nrw/commons/upload/UploadModel.kt +++ b/app/src/main/java/fr/free/nrw/commons/upload/UploadModel.kt @@ -98,10 +98,11 @@ class UploadModel @Inject internal constructor( imageProcessingService.validateImage(uploadItem, inAppPictureLocation) /** - * Calls checkDuplicateImage() of ImageProcessingService to check if image is duplicate + * Calls checkDuplicateImage() of ImageProcessingService to check if the image is a duplicate. * - * @param filePath file to be checked - * @return IMAGE_DUPLICATE or IMAGE_OK + * @param originalFilePath The original file URI. + * @param modifiedFilePath The modified file URI. + * @return IMAGE_DUPLICATE if the file already exists, IMAGE_OK otherwise. */ fun checkDuplicateImage(originalFilePath: Uri?, modifiedFilePath: Uri?): Single = imageProcessingService.checkIfFileAlreadyExists( diff --git a/app/src/main/java/fr/free/nrw/commons/utils/LocationUtils.kt b/app/src/main/java/fr/free/nrw/commons/utils/LocationUtils.kt index 2df42270e..1fbd87581 100644 --- a/app/src/main/java/fr/free/nrw/commons/utils/LocationUtils.kt +++ b/app/src/main/java/fr/free/nrw/commons/utils/LocationUtils.kt @@ -16,12 +16,12 @@ object LocationUtils { val indexOfPrefix = customQuery.indexOf("Point(") if (indexOfPrefix == -1) { Timber.e("Invalid prefix index - Seems like user has entered an invalid query") - return latLng + return null } val indexOfSuffix = customQuery.indexOf(")\"", indexOfPrefix) if (indexOfSuffix == -1) { Timber.e("Invalid suffix index - Seems like user has entered an invalid query") - return latLng + return null } val latLngString = customQuery.substring(indexOfPrefix + "Point(".length, indexOfSuffix) if (latLngString.isEmpty()) { diff --git a/app/src/main/java/fr/free/nrw/commons/wikidata/model/page/PageTitle.kt b/app/src/main/java/fr/free/nrw/commons/wikidata/model/page/PageTitle.kt index b039f55d6..98885a135 100644 --- a/app/src/main/java/fr/free/nrw/commons/wikidata/model/page/PageTitle.kt +++ b/app/src/main/java/fr/free/nrw/commons/wikidata/model/page/PageTitle.kt @@ -32,8 +32,8 @@ class PageTitle : Parcelable { * looking at. * * Examples: - * * [[Manchester]] on enwiki will have a namespace of null - * * [[Deutschland]] on dewiki will have a namespace of null + * * \[\[Manchester\]\] on enwiki will have a namespace of null + * * \[\[Deutschland\]\] on dewiki will have a namespace of null * * [[User:Deskana]] on enwiki will have a namespace of "User" * * [[Utilisateur:Deskana]] on frwiki will have a namespace of "Utilisateur", even if you got * to the page by going to [[User:Deskana]] and having MediaWiki automatically redirect you. From 95b8ac74b9c8a0eb247931b99fccd891fff652f4 Mon Sep 17 00:00:00 2001 From: "translatewiki.net" Date: Thu, 29 May 2025 14:01:51 +0200 Subject: [PATCH 009/162] Localisation updates from https://translatewiki.net. --- app/src/main/res/values-it/strings.xml | 31 +++++++++++++++++++++++--- app/src/main/res/values-iw/strings.xml | 1 + app/src/main/res/values-mk/strings.xml | 1 + app/src/main/res/values-ru/strings.xml | 1 + app/src/main/res/values-sv/strings.xml | 2 ++ app/src/main/res/values-ta/strings.xml | 5 +++++ 6 files changed, 38 insertions(+), 3 deletions(-) diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index 221f55da6..b639c31fd 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -4,6 +4,7 @@ * Albe Albe 460 * Albe Albe460 * Ale.salmo +* Antonino Faro * Beta16 * Black Sky83 * Champ0999 @@ -34,7 +35,7 @@ Aggiungi nuovo contributo Aggiungi contributo dalla fotocamera Aggiungi contributo da Foto - Aggiungi contributo dalla galleria dei contributi precedenti + Aggiungi un contributo dalla galleria dei contributi precedenti Didascalie Descrizione della lingua Didascalia @@ -86,7 +87,7 @@ Nome utente Password Accedi alla tua utenza in Commons Beta - Entra + Accedi Password dimenticata? Registrati Accesso in corso @@ -103,7 +104,7 @@ Caricamento iniziato! Caricamento in coda (attivata modalità di connessione limitata) %1$s caricato! - Premi per vedere i tuoi caricamenti + Tocca per visualizzare il tuo caricamento Caricamento file: %s Sto caricando %1$s Terminato il caricamento di %1$s @@ -301,6 +302,7 @@ Internet non disponibile. Vengono mostrati solo i luoghi memorizzati nella cache. Accesso alla posizione negato. Impostala manualmente per utilizzare questa funzione. È richiesta l\'autorizzazione per visualizzare un elenco di luoghi nelle vicinanze + È richiesta l\'autorizzazione per visualizzare un elenco di luoghi nelle vicinanze Indicazioni Wikidata Wikipedia @@ -608,6 +610,7 @@ Accendere la localizzazione? Si prega di attivare i servizi di localizzazione dell’app per mostrare la tua posizione attuale La funzione \'nelle vicinanze\' richiede l\'abilitazione della localizzazione per operare correttamente + La mappa Esplora necessita dell\'autorizzazione di posizione per visualizzare le immagini vicine È necessario fornire l\'autorizzazione alla posizione per impostare automaticamente la posizione. Hai scattato queste immagini nello stesso posto? Vuoi usare la latitudine e la longitudine dell\'immagine indicate a destra? Caricane ancora @@ -721,6 +724,7 @@ Aggiungi luogo Rimuovi da questa email tutte le informazioni che non sei disposto a condividere pubblicamente. Inoltre, tieni presente che il tuo indirizzo email con cui stai scrivendo, il nome e l\'immagine del profilo associati saranno visibili pubblicamente. Dettagli + La classifica è disponibile solo nella versione prod. Consulta la documentazione per gli sviluppatori. La classifica è disponibile solo nella versione prod. Consulta la documentazione per gli sviluppatori. Per favore carica solo le foto che hai scattato tu. Gli autori che caricano immagini protette da copyright verranno bloccati. Questo vale anche per la versione beta. Grazie per aver testato l\'app! Deseleziona tutte le informazioni che non ti senti a tuo agio nel condividere pubblicamente. @@ -755,6 +759,7 @@ Benvenuto nella modalità di selezione a schermo intero Usa due dita per ingrandire e rimpicciolire. Scorri velocemente e a lungo per eseguire queste azioni: \n- Sinistra/destra: vai al precedente/successivo \n- Su: seleziona\n- Giù: contrassegna come da non caricare. + Per impostare il tuo avatar nella classifica, tocca \"Imposta come avatar\" nel menu a tre punti di qualsiasi immagine. Le coordinate non sono esatte, ma la persona che ha caricato questa immagine pensa che siano abbastanza vicine. Autorizzazioni di archiviazione negate Impossibile condividere questo elemento @@ -765,9 +770,14 @@ Modifica Immagine Modifica Posizione Posizione aggiornata! + Rimuovi posizione + Rimuovi avviso di posizione + La posizione rende le immagini più utili e facili da trovare. Vuoi davvero rimuovere la posizione da questa immagine? + Posizione rimossa! Ringrazia l\'autore Errore nell\'invio di ringraziamenti all\'autore. Sessione scaduta. Accedi nuovamente. + Nessuna applicazione disponibile per aprire i file GPX File salvato con successo Vuoi aprire il file GPX? Vuoi aprire il file KML? @@ -781,23 +791,38 @@ Ricorda che tutte le immagini in un caricamento multiplo hanno le stesse categorie e descrizioni. Se le immagini non condividono descrizioni e categorie, esegui caricamenti separati. Osservazione sui caricamenti multipli + Segnala un problema su questo elemento su Wikidata + Inserisci dei commenti + Discussione + \' %1$s \' si trova in un luogo diverso. + Sei sicuro di voler cancellare tutti i caricamenti? + Cancellando tutti i caricamenti... Caricamenti In attesa Non riuscito + Impossibile caricare i dati del luogo Cancella cartella Conferma cancellazione Sei sicuro di voler eliminare la cartella %1$s contenente elementi %2$d? Cancella Annulla Cartella %1$s cancellata correttamente + Impossibile eliminare la cartella %1$s Questo posto non ha ancora una foto, scattane una! Questo posto ha già una foto. Ora controlliamo se questo posto ha una foto. + Errore durante il caricamento Commons Altri wiki Utilizzi del file + SingleWebViewActivity + Utenza + Elimina l\'utenza + Avviso di eliminazione dell\'utenza Didascalia Didascalia copiata negli appunti + Mostra in Esplora + Mostra nelle vicinanze Creato e caricato da: %1$s Creato da %1$s e caricato da %2$s diff --git a/app/src/main/res/values-iw/strings.xml b/app/src/main/res/values-iw/strings.xml index fbeddc0d5..6aecaf1e8 100644 --- a/app/src/main/res/values-iw/strings.xml +++ b/app/src/main/res/values-iw/strings.xml @@ -822,6 +822,7 @@ שיחה נא לכתוב משהו על פריט \"%1$s\". זה יוצג לציבור. \"%1$s\" כבר לא קיים, אי־אפשר לצלם אותו. + ‚%1$s’ נמצא במקום אחר. \"%1$s\" נמצא במקום אחר. נא לציין את המקום הנכון למטה, ואם אפשר, לכתוב את קו הרוחב ואת קו האורך הנכונים. בעיה אחרת או מידע אחר (נא להסביר הלאה). המשוב שלך מתפרסם בדף הוויקי הבא: <a href=\"https://commons.wikimedia.org/wiki/Commons:Mobile_app/Feedback\">Commons:Mobile app/Feedback</a> diff --git a/app/src/main/res/values-mk/strings.xml b/app/src/main/res/values-mk/strings.xml index b055b1ff0..b3058b81e 100644 --- a/app/src/main/res/values-mk/strings.xml +++ b/app/src/main/res/values-mk/strings.xml @@ -785,6 +785,7 @@ Разговор Напишете нешто за предметот „%1$s“. Ова ќе биде јавно видливо. „%1$s“ повеќе не постои, нема да може да се фотографира. + „%1$s“ се наоѓа на друго место. „%1$s“ се наоѓа на друго место. Подолу укажете го исправното место и, ако е можно, ставете исправна географска ширина и должина. Друг проблем или информација (објаснете подолу). Вашите мислења се објавуваат на следнава викистраница: <a href=\"https://commons.wikimedia.org/wiki/Commons:Mobile_app/Feedback\">Commons:Mobile app/Feedback</a> diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index aa287c9cb..ecef5c74b 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -848,6 +848,7 @@ Обсуждение Напишите что-нибудь об элементе \'%1$s\'. Это будет видно всем. \'%1$s\' больше не существует, его невозможно сфотографировать. + \'%1$s\' находится в другом месте. \'%1$s\' находится в другом месте. Пожалуйста, укажите правильное место ниже и, если возможно, напишите правильную широту и долготу. Другая проблема или информация (пожалуйста, объясните ниже). Ваш отзыв будет опубликован на следующей вики-странице: <a href=\"https://commons.wikimedia.org/wiki/Commons:Mobile_app/Feedback\">Commons:Mobile app/Feedback</a> diff --git a/app/src/main/res/values-sv/strings.xml b/app/src/main/res/values-sv/strings.xml index 6d8878f86..28a0896c0 100644 --- a/app/src/main/res/values-sv/strings.xml +++ b/app/src/main/res/values-sv/strings.xml @@ -2,6 +2,7 @@ @@ -459,6 +460,7 @@ Nascondi Attiva l\'accesso alla posizione dalle Impostazioni e riprova. \n\nNota: il caricamento potrebbe non contenere la posizione se l\'app non è in grado di recuperarla dal dispositivo entro un breve intervallo. La fotocamera in-app necessita dell\'autorizzazione alla posizione per allegarla alle tue immagini nel caso in cui la posizione non sia disponibile in EXIF. Consenti all\'app di accedere alla tua posizione e riprova.\n\nNota: il caricamento potrebbe non avere la posizione se l\'app non è in grado di recuperare la posizione dal dispositivo entro un breve intervallo. + L\'app non registra la posizione insieme alle riprese a causa della mancanza di autorizzazione alla posizione L\'app non registra la posizione insieme alle foto in quanto il GPS è disattivato Utilizza il selettore di foto basato sui documenti Il nuovo selettore di foto di Android rischia di perdere le informazioni sulla posizione. Abilita se pensi di usarlo. @@ -668,6 +670,7 @@ Per favore scrivi una breve descrizione su cosa è ritratto nella tua immagine. Nella descrizione, indica che cosa rende l\'immagine interessante, tipica o rara, e spiega il contesto, visibile o non. Impiega il più possibile una terminologia esatta. Trova e seleziona tutti i concetti rappresentati da questa immagine. Sii il più specifico possibile. Se l\'immagine ritrae più elementi, sceglili tutti entro limiti ragionevoli. Non scegliere etichette generali se sono disponibili etichette più specifiche. Si prega di selezionare le categorie appropriate. A differenza delle raffigurazioni, le categorie sono solo in inglese. + Commons rende le tue immagini riutilizzabili e adattabili da chiunque. Vuoi rinunciare a tutti i diritti? Vuoi che ti venga attribuita la paternità? Vuoi che gli adattamenti utilizzino la stessa licenza? Raffigura Licenza per il file Dettagli sul file @@ -794,7 +797,12 @@ Segnala un problema su questo elemento su Wikidata Inserisci dei commenti Discussione + Scrivi qualcosa su \' %1$s \'. Sarà visibile pubblicamente. + \'%1$s\' non esiste più, non potrà mai più essere fotografato. \' %1$s \' si trova in un luogo diverso. + \' %1$s \' si trova in un luogo diverso. Specifica il luogo corretto qui sotto e, se possibile, scrivi latitudine e longitudine corrette. + Altro problema o informazione (si prega di spiegare di seguito). + Il tuo feedback verrà pubblicato sulla seguente pagina wiki: <a href=\"https://commons.wikimedia.org/wiki/Commons:Mobile_app/Feedback\">Commons:App mobile/Feedback</a> Sei sicuro di voler cancellare tutti i caricamenti? Cancellando tutti i caricamenti... Caricamenti @@ -808,6 +816,7 @@ Annulla Cartella %1$s cancellata correttamente Impossibile eliminare la cartella %1$s + Impossibile eliminare i contenuti nella cartella: %1$s Questo posto non ha ancora una foto, scattane una! Questo posto ha già una foto. Ora controlliamo se questo posto ha una foto. @@ -819,8 +828,10 @@ Utenza Elimina l\'utenza Avviso di eliminazione dell\'utenza + Il diritto all\'oblio è una <b>soluzione estrema</b> e dovrebbe essere utilizzata solo quando si desidera smettere di contribuire per sempre e anche per nascondere il più possibile le proprie associazioni passate. \n\nLa cancellazione di un utenza su Wikimedia commons avviene cambiando il nome dell\'utenza in modo che gli altri non possano riconoscere i contributi, attraverso un processo chiamato scomparsa dell\'utenza. <b>L\'oblio non garantisce un anonimato completo né la rimozione dei contributi ai progetti.</b> Didascalia Didascalia copiata negli appunti + Congratulazioni, tutte le foto di questo album sono state caricate o contrassegnate come non adatte al caricamento. Mostra in Esplora Mostra nelle vicinanze Creato e caricato da: %1$s diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index 699c60857..29cbf44c9 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -826,6 +826,7 @@ Dyskusja Napisz coś o elemencie \' %1$s\'. Będzie to publicznie widoczne. \'%1$s\' już nie istnieje, nie da się zrobić dla niego zdjęcia. + \'%1$s\' znajduje się w innym miejscu. \'%1$s\' jest w innym miejscu. Proszę podać poniżej prawidłowe miejsce i jeśli to możliwe, wpisać jego prawidłową szerokość i długość geograficzną. Inny problem lub informacja (proszę wyjaśnić poniżej). Twoja opinia zostanie opublikowana na następującej stronie wiki: <a href=\"https://commons.wikimedia.org/wiki/Commons:Mobile_app/Feedback\">Commons:Aplikacja mobilna/Opinie</a> @@ -855,6 +856,7 @@ Konto Wymaż konto Ostrzeżenie o wymazaniu konta + Wymazanie to <b>ostateczność</b> i należy z niej skorzystać <b>tylko wtedy, gdy chcesz na zawsze zaprzestać edytowania</b> oraz ukryć jak najwięcej swoich przeszłych powiązań.<br/><br/>Usunięcie konta w Wikimedia Commons odbywa się poprzez zmianę nazwy konta, tak aby inni nie mogli rozpoznać Twoich wkładów, w procesie zwanym wymazaniem konta. <b>Wymazanie nie gwarantuje pełnej anonimowości ani nie usuwa wkładów wniesionych do projektów</b>. Podpis Podpis skopiowano do schowka Gratulacje, wszystkie zdjęcia w tym albumie zostały przesłane lub zostały oznaczone jako nie do przesłania. diff --git a/app/src/main/res/values-pms/strings.xml b/app/src/main/res/values-pms/strings.xml index 5f494f044..b0ecdcfe1 100644 --- a/app/src/main/res/values-pms/strings.xml +++ b/app/src/main/res/values-pms/strings.xml @@ -781,6 +781,7 @@ Ciaciarade Scrive cheicòs a propòsit ëd l\'element \'%1$s\'. Sòn a sarà visìbil për tuti. \'%1$s\' a esist pi nen, a peul pa esse fotografà. + \'%1$s\' a l\'é ant un pòst diferent. \'%1$s\' a l\'é ant un pòst diferent. Për piasì, ch\'a spessìfica ël pòst giust sì-sota e, si possìbil, ch\'a scriva latitùdin e longitùdin giuste. Àutr problema o anformassion (për piasì, ch\'a spiega sì-sota). Ij sò sugeriment a saran giontà a coste pàgine wiki: <a href=\"https://commons.wikimedia.org/wiki/Commons:Mobile_app/Feedback\">Commons:Mobile app/Feedback</a> diff --git a/app/src/main/res/values-te/strings.xml b/app/src/main/res/values-te/strings.xml index 98898884d..ba67a7b35 100644 --- a/app/src/main/res/values-te/strings.xml +++ b/app/src/main/res/values-te/strings.xml @@ -2,6 +2,7 @@ @@ -45,29 +46,29 @@ పంచుకున్న కంటెంటును అందుకుంటున్నాం. బొమ్మల పరిమాణాన్ని బట్టి, మీ పరికరాన్ని బట్టీ ప్రాసెసింగు చేసేందుకు కొంత సమయం పట్టవచ్చు శోధించండి - రూపురేఖలు - సాధారణం - ప్రతిస్పందన - అంతరంగికత - కామన్స్ + స్వరూపం + సాధారణ + ప్రతిపుష్టి + గోప్యత + సామూహిక అమరికలు - కామన్స్ లోకి ఎక్కించండి + సామూహిక కు ఎగుమోత వాడుకరిపేరు సంకేతపదం - మీ కామన్స్ బీటా ఖాతా లోనికి ప్రవేశించండి - లాగినవండి + మీ సామూహికా బీటా ఖాతా లోనికి ప్రవేశించండి + ప్రవేశం సంకేతపదం మర్చిపోయారా? - నమోదవ్వండి - లాగినవుతున్నారు - వేచివుండండి… - ఉల్లేఖనలను, వివరణలనూ తాజాకరిస్తున్నాం - వేచి ఉండండి… + నమోదు + ప్రవేశిస్తున్నారు... + దయచేసి వేచివుండండి … + ఉల్లేఖనలను, వివరణలను నవీకరిస్తోంది + దయచేసి వేచివుండండి … లాగిన్ విజయవంతమైంది! లాగిన్ విఫలమైంది! - ఫైలు కనబడలేదు. మరో ఫైలు కోసం ప్రయత్నించండి. + దస్త్రం కనబడలేదు. దయచేసి మరో దస్త్రం కోసం ప్రయత్నించండి. అథీకరణ విఫలమైంది, మళ్ళీ ప్రయత్నించండి - ఎక్కింపు మొదలైంది! - ఎక్కింపు వరుసలో ఉంది (పరిమిత కనెక్షన్ల మోడ్ చేతనంగా ఉంది) + ఎగుమోత మొదలైంది! + ఎగుమోత వరుసలో ఉంది (పరిమిత సంబంధ పద్దతి చేతనం) %1$s ను ఎక్కించాం! మీ ఎక్కింపును చూసేందుకు నొక్కండి దస్త్రాన్ని ఎక్కిస్తున్నాం: $s diff --git a/app/src/main/res/values-ks/error.xml b/app/src/main/res/values-x-invalidLanguageCode/error.xml similarity index 98% rename from app/src/main/res/values-ks/error.xml rename to app/src/main/res/values-x-invalidLanguageCode/error.xml index 3ef53fda5..f4e2fe125 100644 --- a/app/src/main/res/values-ks/error.xml +++ b/app/src/main/res/values-x-invalidLanguageCode/error.xml @@ -1,6 +1,6 @@ کامَنٕز گوو رُکِتھ From f45f26e602497f155037d1849bf4561f5b5e6543 Mon Sep 17 00:00:00 2001 From: Sonal Yadav Date: Sat, 7 Jun 2025 19:39:47 +0530 Subject: [PATCH 017/162] Implement single selection logic in custom image picker (#6341) * build failure cause * Fix image selector logic in custom picker --- .../contributions/ContributionController.kt | 5 +++-- .../customselector/ui/adapter/ImageAdapter.kt | 20 ++++++++++++++++--- .../ui/selector/CustomSelectorActivity.kt | 6 +++++- .../ui/selector/ImageFragment.kt | 3 +++ .../free/nrw/commons/filepicker/FilePicker.kt | 17 ++++++++++++---- .../nearby/fragments/NearbyParentFragment.kt | 6 ++++-- .../values-x-invalidLanguageCode/error.xml | 10 ---------- 7 files changed, 45 insertions(+), 22 deletions(-) delete mode 100644 app/src/main/res/values-x-invalidLanguageCode/error.xml diff --git a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionController.kt b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionController.kt index 296391c6d..29267452b 100644 --- a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionController.kt +++ b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionController.kt @@ -253,13 +253,14 @@ class ContributionController @Inject constructor(@param:Named("default_preferenc */ fun initiateCustomGalleryPickWithPermission( activity: Activity, - resultLauncher: ActivityResultLauncher + resultLauncher: ActivityResultLauncher, + singleSelection: Boolean = false ) { setPickerConfiguration(activity, true) checkPermissionsAndPerformAction( activity, - { openCustomSelector(activity, resultLauncher, 0) }, + { FilePicker.openCustomSelector(activity, resultLauncher, 0, singleSelection) }, R.string.storage_permission_title, R.string.write_storage_permission_rationale, *PERMISSIONS_STORAGE diff --git a/app/src/main/java/fr/free/nrw/commons/customselector/ui/adapter/ImageAdapter.kt b/app/src/main/java/fr/free/nrw/commons/customselector/ui/adapter/ImageAdapter.kt index 20a2fe70a..62a440ff4 100644 --- a/app/src/main/java/fr/free/nrw/commons/customselector/ui/adapter/ImageAdapter.kt +++ b/app/src/main/java/fr/free/nrw/commons/customselector/ui/adapter/ImageAdapter.kt @@ -327,12 +327,17 @@ class ImageAdapter( // Getting clicked index from all images index when show_already_actioned_images // switch is on + if (singleSelection) { + // If single selection mode, clear previous selection and select only the new one + if (selectedImages.isNotEmpty() && (selectedImages[0] != images[position])) { + val prevIndex = images.indexOf(selectedImages[0]) + selectedImages.clear() + notifyItemChanged(prevIndex, ImageUnselected()) + } + } val clickedIndex: Int = if (showAlreadyActionedImages) { ImageHelper.getIndex(selectedImages, images[position]) - - // Getting clicked index from actionable images when show_already_actioned_images - // switch is off } else { ImageHelper.getIndex(selectedImages, ArrayList(actionableImagesMap.values)[position]) } @@ -618,4 +623,13 @@ class ImageAdapter( * Returns the text for showing inside the bubble during bubble scroll. */ override fun getSectionName(position: Int): String = images[position].date + + private var singleSelection: Boolean = false + + /** + * Set single selection mode + */ + fun setSingleSelection(single: Boolean) { + singleSelection = single + } } diff --git a/app/src/main/java/fr/free/nrw/commons/customselector/ui/selector/CustomSelectorActivity.kt b/app/src/main/java/fr/free/nrw/commons/customselector/ui/selector/CustomSelectorActivity.kt index f872d3044..7e7d7e4cd 100644 --- a/app/src/main/java/fr/free/nrw/commons/customselector/ui/selector/CustomSelectorActivity.kt +++ b/app/src/main/java/fr/free/nrw/commons/customselector/ui/selector/CustomSelectorActivity.kt @@ -104,7 +104,7 @@ class CustomSelectorActivity : /** * Maximum number of images that can be selected. */ - private val uploadLimit: Int = 20 + private var uploadLimit: Int = 20 /** * Flag that is marked true when the amount @@ -207,6 +207,9 @@ class CustomSelectorActivity : CustomSelectorViewModel::class.java, ) + // Check for single selection extra + uploadLimit = if (intent.getBooleanExtra(EXTRA_SINGLE_SELECTION, false)) 1 else 20 + setupViews() if (prefs.getBoolean("customSelectorFirstLaunch", true)) { @@ -728,6 +731,7 @@ class CustomSelectorActivity : const val FOLDER_ID: String = "FolderId" const val FOLDER_NAME: String = "FolderName" const val ITEM_ID: String = "ItemId" + const val EXTRA_SINGLE_SELECTION: String = "EXTRA_SINGLE_SELECTION" } } diff --git a/app/src/main/java/fr/free/nrw/commons/customselector/ui/selector/ImageFragment.kt b/app/src/main/java/fr/free/nrw/commons/customselector/ui/selector/ImageFragment.kt index 39d0d545a..6e08e30f1 100644 --- a/app/src/main/java/fr/free/nrw/commons/customselector/ui/selector/ImageFragment.kt +++ b/app/src/main/java/fr/free/nrw/commons/customselector/ui/selector/ImageFragment.kt @@ -212,6 +212,9 @@ class ImageFragment : _binding = FragmentCustomSelectorBinding.inflate(inflater, container, false) imageAdapter = ImageAdapter(requireActivity(), activity as ImageSelectListener, imageLoader!!) + // Set single selection mode if needed + val singleSelection = (activity as? CustomSelectorActivity)?.intent?.getBooleanExtra(CustomSelectorActivity.EXTRA_SINGLE_SELECTION, false) == true + imageAdapter.setSingleSelection(singleSelection) gridLayoutManager = GridLayoutManager(context, getSpanCount()) with(binding?.selectorRv) { this?.layoutManager = gridLayoutManager diff --git a/app/src/main/java/fr/free/nrw/commons/filepicker/FilePicker.kt b/app/src/main/java/fr/free/nrw/commons/filepicker/FilePicker.kt index acf072f02..ccccfbd34 100644 --- a/app/src/main/java/fr/free/nrw/commons/filepicker/FilePicker.kt +++ b/app/src/main/java/fr/free/nrw/commons/filepicker/FilePicker.kt @@ -25,6 +25,9 @@ object FilePicker : Constants { private const val KEY_LAST_CAMERA_VIDEO = "last_video" private const val KEY_TYPE = "type" + // Add extra for single selection + private const val EXTRA_SINGLE_SELECTION = "EXTRA_SINGLE_SELECTION" + /** * Returns the uri of the clicked image so that it can be put in MediaStore */ @@ -73,12 +76,17 @@ object FilePicker : Constants { * CreateCustomSectorIntent, creates intent for custom selector activity. * @param context * @param type + * @param singleSelection If true, restricts to single image selection * @return Custom selector intent */ @JvmStatic - private fun createCustomSelectorIntent(context: Context, type: Int): Intent { + private fun createCustomSelectorIntent(context: Context, type: Int, singleSelection: Boolean = false): Intent { storeType(context, type) - return Intent(context, CustomSelectorActivity::class.java) + val intent = Intent(context, CustomSelectorActivity::class.java) + if (singleSelection) { + intent.putExtra(EXTRA_SINGLE_SELECTION, true) + } + return intent } @JvmStatic @@ -153,9 +161,10 @@ object FilePicker : Constants { fun openCustomSelector( activity: Activity, resultLauncher: ActivityResultLauncher, - type: Int + type: Int, + singleSelection: Boolean = false ) { - val intent = createCustomSelectorIntent(activity, type) + val intent = createCustomSelectorIntent(activity, type, singleSelection) resultLauncher.launch(intent) } diff --git a/app/src/main/java/fr/free/nrw/commons/nearby/fragments/NearbyParentFragment.kt b/app/src/main/java/fr/free/nrw/commons/nearby/fragments/NearbyParentFragment.kt index 56af614d7..5b52c0ce5 100644 --- a/app/src/main/java/fr/free/nrw/commons/nearby/fragments/NearbyParentFragment.kt +++ b/app/src/main/java/fr/free/nrw/commons/nearby/fragments/NearbyParentFragment.kt @@ -974,7 +974,7 @@ class NearbyParentFragment : CommonsDaggerSupportFragment(), } else if (bottomSheetDetailsBehavior!!.state == BottomSheetBehavior.STATE_EXPANDED ) { - bottomSheetDetailsBehavior!!.state = BottomSheetBehavior.STATE_COLLAPSED + bottomSheetDetailsBehavior!!.setState(BottomSheetBehavior.STATE_COLLAPSED) } } @@ -2457,9 +2457,11 @@ class NearbyParentFragment : CommonsDaggerSupportFragment(), Timber.d("Gallery button tapped. Place: %s", selectedPlace.toString()) storeSharedPrefs(selectedPlace!!) activity?.let { + // Pass singleSelection = true for Nearby flow controller!!.initiateCustomGalleryPickWithPermission( it, - customSelectorLauncherForResult + customSelectorLauncherForResult, + singleSelection = true ) } } diff --git a/app/src/main/res/values-x-invalidLanguageCode/error.xml b/app/src/main/res/values-x-invalidLanguageCode/error.xml deleted file mode 100644 index f4e2fe125..000000000 --- a/app/src/main/res/values-x-invalidLanguageCode/error.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - کامَنٕز گوو رُکِتھ - Oops. کیہہ تام گوو غلط! - ؤنِیوٚ اَسہِ توٚہہِ کیاہ ٲسِیوٚ کران، تہٕ کٕریٚو تہِ اَسہِ سٕتی شیر بذریعہِ برقی خط. یُس مَدَتھ کَرِ اَسہِ اَتھ شہَرنَس منٛز! - شُکریہ! - From 767b62528993618de8eea876a3782a282f9e5d95 Mon Sep 17 00:00:00 2001 From: Ritika Pahwa <83745993+RitikaPahwa4444@users.noreply.github.com> Date: Sun, 8 Jun 2025 12:35:24 +0530 Subject: [PATCH 018/162] Bump up version code to 1052 --- app/build.gradle.kts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index c74f95fb4..2d9e213b2 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -24,8 +24,8 @@ android { applicationId = "fr.free.nrw.commons" minSdk = 21 targetSdk = 34 - versionCode = 1043 - versionName = "5.1.2" + versionCode = 1052 + versionName = "5.4.1" setProperty("archivesBaseName", "app-commons-v$versionName-" + getBranchName()) testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" @@ -442,4 +442,4 @@ fun getBranchName(): String? { } catch (e: Exception) { null } -} \ No newline at end of file +} From c41b5cc9dae2f107a15918161d149ba401cb8787 Mon Sep 17 00:00:00 2001 From: Ritika Pahwa <83745993+RitikaPahwa4444@users.noreply.github.com> Date: Sun, 8 Jun 2025 12:38:14 +0530 Subject: [PATCH 019/162] Add v5.4.1 to CHANGELOG.md --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index df55b1124..cd4e70b6c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Wikimedia Commons for Android +## v5.4.1 + +### What's changed +* Custom picker now detects images that are already available on Commons +* Improve credit line in image list +* Show place cards with loaded names only in the Nearby list +* Fix the error that occurs while loading images in Explore + ## v5.3.0 ### What's changed From 8ff52e681560fb79e9deccd8b321afee3791c60f Mon Sep 17 00:00:00 2001 From: Ritika Pahwa <83745993+RitikaPahwa4444@users.noreply.github.com> Date: Sun, 8 Jun 2025 19:16:01 +0530 Subject: [PATCH 020/162] Fix crash on app startup by bumping up room database version --- app/src/main/java/fr/free/nrw/commons/db/AppDatabase.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/fr/free/nrw/commons/db/AppDatabase.kt b/app/src/main/java/fr/free/nrw/commons/db/AppDatabase.kt index 74ec9bc89..79a655223 100644 --- a/app/src/main/java/fr/free/nrw/commons/db/AppDatabase.kt +++ b/app/src/main/java/fr/free/nrw/commons/db/AppDatabase.kt @@ -30,7 +30,7 @@ import fr.free.nrw.commons.upload.depicts.DepictsDao */ @Database( entities = [Contribution::class, Depicts::class, UploadedStatus::class, NotForUploadStatus::class, ReviewEntity::class, Place::class, BookmarksCategoryModal::class, BookmarksLocations::class], - version = 20, + version = 21, exportSchema = false, ) @TypeConverters(Converters::class) From 9b04031c916d1190c9f442974d0c723fdb4cd293 Mon Sep 17 00:00:00 2001 From: "translatewiki.net" Date: Mon, 9 Jun 2025 14:01:52 +0200 Subject: [PATCH 021/162] Localisation updates from https://translatewiki.net. --- app/src/main/res/values-el/strings.xml | 8 +++++++- .../main/res/values-x-invalidLanguageCode/error.xml | 10 ++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 app/src/main/res/values-x-invalidLanguageCode/error.xml diff --git a/app/src/main/res/values-el/strings.xml b/app/src/main/res/values-el/strings.xml index 1d718ddd2..da816259e 100644 --- a/app/src/main/res/values-el/strings.xml +++ b/app/src/main/res/values-el/strings.xml @@ -256,7 +256,7 @@ Κλείσιμο Αρχική σελίδα Μεταφόρτωση αρχείου - Κοντά σας + Κοντινά Σχετικά Ρυθμίσεις Ανατροφοδότηση @@ -803,6 +803,7 @@ Συζήτηση Γράψτε κάτι για το αντικείμενο \'%1$s\'. Θα είναι δημόσια ορατό. Το \'%1$s\' δεν υφίσταται πλέον, καμία φωτογραφία δεν μπορεί να εξαχθεί. + Το \'%1$s\' βρίσκεται σε διαφορετικό μέρος. Το \'%1$s\' βρίσκεται σε διαφορετική θέση. Παρακαλούμε προσδιορίστε τη σωστή θέση παρακαλώ, και αν είναι εφικτό, γράψτε το σωστό γεωγραφικό πλάτος και μήκος. Άλλο πρόβλημα ή πληροφορίες (παρακαλούμε εξηγήστε παρακάτω). Τα σχόλιά σας δημοσιεύονται στην ακόλουθη σελίδα wiki: <a href=\"https://commons.wikimedia.org/wiki/Commons:Mobile_app/Feedback\">Commons:Εφαρμογή για κινητά/Σχόλια</a> @@ -828,4 +829,9 @@ Λογαριασμός Λεζάντα Η λεζάντα αντιγράφηκε στο πρόχειρο + Συγχαρητήρια, όλες οι φωτογραφίες σε αυτό το άλμπουμ έχουν είτε μεταφορτωθεί είτε επισημανθεί για μη μεταφόρτωση. + Εμφάνιση στην Εξερεύνηση + Εμφάνιση στα Κοντινά + Δημιουργήθηκε και μεταφορτώθηκε από: %1$s + Δημιουργήθηκε από %1$s και μεταφορτώθηκε από %2$s diff --git a/app/src/main/res/values-x-invalidLanguageCode/error.xml b/app/src/main/res/values-x-invalidLanguageCode/error.xml new file mode 100644 index 000000000..f4e2fe125 --- /dev/null +++ b/app/src/main/res/values-x-invalidLanguageCode/error.xml @@ -0,0 +1,10 @@ + + + + کامَنٕز گوو رُکِتھ + Oops. کیہہ تام گوو غلط! + ؤنِیوٚ اَسہِ توٚہہِ کیاہ ٲسِیوٚ کران، تہٕ کٕریٚو تہِ اَسہِ سٕتی شیر بذریعہِ برقی خط. یُس مَدَتھ کَرِ اَسہِ اَتھ شہَرنَس منٛز! + شُکریہ! + From 2b5f0e4ac9aaabe9eb56dcfb5f9eaf3855beb08b Mon Sep 17 00:00:00 2001 From: Sonal Yadav Date: Wed, 11 Jun 2025 17:41:49 +0530 Subject: [PATCH 022/162] drop down menu in the Upload Wizard now show the language in which the pin's label is shown (#6346) --- .../nearby/presenter/NearbyParentFragmentPresenter.kt | 1 + .../main/res/values-x-invalidLanguageCode/error.xml | 10 ---------- 2 files changed, 1 insertion(+), 10 deletions(-) delete mode 100644 app/src/main/res/values-x-invalidLanguageCode/error.xml diff --git a/app/src/main/java/fr/free/nrw/commons/nearby/presenter/NearbyParentFragmentPresenter.kt b/app/src/main/java/fr/free/nrw/commons/nearby/presenter/NearbyParentFragmentPresenter.kt index b4639b14a..6ec1064be 100644 --- a/app/src/main/java/fr/free/nrw/commons/nearby/presenter/NearbyParentFragmentPresenter.kt +++ b/app/src/main/java/fr/free/nrw/commons/nearby/presenter/NearbyParentFragmentPresenter.kt @@ -351,6 +351,7 @@ class NearbyParentFragmentPresenter pic = repoPlace.pic ?: "" exists = repoPlace.exists ?: true longDescription = repoPlace.longDescription ?: "" + language = repoPlace.language } } else { indicesToUpdate.add(i) diff --git a/app/src/main/res/values-x-invalidLanguageCode/error.xml b/app/src/main/res/values-x-invalidLanguageCode/error.xml deleted file mode 100644 index f4e2fe125..000000000 --- a/app/src/main/res/values-x-invalidLanguageCode/error.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - کامَنٕز گوو رُکِتھ - Oops. کیہہ تام گوو غلط! - ؤنِیوٚ اَسہِ توٚہہِ کیاہ ٲسِیوٚ کران، تہٕ کٕریٚو تہِ اَسہِ سٕتی شیر بذریعہِ برقی خط. یُس مَدَتھ کَرِ اَسہِ اَتھ شہَرنَس منٛز! - شُکریہ! - From 91564a1dffc390bb5c8184707525da8f73375414 Mon Sep 17 00:00:00 2001 From: "translatewiki.net" Date: Thu, 12 Jun 2025 04:36:42 +0200 Subject: [PATCH 023/162] Localisation updates from https://translatewiki.net. --- app/src/main/res/values-hi/strings.xml | 11 +++--- app/src/main/res/values-ia/strings.xml | 15 ++++++++ app/src/main/res/values-ks/error.xml | 7 ++++ app/src/main/res/values-pt-rBR/strings.xml | 14 ++++++++ app/src/main/res/values-pt/strings.xml | 34 ++++++++++++------- .../values-x-invalidLanguageCode/error.xml | 10 ++++++ 6 files changed, 75 insertions(+), 16 deletions(-) create mode 100644 app/src/main/res/values-ks/error.xml create mode 100644 app/src/main/res/values-x-invalidLanguageCode/error.xml diff --git a/app/src/main/res/values-hi/strings.xml b/app/src/main/res/values-hi/strings.xml index 7f742a319..1c6685b7f 100644 --- a/app/src/main/res/values-hi/strings.xml +++ b/app/src/main/res/values-hi/strings.xml @@ -108,6 +108,7 @@ फ़ोटो लें आसपास मेरे अपलोड + लिंक कॉपी करें साझा करें शीर्षक (आवश्यक) विवरण @@ -193,6 +194,7 @@ अपलोड करें हाँ नहीं + कैप्शन शीर्षक विवरण चर्चा @@ -258,11 +260,11 @@ विकिटेक्सट क्लिपबोर्ड पर कॉपी किया जा चुका है स्थान उपलब्ध नहीं है। आसपास के स्थान दिखाने के लिए अनुमति चाहिए - दिशा-निर्देश - विकीडाटा - विकीपीडिया + दिशा-निर्देश + विकीडाटा + विकीपीडिया कॉमन्स - <u>हमें रेट करें</u> + हमें रेट करें अक्सर पूछे जाने वाले प्रश्न प्रशिक्षण छोड़ें इंटरनेट उपलब्ध नहीं @@ -286,6 +288,7 @@ श्रेणी लोड करते समय त्रुटि उत्पन्न हुई। मीडिया श्रेणियाँ + आयटम निर्वाचित नक्शा चित्र सफ़लतापूर्वक विकिडाटा के %1$s पर सफलतापूर्वक जोड़ दिया गया है। diff --git a/app/src/main/res/values-ia/strings.xml b/app/src/main/res/values-ia/strings.xml index f12022169..386bddf2e 100644 --- a/app/src/main/res/values-ia/strings.xml +++ b/app/src/main/res/values-ia/strings.xml @@ -112,6 +112,7 @@ Troppo de tentativas fallite. Per favor reproba in alcun minutas. Iste usator ha essite blocate sur Commons Tu debe fornir tu codice de authentication bifactorial. + Un codice de verification de session ha essite inviate a tu adresse de e-mail. Per favor insere iste codice pro aperir session. Apertura de session fallite Incargar Nomine de iste insimul @@ -212,6 +213,7 @@ Devenir testator beta Abona te a nostre canal beta sur Google Play e sia le prime a ganiar accesso a nove functiones e correctiones de anomalias Codice 2FA + Codice de verification in e-mail Vole tu vermente clauder session? Imagine multimedial fallite Necun subcategoria trovate @@ -775,6 +777,7 @@ Discussion Scribe qualcosa sur le elemento ‘%1$s’. Isto essera visibile publicamente. ‘%1$s’ non existe plus, necun imagine pote jammais esser prendite de illo. + ‘%1$s’ se trova in un altere loco. ‘%1$s’ es in un altere loco. Per favor specifica le loco correcte hic infra, e si possibile, indica le latitude e longitude correcte. Altere problema o information (per favor explica hic infra). Tu retroaction apparera sur le sequente pagina wiki: <a href=\"https://commons.wikimedia.org/wiki/Commons:Mobile_app/Feedback\">Commons:Mobile app/Feedback</a> @@ -801,4 +804,16 @@ Commons Altere wikis Usos del file + Activitate de singule visita web + Conto + Facer disparer le conto + Advertimento concernente le disparition del conto + Le disparition es un <b>ultime recurso</b> e debe <b>solmente esser usate quando tu vole cessar de modificar pro sempre</b> e celar le maximo possibile de tu associationes anterior.<br/><br/>Le deletion del conto sur Wikipedia se effectua cambiante tu nomine de conto de maniera que alteres non pote recognoscer tu contributiones. Iste processo se appella le disparition del conto. <b>Le disparition non garanti le anonymitate complete ni remove contributiones al projectos.</b> + Legenda + Legenda copiate al area de transferentia + Felicitationes, tote le imagines in iste album ha essite incargate o marcate como non incargabile. + Monstrar in Explorar + Monstrar in A proximitate + Create e incargate per: %1$s + Create per %1$s e incargate per %2$s diff --git a/app/src/main/res/values-ks/error.xml b/app/src/main/res/values-ks/error.xml new file mode 100644 index 000000000..838231c2b --- /dev/null +++ b/app/src/main/res/values-ks/error.xml @@ -0,0 +1,7 @@ + + + کامَنٕز گوو رُکِتھ + Oops. کیہہ تام گوو غلط! + ؤنِیوٚ اَسہِ توٚہہِ کیاہ ٲسِیوٚ کران، تہٕ کٕریٚو تہِ اَسہِ سٕتی شیر بذریعہِ برقی خط. یُس مَدَتھ کَرِ اَسہِ اَتھ شہَرنَس منٛز! + شُکریہ! + diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index 6bc192c68..947d65ace 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -126,6 +126,7 @@ Tirar foto Próximo Meus envios + Copiar link Compartilhar Ver página do arquivo Legenda (Obrigatório) @@ -694,6 +695,8 @@ Diferente da imagem à esquerda, a da direita possui o logotipo do Commons, o que indica que o envio dela já está concluído.\n Toque e segure para pré-visualizar a imagem. Ótimo Esta imagem já foi enviada para Commons. + Ignorar + Máx.: %1$d WLM Essa imagem será enviada ao concurso Wiki Loves Monuments Monumentos de exibição @@ -755,6 +758,8 @@ As coordenadas não são exatas, mas a pessoa que carregou essa imagem crê que sejam próximas o suficiente. Permissão de armazenamento negada Incapaz de compartilhar esse item + Editar imagem + Editar localização Localização atualizada! Remover localização Localização removida! @@ -771,4 +776,13 @@ %d imagens selecionadas Escreva algo sobre o item %1$s. Isso será visivel publicamente. + Envios + Pendente + Falhou + Excluir pasta + Confirmar exclusão + Excluir + Cancelar + Conta + Legenda diff --git a/app/src/main/res/values-pt/strings.xml b/app/src/main/res/values-pt/strings.xml index 0ae9736d5..15c5983c4 100644 --- a/app/src/main/res/values-pt/strings.xml +++ b/app/src/main/res/values-pt/strings.xml @@ -16,6 +16,7 @@ * Mansil alfalb * McDutchie * Mirzali +* O andras * Sarilho1 * Unamane * Vitorvicentevalente @@ -90,7 +91,7 @@ Aguarde, por favor… A atualizar legendas e descrições Aguarde, por favor… - Sessão iniciada! + Sessão iniciada! O início de sessão falhou! O ficheiro não foi encontrado. Tente outro, por favor. Limite máximo de novas tentativas atingido! Cancele o carregamento e tente novamente, por favor @@ -117,13 +118,15 @@ Tirar foto Nas redondezas Carregamentos + Copiar ligação + A ligação foi copiada para a área de transferência Partilhar Ver página do ficheiro Legenda (obrigatória) Forneça uma legenda para este ficheiro, por favor Descrição Legenda - Não é possível iniciar uma sessão - falha de rede + Não foi possível iniciar sessão - falha de rede Demasiadas tentativas mal sucedidas. Por favor, tente novamente dentro de minutos. Desculpe, este utilizador foi bloqueado na wiki Commons Tem de fornecer o seu código de autenticação de dois fatores. @@ -285,7 +288,7 @@ Saltar Entrar Pretende mesmo ignorar o início de sessão? - Terá de iniciar sessão para carregar fotografias mais tarde. + Terá de iniciar sessão para carregar fotografias no futuro. Inicie uma sessão para usar esta funcionalidade Copiar o texto wiki para a área de transferência O texto wiki foi copiado para a área de transferência @@ -359,7 +362,7 @@ Esta captura de ecrã pode ser carregada? Partilhar aplicação Rodar - Erro ao procurar locais próximos. + Não foi possível carregar locais próximos Não existem locais próximos Erro ao procurar monumentos próximos. Não há pesquisas recentes @@ -371,11 +374,13 @@ Eliminar Realizações Perfil + Medalhas Estatísticas Agradecimentos recebidos Imagens destacadas Imagens via \"Locais próximos\" - Nível + Nível %d + %s (Nível %s) Imagens carregadas Imagens não revertidas Imagens usadas @@ -407,6 +412,7 @@ Não foi encontrada no seu dispositivo nenhuma aplicação de mapas compatível. Para usar esta funcionalidade instale uma aplicação de mapas, por favor. Fotografias Locais + Categorias Adicionar ou remover dos marcadores Marcadores Não adicionou nenhum marcador @@ -450,7 +456,7 @@ O novo seletor de fotografias do Android corre o risco de perder informações de localização. Ativar se pensa vir a usá-lo. Desativar pode acionar o novo seletor de fotografias do Android. Este corre o risco de perder informações de localização.\n\nToque em \'Ler mais\' para mais informações. Deixará de ver as campanhas. No entanto, pode reativar esta notificação nas configurações, se desejar. - Esta função requer uma ligação de rede. Verifique as suas configurações de ligação, por favor. + Esta função necessita de ligação à rede. Por favor, verifique as suas configurações de ligação. Ocorreu um erro ao processar a imagem. Tente novamente, por favor! A obter chave para edição A adicionar predefinição para verificação da categoria @@ -488,6 +494,7 @@ Não tem nenhuma notificação por ler Não tem nenhuma notificação lida Partilhar os registos usando + Verifique sua caixa de entrada de e-mail Ver lidas Ver não lidas Ocorreu um erro ao escolher imagens @@ -562,7 +569,7 @@ Não foi possível adicionar coordenadas. Não foi possível adicionar as descrições. Não foi possível adicionar a legenda. - Não foi possível obter coordenadas. + Coordenadas da imagem não actualizadas Não foi possível obter as descrições. Editar descrições e legendas Partilhar imagem via @@ -577,12 +584,13 @@ Necessita fotografia Tipo de local: Ponte, museu, hotel, etc. - Ocorreu algo de errado com a sessão, tem de redefinir a sua palavra-passe! + Ocorreu um erro ao iniciar sessão. Tem de redefinir a sua palavra-passe! MULTIMÉDIA CLASSES DESCENDENTES CLASSES PROGENITORAS Foi encontrado um local próximo - Isto é uma fotografia de %1$s? + Estas imagens são de %1$s? + Isto é uma imagem de %1$s? Marcadores Definições Removido dos marcadores @@ -597,7 +605,7 @@ Para obter os melhores resultados, escolha o modo Alta Precisão. Ativar a localização? A funcionalidade de proximidade precisa que a localização esteja ativada para funcionar corretamente - Precisa de dar acesso à sua localização atual para gravar automaticamente a localização. + Precisa de dar permissão da sua localização geográfica para a gravar automaticamente. Tirou estas duas fotos no mesmo lugar? Quer usar a latitude/longitude da fotografia da direita? Carregar mais Não foi encontrado nenhum local; tente alterar os seus critérios de pesquisa. @@ -698,7 +706,7 @@ Os mapas de locais próximos precisam de ler ESTADO DO TELEFONE para funcionar devidamente Contribuições do utilizador: %s Realizações do utilizador: %s - Ver página de utilizador + Ver perfil de utilizador Editar elementos retratados Editar categorias Opções avançadas @@ -711,7 +719,7 @@ Adicionar localização Remova desta mensagem de correio todas as informações que não se sinta à vontade em partilhar publicamente, por favor. Adicionalmente, esteja consciente de que o seu endereço de correio eletrónico, com o qual está a fazer esta publicação, e o nome e imagem de perfil a ele associados, serão visíveis pelo público geral. Detalhes - As realizações só estão disponíveis na versão de produção; consulte a documentação para programadores, por favor. + As conquistas só estão disponíveis na versão de produção. Consulte a documentação para programadores. A tabela de classificação só está disponível na versão prod. Consulte a documentação do desenvolvedor. Carregue somente fotografias tiradas por si. Os utilizadores que carregarem imagens cujos direitos de autor estão protegidos serão bloqueados. Isto também se aplica à versão beta. Obrigado por testar a aplicação! Desmarque todas as informações que não se sente à vontade em tornar públicas. @@ -756,6 +764,8 @@ Ver as suas realizações Editar imagem Editar localização + Localização actualizada! + Remover Localização Agradecer ao autor Erro no envio de agradecimento ao autor. diff --git a/app/src/main/res/values-x-invalidLanguageCode/error.xml b/app/src/main/res/values-x-invalidLanguageCode/error.xml new file mode 100644 index 000000000..f4e2fe125 --- /dev/null +++ b/app/src/main/res/values-x-invalidLanguageCode/error.xml @@ -0,0 +1,10 @@ + + + + کامَنٕز گوو رُکِتھ + Oops. کیہہ تام گوو غلط! + ؤنِیوٚ اَسہِ توٚہہِ کیاہ ٲسِیوٚ کران، تہٕ کٕریٚو تہِ اَسہِ سٕتی شیر بذریعہِ برقی خط. یُس مَدَتھ کَرِ اَسہِ اَتھ شہَرنَس منٛز! + شُکریہ! + From 7979be17c1699b356531ce98fc973a6b453458a7 Mon Sep 17 00:00:00 2001 From: "translatewiki.net" Date: Thu, 12 Jun 2025 05:05:50 +0200 Subject: [PATCH 024/162] Localisation updates from https://translatewiki.net. --- .../main/res/values-x-invalidLanguageCode/error.xml | 10 ---------- 1 file changed, 10 deletions(-) delete mode 100644 app/src/main/res/values-x-invalidLanguageCode/error.xml diff --git a/app/src/main/res/values-x-invalidLanguageCode/error.xml b/app/src/main/res/values-x-invalidLanguageCode/error.xml deleted file mode 100644 index f4e2fe125..000000000 --- a/app/src/main/res/values-x-invalidLanguageCode/error.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - کامَنٕز گوو رُکِتھ - Oops. کیہہ تام گوو غلط! - ؤنِیوٚ اَسہِ توٚہہِ کیاہ ٲسِیوٚ کران، تہٕ کٕریٚو تہِ اَسہِ سٕتی شیر بذریعہِ برقی خط. یُس مَدَتھ کَرِ اَسہِ اَتھ شہَرنَس منٛز! - شُکریہ! - From 54bb789461b2800f019e77ae3890735012f9c688 Mon Sep 17 00:00:00 2001 From: "translatewiki.net" Date: Thu, 12 Jun 2025 05:20:45 +0200 Subject: [PATCH 025/162] Localisation updates from https://translatewiki.net. --- app/src/main/res/values-hi/strings.xml | 11 +++++++++-- .../main/res/values-x-invalidLanguageCode/error.xml | 10 ++++++++++ 2 files changed, 19 insertions(+), 2 deletions(-) create mode 100644 app/src/main/res/values-x-invalidLanguageCode/error.xml diff --git a/app/src/main/res/values-hi/strings.xml b/app/src/main/res/values-hi/strings.xml index 1c6685b7f..dcb769ca1 100644 --- a/app/src/main/res/values-hi/strings.xml +++ b/app/src/main/res/values-hi/strings.xml @@ -126,7 +126,7 @@ सहेजें ताजा करें सूची - अभी तक कोई अपलोड नहीं + (अभी तक कोई अपलोड नहीं) %1$s से कोई श्रेणी मेल नहीं खाती विकिमीडिया कॉमन्स पर अपनी छवियों को अधिक खोजने योग्य बनाने के लिए श्रेणियां जोड़ें|\nश्रेणियां जोड़ने के लिए टाइप करना प्रारंभ करें| श्रेणियाँ @@ -180,7 +180,7 @@ इंटरनेट से मिली कोई कॉपीराइट सामग्री के साथ साथ पोस्टर, पुस्तक के खड्डे आदि को भी अपलोड करने से बचें। क्या आपको लगता है कि आप समझ गए? हाँ! - <u>अधिक जानकारी</u> + अधिक जानकारी श्रेणियाँ लोड हो रहा है… कुछ चयनित नहीं @@ -196,6 +196,7 @@ नहीं कैप्शन शीर्षक + चित्रण विवरण चर्चा लेखक @@ -278,6 +279,7 @@ कोई चित्र नहीं मिला! चित्र अपलोड करते समय त्रुटि उत्पन्न हुई। अपलोड: %1$s + अवरोधित कॉमन्स पर सम्पादन से आप अवरोधित हो चुके हैं आज का चित्र खोजें @@ -315,10 +317,12 @@ हटाने के लिये नामांकन करें हटाएँ उपलब्धियाँ + प्रोफ़ाइल सांख्यिकी धन्यवाद प्राप्त किया निर्वाचित चित्र स्तर %d + %s (स्तर %s ) चित्र अपलोड हुआ चित्रों को वापस नहीं किया गया उपयोग हुए चित्र @@ -356,7 +360,10 @@ खत्म होगा: दृश्य अभियान वर्तमान में चल रहे अभियानों को जानने के लिये यहाँ दबायें + अनुमति दें + रद्द करें छवि संसाधित करते समय त्रुटि आई। कृपया पुन: प्रयास करें! + पूर्ण हुआ कोई चित्र उपयोग नहीं हुआ कोई चित्र वापस नहीं लाया कोई चित्र अपलोड नहीं किया diff --git a/app/src/main/res/values-x-invalidLanguageCode/error.xml b/app/src/main/res/values-x-invalidLanguageCode/error.xml new file mode 100644 index 000000000..f4e2fe125 --- /dev/null +++ b/app/src/main/res/values-x-invalidLanguageCode/error.xml @@ -0,0 +1,10 @@ + + + + کامَنٕز گوو رُکِتھ + Oops. کیہہ تام گوو غلط! + ؤنِیوٚ اَسہِ توٚہہِ کیاہ ٲسِیوٚ کران، تہٕ کٕریٚو تہِ اَسہِ سٕتی شیر بذریعہِ برقی خط. یُس مَدَتھ کَرِ اَسہِ اَتھ شہَرنَس منٛز! + شُکریہ! + From 6b40560dfcb71cf4471794244ba563f16da8da0a Mon Sep 17 00:00:00 2001 From: "translatewiki.net" Date: Thu, 12 Jun 2025 05:27:59 +0200 Subject: [PATCH 026/162] Localisation updates from https://translatewiki.net. --- .../main/res/values-x-invalidLanguageCode/error.xml | 10 ---------- 1 file changed, 10 deletions(-) delete mode 100644 app/src/main/res/values-x-invalidLanguageCode/error.xml diff --git a/app/src/main/res/values-x-invalidLanguageCode/error.xml b/app/src/main/res/values-x-invalidLanguageCode/error.xml deleted file mode 100644 index f4e2fe125..000000000 --- a/app/src/main/res/values-x-invalidLanguageCode/error.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - کامَنٕز گوو رُکِتھ - Oops. کیہہ تام گوو غلط! - ؤنِیوٚ اَسہِ توٚہہِ کیاہ ٲسِیوٚ کران، تہٕ کٕریٚو تہِ اَسہِ سٕتی شیر بذریعہِ برقی خط. یُس مَدَتھ کَرِ اَسہِ اَتھ شہَرنَس منٛز! - شُکریہ! - From 7df52e3f9c91795d0fb61522b29b0813eb442588 Mon Sep 17 00:00:00 2001 From: "translatewiki.net" Date: Thu, 12 Jun 2025 06:06:15 +0200 Subject: [PATCH 027/162] Localisation updates from https://translatewiki.net. --- .../main/res/values-x-invalidLanguageCode/error.xml | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 app/src/main/res/values-x-invalidLanguageCode/error.xml diff --git a/app/src/main/res/values-x-invalidLanguageCode/error.xml b/app/src/main/res/values-x-invalidLanguageCode/error.xml new file mode 100644 index 000000000..f4e2fe125 --- /dev/null +++ b/app/src/main/res/values-x-invalidLanguageCode/error.xml @@ -0,0 +1,10 @@ + + + + کامَنٕز گوو رُکِتھ + Oops. کیہہ تام گوو غلط! + ؤنِیوٚ اَسہِ توٚہہِ کیاہ ٲسِیوٚ کران، تہٕ کٕریٚو تہِ اَسہِ سٕتی شیر بذریعہِ برقی خط. یُس مَدَتھ کَرِ اَسہِ اَتھ شہَرنَس منٛز! + شُکریہ! + From af82cb2123506ed965c8a9acbe72436749a33702 Mon Sep 17 00:00:00 2001 From: "translatewiki.net" Date: Thu, 12 Jun 2025 06:17:24 +0200 Subject: [PATCH 028/162] Localisation updates from https://translatewiki.net. --- .../main/res/values-x-invalidLanguageCode/error.xml | 10 ---------- 1 file changed, 10 deletions(-) delete mode 100644 app/src/main/res/values-x-invalidLanguageCode/error.xml diff --git a/app/src/main/res/values-x-invalidLanguageCode/error.xml b/app/src/main/res/values-x-invalidLanguageCode/error.xml deleted file mode 100644 index f4e2fe125..000000000 --- a/app/src/main/res/values-x-invalidLanguageCode/error.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - کامَنٕز گوو رُکِتھ - Oops. کیہہ تام گوو غلط! - ؤنِیوٚ اَسہِ توٚہہِ کیاہ ٲسِیوٚ کران، تہٕ کٕریٚو تہِ اَسہِ سٕتی شیر بذریعہِ برقی خط. یُس مَدَتھ کَرِ اَسہِ اَتھ شہَرنَس منٛز! - شُکریہ! - From d3ae92556719f0597863cdf58c419472a8bc2512 Mon Sep 17 00:00:00 2001 From: "translatewiki.net" Date: Thu, 12 Jun 2025 14:01:42 +0200 Subject: [PATCH 029/162] Localisation updates from https://translatewiki.net. --- .../main/res/values-x-invalidLanguageCode/error.xml | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 app/src/main/res/values-x-invalidLanguageCode/error.xml diff --git a/app/src/main/res/values-x-invalidLanguageCode/error.xml b/app/src/main/res/values-x-invalidLanguageCode/error.xml new file mode 100644 index 000000000..f4e2fe125 --- /dev/null +++ b/app/src/main/res/values-x-invalidLanguageCode/error.xml @@ -0,0 +1,10 @@ + + + + کامَنٕز گوو رُکِتھ + Oops. کیہہ تام گوو غلط! + ؤنِیوٚ اَسہِ توٚہہِ کیاہ ٲسِیوٚ کران، تہٕ کٕریٚو تہِ اَسہِ سٕتی شیر بذریعہِ برقی خط. یُس مَدَتھ کَرِ اَسہِ اَتھ شہَرنَس منٛز! + شُکریہ! + From 20e5df7d49a0ce6fe181a85d5b06814fbc0efe8a Mon Sep 17 00:00:00 2001 From: "translatewiki.net" Date: Mon, 16 Jun 2025 14:01:42 +0200 Subject: [PATCH 030/162] Localisation updates from https://translatewiki.net. --- app/src/main/res/values-ps/strings.xml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/app/src/main/res/values-ps/strings.xml b/app/src/main/res/values-ps/strings.xml index a9ecd54f9..6b3970c88 100644 --- a/app/src/main/res/values-ps/strings.xml +++ b/app/src/main/res/values-ps/strings.xml @@ -195,11 +195,19 @@ اړينه پرېښولی: بهرنۍ زېرمه ولولئ. کاريال ستاسو انځورتونه ته پرته له دې لاسرسی نشي موندلی. ښه گواښنه + راپورته‌کول هو نه + نيونگ سرليک څرگندونه + شننه + ليکوال + راپورته‌کېدلو نېټه + منښتليک کورډيناټونه + هېڅ نه دي چمتو شوي + ازمېښتي ازمايښتگر شئ ويکيپېډياښه راغلئ ناگارل پرانيستل @@ -211,6 +219,8 @@ امستنې غبرگون وتل + بياکتنه + هيڅ څرگنداوی ونهٔ موندل شو تگلوري ويکي‌اومتوک ويکيپېډيا From 5665bc7f93f6db6adb13fc8d899b3fd6acd277ca Mon Sep 17 00:00:00 2001 From: Rohit Verma <101377978+rohit9625@users.noreply.github.com> Date: Tue, 17 Jun 2025 14:03:43 +0530 Subject: [PATCH 031/162] fix: make userName private to prevent conflict when passing arguments (#6339) --- .../fr/free/nrw/commons/contributions/ContributionsFragment.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsFragment.kt b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsFragment.kt index f50df13ff..3992d35dd 100644 --- a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsFragment.kt +++ b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsFragment.kt @@ -139,7 +139,7 @@ class ContributionsFragment : CommonsDaggerSupportFragment(), FragmentManager.On private var wlmCampaign: Campaign? = null - var userName: String? = null + private var userName: String? = null private var isUserProfile = false private var mSensorManager: SensorManager? = null From 9eff9e8e821677975d9d358eaaced92f093310a8 Mon Sep 17 00:00:00 2001 From: "translatewiki.net" Date: Thu, 19 Jun 2025 14:01:44 +0200 Subject: [PATCH 032/162] Localisation updates from https://translatewiki.net. --- app/src/main/res/values-bn/strings.xml | 38 ++++++++++++++++++++++---- app/src/main/res/values-es/strings.xml | 25 +++++++++++++++++ app/src/main/res/values-tr/strings.xml | 37 ++++++++++++++++++++++++- app/src/main/res/values-zh/strings.xml | 2 ++ 4 files changed, 95 insertions(+), 7 deletions(-) diff --git a/app/src/main/res/values-bn/strings.xml b/app/src/main/res/values-bn/strings.xml index 9b2fde313..e53d8025f 100644 --- a/app/src/main/res/values-bn/strings.xml +++ b/app/src/main/res/values-bn/strings.xml @@ -12,6 +12,7 @@ * Mohammed Galib Hasan * Muktogayn * NahidHossain +* Nokib Sarkar * R4356th * Rasal Lia * Sankarshan @@ -32,6 +33,7 @@ কমন্স গিটহাব উৎস কোড কমন্সের লোগো কমন্স ওয়েবসাইট + লোকেশন পিকার থেকে বেরিয়ে আসুন জমা দিন আরেকটি বিবরণ যোগ করুন নতুন অবদান যোগ করুন @@ -44,6 +46,9 @@ বিবরণ চিত্র সব + টগল আপ + অনুসন্ধান দৃশ্য + স্থানের অবস্থা আজকের চিত্র %1$dটি ফাইল আপলোড হচ্ছে @@ -70,6 +75,10 @@ %1$dটি আপলোড %1$dটি আপলোড + + শেয়ার করা কন্টেন্ট পাওয়া। ছবির আকার এবং আপনার ডিভাইসের উপর নির্ভর করে ছবিটি প্রক্রিয়াকরণে কিছুটা সময় লাগতে পারে + শেয়ার করা কন্টেন্ট পাওয়া। ছবির আকার এবং আপনার ডিভাইসের উপর নির্ভর করে ছবি প্রক্রিয়াকরণে কিছুটা সময় লাগতে পারে + অন্বেষণ অবয়ব সাধারণ @@ -89,9 +98,11 @@ অনুগ্রহ করে অপেক্ষা করুন… ক্যাপশন ও বিবরণ হালনাগাদ করা হচ্ছে অনুগ্রহ করে অপেক্ষা করুন… - প্রবেশ সফল! + প্রবেশ সফল প্রবেশ ব্যর্থ! ফাইল পাওয়া যায়নি। আরেকটি ফাইল চেষ্টা করুন। + সর্বোচ্চ পুনচেষ্টা করার সীমা পেরিয়ে গেছে! অনুগ্রহ করে আপলোডটি বাতিল করে আবার চেষ্টা করুন। + ব্যাটারি অপ্টিমাইজেশন বন্ধ করবেন? প্রমাণীকরণ ব্যর্থ হয়েছে। অনুগ্রহ করে আবার প্রবেশ করুন। আপলোড আরম্ভ হয়েছে! আপলোড সারিবদ্ধ করা হয়েছে (সীমিত সংযোগ মোড সক্রিয় করা) @@ -113,6 +124,8 @@ ছবি তুলুন কাছাকাছি আমার আপলোড + লিংক কপি করুন + লিঙ্কটি ক্লিপবোর্ডে কপি করা হয়েছে। বণ্টন ফাইলের পাতাটি দেখুন ক্যাপশন (আবশ্যক) @@ -123,7 +136,8 @@ খুব বেশি অসফল প্রচেষ্টা। অনুগ্রহ করে কয়েক মিনিট পরে আবারও চেষ্টা করুন। দুঃখিত, এই ব্যবহারকারীকে কমন্সে বাধা দেয়া হয়েছে আপনাকে অবশ্যই আপনার দু\'স্তরের সত্যায়নকরণ কোড দিতে হবে। - প্রবেশ ব্যর্থ + আপনার ইমেল ঠিকানায় একটি লগইন যাচাইকরণ কোড পাঠানো হয়েছে। লগ ইন করার জন্য অনুগ্রহ করে কোডটি প্রদান করুন। + প্রবেশ ব্যর্থ আপলোড এই সেটের নাম পরিবর্তনসমূহ @@ -131,6 +145,7 @@ বিষয়শ্রেণী অনুসন্ধান আপনার মিডিয়া চিত্রিত আইটেমগুলি অনুসন্ধান করুন (পর্বত, তাজমহল, ইত্যাদি) সংরক্ষণ + ওভারফ্লো মেনু পুনঃসতেজ তালিকা (আপলোড করেন নি) @@ -223,6 +238,7 @@ বিটা টেস্টার হোন গুগল প্লেতে আমাদের বেটা চ্যানেলে যুক্ত হন! এতে নতুন বৈশিষ্ট্যের পাশাপাশি পুরানো বাগগুলো\'র সংশোধিত রুপ সবার আগে ব্যবহারের সুযোগ পাবেন 2FA কোড + ইমেল যাচাইকরণ কোড আপনি কি সত্যিই প্রস্থান করতে চান? মিডিয়া চিত্র ব্যর্থ হয়েছে কোন উপবিষয়শ্রেনী পাওয়া যায় নি। @@ -243,6 +259,7 @@ সম্পর্কে সেটিং প্রতিক্রিয়া + GitHub এর মাধ্যমে প্রতিক্রিয়া প্রস্থান ভূমিকা বিজ্ঞপ্তি @@ -252,6 +269,7 @@ উইকিউপাত্ত আইটেম উইকিপিডিয়া নিবন্ধ যতটা সম্ভব মিডিয়াটি বর্ণনা করুন: এটি কোথায় ধারণ করা হয়েছিল? এটি কি প্রদর্শন করে? এটির প্রসঙ্গ কি? ধারণকৃত বস্তু অথবা ব্যক্তির বর্ণনা করুন। সহজে অনুমান করা যায়না সেরকম তথ্য উদঘাটন করুন, উদাহরণস্বরূপ, যদি ল্যান্ডস্কেপ হয় তাহলে দিবসকালের সময় দিন। + দয়া করে ছবির একটি সংক্ষিপ্ত বিবরণ লিখুন। প্রথম ক্যাপশনটি ছবির শিরোনাম হিসেবে ব্যবহার করা হবে। ২৫৫ অক্ষরের মধ্যে সীমাবদ্ধ। এই চিত্রের সম্ভাব্য সমস্যাগুলি: চিত্রটি খুব অন্ধকারযুক্ত। চিত্রটি অস্পষ্ট। @@ -275,12 +293,13 @@ বিশদের জন্য ওয়েবপৃষ্ঠা দেখুন এড়ান প্রবেশ করুন - আপনি কি সত্যিই প্রবেশকরণ এড়িয়ে যেতে চান? - ভবিষ্যতে চিত্র আপলোড করতে চাইলে আপনাকে প্রবেশ করতে হবে। + আপনি কি সত্যিই লগ-ইন এড়িয়ে যেতে চান? + ভবিষ্যতে চিত্র আপলোড করতে চাইলে আপনাকে প্রবেশ করতে হবে। এই সুবিধাটি ব্যাবহার করতে প্রবেশ করুন উইকিপাঠ্যটি ক্লিপবোর্ডে অনুলিপি করুন উইকিপাঠ্যটি ক্লিপবোর্ডে অনুলিপি করা হয়েছে কাছাকাছি সঠিকভাবে কাজ করছে না, অবস্থান উপলব্ধ নয়। + ইন্টারনেট অনুপলব্ধ। শুধুমাত্র ক্যাশে করা স্থানগুলো দেখানো হচ্ছে। কাছাকাছি স্থানসমূহের একটি তালিকা প্রদর্শন করতে অনুমতি প্রয়োজন দিকনির্দেশ উইকিউপাত্ত @@ -334,19 +353,26 @@ এই স্ক্রিনশটটি কি আপলোড করা ঠিক হয়েছে? অ্যাপ শেয়ার করুন ঘোরান - কাছাকাছি স্থানগুলি আনতে ত্রুটি। + কাছাকাছি জায়গাগুলি লোড করা যায়নি + এই এলাকার কোনও ছবি নেই আশেপাশে কোনো এলাকা পাওয়া যায়নি আশেপাশের স্মৃতিস্তম্ভগুলি আনায়নে ত্রুটি৷ কোনও সাম্প্রতিক অনুসন্ধান নেই আপনি কি নিশ্চিত যে আপনি আপনার অনুসন্ধান ইতিহাস মুছে ফেলতে চান? + আপনি কি নিশ্চিত যে আপনি এই আপলোডটি বাতিল করতে চান? + আপনি কি এই অনুসন্ধানটি মুছে ফেলতে চান? + অনুসন্ধানের ইতিহাস মুছে ফেলা হয়েছে অপসারণের জন্য মনোনীত করুন অপসারণ কৃতিত্বগুলি প্রোফাইল + ব্যাজ পরিসংখ্যান ধন্যবাদ পেয়েছেন নির্বাচিত ছবি - স্তর + \"কাছাকাছি স্থান\" এর মাধ্যমে ছবি + স্তর %d + %s (স্তর %s ) আপলোডকৃত চিত্র ছবিগুলো প্রত্যাবর্তন করা হয়নি ব্যবহৃত ছবি diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 8622b6944..baed7bc1b 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -30,6 +30,7 @@ * Jduranboger * Jelou * Johnny243 +* JorgeElias2302 * Josuert * Juanman * Keneth Urrutia @@ -152,6 +153,7 @@ Cercanos Mis subidas Copiar enlace + El enlace ha sido copiado al portapapeles. Compartir Ver página del archivo Leyenda (requerido) @@ -162,6 +164,7 @@ Demasiados intentos fallidos. Inténtalo de nuevo en unos minutos. Lo sentimos, este usuario ha sido bloqueado en Commons Debe proporcionar su código de autenticación de dos factores. + Se ha enviado un código de verificación de inicio de sesión a tu correo electrónico. Indícalo para iniciar sesión. Falló el inicio de sesión Subir Nombrar este conjunto @@ -267,6 +270,7 @@ Prueba la versión beta Apúntate a nuestro canal beta en Google Play y obtén acceso a funcionalidades nuevas y correcciones de errores Código de autenticación de 2 pasos + Código de verificación de correo electrónico ¿Confirmas que quieres salir? Falló la imagen de multimedia No se encontró ninguna subcategoría @@ -327,6 +331,7 @@ Copia el wikitexto al portapapeles El wikitexto fue copiado al portapapeles Cercanos no puede funcionar correctamente. La ubicación no está disponible. + Internet no disponible. Solo se muestran ubicaciones en caché. Acceso a la ubicación denegado. Configura tu ubicación manualmente para utilizar esta función. Se necesita permiso para mostrar una lista de lugares cercanos Se necesita permiso para mostrar una lista de lugares cercanos @@ -416,6 +421,7 @@ Imágenes destacadas Imágenes vía \"Sitios Cercanos\" Nivel %d + %s (Nivel %s) Imágenes subidas Imágenes no revertidas Imágenes utilizadas @@ -447,6 +453,7 @@ No se encontró una aplicación de mapas compatible en tu dispositivo. Instala una para usar esta característica. Imágenes Ubicaciones + Categorías Añadir o quitar de marcadores Marcadores No has añadido ningún marcador @@ -827,6 +834,7 @@ Discusión Escriba algo sobre el elemento \'%1$s\'. Será visible públicamente. \' %1$s \' ya no existe, nunca se podrá tomar ninguna fotografía de él. + \'%1$s\' está en un lugar diferente. \' %1$s \' está en un lugar diferente. Especifique el lugar correcto a continuación y, si es posible, escriba la latitud y longitud correctas. Otro problema o información (por favor explique a continuación). Sus comentarios se publicarán en la siguiente página wiki: <a href=\"https://commons.wikimedia.org/wiki/Commons:Mobile_app/Feedback\">Commons:Mobile_app/Feedback</a> @@ -848,4 +856,21 @@ Este lugar aún no tiene foto, ¡ve y toma una! Este lugar ya tiene una foto. Ahora comprobando si este lugar tiene una foto. + Error al cargar + No se encontraron usos + Commons + Otras wikis + Usos de archivos + Actividad de vista web única + Cuenta + Desaparecer cuenta + Advertencia sobre la desaparición de la cuenta + La desaparición de una cuenta en Wikimedia Commons es un <b>último recurso</b> y <b>solo debe usarse cuando desee dejar de editar para siempre y también para ocultar la mayor cantidad posible de sus asociaciones pasadas.<br/><br/>La desaparición de una cuenta en Wikimedia Commons se realiza cambiando el nombre de la cuenta para que otros no puedan reconocer sus contribuciones en un proceso llamado desaparición de la cuenta. <b>La desaparición de la cuenta no garantiza el anonimato completo ni elimina las contribuciones a los proyectos</b>. + Leyenda + Leyenda copiado al portapapeles + Felicitaciones, todas las imágenes de este álbum han sido cargadas o marcadas como no para cargar. + Mostrar en Explorar + Mostrar en las cercanías + Creado y cargado por: %1$s + Creado por %1$s y cargado por %2$s diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml index b8ebc9db3..2e2b13216 100644 --- a/app/src/main/res/values-tr/strings.xml +++ b/app/src/main/res/values-tr/strings.xml @@ -12,6 +12,7 @@ * JackUKElliott * Jelican9 * Joseph +* Leo * McAang * McDutchie * Mirzali @@ -129,6 +130,8 @@ Fotoğraf çek Yakınımdakiler Yüklemelerim + Bağlantıyı kopyala + Bağlantı panoya kopyalandı Paylaş Dosya sayfasını görüntüle Başlık (Zorunlu) @@ -139,6 +142,7 @@ Çok sayıda başarısız girişimde bulundunuz. Birkaç dakika sonra tekrar deneyin. Üzgünüz, bu kullanıcı Commons\'ta engellendi İki faktörlü kimlik doğrulama kodunu sağlamalısınız. + E-posta adresinize bir giriş doğrulama kodu gönderildi. Lütfen giriş yapmak için kodu sağlayın. Oturum açma başarısız Yükle Bu ayarı adlandırın @@ -244,6 +248,7 @@ Beta Test Kullanıcısı Olun Google Play\'de beta kanalımıza katılın ve yeni özelliklere ve hata düzeltmelerine erken erişin 2 Faktörlü Kimlik Doğrulama (2FA) Kodu + E-posta doğrulama kodu Gerçekten çıkış yapmak istiyor musunuz? Medya Görüntüsü Başarısız Oldu Alt kategori bulunamadı @@ -304,6 +309,7 @@ Vikimetnini panoya kopyala Vikimetin panoya kopyalandı Yakınımdakiler düzgün çalışmayabilir, Konum kullanılamıyor. + İnternet kullanılamıyor. Yalnızca önbelleğe alınmış yerler gösteriliyor. Konum erişimi reddedildi. Bu özelliği kullanmak için lütfen konumunuzu manuel olarak ayarlayın. Yakındaki yerler listesini görüntülemek için izin vermeniz gerekiyor Yakındaki resimlerin listesini görüntülemek için izin gerekli @@ -387,11 +393,13 @@ Sil Başarılar Profil + Rozetler İstatistikler Teşekkür Alındı Seçkin Resimler \"Yakındaki Yerler\"den Resimler - Seviye + Seviye %d + %s (Seviye %s) Resimler Yüklendi Resimler Geri Alınmadı Resimler Kullanıldı @@ -423,6 +431,7 @@ Cihazınızda uyumlu bir harita uygulaması bulunamadı. Lütfen bu özelliği kullanmak için bir harita uygulaması yükleyin. Resimler Konumlar + Kategoriler Yer imlerini ekle/kaldır Yer imleri Henüz yer imlerine bir şey eklemediniz @@ -803,6 +812,8 @@ Tartışma \' %1$s \' öğesi hakkında bir şeyler yazın. Herkes tarafından görülebilir olacaktır. \'%1$s\' artık yok, dolayısı ile resmi çekilemez. + \'%1$s\' farklı bir yerde. + \'%1$s\' farklı bir yerde. Lütfen aşağıdaki doğru yeri belirtin ve mümkünse doğru enlem ve boylamı yazın. Diğer sorun veya bilgi (lütfen aşağıda açıklayınız). Geri bildiriminiz aşağıdaki wiki sayfasına gönderilir: <a href=\"https://commons.wikimedia.org/wiki/Commons:Mobile_app/Feedback\">Commons:Mobile app/Feedback</a> Tüm yüklemeleri iptal etmek istediğinizden emin misiniz? @@ -810,10 +821,34 @@ Yüklemeler Beklemede Başarısız + Yer verileri yüklenemedi + Klasörü Sil + Silmeyi Onayla + %2$d öğe içeren %1$s klasörünü silmek istediğinizden emin misiniz? Sil İptal %1$s klasörü başarıyla silindi %1$s klasörü silinemedi + Klasör içerikleri çöpe atılırken hata oluştu: %1$s + Kova kimliği için klasör yolu alınamadı: %1$d + Bu yerin henüz fotoğrafı yok, gidin ve çekin! Bu yerin zaten bir resmi var. Şimdi bu yerin bir resime sahip olup olmadığı denetleniyor. + Yükleme sırasında hata oluştu + Hiçbir kullanım bulunamadı + Commons + Diğer vikiler + Dosya kullanımları + SingleWebViewActivity + Hesap + Kaybolma + Hesap kaybolma uyarısı + Kaybolma <b>son çaredir</b> ve <b>sadece düzenlemeyi sonsuza dek durdurmak istediğinizde</b> ve ayrıca mümkün olduğunca çok sayıda geçmiş ilişkinizi gizlemek için kullanılmalıdır.<br/><br/>Wikimedia Commons\'ta hesap silme, hesap adınızı değiştirerek başkalarının katkılarınızı tanımasını önleyerek hesap kaybolması adı verilen bir işlemle yapılır. <b>Kaybolma, projelere yapılan katkıları tamamen anonimleştirmeyi veya kaldırmayı garanti etmez</b>. + Altyazı + Başlık panoya kopyalandı + Tebrikler, bu albümdeki tüm resimler yüklendi veya yüklenemez olarak işaretlendi. + Keşfet\'te göster + Yakınlarda Göster + Oluşturan ve yükleyen: %1$s + %1$s tarafından oluşturuldu ve %2$s tarafından yüklendi diff --git a/app/src/main/res/values-zh/strings.xml b/app/src/main/res/values-zh/strings.xml index 5c7db0aae..930c9e4fb 100644 --- a/app/src/main/res/values-zh/strings.xml +++ b/app/src/main/res/values-zh/strings.xml @@ -52,6 +52,7 @@ * ZhaoGang * 七八年再来一次 * 予弦 +* 人间百态 * 佛壁灯 * 列维劳德 * 坑触可 @@ -840,6 +841,7 @@ 讨论 请写一些关于项目“%1$s”的信息。所写的内容是公开可见的。 “%1$s”已不再存在,无法拍摄它的照片。 + “%1$s”位于他处。 “%1$s”位于一个不同的位置。请在下方给出正确的位置,可以的话请填写正确的经纬度。 其他问题或信息(请在下方解释)。 您的反馈已经发布在以下wiki页面:<a href=\"https://commons.wikimedia.org/wiki/Commons:Mobile_app/Feedback\">Commons:Mobile app/Feedback</a> From ca5c7ec966da349fe5352962428d0eadbd91b9fe Mon Sep 17 00:00:00 2001 From: Ritika Pahwa <83745993+RitikaPahwa4444@users.noreply.github.com> Date: Sat, 21 Jun 2025 13:21:05 +0530 Subject: [PATCH 033/162] Bump up version code to 1053 --- app/build.gradle.kts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 2d9e213b2..9c53155a7 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -24,8 +24,8 @@ android { applicationId = "fr.free.nrw.commons" minSdk = 21 targetSdk = 34 - versionCode = 1052 - versionName = "5.4.1" + versionCode = 1053 + versionName = "5.5.0" setProperty("archivesBaseName", "app-commons-v$versionName-" + getBranchName()) testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" From 09da7b8d68169d1e9d6ca539b653d9aae7f50bb4 Mon Sep 17 00:00:00 2001 From: Sonal Yadav Date: Sun, 22 Jun 2025 19:10:15 +0530 Subject: [PATCH 034/162] Skip image upload to Wikidata (nearby -> green pins) (#6349) * Skip image upload to Wikidata if item already has image * Re-run CI * no more Failed to update Wikidata for green pins --- .../fr/free/nrw/commons/upload/worker/UploadWorker.kt | 8 +++++++- .../free/nrw/commons/wikidata/WikidataEditService.kt | 7 +++++-- .../main/res/values-x-invalidLanguageCode/error.xml | 10 ---------- 3 files changed, 12 insertions(+), 13 deletions(-) delete mode 100644 app/src/main/res/values-x-invalidLanguageCode/error.xml diff --git a/app/src/main/java/fr/free/nrw/commons/upload/worker/UploadWorker.kt b/app/src/main/java/fr/free/nrw/commons/upload/worker/UploadWorker.kt index 6d28085b2..c8a1d9b98 100644 --- a/app/src/main/java/fr/free/nrw/commons/upload/worker/UploadWorker.kt +++ b/app/src/main/java/fr/free/nrw/commons/upload/worker/UploadWorker.kt @@ -472,7 +472,10 @@ class UploadWorker( if (wikiDataPlace != null) { if (!contribution.hasInvalidLocation()) { var revisionID: Long? = null + val p18WasSkipped = !wikiDataPlace.imageValue.isNullOrBlank() try { + if (!p18WasSkipped) { + // Only set P18 if the place does not already have a picture revisionID = wikidataEditService.createClaim( wikiDataPlace, @@ -489,9 +492,11 @@ class UploadWorker( .subscribeOn(Schedulers.io()) .blockingAwait() Timber.d("Updated WikiItem place ${place.name} with image ${place.pic}") + } } - showSuccessNotification(contribution) } + // Always show success notification, whether P18 was set or skipped + showSuccessNotification(contribution) } catch (exception: Exception) { Timber.e(exception) } @@ -500,6 +505,7 @@ class UploadWorker( wikidataEditService.handleImageClaimResult( contribution.wikidataPlace!!, revisionID, + p18WasSkipped = p18WasSkipped ) } } else { diff --git a/app/src/main/java/fr/free/nrw/commons/wikidata/WikidataEditService.kt b/app/src/main/java/fr/free/nrw/commons/wikidata/WikidataEditService.kt index 0b49c03e9..f4bf23073 100644 --- a/app/src/main/java/fr/free/nrw/commons/wikidata/WikidataEditService.kt +++ b/app/src/main/java/fr/free/nrw/commons/wikidata/WikidataEditService.kt @@ -196,13 +196,16 @@ class WikidataEditService @Inject constructor( return wikidataClient.setClaim(claim, COMMONS_APP_TAG).blockingSingle() } - fun handleImageClaimResult(wikidataItem: WikidataItem, revisionId: Long?) { + fun handleImageClaimResult(wikidataItem: WikidataItem, revisionId: Long?, p18WasSkipped: Boolean = false) { if (revisionId != null) { wikidataEditListener?.onSuccessfulWikidataEdit() showSuccessToast(wikidataItem.name) - } else { + } else if (!p18WasSkipped) { Timber.d("Unable to make wiki data edit for entity %s", wikidataItem) showLongToast(context, context.getString(R.string.wikidata_edit_failure)) + } else { + Timber.d("Wikidata edit skipped for entity %s because P18 already exists", wikidataItem) + // No error shown to user, as this is not a failure } } diff --git a/app/src/main/res/values-x-invalidLanguageCode/error.xml b/app/src/main/res/values-x-invalidLanguageCode/error.xml deleted file mode 100644 index f4e2fe125..000000000 --- a/app/src/main/res/values-x-invalidLanguageCode/error.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - کامَنٕز گوو رُکِتھ - Oops. کیہہ تام گوو غلط! - ؤنِیوٚ اَسہِ توٚہہِ کیاہ ٲسِیوٚ کران، تہٕ کٕریٚو تہِ اَسہِ سٕتی شیر بذریعہِ برقی خط. یُس مَدَتھ کَرِ اَسہِ اَتھ شہَرنَس منٛز! - شُکریہ! - From d9e89174187d983aabdc9c0f3d1791b39e932538 Mon Sep 17 00:00:00 2001 From: "translatewiki.net" Date: Mon, 23 Jun 2025 14:01:45 +0200 Subject: [PATCH 035/162] Localisation updates from https://translatewiki.net. --- app/src/main/res/values-fi/strings.xml | 2 +- app/src/main/res/values-ps/strings.xml | 4 +- .../values-x-invalidLanguageCode/error.xml | 10 ++++ app/src/main/res/values-xmf/strings.xml | 46 ++++++++++++++++++- 4 files changed, 57 insertions(+), 5 deletions(-) create mode 100644 app/src/main/res/values-x-invalidLanguageCode/error.xml diff --git a/app/src/main/res/values-fi/strings.xml b/app/src/main/res/values-fi/strings.xml index cdb25defc..e65f05825 100644 --- a/app/src/main/res/values-fi/strings.xml +++ b/app/src/main/res/values-fi/strings.xml @@ -180,7 +180,7 @@ Kuvaus: Sydneyn oopperatalo lahden toiselta puolelta katsottuna Luokat: Sydneyn oopperatalo lännestä katsottuna, Sydneyn oopperatalo kaukaa katsottuna Herätä Wikipedia-artikkelit eloon kuvillasi! Tuo kuvasi Wikipediaan. - Wikipedian kuvat tulevat Wikimedia Commonsista. + Wikipedian kuvat ovat peräisin Wikimedia Commonsista. Kuvasi auttavat useita ihmisiä ympäri maailmaa artikkeleiden ymmärtämisessä. Vältä tekijänoikeuksien alaista materiaalia, kuten julisteita, kirjan kansia ja useimpia Internetistä löydettyjä kuvia. Luuletko ymmärtäneesi tämän? diff --git a/app/src/main/res/values-ps/strings.xml b/app/src/main/res/values-ps/strings.xml index 6b3970c88..98bd626e9 100644 --- a/app/src/main/res/values-ps/strings.xml +++ b/app/src/main/res/values-ps/strings.xml @@ -136,7 +136,7 @@ %1$s مور ټولگې نه لري ويکي‌اوتوک خونديځ کې د خپلو انځورونو موندلو لپاره وېشنيزې ورگډې کړئ.\nوېشنيزو ورگډولو لپاره ټاپل پيل کړئ. وېشنيزې - امستنې + اوڼنې نومليکنه ټاکلی انځور دوديز ټاکونکی @@ -216,7 +216,7 @@ پورته کول نژدې په اړه - امستنې + اوڼنې غبرگون وتل بياکتنه diff --git a/app/src/main/res/values-x-invalidLanguageCode/error.xml b/app/src/main/res/values-x-invalidLanguageCode/error.xml new file mode 100644 index 000000000..f4e2fe125 --- /dev/null +++ b/app/src/main/res/values-x-invalidLanguageCode/error.xml @@ -0,0 +1,10 @@ + + + + کامَنٕز گوو رُکِتھ + Oops. کیہہ تام گوو غلط! + ؤنِیوٚ اَسہِ توٚہہِ کیاہ ٲسِیوٚ کران، تہٕ کٕریٚو تہِ اَسہِ سٕتی شیر بذریعہِ برقی خط. یُس مَدَتھ کَرِ اَسہِ اَتھ شہَرنَس منٛز! + شُکریہ! + diff --git a/app/src/main/res/values-xmf/strings.xml b/app/src/main/res/values-xmf/strings.xml index 153d88b54..3f9b0e59f 100644 --- a/app/src/main/res/values-xmf/strings.xml +++ b/app/src/main/res/values-xmf/strings.xml @@ -99,6 +99,8 @@ ფოტოშ გინოღალა გოხოლუას ჩქიმი ეხარგუეფი + რსხილიშ კოპირება + რსხილი კოპირებული რე ბუფერულ შვენას გობჟინაფა ფაილიშ ხასჷლაშ ძირაფა მუკნაჭარა (უციო) @@ -109,6 +111,7 @@ ძალამ მიარე უმწუძინუ ცადება. ქორთხინ, მუხირენ წუთშა ხოლო ქოცადით. მორდება, თე მახვარებუ ბლოკირი რე ვიკიოწკარუეს თქვა გემშიონათ ოკო ჟირფაქტორიანი ავტორიზაციაშ კოდი. + დოდასურაფაშ კოდი ჯღონელი რე თქვანი ელექტრონული ფოშტაშა. ქორთხიინთ, მოჯღონელი კოდი გენშეჸონათ მიშაულარო. მიშულაქ ვემიხუჯინუ ეხარგუა სერიაშ ჯოხო @@ -117,6 +120,7 @@ კატეგორიაშ გიშაგორუა დოგორით ელემენტეფი, ნამუეფით მოჩამილი რე თქვანი სურათის (გვალა, ტაჯ-მაჰალი დო თ.უ.) ჩუალა + გეძინელი მენიუ გოახალაფა ერკებული (ეხარგუეფი ვა რე) @@ -213,6 +217,7 @@ ბეტა ტესტირებას კათაფი ჩართით Beta-შა ჭირინაფა Google Play-ს დო მიღით ორდოიანი ჭირინაფა ახალ ფუნქციეფშა დო ჩილათეფიშ ეშახინტკალო 2ფა კოდი + ელექტრონული ფოშტაშ დოდასურაფაშ კოდი გოკონანო გიშულა? მედიაფაილიშ ჩილათა გიმენკატეგორიეფქ ვეგორინუ @@ -360,6 +365,7 @@ კინოხიანი სურათეფი ორენეფი + კატეგორიეფი მიკოწონებულეფშა გეძინა/ლასუა მიკოწონებულეფი თქვა ვეგეიძინჷნა აკა მიკოწონებული @@ -373,8 +379,10 @@ მოზოჯით ვიკიოწკარუეშა!\n\nგეხარგეთ თქვანი პირველი ფაილი, ქეგუნჭირით კონჭის გეძინა. კატეგორია ვა რე გიშაგორილი სურათეფი კატეგორიზაციაშ უმუშო შხირას მერკეთ გჷმორინაფონი რე. დასურო გონებჷნანო კატეგორიეფიშ მეწურაფაშ უმუშო გაგჷნძარაფა? + ეჭარუა ვა რე გიშაგორილი ეხარგუაშ გოუქვაფა ეხარგუაშ გოგჷნძორაფა + (ნაკორობაშ არძა სურათიშო) ათე არანს გორუა ალობაშ მოთხირი თენა კჷნ დღას ვაბკითხა @@ -383,9 +391,20 @@ ალობაშ მეჩამა გოუქვაფა ღოლამირჷ რე + თინას რენო კათეგორიეფი მეწურაფილი? + გეჸვენჯი სურათი + ქო, მუშენ ვარი ვა რე გუმორინაფილი სურათეფი + ვა რე ეხარგილი სურათეფი + თქვა ვაიღჷნა უკითხირუ გინაფეფი + ვა ვაიღჷნა კითხირებული გინაფეფი + ქოძირით თქვანი ელექტრონული ფოსტა + კითხირებულიშ ძირაფა + უკითხირებუშ ძირაფა სურათიშ ეხარგუაშ ბორჯის ჩილათაქ მოხვადჷ ქორთხინთ ქჷმიცადით … + კოპირაფილი რე + თე სურათიშ გიშატება ავტორი ორენი კამერაშ მოდელი @@ -393,9 +412,32 @@ სერიული ნომერი პროგრამული უნარღელჸუა სურათიშ ინფორმაცია - სელფი - ჸურილი + კატეგორიეფქ ვეგორინუ + ეჭარუეფქ ვეორინუ + ეხარგუაქ გეუქვუ + მუშენ დილასას ოკო %1$s-ქ? + %1$s ეხარგილი რე: %2$s + წუმოძინელო + %1$s ნომინირებული რე ოლასარო. + ვემიხუჯინუ + ვეშილებე ლასუაშ მოთხირი. + სელფი, ნამუთ ვეგჷმირინუაფუ ნამთინ სტატიას + ედომუშამო გინობარდილი რე + უაზრობა, აბსოლუტურო უმუხუჯუ რე ირნერი სტატიას + ახალი ამბეეფიშ სურათი + ნამდგა სურათი ინტერნეტიშე + ლოგო + პანორამაშ დუდიშულაშ აკორცუაფა თიშენ ნამჷ-და თინა რე + კატეგორიეფიშ მოახალებაშ ცადება. + კატეგორიაშ მოახალება + წუმოძინელო + + კატეგორია %1$s გეძინელი რე. + კატეგორიეფი %1$sგეძინელი რე. + + ვემიხუჯინუ კატეგორიეფიშ გეძინაქ. + კატეგორიეფიშ მოახალება მიკოწონებეფი პარამეტრეფი რუმე From 5d7f42d127600f205773214bb877472f259ff552 Mon Sep 17 00:00:00 2001 From: Rohit Verma <101377978+rohit9625@users.noreply.github.com> Date: Tue, 24 Jun 2025 18:26:00 +0530 Subject: [PATCH 036/162] Fix/file usage not working (#6354) * chore: add R8 rules to prevent obfuscating file usage classes * chore: upgrade lifecycle-runtime dependency to resolve lint errors * remove invalid resource directory --- app/proguard-rules.txt | 3 +++ .../main/res/values-x-invalidLanguageCode/error.xml | 10 ---------- gradle/libs.versions.toml | 2 +- 3 files changed, 4 insertions(+), 11 deletions(-) delete mode 100644 app/src/main/res/values-x-invalidLanguageCode/error.xml diff --git a/app/proguard-rules.txt b/app/proguard-rules.txt index 63981633b..21c584ba9 100644 --- a/app/proguard-rules.txt +++ b/app/proguard-rules.txt @@ -66,6 +66,9 @@ # Application classes that will be serialized/deserialized over Gson -keep class com.google.gson.examples.android.model.** { *; } +# Prevent R8 from obfuscating project classes used by Gson for parsing +-keep class fr.free.nrw.commons.fileusages.** { *; } + # Prevent proguard from stripping interface information from TypeAdapterFactory, # JsonSerializer, JsonDeserializer instances (so they can be used in @JsonAdapter) -keep class * implements com.google.gson.TypeAdapterFactory diff --git a/app/src/main/res/values-x-invalidLanguageCode/error.xml b/app/src/main/res/values-x-invalidLanguageCode/error.xml deleted file mode 100644 index f4e2fe125..000000000 --- a/app/src/main/res/values-x-invalidLanguageCode/error.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - کامَنٕز گوو رُکِتھ - Oops. کیہہ تام گوو غلط! - ؤنِیوٚ اَسہِ توٚہہِ کیاہ ٲسِیوٚ کران، تہٕ کٕریٚو تہِ اَسہِ سٕتی شیر بذریعہِ برقی خط. یُس مَدَتھ کَرِ اَسہِ اَتھ شہَرنَس منٛز! - شُکریہ! - diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index afb3615d2..f38357b04 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -39,7 +39,7 @@ leakcanary = "2.10" livedataTesting = "1.2.0" swipelayout = "1.2.0" viewpagerIndicator = "2.4.1.1" -lifecycleRuntimeKtx = "2.8.4" +lifecycleRuntimeKtx = "2.8.7" loggingInterceptor = "4.10.0" logbackAndroidClassic = "1.1.1-6" material = "1.12.0" From ad7dddaac439b3af4332e43552fc25994a74f219 Mon Sep 17 00:00:00 2001 From: Rohit Verma <101377978+rohit9625@users.noreply.github.com> Date: Wed, 25 Jun 2025 08:54:03 +0530 Subject: [PATCH 037/162] Fix infinite loading circular progress bar after nominating for deletion (#6324) * fix: infinite loading progress bar after nominating for deletion * add logs for testing * refactor: use globalFileUsage instead of achievement to append in reason Fetching achievements is a time consuming operation and globalFileUsage gives the similar result in optimal time * test(ReasonBuilder): fix tests according to new behavior * refactor: remove logs added for testing * test: await for async getReason method call --------- Co-authored-by: Neel Doshi Co-authored-by: Nicolas Raoul --- app/build.gradle.kts | 1 + .../free/nrw/commons/delete/DeleteHelper.kt | 2 - .../free/nrw/commons/delete/ReasonBuilder.kt | 51 +++++++----- .../nrw/commons/media/MediaDetailFragment.kt | 79 +++++++++++-------- .../nrw/commons/mwapi/OkHttpJsonApiClient.kt | 1 + app/src/main/res/values/strings.xml | 3 +- .../nrw/commons/delete/ReasonBuilderTest.kt | 15 ++-- gradle/libs.versions.toml | 2 + 8 files changed, 88 insertions(+), 66 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 9c53155a7..2e391a24f 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -347,6 +347,7 @@ dependencies { // Kotlin + coroutines implementation(libs.androidx.work.runtime.ktx) implementation(libs.androidx.work.runtime) + implementation(libs.kotlinx.coroutines.rx2) testImplementation(libs.androidx.work.testing) //Glide diff --git a/app/src/main/java/fr/free/nrw/commons/delete/DeleteHelper.kt b/app/src/main/java/fr/free/nrw/commons/delete/DeleteHelper.kt index 09959d0ef..3f9ae47ac 100644 --- a/app/src/main/java/fr/free/nrw/commons/delete/DeleteHelper.kt +++ b/app/src/main/java/fr/free/nrw/commons/delete/DeleteHelper.kt @@ -53,7 +53,6 @@ class DeleteHelper @Inject constructor( media: Media?, reason: String? ): Single? { - if(context == null && media == null) { return null } @@ -86,7 +85,6 @@ class DeleteHelper @Inject constructor( * @return */ private fun delete(media: Media, reason: String): Observable { - Timber.d("thread is delete %s", Thread.currentThread().name) val summary = "Nominating ${media.filename} for deletion." val calendar = Calendar.getInstance() val fileDeleteString = """ diff --git a/app/src/main/java/fr/free/nrw/commons/delete/ReasonBuilder.kt b/app/src/main/java/fr/free/nrw/commons/delete/ReasonBuilder.kt index 09018c249..c4cd73b8a 100644 --- a/app/src/main/java/fr/free/nrw/commons/delete/ReasonBuilder.kt +++ b/app/src/main/java/fr/free/nrw/commons/delete/ReasonBuilder.kt @@ -2,21 +2,19 @@ package fr.free.nrw.commons.delete import android.annotation.SuppressLint import android.content.Context - -import fr.free.nrw.commons.utils.DateUtil -import java.util.Locale - -import javax.inject.Inject -import javax.inject.Singleton - import fr.free.nrw.commons.Media import fr.free.nrw.commons.R -import fr.free.nrw.commons.profile.achievements.FeedbackResponse import fr.free.nrw.commons.auth.SessionManager import fr.free.nrw.commons.mwapi.OkHttpJsonApiClient +import fr.free.nrw.commons.utils.DateUtil import fr.free.nrw.commons.utils.ViewUtilWrapper import io.reactivex.Single +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.rx2.rxSingle import timber.log.Timber +import java.util.Locale +import javax.inject.Inject +import javax.inject.Singleton /** * This class handles the reason for deleting a Media object @@ -29,6 +27,8 @@ class ReasonBuilder @Inject constructor( private val viewUtilWrapper: ViewUtilWrapper ) { + private val defaultFileUsagePageSize = 10 + /** * To process the reason and append the media's upload date and uploaded_by_me string * @param media @@ -39,7 +39,7 @@ class ReasonBuilder @Inject constructor( if (media == null || reason == null) { return Single.just("Not known") } - return fetchArticleNumber(media, reason) + return getAndAppendFileUsage(media, reason) } /** @@ -54,27 +54,36 @@ class ReasonBuilder @Inject constructor( } } - private fun fetchArticleNumber(media: Media, reason: String): Single { - return if (checkAccount()) { - okHttpJsonApiClient - .getAchievements(sessionManager.userName) - .map { feedbackResponse -> appendArticlesUsed(feedbackResponse, media, reason) } - } else { - Single.just("") + private fun getAndAppendFileUsage(media: Media, reason: String): Single { + return rxSingle(context = Dispatchers.IO) { + if (!checkAccount()) return@rxSingle "" + + try { + val globalFileUsage = okHttpJsonApiClient.getGlobalFileUsages( + fileName = media.filename, + pageSize = defaultFileUsagePageSize + ) + val globalUsages = globalFileUsage?.query?.pages?.sumOf { it.fileUsage.size } ?: 0 + + appendArticlesUsed(globalUsages, media, reason) + } catch (e: Exception) { + Timber.e(e, "Error fetching file usage") + throw e + } } } /** - * Takes the uploaded_by_me string, the upload date, name of articles using images + * Takes the uploaded_by_me string, the upload date, no. of articles using images * and appends it to the received reason - * @param feedBack object + * @param fileUsages No. of files/articles using this image * @param media whose upload data is to be fetched - * @param reason + * @param reason string to be appended */ @SuppressLint("StringFormatInvalid") - private fun appendArticlesUsed(feedBack: FeedbackResponse, media: Media, reason: String): String { + private fun appendArticlesUsed(fileUsages: Int, media: Media, reason: String): String { val reason1Template = context.getString(R.string.uploaded_by_myself) - return reason + String.format(Locale.getDefault(), reason1Template, prettyUploadedDate(media), feedBack.articlesUsingImages) + return reason + String.format(Locale.getDefault(), reason1Template, prettyUploadedDate(media), fileUsages) .also { Timber.i("New Reason %s", it) } } diff --git a/app/src/main/java/fr/free/nrw/commons/media/MediaDetailFragment.kt b/app/src/main/java/fr/free/nrw/commons/media/MediaDetailFragment.kt index 8a4d530c4..f371b733f 100644 --- a/app/src/main/java/fr/free/nrw/commons/media/MediaDetailFragment.kt +++ b/app/src/main/java/fr/free/nrw/commons/media/MediaDetailFragment.kt @@ -74,7 +74,6 @@ import fr.free.nrw.commons.BuildConfig import fr.free.nrw.commons.CameraPosition import fr.free.nrw.commons.CommonsApplication import fr.free.nrw.commons.CommonsApplication.Companion.instance -import fr.free.nrw.commons.locationpicker.LocationPicker import fr.free.nrw.commons.Media import fr.free.nrw.commons.MediaDataExtractor import fr.free.nrw.commons.R @@ -102,6 +101,7 @@ import fr.free.nrw.commons.explore.depictions.WikidataItemDetailsActivity import fr.free.nrw.commons.kvstore.JsonKvStore import fr.free.nrw.commons.language.AppLanguageLookUpTable import fr.free.nrw.commons.location.LocationServiceManager +import fr.free.nrw.commons.locationpicker.LocationPicker import fr.free.nrw.commons.media.MediaDetailPagerFragment.MediaDetailProvider import fr.free.nrw.commons.profile.ProfileActivity import fr.free.nrw.commons.review.ReviewHelper @@ -116,6 +116,7 @@ import fr.free.nrw.commons.utils.LangCodeUtils.getLocalizedResources import fr.free.nrw.commons.utils.PermissionUtils.PERMISSIONS_STORAGE import fr.free.nrw.commons.utils.PermissionUtils.checkPermissionsAndPerformAction import fr.free.nrw.commons.utils.PermissionUtils.hasPermission +import fr.free.nrw.commons.utils.ViewUtil import fr.free.nrw.commons.utils.ViewUtil.showShortToast import fr.free.nrw.commons.utils.ViewUtilWrapper import fr.free.nrw.commons.wikidata.mwapi.MwQueryPage.Revision @@ -125,6 +126,7 @@ import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.schedulers.Schedulers import org.apache.commons.lang3.StringUtils import timber.log.Timber +import java.lang.String.format import java.util.Date import java.util.Locale import java.util.Objects @@ -1646,7 +1648,7 @@ class MediaDetailFragment : CommonsDaggerSupportFragment(), CategoryEditHelper.C getString(R.string.cancel), { val reason: String = input.text.toString() - onDeleteClickeddialogtext(reason) + onDeleteClickedDialogText(reason) }, {}, input @@ -1700,26 +1702,48 @@ class MediaDetailFragment : CommonsDaggerSupportFragment(), CategoryEditHelper.C resultSingle .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) - .subscribe { _ -> - if (applicationKvStore.getBoolean( - String.format( - NOMINATING_FOR_DELETION_MEDIA, media!!.imageUrl - ), false - ) - ) { - applicationKvStore.remove( - String.format( - NOMINATING_FOR_DELETION_MEDIA, - media!!.imageUrl - ) - ) - callback!!.nominatingForDeletion(index) - } - } + .subscribe(this::handleDeletionResult, this::handleDeletionError); + } + + /** + * Disables Progress Bar and Update delete button text. + */ + private fun disableProgressBar() { + activity?.run { + runOnUiThread(Runnable { + binding.progressBarDeletion.visibility = View.GONE + }) + } ?: return // Prevent NullPointerException when fragment is not attached to activity + } + + private fun handleDeletionResult(success: Boolean) { + if (success) { + binding.nominateDeletion.text = getString(R.string.nominated_for_deletion_btn) + ViewUtil.showLongSnackbar(requireView(), getString(R.string.nominated_for_deletion)) + disableProgressBar() + checkAndClearDeletionFlag() + } else { + disableProgressBar() + } + } + + private fun handleDeletionError(throwable: Throwable) { + throwable.printStackTrace() + disableProgressBar() + checkAndClearDeletionFlag() + } + + private fun checkAndClearDeletionFlag() { + if (applicationKvStore + .getBoolean(format(NOMINATING_FOR_DELETION_MEDIA, media!!.imageUrl), false) + ) { + applicationKvStore.remove(format(NOMINATING_FOR_DELETION_MEDIA, media!!.imageUrl)) + callback!!.nominatingForDeletion(index) + } } @SuppressLint("CheckResult") - private fun onDeleteClickeddialogtext(reason: String) { + private fun onDeleteClickedDialogText(reason: String) { applicationKvStore.putBoolean( String.format( NOMINATING_FOR_DELETION_MEDIA, @@ -1736,22 +1760,7 @@ class MediaDetailFragment : CommonsDaggerSupportFragment(), CategoryEditHelper.C resultSingletext .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) - .subscribe { _ -> - if (applicationKvStore.getBoolean( - String.format( - NOMINATING_FOR_DELETION_MEDIA, media!!.imageUrl - ), false - ) - ) { - applicationKvStore.remove( - String.format( - NOMINATING_FOR_DELETION_MEDIA, - media!!.imageUrl - ) - ) - callback!!.nominatingForDeletion(index) - } - } + .subscribe(this::handleDeletionResult, this::handleDeletionError); } private fun onSeeMoreClicked() { diff --git a/app/src/main/java/fr/free/nrw/commons/mwapi/OkHttpJsonApiClient.kt b/app/src/main/java/fr/free/nrw/commons/mwapi/OkHttpJsonApiClient.kt index 4fa7979d2..a2f92c2e6 100644 --- a/app/src/main/java/fr/free/nrw/commons/mwapi/OkHttpJsonApiClient.kt +++ b/app/src/main/java/fr/free/nrw/commons/mwapi/OkHttpJsonApiClient.kt @@ -281,6 +281,7 @@ class OkHttpJsonApiClient @Inject constructor( FeedbackResponse::class.java ) } catch (e: Exception) { + e.printStackTrace() return@fromCallable FeedbackResponse(0, 0, 0, FeaturedImages(0, 0), 0, "") } } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 68dba88be..c9a2d16c8 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -431,7 +431,7 @@ I changed my mind, I don\'t want it to be publicly visible anymore Sorry this picture is not interesting for an encyclopedia - Uploaded by myself on %1$s, used in %2$d article(s). + Uploaded by myself on %1$s, used in %2$d article(s) at least. Welcome to Commons!\n Upload your first media by tapping on the add button. @@ -876,4 +876,5 @@ Upload your first media by tapping on the add button. Show in Nearby Created and uploaded by: %1$s Created by %1$s and uploaded by %2$s + Nominated for Deletion diff --git a/app/src/test/kotlin/fr/free/nrw/commons/delete/ReasonBuilderTest.kt b/app/src/test/kotlin/fr/free/nrw/commons/delete/ReasonBuilderTest.kt index e89a02dec..bd67475ee 100644 --- a/app/src/test/kotlin/fr/free/nrw/commons/delete/ReasonBuilderTest.kt +++ b/app/src/test/kotlin/fr/free/nrw/commons/delete/ReasonBuilderTest.kt @@ -5,13 +5,14 @@ import android.content.res.Resources import fr.free.nrw.commons.Media import fr.free.nrw.commons.R import fr.free.nrw.commons.auth.SessionManager +import fr.free.nrw.commons.fileusages.GlobalFileUsagesResponse import fr.free.nrw.commons.mwapi.OkHttpJsonApiClient -import fr.free.nrw.commons.profile.achievements.FeedbackResponse import fr.free.nrw.commons.profile.leaderboard.LeaderboardResponse import fr.free.nrw.commons.profile.leaderboard.UpdateAvatarResponse import fr.free.nrw.commons.utils.ViewUtilWrapper import io.reactivex.Observable import io.reactivex.Single +import kotlinx.coroutines.test.runTest import media import org.junit.Before import org.junit.Test @@ -58,16 +59,16 @@ class ReasonBuilderTest { PowerMockito.`when`(context?.getString(R.string.user_not_logged_in)) .thenReturn("Log-in expired. Please log in again.") - reasonBuilder!!.getReason(mock(Media::class.java), "test") + reasonBuilder!!.getReason(mock(Media::class.java), "test").test().await() verify(sessionManager, times(1))!!.forceLogin(any(Context::class.java)) } @Test - fun getReason() { + fun getReason() = runTest { `when`(sessionManager?.userName).thenReturn("Testuser") `when`(sessionManager?.doesAccountExist()).thenReturn(true) - `when`(okHttpJsonApiClient!!.getAchievements(anyString())) - .thenReturn(Single.just(mock(FeedbackResponse::class.java))) + `when`(okHttpJsonApiClient!!.getGlobalFileUsages(anyString(), anyInt())) + .thenReturn(mock(GlobalFileUsagesResponse::class.java)) `when`(okHttpJsonApiClient!!.getLeaderboard(anyString(), anyString(), anyString(), anyString(), anyString())) .thenReturn(Observable.just(mock(LeaderboardResponse::class.java))) `when`(okHttpJsonApiClient!!.setAvatar(anyString(), anyString())) @@ -75,8 +76,8 @@ class ReasonBuilderTest { val media = media(filename = "test_file", dateUploaded = Date()) - reasonBuilder!!.getReason(media, "test") + reasonBuilder!!.getReason(media, "test").test().await() verify(sessionManager, times(0))!!.forceLogin(any(Context::class.java)) - verify(okHttpJsonApiClient, times(1))!!.getAchievements(anyString()) + verify(okHttpJsonApiClient, times(1))!!.getGlobalFileUsages(anyString(), anyInt()) } } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index f38357b04..df4b7bb43 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -16,6 +16,7 @@ constraintlayout = "1.1.3" coordinates2country = "1.8" dexcount = "4.0.0" githubTripletPlay = "2.7.2" +kotlinxCoroutinesRx2 = "1.8.0" osmdroidAndroid = "6.1.17" testCore = "1.4.0" coreKtx = "1.9.0" @@ -127,6 +128,7 @@ dagger-compiler = { module = "com.google.dagger:dagger-compiler", version.ref = facebook-fresco = { module = "com.facebook.fresco:fresco", version.ref = "frescoVersion" } glide-compiler = { module = "com.github.bumptech.glide:compiler", version.ref = "glide" } glide = { module = "com.github.bumptech.glide:glide", version.ref = "glide" } +kotlinx-coroutines-rx2 = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-rx2", version.ref = "kotlinxCoroutinesRx2" } photoview = { module = "com.github.chrisbanes:PhotoView", version.ref = "photoviewVersion" } # RxJava and Reactive Programming From b1a8308aaf244c93cdf3c72c0d897ad0f4b9fbcd Mon Sep 17 00:00:00 2001 From: "translatewiki.net" Date: Thu, 26 Jun 2025 14:02:13 +0200 Subject: [PATCH 038/162] Localisation updates from https://translatewiki.net. --- app/src/main/res/values-af/strings.xml | 2 +- app/src/main/res/values-ar/strings.xml | 2 +- app/src/main/res/values-ast/strings.xml | 2 +- app/src/main/res/values-b+sr+Latn/strings.xml | 2 +- app/src/main/res/values-cs/strings.xml | 2 +- app/src/main/res/values-da/strings.xml | 3 ++- app/src/main/res/values-de/strings.xml | 2 +- app/src/main/res/values-el/strings.xml | 2 +- app/src/main/res/values-eo/strings.xml | 2 +- app/src/main/res/values-es/strings.xml | 2 +- app/src/main/res/values-fa/strings.xml | 2 +- app/src/main/res/values-fi/strings.xml | 2 +- app/src/main/res/values-fr/strings.xml | 2 +- app/src/main/res/values-gl/strings.xml | 2 +- app/src/main/res/values-hu/strings.xml | 2 +- app/src/main/res/values-ia/strings.xml | 2 +- app/src/main/res/values-in/strings.xml | 2 +- app/src/main/res/values-io/strings.xml | 2 +- app/src/main/res/values-is/strings.xml | 2 +- app/src/main/res/values-it/strings.xml | 5 +++-- app/src/main/res/values-iw/strings.xml | 3 ++- app/src/main/res/values-ja/strings.xml | 2 +- app/src/main/res/values-krc/strings.xml | 2 +- app/src/main/res/values-kus/strings.xml | 2 +- app/src/main/res/values-lb/strings.xml | 5 +++-- app/src/main/res/values-lt/strings.xml | 2 +- app/src/main/res/values-mk/strings.xml | 2 +- app/src/main/res/values-nb/strings.xml | 2 +- app/src/main/res/values-nl/strings.xml | 3 ++- app/src/main/res/values-nqo/strings.xml | 2 +- app/src/main/res/values-pl/strings.xml | 2 +- app/src/main/res/values-pms/strings.xml | 3 ++- app/src/main/res/values-pt-rBR/strings.xml | 2 +- app/src/main/res/values-pt/strings.xml | 2 +- app/src/main/res/values-ro/strings.xml | 2 +- app/src/main/res/values-ru/strings.xml | 2 +- app/src/main/res/values-sk/strings.xml | 2 +- app/src/main/res/values-sl/strings.xml | 2 +- app/src/main/res/values-sr/strings.xml | 3 ++- app/src/main/res/values-sv/strings.xml | 2 +- app/src/main/res/values-te/strings.xml | 2 +- app/src/main/res/values-tr/strings.xml | 2 +- app/src/main/res/values-uk/strings.xml | 2 +- app/src/main/res/values-vec/strings.xml | 2 +- .../main/res/values-x-invalidLanguageCode/error.xml | 10 ++++++++++ app/src/main/res/values-xmf/strings.xml | 2 +- app/src/main/res/values-zh-rTW/strings.xml | 2 +- app/src/main/res/values-zh/strings.xml | 2 +- 48 files changed, 66 insertions(+), 49 deletions(-) create mode 100644 app/src/main/res/values-x-invalidLanguageCode/error.xml diff --git a/app/src/main/res/values-af/strings.xml b/app/src/main/res/values-af/strings.xml index 8a6a5ccd9..51aaea77e 100644 --- a/app/src/main/res/values-af/strings.xml +++ b/app/src/main/res/values-af/strings.xml @@ -341,7 +341,7 @@ Ek het besef dat dit sleg is vir my privaatheid Ek het van plan verander, ek wil nie hê dit moet meer in die openbaar sigbaar wees nie Jammer, hierdie foto is nie interessant vir \'n ensiklopedie nie - Opgelaai deur myself op %1$s, gebruik in %2$d artikel(s). + Opgelaai deur myself op %1$s, gebruik in %2$d artikel(s). Welkom by Commons!\n\nLaai u eerste media op deur op die byvoegknoppie te tik. Geen kategorieë gekies nie Beelde sonder kategorieë is selde bruikbaar. Is u seker dat u wil indien sonder om kategorieë te kies? diff --git a/app/src/main/res/values-ar/strings.xml b/app/src/main/res/values-ar/strings.xml index 5025b94cb..daa5e9b1c 100644 --- a/app/src/main/res/values-ar/strings.xml +++ b/app/src/main/res/values-ar/strings.xml @@ -469,7 +469,7 @@ أدركت أنه سيئ لخصوصيتي لقد غيرت رأيي، ولا أريد أن يكون مرئيا للجميع بعد الآن آسف هذه الصورة ليست مثيرة للاهتمام لموسوعة - رفعته بنفسي في %1$s، مستخدم في %2$d مقالة(ات). + رفعته بنفسي في %1$s، مستخدم في %2$d مقالة(ات). مرحبا بك في كومنز! \n\nارفع الوسائط الأولى عن طريق النقر على زر الإضافة. لا توجد تصنيفات مختارة نادرًا ما تكون الصور الخالية من التصنيفات قابلة للاستخدام، هل أنت متأكد أنك تريد الإرسال دون تحديد التصنيفات؟ diff --git a/app/src/main/res/values-ast/strings.xml b/app/src/main/res/values-ast/strings.xml index 8d0dba79a..591c21395 100644 --- a/app/src/main/res/values-ast/strings.xml +++ b/app/src/main/res/values-ast/strings.xml @@ -395,7 +395,7 @@ Decatéme que ye malo pa la mio privacidá Cambié d\'opinión, nun quiero que siga siendo visible públicamente Sentímoslo, esta imaxe nun ye interesante pa una enciclopedia - Xubíla yo mesmu\'l %1$s, usada en %2$d artículu(os). + Xubíla yo mesmu\'l %1$s, usada en %2$d artículu(os). ¡Afáyate\'n Commons.\n\nCarga\'l to primer ficheru tocando nel botón amestar. Nun hai categoríes seleicionaes Les imáxenes ensin categoríes raramente puen usase. ¿Seguro que quies siguir ensin escoyer categoría dala? diff --git a/app/src/main/res/values-b+sr+Latn/strings.xml b/app/src/main/res/values-b+sr+Latn/strings.xml index 47e1cb0bd..459f75852 100644 --- a/app/src/main/res/values-b+sr+Latn/strings.xml +++ b/app/src/main/res/values-b+sr+Latn/strings.xml @@ -394,7 +394,7 @@ Shvatio/la sam da je loša za moju privatnost Promenio/la sam mišljenje, ne želim da više javno budu vidljive Ova slika nije zanimljiva za enciklopediju - Otpremio/la sam na %1$s, koristi se u članku/cima — %2$d. + Otpremio/la sam na %1$s, koristi se u članku/cima — %2$d. Dobro došli na Ostavu!\n\nOtpremite prve medije dodirom dugmeta za dodavanje. Kategorije nisu izabrane Slike bez kategorija retko su upotrebljive. Zaista želite da nastavite bez izbora kategorija? diff --git a/app/src/main/res/values-cs/strings.xml b/app/src/main/res/values-cs/strings.xml index 3250b01d7..f3d645530 100644 --- a/app/src/main/res/values-cs/strings.xml +++ b/app/src/main/res/values-cs/strings.xml @@ -448,7 +448,7 @@ Uvědomil/a jsem si, že je to špatné pro mé soukromí Změnil/a jsem názor, nechci, aby to bylo veřejně viditelné Omlouváme se, že tento obrázek není zajímavý pro encyklopedii - Náhráno mnou %1$s, použito v(e) %2$d článku/článcích. + Náhráno mnou %1$s, použito v(e) %2$d článku/článcích. Vítejte na Commons!\n\nNahrajte svá první média klepnutím na tlačítko přidat. Nebyly vybrány žádné kategorie Obrázky bez kategorií jsou používány jen zřídka. Opravdu chcete nahrát obrázek bez výběru kategorií? diff --git a/app/src/main/res/values-da/strings.xml b/app/src/main/res/values-da/strings.xml index bc2b23dbf..043cd871b 100644 --- a/app/src/main/res/values-da/strings.xml +++ b/app/src/main/res/values-da/strings.xml @@ -419,7 +419,7 @@ Jeg indså, det var skidt for mit privatliv Jeg ombestemte mig, jeg ønsker ikke at det skal være offentligt synligt længere Beklager dette billede er ikke interessant for en encyklopædi - Uploadet af mig selv på %1$s , brugt i %2$d artikel(er). + Uploadet af mig selv på %1$s , brugt i mindst %2$d artikel(er). Velkommen til Commons!\n\nUpload dit første medie ved at trykke på Tilføj-knappen. Ingen kategorier valgt Billeder uden kategorier er sjældent brugbare. Er du sikker på, at du vil fortsætte uden at vælge kategorier? @@ -828,4 +828,5 @@ Vis i I nærheden Oprettet og uploadet af: %1$s Oprettet af %1$s og uploadet af %2$s + Nomineret til sletning diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 705dfefd0..1c34182f1 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -453,7 +453,7 @@ Ich habe erkannt, dass es schlecht für meine Privatsphäre ist. Ich habe meine Meinung geändert. Ich möchte nicht mehr, dass es öffentlich sichtbar ist. Entschuldigung, aber dieses Bild ist für eine Enzyklopädie nicht relevant. - Von mir selbst hochgeladen am %1$s, verwendet in %2$d Artikel(n). + Von mir selbst hochgeladen am %1$s, verwendet in %2$d Artikel(n). Willkommen bei Commons!\n\nLade deine erste Datei hoch, indem du auf die Hinzufügen-Schaltfläche tippst. Keine Kategorien ausgewählt Bilder ohne Kategorien sind selten nutzbar. Bist du sicher, dass du ohne die Auswahl von Kategorien hochladen möchtest? diff --git a/app/src/main/res/values-el/strings.xml b/app/src/main/res/values-el/strings.xml index da816259e..c89bca41e 100644 --- a/app/src/main/res/values-el/strings.xml +++ b/app/src/main/res/values-el/strings.xml @@ -433,7 +433,7 @@ Συνειδητοποίησα ότι είναι κακό για την ιδιωτικότητά μου Άλλαξα γνώμη, δε θέλω να προβάλλεται πλέον δημόσια Συγγνώμη, αυτή η φωτογραφία δεν είναι ενδιαφέρουσα για μια εγκυκλοπαίδεια - Ανέβηκε από εμένα στο %1$s, χρησιμοποιήθηκε σε %2$d άρθρο/α + Ανέβηκε από εμένα στο %1$s, χρησιμοποιήθηκε σε %2$d άρθρο/α Καλώς ήρθατε στα Commons!\n\nΑνεβάστε τα πρώτα σας πολυμέσα πατώντας το κουμπί της προσθήκης. Δεν επιλέχθηκαν κατηγορίες Οι εικόνες χωρίς κατηγορίες χρησιμοποιούνται σπάνια. Θέλετε πράγματι να συνεχίσετε δίχως να επιλέξετε κατηγορίες; diff --git a/app/src/main/res/values-eo/strings.xml b/app/src/main/res/values-eo/strings.xml index d754c4a91..28f3f0eb8 100644 --- a/app/src/main/res/values-eo/strings.xml +++ b/app/src/main/res/values-eo/strings.xml @@ -408,7 +408,7 @@ Mi eksciis ke ĝi esta malbona por mia privateco Mi ŝanĝis mian preferon; mi ne plu volas ke ĝi estu publike videbla Domaĝe, ĉi tiu bildo ne estas interesa por enciklopedio - Alŝutita de mi je %1$s, uzata en %2$d artikolo(j). + Alŝutita de mi je %1$s, uzata en %2$d artikolo(j). Bonvenon al Komunejo!\n\nAlŝutu vian unuan aŭdvidaĵon per frapeto de la butono \'Aldoni\'. Neniu Elektita Kategorio Bildoj sen kategorioj estas malofte uzebla. Ĉu vi certas, ke vi volas daŭrigi sen elekti kategoriojn? diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index baed7bc1b..eb8caa3ba 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -464,7 +464,7 @@ Me di cuenta que es malo para mi privacidad Cambié de opinión, no quiero que siga siendo visible públicamente Lo sentimos, esta imagen no es interesante para una enciclopedia - Subida por mí mismo el %1$s, usado en %2$d artículo(s). + Subida por mí mismo el %1$s, usado en %2$d artículo(s). Te damos la bienvenida a Commons.\n\nCarga tu primer archivo mediante el botón Añadir. No hay categorías seleccionadas Las imágenes sin categorías raramente se pueden usar. ¿Seguro que quieres continuar sin seleccionar ninguna categoría? diff --git a/app/src/main/res/values-fa/strings.xml b/app/src/main/res/values-fa/strings.xml index 1cbdf5c47..32ec53638 100644 --- a/app/src/main/res/values-fa/strings.xml +++ b/app/src/main/res/values-fa/strings.xml @@ -386,7 +386,7 @@ فهمیدم که این برای حریم خصوصی من بد است. من تغییر عقیده دادم، نمی‌خواهم دیگر برای همه قابل‌مشاهده باشد. با پوزش، این تصویر برای یک دانشنامه مناسب نیست - بارگذاری‌شده توسط خودم در %1$s؛ استفاده‌شده در %2$d مقاله. + بارگذاری‌شده توسط خودم در %1$s؛ استفاده‌شده در %2$d مقاله. به ویکی‌انبار خوش آمدید!\n\nاولین فایلتان را با فشردن کلید اضافه بارگذاری کنید. رده‌ای انتخاب نشده است تصاویر بدون رده به ندرت قابل‌استفاده هستند. آیا مطمئنید که می‌خواهید بدون انتخاب رده ادامه دهید؟ diff --git a/app/src/main/res/values-fi/strings.xml b/app/src/main/res/values-fi/strings.xml index e65f05825..7561ca533 100644 --- a/app/src/main/res/values-fi/strings.xml +++ b/app/src/main/res/values-fi/strings.xml @@ -404,7 +404,7 @@ Huomasin, että se on haitallinen yksityisyydelleni. Muutin mieleni, en halua että se on enää julkisesti näkyvissä. Valitettavasti tämä kuva ei ole kiinnostava tietosanakirjaan - Minä olen ladannut kohteen %1$s käytetty %2$d artikkelissa. + Minä olen ladannut kohteen %1$s käytetty %2$d artikkelissa. Tervetuloa Commonsiin!\n\nTallenna ensimmäinen mediasi koskettamalla lisäyspainiketta. Luokkia ei valittu Kuvat, jotka eivät ole luokissa, ovat harvoin käyttökelpoisia. Haluatko varmasti jatkaa valitsematta luokkia? diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 9603f1806..124139b9a 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -457,7 +457,7 @@ J’ai pensé que ce n’était pas bon pour ma vie privée J’ai changé d\'avis, je ne désire plus que cel soit visible publiquement Désolé mais cette image n’est pas intéressante pour une encyclopédie - Téléversé par moi-même le %1$s, utilisé dans %2$d article(s). + Téléversé par moi-même le %1$s, utilisé dans %2$d article(s). Bienvenue sur Commons !\n\nTéléversez votre premier média en tapant sur le bouton Ajouter. Aucune catégorie sélectionnée Les images sans catégories sont rarement utilisables. Voulez-vous vraiment continuer sans sélectionner des catégories  appropriées ? diff --git a/app/src/main/res/values-gl/strings.xml b/app/src/main/res/values-gl/strings.xml index 0cf3aed91..bac417647 100644 --- a/app/src/main/res/values-gl/strings.xml +++ b/app/src/main/res/values-gl/strings.xml @@ -394,7 +394,7 @@ Decateime de que prexudica a miña privacidade Cambiei de idea, non quero que siga sendo visible de forma pública Desculpas, esta imaxe non é interesante para unha enciclopedia - Cargada por min o %1$s, usada en %2$d artigo(s). + Cargada por min o %1$s, usada en %2$d artigo(s). Dámoslle a benvida ó Commonsǃ\n\nCargue o seu primeiro ficheiro premendo no botón Engadir. Non hai categorías seleccionadas As imaxes sen categorías só son utilizables en contadas ocasións. Está seguro de que quere continuar sen seleccionar categorías? diff --git a/app/src/main/res/values-hu/strings.xml b/app/src/main/res/values-hu/strings.xml index 629312a57..a52805873 100644 --- a/app/src/main/res/values-hu/strings.xml +++ b/app/src/main/res/values-hu/strings.xml @@ -362,7 +362,7 @@ Észleltem, hogy ez rossz a magánszférámnak Meggondoltam magam, nem szeretném, hogy nyilvánosan látható legyen Sajnos ez a fénykép nem érdekes egy enciklopédia számára - Feltöltve ekkorː %1$s, %2$d cikkben használva. + Feltöltve ekkorː %1$s, %2$d cikkben használva. Üdvözlünk a Commons-ban. \n\nA hozzáadás gombra koppintva feltöltheted első képedet. Nincs kiválasztott kategória A kategória nélküli képek ritkán használhatóak. Biztos, hogy kategória kiválasztása nélkül akarsz továbblépni? diff --git a/app/src/main/res/values-ia/strings.xml b/app/src/main/res/values-ia/strings.xml index 386bddf2e..d139124d2 100644 --- a/app/src/main/res/values-ia/strings.xml +++ b/app/src/main/res/values-ia/strings.xml @@ -407,7 +407,7 @@ Io ha comprendite que es mal pro mi vita private Io ha cambiate de idea, io non vole plus que illo sia publicamente visibile Iste imagine non es interessante pro un encyclopedia - Incargate per me mesme le %1$s, usate in %2$d articulo(s). + Incargate per me mesme le %1$s, usate in %2$d articulo(s). Benvenite a Commons!\n\nPro incargar tu prime file multimedial, tocca le button Adder. Necun categoria seligite Imagines sin categorias es rarmente usabile. Es tu secur de voler continuar sin seliger categorias? diff --git a/app/src/main/res/values-in/strings.xml b/app/src/main/res/values-in/strings.xml index e977e56d5..8a44ef84d 100644 --- a/app/src/main/res/values-in/strings.xml +++ b/app/src/main/res/values-in/strings.xml @@ -410,7 +410,7 @@ Saya menyadari itu buruk untuk privasi saya Saya berubah pikiran, saya tidak ingin itu terlihat publik lagi Maaf gambar ini tidak menarik untuk ensiklopedia - Diunggah saya sendiri pada %1$s, digunakan dalam %2$d artikel. + Diunggah saya sendiri pada %1$s, digunakan dalam %2$d artikel. Unggah media pertama Anda dengan mengetuk tombol. Tidak ada Kategori yang Dipilih Gambar tanpa kategori jarang dapat digunakan. Apakah Anda yakin ingin mengirim tanpa memilih kategori? diff --git a/app/src/main/res/values-io/strings.xml b/app/src/main/res/values-io/strings.xml index f4802280d..1a74c2cc4 100644 --- a/app/src/main/res/values-io/strings.xml +++ b/app/src/main/res/values-io/strings.xml @@ -410,7 +410,7 @@ Me konstatis ke ol esas mala por mea privateso Me chanjis mea ideo: me ne pluse deziras ke ol esos publike videbla Pardonez! Ca imajo ne esas interesanta por ula enciklopedio - Adjuntita da me, che %1$s, uzita en %2$d artiklo/artikli. + Adjuntita da me, che %1$s, uzita en %2$d artiklo/artikli. Bonveno a Commons!\n\nSendez vua unesma arkivo kliktanta sur butono \"adjuntez\" (\'\'add\'\'). Nula kategorio selektita Imaji sen kategorii rare esas uzebla. Ka vu fakte deziras sendar ol sen selektar irga kategorio? diff --git a/app/src/main/res/values-is/strings.xml b/app/src/main/res/values-is/strings.xml index ad215efbc..427e3cec3 100644 --- a/app/src/main/res/values-is/strings.xml +++ b/app/src/main/res/values-is/strings.xml @@ -392,7 +392,7 @@ Ég áttaði mig á að þetta væri slæmt fyrir gagnaleynd mína Ég skipti um skoðun, ég vil ekki að hún sé lengur öllum sýnileg Afsakið, þessi mynd hefur ekkert gildi fyrir alfræðirit - Sent inn af mér sjálfum %1$s, notað í %2$d grein(um). + Sent inn af mér sjálfum %1$s, notað í %2$d grein(um). Velkomin í Commons!\n\nSendu inn fyrstu margmiðlunargögnin þín með því að ýta á viðbætingarhnappinn. Engir flokkar valdir Myndir án flokka eru sjaldnast nýtilegar. Ertu viss um að þú viljir halda áfram án þess að velja flokka? diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index b923b699b..fde465b06 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -289,7 +289,7 @@ Invia il file di registro agli sviluppatori tramite email per aiutarli a risolvere i problemi con l\'applicazione. Nota: i log potrebbero contenere informazioni di identificazione Nessun browser web trovato per aprire l\'URL Errore! URL non trovato - Proponi per la Cancellazione + Proponi per la cancellazione Questa immagine è stata proposta per la cancellazione. Vedi la pagina web per i dettagli Salta @@ -433,7 +433,7 @@ Mi sono reso conto che viola la mia privacy Ho cambiato idea, non voglio più che sia pubblicamente visibile Spiacente, questa immagine non è interessante per un\'enciclopedia - Caricato da me stesso il %1$s, utilizzato in %2$d voce/i. + Caricato da me stesso il %1$s, utilizzato almeno in %2$d voce/i. Benvenuto su Commons!\n\nCarica il tuo primo file multimediale toccando il pulsante aggiungi. Nessuna categoria selezionata Le immagini senza categorie sono raramente utilizzabili. Sei sicuro di voler continuare senza selezionare le categorie? @@ -836,4 +836,5 @@ Mostra nelle vicinanze Creato e caricato da: %1$s Creato da %1$s e caricato da %2$s + Proposto per la cancellazione diff --git a/app/src/main/res/values-iw/strings.xml b/app/src/main/res/values-iw/strings.xml index 6aecaf1e8..355e12dc6 100644 --- a/app/src/main/res/values-iw/strings.xml +++ b/app/src/main/res/values-iw/strings.xml @@ -444,7 +444,7 @@ הבנתי שזה לא טוב לפרטיות שלי התחרטתי, אינני רוצה עוד שהיא תוצג לציבור סליחה, התמונה אינה מעניינת עבור אנציקלופדיה - הועלה על ידי ב-%1$s, בשימוש ב-%2$d מאמר(ים) + הועלה על ידי ב־%1$s, בשימוש ב־%2$d מאמר(ים) לפחות. ברוך בואך לוויקישיתוף!\n\nכדי להעלות את המדיה הראשונה שלך, נא להקיש על כפתור ההוספה. לא נבחרו קטגוריות תמונות ללא קטגוריות בדרך כלל אינן שימושיות. להמשיך ללא בחירת קטגוריות? @@ -862,4 +862,5 @@ בתצוגת בסביבה נוצר והועלה על־ידי: %1$s נוצר על־ידי %1$s והועלה על־ידי %2$s + העמדה למחיקה diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index 662ddcd23..f051ba27a 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -408,7 +408,7 @@ 自分のプライバシーを傷つけると気がつきました 以前とは考えが変わりました。今後は公衆の場で自分の画像を公開したくありません 残念ですがこの画像は百科事典の目的に合いません - 私本人が%1$sにアップロードし、%2$d件の記事で使用されました。 + 私本人が%1$sにアップロードし、%2$d件の記事で使用されました。 コモンズへようこそ!\n\n追加ボタンを押して、ぜひご自分のメディアの初投稿をしましょう。 カテゴリが選択されていません カテゴリを指定しない画像は使用されることがほとんどありません。ほんとうにカテゴリを選択しないまま作業を続けますか? diff --git a/app/src/main/res/values-krc/strings.xml b/app/src/main/res/values-krc/strings.xml index 81d8842ff..f8fb0e45b 100644 --- a/app/src/main/res/values-krc/strings.xml +++ b/app/src/main/res/values-krc/strings.xml @@ -409,7 +409,7 @@ Ташалыгъыма аман болгъанын ангыладым Сагъышымы тюрлендирдим, энди хар кимге кёрюннюгюмю излемейме Кечериксиз, бу сурат энциклопедия ючюн эс бёлюрча тюлдю - Кесим джюклеген %1$s сайтха джюкленди эмда %2$d статьяда хайырландырылды. + Кесим джюклеген %1$s сайтха джюкленди эмда %2$d статьяда хайырландырылды. Гёзеннге Хош Келигиз!\n\nКъош тиекге басыб биринчи медиагъызны джюклегиз. Категорияла Сайланмадыла Категориясыз суратла аз хайырланадыла. Категория сайламай бардырыргъа излегенигизге ишексизмисиз? diff --git a/app/src/main/res/values-kus/strings.xml b/app/src/main/res/values-kus/strings.xml index ede3cbe19..75447a96b 100644 --- a/app/src/main/res/values-kus/strings.xml +++ b/app/src/main/res/values-kus/strings.xml @@ -345,7 +345,7 @@ M tɛn\'ɛs ye di na an bɛ\'ɛd tisi m mɛŋ gu\'udim yɛla M tiaki m pʋtɛ\'ɛr, m pʋ lɛm bɔɔd ye di bɛ zin\'ikanɛ ka sɔ\' wʋsa na nyɛ ya\'asa Gafara footo kaŋa pʋ nar ye di bɛ encyclopedia - M kpɛ\'ɛsidinɛ %1$s m mɛŋ, ka nɔki tʋm %2$d atikil (nam) ni. + M kpɛ\'ɛsidinɛ %1$s m mɛŋ, ka nɔki tʋm %2$d atikil (nam) ni. Commons pʋ\'ʋsidif ken-ken!\n\nKpɛn\'ɛmi fʋ yiiga media dɔlisid fʋn na din paasim la. Fʋ pʋ gaŋ buudsi\'a Fʋ pʋ gaŋ banɛ nwan taaba diff --git a/app/src/main/res/values-lb/strings.xml b/app/src/main/res/values-lb/strings.xml index afca8fcd4..599970d92 100644 --- a/app/src/main/res/values-lb/strings.xml +++ b/app/src/main/res/values-lb/strings.xml @@ -134,7 +134,7 @@ Eroflueden Standardlizenz Viregen Titel a Beschreiwung benotzen - Faarfschema + Faarfscheema Attribution-ShareAlike 4.0 Attribution 4.0 CC Attribution-ShareAlike 3.0 @@ -295,6 +295,7 @@ Virufueren Richteg Äntwert Falsch Äntwert + Ass et an der Rei fir dëse Screenshot eropzelueden? App deelen Dréinen Keng Biller an dëser Géigend @@ -332,7 +333,7 @@ Ech hu gemierkt, datt et schlecht fir meng Privatsphär ass Ech hu meng Meenung geännert, ech wëll net méi, datt et ëffentlech siichtbar ass Pardon, dëst Bild ass net interessant fir eng Enzyklopedie - Vu mir selwer de(n) %1$s eropgelueden, benotzt a(n) %2$d Artikel(en). + Vu mir selwer de(n) %1$s eropgelueden, benotzt a(n) %2$d Artikel(en). Keng Kategorien erausgesicht Biller ouni Kategorië si meeschtens net benotzbar. Sidd Dir sécher, datt Dir weider maache wëllt ouni eng Kategorie auszewielen? Eroplueden ofbriechen diff --git a/app/src/main/res/values-lt/strings.xml b/app/src/main/res/values-lt/strings.xml index 04c1f931f..e148a0a20 100644 --- a/app/src/main/res/values-lt/strings.xml +++ b/app/src/main/res/values-lt/strings.xml @@ -396,7 +396,7 @@ Supratau, kad tai kenkia mano privatumui Persigalvojau, nebenoriu, kad tai būtų viešai matoma Atsiprašome, ši nuotrauka neįdomi enciklopedijai - Įkelta mano %1$s, naudojama %2$d straipsnyje(-iuose). + Įkelta mano %1$s, naudojama %2$d straipsnyje(-iuose). Sveiki atvykę į Vikiteką!\n\nĮkelkite pirmąjį failą bakstelėdami pridėjimo mygtuką. Nepasirinkta jokių kategorijų Vaizdai be kategorijų retai naudojami. Ar tikrai norite tęsti nepasirinkę kategorijų? diff --git a/app/src/main/res/values-mk/strings.xml b/app/src/main/res/values-mk/strings.xml index b3058b81e..a0d1dd6ef 100644 --- a/app/src/main/res/values-mk/strings.xml +++ b/app/src/main/res/values-mk/strings.xml @@ -413,7 +413,7 @@ Сфатив дека ќе ми ја наруши приватноста Се премислив. Не сакам повеќе да биде видлива За жал, сликава не е соодветна за енциклопедија - Подигнато од мене %1$s, кое се користи во %2$d статии. + Подигнато од мене %1$s, кое се користи во %2$d статии. Добре дојдовте на Ризницата!\n\nПодигнете ја вашата прва слика или снимка допирајќи го копчето за додавање. Нема избрано категории Некатегоризираните слики се слабо употребливи. Дали сигурно сакате да продолжите без да ставите категории? diff --git a/app/src/main/res/values-nb/strings.xml b/app/src/main/res/values-nb/strings.xml index 5bb18d8e9..81fb7030b 100644 --- a/app/src/main/res/values-nb/strings.xml +++ b/app/src/main/res/values-nb/strings.xml @@ -408,7 +408,7 @@ Jeg innså at det er dårlig for mitt personvern Jeg ombestemte meg, jeg ønsker ikke at det skal være offentlig synlig lenger Beklager, dette bildet har ingen ensyklopedisk interesse - Lastet opp av meg selv %1$s, brukt i %2$d artikkel/artikler. + Lastet opp av meg selv %1$s, brukt i %2$d artikkel/artikler. Velkommen til Commons!\n\nLast opp din første mediefil ved å trykke på legg til-knappen. Ingen kategorier valgt Bilder uten kategorier er sjelden nyttige. Er du sikker på at du vil fortsette uten å velge kategorier? diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml index b800a6c20..c4cad617e 100644 --- a/app/src/main/res/values-nl/strings.xml +++ b/app/src/main/res/values-nl/strings.xml @@ -435,7 +435,7 @@ Ik realiseerde me dat het slecht is voor mijn privacy Ik ben van gedachten veranderd, ik wil niet dat het nog publiekelijk zichtbaar is Sorry, deze foto is niet interessant voor een encyclopedie - Geüpload door mijzelf op %1$s, gebruikt in %2$d artikel(en). + Geüpload door mijzelf op %1$s, gebruikt in %2$d artikel(en). Welkom bij Commons!\n\nUpload je eerste media door op de knop Toevoegen te klikken. Geen categorieën geselecteerd Afbeeldingen zonder categorieën zijn zelden bruikbaar. Weet je zeker dat je verder wilt gaan zonder categorieën te selecteren? @@ -807,6 +807,7 @@ Overleg Schrijf iets over het item \'%1$s\'. Dit is openbaar zichtbaar. ‘%1$s’ bestaat niet meer, er kan nooit een foto van gemaakt worden. + ‘%1$s’ bevindt zich ergens anders. ‘%1$s’ bevindt zich ergens anders. Geef hieronder de juiste plaats aan en noteer, indien mogelijk, de juiste breedte- en lengtegraad. Ander probleem of andere informatie (verklaar hieronder). Uw feedback wordt op de volgende wikipagina geplaatst: <a href=\"https://commons.wikimedia.org/wiki/Commons:Mobile_app/Feedback\">Commons:Mobile app/Feedback</a> diff --git a/app/src/main/res/values-nqo/strings.xml b/app/src/main/res/values-nqo/strings.xml index f7ddc958f..99923ca5f 100644 --- a/app/src/main/res/values-nqo/strings.xml +++ b/app/src/main/res/values-nqo/strings.xml @@ -360,7 +360,7 @@ ߒ ߧߴߊ߬ ߖߊ߬ߕߋ߬ ߟߊ߫ ߒߞߏ߫ ߊ߬ ߡߊ߲ߘߌ߫ ߒ ߖߘߍ߬ߞߊ߬ߣߌ߲߬ ߞߏ ߟߎ߫ ߟߊ߫. ߒ ߓߘߊ߫ ߒ ߡߙߌߦߊ ߡߊߝߊ߬ߟߋ߲߬߸ ߒ ߕߴߊ߬ ߝߵߊ߬ ߦߋ߫ ߜߍߘߐ߫ ߦߋߕߊ߫ ߘߴߏ߬ ߞߐ߫ ߡߎ߰ߡߍ߫ ߤߊߞߍ߬ߕߏ߬ ߔߘߋߞߎ ߘߐ߱ߘߏ߲߬ߣߍ߲߫ ߕߍ߫ ߖߌ߬ߦߊ߬ߓߍ ߣߌ߲߬ ߠߊ߫ - ߡߍ߲ ߠߎ߬ ߟߊߦߟߍ߬ߣߍ߲߬ ߦߋ߫ ߒ ߖߘߍ߬ߞߊߣߌ߲ ߓߟߏ߫ %1$s ߟߊ߫߸ ߣߴߊ߬ ߟߊߓߊ߯ߙߊߣߍ߲߫ ߦߋ߫ %2$d ߞߎߡߘߊ (ߟߎ߬) ߘߐ߫. + ߡߍ߲ ߠߎ߬ ߟߊߦߟߍ߬ߣߍ߲߬ ߦߋ߫ ߒ ߖߘߍ߬ߞߊߣߌ߲ ߓߟߏ߫ %1$s ߟߊ߫߸ ߣߴߊ߬ ߟߊߓߊ߯ߙߊߣߍ߲߫ ߦߋ߫ %2$d ߞߎߡߘߊ (ߟߎ߬) ߘߐ߫. ߌ ߣߌ߫ ߛߣߍ߫ ߞߐߡߐ߲ߛ ߞߊ߲߬߹ \nߌ ߟߊ߫ ߡߋߘߌߦߊ߫ ߝߟߐ ߟߊߦߟߍ߬ ߝߙߊ߬ߟߌ ߞߎ߬ߘߎ ߛߐ߲߬ߞߌ߲ ߠߊ߫. ߦߌߟߡߊ߫ ߡߊ߫ ߓߊߕߐ߬ߡߐ߲߬ ߦߌߟߡߊ߫ ߕߍ߫ ߖߌ߬ߦߊ߬ߓߍ ߡߍ߲ ߠߊ߫߸ ߏ߬ ߟߊߓߊ߯ߙߊ ߜߟߍ߬ߡߊ߲߫. ߌ ߦߴߊ߬ ߝߍ߬ ߞߵߊ߬ ߞߘߊߡߊ߫ ߓߊ߬ ߞߵߊ߬ ߕߘߍ߬ ߌ ߡߊ߫ ߦߌߟߡߊ ߘߏ߫ ߓߊߕߐ߬ߡߐ߲߬؟ diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index 29cbf44c9..198b57c7f 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -450,7 +450,7 @@ Zdałem sobie sprawę, że jest to szkodliwe dla mojej prywatności Zmieniłem zdanie, nie chcę, aby było to już publicznie widoczne Przepraszamy, to zdjęcie nie jest interesujące dla encyklopedii - Przesłane przeze mnie na %1$s, używane w artykułach %2$d. + Przesłane przeze mnie na %1$s, używane w artykułach %2$d. Prześlij swoje pierwsze multimedia, dotykając przycisku Dodaj. Nie wybrano kategorii Obrazy bez kategorii rzadko nadają się do użycia. Czy na pewno chcesz kontynuować bez wybierania kategorii? diff --git a/app/src/main/res/values-pms/strings.xml b/app/src/main/res/values-pms/strings.xml index b0ecdcfe1..9b12b3989 100644 --- a/app/src/main/res/values-pms/strings.xml +++ b/app/src/main/res/values-pms/strings.xml @@ -411,7 +411,7 @@ I l\'hai pensa ch\'a l\'era nen bon për mia arservatëssa I l\'hai cangià d\'idèja, i veui pi nen ch\'a sia visìbil ëd fasson pùblica Am dëspias, ma costa plancia a l\'é nen anteressanta për n\'enciclopedìa - Carià da mi-midem ai %1$s, dovrà an %2$d artìcoj. + Carià da mi-midem ai %1$s, dovrà an almanch %2$d artìcoj. Bin-ëvnù su Commons!\n\nCh\'a caria sò prim archivi multimedial an sgnacand an sël boton për gionté. Gnun-a categorìa selessionà Le plance sensa categorìa, a so da ràir dovràbij. É-lo sigur ëd vorèj continué sensa serne dle categorìe? @@ -821,4 +821,5 @@ Smon-e andrinta a Nearby Creà e carià da: %1$s Creà da %1$s e carià da %2$s + Nominà për esse dëscancelà diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index 947d65ace..7f45ab484 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -427,7 +427,7 @@ Eu percebi que é ruim para minha privacidade Eu mudei de ideia, eu não quero mais que seja publicamente visível Desculpe, esta foto não é interessante para uma enciclopédia - Carregada por mim em %1$s, usada em %2$d artigo(s). + Carregada por mim em %1$s, usada em %2$d artigo(s). Bem-vindo ao Commons!\n\nCarregue sua primeira mídia tocando no botão Adicionar. Nenhuma categoria selecionada Imagens sem categorias raramente são utilizáveis. Tem certeza de que deseja continuar sem selecionar categorias? diff --git a/app/src/main/res/values-pt/strings.xml b/app/src/main/res/values-pt/strings.xml index 15c5983c4..f2153caa6 100644 --- a/app/src/main/res/values-pt/strings.xml +++ b/app/src/main/res/values-pt/strings.xml @@ -423,7 +423,7 @@ Apercebi-me de que prejudica a minha privacidade Mudei de ideias, já não quero possa ser vista pelo público Desculpe, esta fotografia não tem interesse para uma enciclopédia - Carregada por mim em %1$s, usada em %2$d artigo(s). + Carregada por mim em %1$s, usada em %2$d artigo(s). Bem-vindo(a) à wiki Commons!\n\nCarregue o seu primeiro ficheiro multimédia tocando no botão Adicionar. Não foi selecionada nenhuma categoria As imagens sem categorias só raramente são utilizáveis. Tem a certeza de que deseja continuar sem selecionar categorias? diff --git a/app/src/main/res/values-ro/strings.xml b/app/src/main/res/values-ro/strings.xml index 550f09968..602fb69bf 100644 --- a/app/src/main/res/values-ro/strings.xml +++ b/app/src/main/res/values-ro/strings.xml @@ -394,7 +394,7 @@ Mi-am dat seama că este rău pentru intimitatea mea M-am răzgândit, nu mai vreau să fie publică Ne pare rău că această imagine nu este interesantă pentru o enciclopedie - Încărcat de mine pe %1$s, folosit în %2$d articol(e). + Încărcat de mine pe %1$s, folosit în %2$d articol(e). Bine ați venit la Commons!\n\nÎncărcați primul dvs. media apăsând pe butonul de adăugare. Nici o categorie selectată Imaginile fără categorii sunt rareori utilizabile. Sigur doriți să continuați fără a selecta categorii? diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index ecef5c74b..7a0e1c247 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -470,7 +470,7 @@ Я осознал, что это разглашает мою приватность Я передумал. Больше не хочу чтобы было доступным публично Извините, это изображение не для энциклопедии - Загружено мною на сайт «%1$s» и использовано в {{PLURAL:%2$d|one=одной статье|%2$d статьях}}. + Загружено мною на сайт «%1$s» и использовано в {{PLURAL:%2$d|one=одной статье|%2$d статьях}}. Добро пожаловать на Викисклад!\n\nЗагрузите ваш первый файл, нажав на кнопку добавления. Не выбраны категории Изображения без категорий используются редко. Вы уверены, что хотите продолжить, не выбрав категории? diff --git a/app/src/main/res/values-sk/strings.xml b/app/src/main/res/values-sk/strings.xml index 5def2523d..cbaca17c5 100644 --- a/app/src/main/res/values-sk/strings.xml +++ b/app/src/main/res/values-sk/strings.xml @@ -423,7 +423,7 @@ Uvedomil/a som si, že je to zlé pre moje súkromie Zmenil/a som názor, nechcem byť viac verejne viditeľný/á Prepáčte, tento obrázok pre encyklopédiu nie je zaujímavý - Nahrané mnou %1$s, použité v %2$d článku/článkoch. + Nahrané mnou %1$s, použité v %2$d článku/článkoch. Vitajte na Commons!\n\nNahrajte svoje prvé súbory ťuknutím na tlačidlo pridať. Neboli vybrané žiadne kategórie Obrázky bez kategórií sú zriedka použiteľné. Naozaj chcete nahrať obrázok bez výberu kategórií? diff --git a/app/src/main/res/values-sl/strings.xml b/app/src/main/res/values-sl/strings.xml index d81d5ba73..ebcfba109 100644 --- a/app/src/main/res/values-sl/strings.xml +++ b/app/src/main/res/values-sl/strings.xml @@ -429,7 +429,7 @@ Spoznal sem, da je to slabo za mojo zasebnost Premislil_a sem si, ne želim več biti javno viden_na Ta slika žal ni zanimiva za enciklopedijo. - Sliko sem naložil/a sam/a dne %1$s. Uporablja se v %2$d članku(ih). + Sliko sem naložil/a sam/a dne %1$s. Uporablja se v %2$d članku(ih). Pozdravljeni v Wikimedijini zbirki!\n\nTapnite gumb dodaj in naložite svojo prvo predstavnostno datoteko. Izbrana ni nobena kategorija Slike brez kategorij so le redko uporabne. Ali res želite nadaljevati brez izbire kategorij? diff --git a/app/src/main/res/values-sr/strings.xml b/app/src/main/res/values-sr/strings.xml index cb09f2f80..a41096306 100644 --- a/app/src/main/res/values-sr/strings.xml +++ b/app/src/main/res/values-sr/strings.xml @@ -409,7 +409,7 @@ Схватио/ла сам да је лоша за моју приватност Променио/ла сам мишљење, не желим да више јавно буду видљиве Ова слика није занимљива за енциклопедију - Отпремио/ла сам на %1$s, користи се у чланку/цима — %2$d. + Отпремио/ла сам на %1$s, користи се у чланку/цима — %2$d (бар). Добро дошли на Оставу!\n\nОтпремите прве медије додиром дугмета за додавање. Категорије нису изабране Слике без категорија ретко су употребљиве. Заиста желите да наставите без избора категорија? @@ -751,4 +751,5 @@ Поднапис копиран Направио и отпремио: %1$s Направио %1$s а отпремио %2$s + Номинуј за брисање diff --git a/app/src/main/res/values-sv/strings.xml b/app/src/main/res/values-sv/strings.xml index 28a0896c0..740304f7c 100644 --- a/app/src/main/res/values-sv/strings.xml +++ b/app/src/main/res/values-sv/strings.xml @@ -420,7 +420,7 @@ Jag insåg att den är dålig för mitt privatliv Jag ändrade mig, jag vill inte längre att den ska vara synlig offentligt Tyvärr, denna bild är inte intressant för en encyklopedi - Laddades upp av mig den %1$s och används i %2$d artiklar. + Laddades upp av mig den %1$s och används i %2$d artiklar. Välkommen till Commons!\n\nLadda upp din första mediafil genom att trycka på knappen för att lägga till. Inga kategorier har valts Bilder utan kategorier används sällan. Är du säker på att du vill fortsätta utan att välja kategorier? diff --git a/app/src/main/res/values-te/strings.xml b/app/src/main/res/values-te/strings.xml index ba67a7b35..0d4b323f4 100644 --- a/app/src/main/res/values-te/strings.xml +++ b/app/src/main/res/values-te/strings.xml @@ -377,7 +377,7 @@ నా అంతరంగికతకు ఇది చేటు అని గుర్తించాను నేణు మనసు మార్చుకున్నాను, బహిరంగంగా అందరికీ కనబడేలా ఉండను సారీ, ఈ బొమ్మ విజ్ఞాన సర్వస్వానికి ఆసక్తి కలిగేలా లేదు - %1$s న నేనే ఎక్కించాను, %2$d వ్యాసాల్లో వాడారు. + %1$s న నేనే ఎక్కించాను, %2$d వ్యాసాల్లో వాడారు. కామన్స్‌కు స్వాగతం!\n\nచేర్చు బొత్తాన్ని నొక్కి మీ మొదటి మీడియాను ఎక్కించండి. వర్గాలేమీ ఎంచుకోలేదు వర్గాల్లేని బొమ్మలను అరుదుగా వాడగలం. వర్గాలేమీ ఎంచుకోకుండానే కొనసాగాలని అనుకుంటున్నారా? diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml index 2e2b13216..c741e89c4 100644 --- a/app/src/main/res/values-tr/strings.xml +++ b/app/src/main/res/values-tr/strings.xml @@ -442,7 +442,7 @@ Gizliliğimin kötü olduğunu fark ettim Fikrimi değiştirdim, artık herkese görünür olmasını istemiyorum Üzgünüz, bu resim bir ansiklopedi için ilginç değil - Kendi başıma %1$s üzerine yüklendi, %2$d makalede kullanıldı. + Kendi başıma %1$s üzerine yüklendi, %2$d makalede kullanıldı. Commons\'a Hoş Geldiniz!\n\nEkle düğmesine dokunarak ilk medyanızı yükleyin. Kategori Seçilmedi Kategorisiz görüntüler nadiren kullanılabilir. Kategori seçmeden devam etmek istediğinizden emin misiniz? diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index c457636ff..f005f2969 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -435,7 +435,7 @@ Мені стало зрозуміло, що це шкодить моїй приватності Моя думка змінилась, я не хочу, щоб це було доступно публічно Перепрошую, це зображення нецікаве для енциклопедії - Завантажено мною на сайт «%1$s» та використано у {{PLURAL:%2$d|one=одній статті|%2$d статтях}}. + Завантажено мною на сайт «%1$s» та використано у {{PLURAL:%2$d|one=одній статті|%2$d статтях}}. Ласкаво просимо до Вікісховища!\n\nЗавантажте Ваш перший медіафайл, натиснувши кнопку додавання. Жодної категорії не вибрано Зображення без категорій рідко використовуються. Ви впевнені, що хочете продовжити без вказаних категорій? diff --git a/app/src/main/res/values-vec/strings.xml b/app/src/main/res/values-vec/strings.xml index 66905e758..17765b3ce 100644 --- a/app/src/main/res/values-vec/strings.xml +++ b/app/src/main/res/values-vec/strings.xml @@ -344,7 +344,7 @@ Me so rendesto conto che ła xé on małe par ła me privacy Go canbià idea, no vujo pì che ła sia vardabiłe da tuti Ne despiaxe, sta imajine no ła xé intaresante par na ençiclopedia. - Cargà da mi el %1$s, doparà in %2$d voxe. + Cargà da mi el %1$s, doparà in %2$d voxe. Benvegnuo so Commons!\n\nCarga el to primo file multimediałe strucando el boton \"xonta\". Nisuna categoria sełesionà Le imajini sensa categorie łe xé poche olte doparabiłi. Sito seguro de vołer enviar sensa sełesionar categorie? diff --git a/app/src/main/res/values-x-invalidLanguageCode/error.xml b/app/src/main/res/values-x-invalidLanguageCode/error.xml new file mode 100644 index 000000000..f4e2fe125 --- /dev/null +++ b/app/src/main/res/values-x-invalidLanguageCode/error.xml @@ -0,0 +1,10 @@ + + + + کامَنٕز گوو رُکِتھ + Oops. کیہہ تام گوو غلط! + ؤنِیوٚ اَسہِ توٚہہِ کیاہ ٲسِیوٚ کران، تہٕ کٕریٚو تہِ اَسہِ سٕتی شیر بذریعہِ برقی خط. یُس مَدَتھ کَرِ اَسہِ اَتھ شہَرنَس منٛز! + شُکریہ! + diff --git a/app/src/main/res/values-xmf/strings.xml b/app/src/main/res/values-xmf/strings.xml index 3f9b0e59f..649cab67d 100644 --- a/app/src/main/res/values-xmf/strings.xml +++ b/app/src/main/res/values-xmf/strings.xml @@ -375,7 +375,7 @@ მიბრჩქინე, ნამჷდა თენა ჩქიმი კონფიდენციალურალაშო გლახა იჸუაფუდჷნ არზი დიბთირე დო შუროთ ვამოკო თინა ოჯარალეთ იძირებედასჷნ მორდება, ათე სურათი ენციკლოპედიაშო ვა რე საინტერესო - ჩქიმი ენახარგა რე %1$s-შა, გჷმორინაფილი რე %2$d სტატიას. + ჩქიმი ენახარგა რე %1$s-შა, გჷმორინაფილი რე %2$d სტატიას. მოზოჯით ვიკიოწკარუეშა!\n\nგეხარგეთ თქვანი პირველი ფაილი, ქეგუნჭირით კონჭის გეძინა. კატეგორია ვა რე გიშაგორილი სურათეფი კატეგორიზაციაშ უმუშო შხირას მერკეთ გჷმორინაფონი რე. დასურო გონებჷნანო კატეგორიეფიშ მეწურაფაშ უმუშო გაგჷნძარაფა? diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index 0434441c8..5c35be3e6 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -436,7 +436,7 @@ 我認為這會干擾到我的隱私 我改變我的主意,我不想要公開可見 真抱歉,此圖片對於百科全書沒有意義 - 我自己在%1$s上上傳,在%2$d篇條目中使用。 + 我自己在%1$s上上傳,在%2$d篇條目中使用。 歡迎來到維基共享資源!\n\n透過觸碰添加按鈕來上傳您的首個多媒體內容。 未選擇分類 不帶分類的圖片很難有機會被利用到,您確定您要不選擇分類來繼續嗎? diff --git a/app/src/main/res/values-zh/strings.xml b/app/src/main/res/values-zh/strings.xml index 930c9e4fb..452e54563 100644 --- a/app/src/main/res/values-zh/strings.xml +++ b/app/src/main/res/values-zh/strings.xml @@ -470,7 +470,7 @@ 我意识到这对我的隐私不利 我改变了主意,我不想再让公众看到它了 对不起,这幅图对百科全书没什么意思 - 由我自己上传在%1$s,使用于%2$d个条目。 + 由我自己上传在%1$s,使用于%2$d个条目。 欢迎使用共享资源!\n\n通过点击添加按钮以上传您的首个媒体。 未提交分类 不带分类的图片很难有机会被利用到,您确定您要不选择分类来继续吗? From 9a94dc2548aa54cf994773ee6308fd0a038b9029 Mon Sep 17 00:00:00 2001 From: Jason-Whitmore Date: Sun, 29 Jun 2025 02:30:10 -0700 Subject: [PATCH 039/162] Fixes Issue 6312: GPS has huge error and does not update (in Nearby) (#6352) * NearbyParentFragment.kt: add helper methods for user location overlays and accuracy data. Before this commit, the code used to create the user location overlays was in multiple places. Additionally, there was no easy way to access the location accuracy. This commit places the user location overlay creation code into helper methods, as well as adding a new location accuracy getter method. These methods can now be used to refactor other parts of the file. * NearbyParentFragment.kt: create method to update user location overlays Before this commit, there was no easy way to update the user location overlays. This commit adds the updateUserLocationOverlays() method, which will properly replace the old user location overlays with new ones. It will also add the overlays if they do not already exist. * NearbyParentFragment.kt: replace old code with calls to updateUserLocationOverlays() This commit completes the refactor and fixes the issue of the user overlays not updating. The new method updateUserLocationOverlays is called to refactor and simplify old code. * Removal of file is not related to the issue, but is needed for project to compile and run. * NearbyParentFragment.kt: fix bug where multiple user location overlays would appear Before this commit, the user could see multiple user location overlays if they paused the app and reopened it when there are no Places/pins on the map. This was caused by a linear search failing to identify the target overlay because it compared Drawables between two Overlays, which was unreliable. This commit contains a better solution for replacing existing user location overlays by adding 2 instance variables to keep track of the overlays. The position of these overlays in the overlay list can then be found by using indexOf() with these instance variables rather than the linear search that was implemented before. Some refactoring was also done. --------- Co-authored-by: Nicolas Raoul --- .../nearby/fragments/NearbyParentFragment.kt | 226 ++++++++++++------ 1 file changed, 154 insertions(+), 72 deletions(-) diff --git a/app/src/main/java/fr/free/nrw/commons/nearby/fragments/NearbyParentFragment.kt b/app/src/main/java/fr/free/nrw/commons/nearby/fragments/NearbyParentFragment.kt index 5b52c0ce5..26875927e 100644 --- a/app/src/main/java/fr/free/nrw/commons/nearby/fragments/NearbyParentFragment.kt +++ b/app/src/main/java/fr/free/nrw/commons/nearby/fragments/NearbyParentFragment.kt @@ -123,6 +123,7 @@ import org.osmdroid.views.CustomZoomButtonsController import org.osmdroid.views.MapView import org.osmdroid.views.overlay.MapEventsOverlay import org.osmdroid.views.overlay.Marker +import org.osmdroid.views.overlay.Overlay import org.osmdroid.views.overlay.ScaleBarOverlay import org.osmdroid.views.overlay.ScaleDiskOverlay import org.osmdroid.views.overlay.TilesOverlay @@ -267,6 +268,9 @@ class NearbyParentFragment : CommonsDaggerSupportFragment(), private var dataList: MutableList? = null private var bottomSheetAdapter: BottomSheetAdapter? = null + private var userLocationOverlay: Overlay? = null + private var userLocationErrorOverlay: Overlay? = null + private val galleryPickLauncherForResult = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> controller?.handleActivityResultWithCallback( @@ -724,7 +728,7 @@ class NearbyParentFragment : CommonsDaggerSupportFragment(), val targetP = GeoPoint(target.latitude, target.longitude) mapCenter = targetP binding?.map?.controller?.setCenter(targetP) - recenterMarkerToPosition(targetP) + updateUserLocationOverlays(targetP, true) if (!isCameFromExploreMap()) { moveCameraToPosition(targetP) } @@ -1863,6 +1867,8 @@ class NearbyParentFragment : CommonsDaggerSupportFragment(), lastKnownLocation = latLng NearbyController.currentLocation = lastKnownLocation presenter!!.updateMapAndList(locationChangeType) + + updateUserLocationOverlays(GeoPoint(latLng.latitude, latLng.longitude), true) } override fun onLocationChangedSignificantly(latLng: LatLng) { @@ -2644,43 +2650,14 @@ class NearbyParentFragment : CommonsDaggerSupportFragment(), */ override fun clearAllMarkers() { binding!!.map.overlayManager.clear() - binding!!.map.invalidate() - val geoPoint = mapCenter - if (geoPoint != null) { - val diskOverlay = - ScaleDiskOverlay( - this.context, - geoPoint, 2000, UnitOfMeasure.foot - ) - val circlePaint = Paint() - circlePaint.color = Color.rgb(128, 128, 128) - circlePaint.style = Paint.Style.STROKE - circlePaint.strokeWidth = 2f - diskOverlay.setCirclePaint2(circlePaint) - val diskPaint = Paint() - diskPaint.color = Color.argb(40, 128, 128, 128) - diskPaint.style = Paint.Style.FILL_AND_STROKE - diskOverlay.setCirclePaint1(diskPaint) - diskOverlay.setDisplaySizeMin(900) - diskOverlay.setDisplaySizeMax(1700) - binding!!.map.overlays.add(diskOverlay) - val startMarker = Marker( - binding!!.map - ) - startMarker.position = geoPoint - startMarker.setAnchor( - Marker.ANCHOR_CENTER, - Marker.ANCHOR_BOTTOM - ) - startMarker.icon = - getDrawable( - this.requireContext(), - fr.free.nrw.commons.R.drawable.current_location_marker - ) - startMarker.title = "Your Location" - startMarker.textLabelFontSize = 24 - binding!!.map.overlays.add(startMarker) + + var geoPoint = mapCenter + val lastLatLng = locationManager.getLastLocation() + if (lastLatLng != null) { + geoPoint = GeoPoint(lastLatLng.latitude, lastLatLng.longitude) } + updateUserLocationOverlays(geoPoint, false) + val scaleBarOverlay = ScaleBarOverlay(binding!!.map) scaleBarOverlay.setScaleBarOffset(15, 25) val barPaint = Paint() @@ -2690,6 +2667,7 @@ class NearbyParentFragment : CommonsDaggerSupportFragment(), binding!!.map.overlays.add(scaleBarOverlay) binding!!.map.overlays.add(mapEventsOverlay) binding!!.map.setMultiTouchControls(true) + binding!!.map.invalidate() } /** @@ -2700,45 +2678,149 @@ class NearbyParentFragment : CommonsDaggerSupportFragment(), private fun recenterMarkerToPosition(geoPoint: GeoPoint?) { geoPoint?.let { binding?.map?.controller?.setCenter(it) - val overlays = binding?.map?.overlays ?: return@let - // Remove markers and disks using index-based removal - var i = 0 - while (i < overlays.size) { - when (overlays[i]) { - is Marker, is ScaleDiskOverlay -> overlays.removeAt(i) - else -> i++ - } - } - - // Add disk overlay - ScaleDiskOverlay(context, it, 2000, UnitOfMeasure.foot).apply { - setCirclePaint2(Paint().apply { - color = Color.rgb(128, 128, 128) - style = Paint.Style.STROKE - strokeWidth = 2f - }) - setCirclePaint1(Paint().apply { - color = Color.argb(40, 128, 128, 128) - style = Paint.Style.FILL_AND_STROKE - }) - setDisplaySizeMin(900) - setDisplaySizeMax(1700) - overlays.add(this) - } - - // Add marker - Marker(binding?.map).apply { - position = it - setAnchor(Marker.ANCHOR_CENTER, Marker.ANCHOR_BOTTOM) - icon = getDrawable(context, R.drawable.current_location_marker) - title = "Your Location" - textLabelFontSize = 24 - overlays.add(this) - } + updateUserLocationOverlays(it, true); } } + /** + * Updates the user current location overlays (both the location and error overlays) by + * replacing any existing location overlays with new overlays at the given GeoPoint. If there + * are no existing location and error overlays, then new overlays are added. + * + * @param geoPoint The GeoPoint representing the user's current location. + * @param invalidate If true, the map overlays will be invalidated after the user + * location overlays are updated/added. If false, the overlays will not be invalidated. + */ + private fun updateUserLocationOverlays(geoPoint: GeoPoint?, invalidate: Boolean) { + geoPoint?.let{ + updateUserLocationOverlay(geoPoint) + updateUserLocationErrorOverlay(geoPoint) + } + + if (invalidate) { + binding!!.map.invalidate() + } + } + + /** + * Updates the user location error overlay by either replacing it with or adding a new one. + * + * If the user location error overlay is null, the new overlay is added. If the + * overlay is not null, it is replaced by the new overlay. + * + * @param geoPoint The GeoPoint representing the user's location + */ + private fun updateUserLocationErrorOverlay(geoPoint: GeoPoint) { + val overlays = binding?.map?.overlays ?: return + + // Multiply accuracy by 2 to get 95% confidence interval + val accuracy = getCurrentLocationAccuracy() * 2 + val overlay = createCurrentLocationErrorOverlay(this.context, geoPoint, + (accuracy).toInt(), UnitOfMeasure.meter) + + val index = overlays.indexOf(userLocationErrorOverlay) + + if (userLocationErrorOverlay == null || index == -1) { + overlays.add(overlay) + } else { + overlays[index] = overlay + } + + userLocationErrorOverlay = overlay + } + + /** + * Updates the user location overlay by either replacing it with or adding a new one. + * + * If the user location overlay is null, the new overlay is added. If the + * overlay is not null, it is replaced by the new overlay. + * + * @param geoPoint The GeoPoint representing the user's location + */ + private fun updateUserLocationOverlay(geoPoint: GeoPoint) { + val overlays = binding?.map?.overlays ?: return + + val overlay = createCurrentLocationOverlay(geoPoint) + + val index = overlays.indexOf(userLocationOverlay) + + if (userLocationOverlay == null || index == -1) { + overlays.add(overlay) + } else { + overlays[index] = overlay + } + + userLocationOverlay = overlay + } + + /** + * @return The accuracy of the current location with a confidence at the 68th percentile. + * Units are in meters. Returning 0 may indicate failure. + */ + private fun getCurrentLocationAccuracy(): Float { + var accuracy = 0f + val lastLocation = locationManager.getLastLocation() + if (lastLocation != null) { + accuracy = lastLocation.accuracy + } + + return accuracy + } + + /** + * Creates the current location overlay + * + * @param geoPoint The GeoPoint where the current location overlay will be placed. + * + * @return The current location overlay as a Marker + */ + private fun createCurrentLocationOverlay(geoPoint: GeoPoint): Marker { + val currentLocationOverlay = Marker( + binding!!.map + ) + currentLocationOverlay.position = geoPoint + currentLocationOverlay.icon = + getDrawable( + this.requireContext(), + fr.free.nrw.commons.R.drawable.current_location_marker + ) + currentLocationOverlay.title = "Your Location" + currentLocationOverlay.textLabelFontSize = 24 + currentLocationOverlay.setAnchor(0.5f, 0.5f) + + return currentLocationOverlay + } + + /** + * Creates the location error overlay to show the user how accurate the current location + * overlay is. The edge of the disk is the 95% confidence interval. + * + * @param context The Android context + * @param point The user's location as a GeoPoint + * @param value The radius of the disk + * @param unitOfMeasure The unit of measurement of the value/disk radius. + * + * @return The location error overlay as a ScaleDiskOverlay. + */ + private fun createCurrentLocationErrorOverlay(context: Context?, point: GeoPoint, value: Int, + unitOfMeasure: UnitOfMeasure): ScaleDiskOverlay { + val scaleDisk = ScaleDiskOverlay(context, point, value, unitOfMeasure) + + scaleDisk.setCirclePaint2(Paint().apply { + color = Color.rgb(128, 128, 128) + style = Paint.Style.STROKE + strokeWidth = 2f + }) + + scaleDisk.setCirclePaint1(Paint().apply { + color = Color.argb(40, 128, 128, 128) + style = Paint.Style.FILL_AND_STROKE + }) + + return scaleDisk + } + private fun moveCameraToPosition(geoPoint: GeoPoint) { binding!!.map.controller.animateTo(geoPoint) } From 27b9d70333de121b10e8ba63b7ce1e81f4320fd6 Mon Sep 17 00:00:00 2001 From: "translatewiki.net" Date: Sun, 29 Jun 2025 20:27:27 +0200 Subject: [PATCH 040/162] Localisation updates from https://translatewiki.net. --- app/src/main/res/values-ar/strings.xml | 3 ++- app/src/main/res/values-b+tg+Cyrl/strings.xml | 3 ++- app/src/main/res/values-bn/strings.xml | 1 + app/src/main/res/values-fa/strings.xml | 3 ++- app/src/main/res/values-fr/strings.xml | 3 ++- app/src/main/res/values-ia/strings.xml | 2 +- app/src/main/res/values-it/strings.xml | 1 + app/src/main/res/values-iw/strings.xml | 4 ++-- app/src/main/res/values-lb/strings.xml | 3 ++- app/src/main/res/values-nl/strings.xml | 3 ++- app/src/main/res/values-ru/strings.xml | 3 ++- .../main/res/values-x-invalidLanguageCode/error.xml | 10 ---------- 12 files changed, 19 insertions(+), 20 deletions(-) delete mode 100644 app/src/main/res/values-x-invalidLanguageCode/error.xml diff --git a/app/src/main/res/values-ar/strings.xml b/app/src/main/res/values-ar/strings.xml index daa5e9b1c..b1d805ec7 100644 --- a/app/src/main/res/values-ar/strings.xml +++ b/app/src/main/res/values-ar/strings.xml @@ -469,7 +469,7 @@ أدركت أنه سيئ لخصوصيتي لقد غيرت رأيي، ولا أريد أن يكون مرئيا للجميع بعد الآن آسف هذه الصورة ليست مثيرة للاهتمام لموسوعة - رفعته بنفسي في %1$s، مستخدم في %2$d مقالة(ات). + تم تحميله بواسطة نفسي على %1$s، وتم استخدامه في %2$d مقالة على الأقل. مرحبا بك في كومنز! \n\nارفع الوسائط الأولى عن طريق النقر على زر الإضافة. لا توجد تصنيفات مختارة نادرًا ما تكون الصور الخالية من التصنيفات قابلة للاستخدام، هل أنت متأكد أنك تريد الإرسال دون تحديد التصنيفات؟ @@ -893,4 +893,5 @@ عرض في المناطق القريبة تم الإنشاء والتحميل بواسطة: %1$s تم إنشاؤه بواسطة %1$s وتم تحميله بواسطة %2$s + مرشح للحذف diff --git a/app/src/main/res/values-b+tg+Cyrl/strings.xml b/app/src/main/res/values-b+tg+Cyrl/strings.xml index 5ab1ab282..3404183dc 100644 --- a/app/src/main/res/values-b+tg+Cyrl/strings.xml +++ b/app/src/main/res/values-b+tg+Cyrl/strings.xml @@ -1,5 +1,6 @@ - - کامَنٕز گوو رُکِتھ - Oops. کیہہ تام گوو غلط! - ؤنِیوٚ اَسہِ توٚہہِ کیاہ ٲسِیوٚ کران، تہٕ کٕریٚو تہِ اَسہِ سٕتی شیر بذریعہِ برقی خط. یُس مَدَتھ کَرِ اَسہِ اَتھ شہَرنَس منٛز! - شُکریہ! - From 6de5a07e0dde9900de2e9f2236894b1f346da60a Mon Sep 17 00:00:00 2001 From: "translatewiki.net" Date: Mon, 30 Jun 2025 14:01:39 +0200 Subject: [PATCH 041/162] Localisation updates from https://translatewiki.net. --- app/src/main/res/values-az/strings.xml | 50 +++++++++++++++++++++++--- 1 file changed, 45 insertions(+), 5 deletions(-) diff --git a/app/src/main/res/values-az/strings.xml b/app/src/main/res/values-az/strings.xml index 1662c2301..c498f23f5 100644 --- a/app/src/main/res/values-az/strings.xml +++ b/app/src/main/res/values-az/strings.xml @@ -44,30 +44,63 @@ (%1$d) Yükləmələrə Başlanılır + + %d yükləmə emal edilir + %d yükləmə emal edilir + + + %d yükləmə + %d yükləmə + + + Bu şəkil %1$s lisenziyası altında yayımlanacaq + Bu şəkillər %1$s lisenziyası altında yayımlanacaq + + + %1$d yükləmə + %1$d yükləmə + + + Paylaşılan məzmun qəbul edilir. Şəklin emalı şəklin ölçüsündən və cihazınızdan asılı olaraq bir az vaxt apara bilər + Paylaşılan məzmun qəbul edilir. Şəkillərin emalı şəklin ölçüsündən və cihazınızdan asılı olaraq bir az vaxt apara bilər + + Kəşf et + Görünüş Ümumi + Rəy Məxfilik Vikianbar Tənzimləmələr + Vikianbara yüklə + Yükləmə davam edir İstifadəçi adı Parol + Commons Beta hesabınıza daxil olun Daxil ol + Şifrəni unutmusunuz? Qeydiyyatdan keç Giriş edilir Zəhmət olmasa, gözləyin… + Başlıqların və təsvirlərin yenilənməsi + Zəhmət olmasa, gözləyin… Uğurlu giriş! Giriş baş tutmadı! Fayl tapılmadı. Xahiş edirik başqa bir fayl üzərində cəhd edin. Maksimum təkrar cəhd limitinə çatdınız! Zəhmət olmasa, yükləməni ləğv edin və yenidən cəhd edin Batareya optimallaşdırılması söndürülsün? - Doğrulama alınmadı, xahiş edirəm yenidən daxil olun + 3-dən çox şəklin yüklənməsi batareyanın optimallaşdırılması söndürüldükdə daha yaxşı işləyir. Rahat yükləmə təcrübəsi üçün Vikianbar tətbiqi üçün batareyanın optimallaşdırılmasını parametrlərdən söndürün. \n\nBatareyanın optimallaşdırılmasını söndürmək üçün mümkün addımlar:\n\nAddım 1: Aşağıdakı \"Parametrlər\" düyməsinə toxunun.\n\nAddım 2: \"Optimallaşdırılmayıb\"dan \"Bütün proqramlar\"a keçin.\n\nAddım 3: \"Commons\" və ya \"fr.free.nrw.commons\" axtarın.\n\nAddım 4: \"Optimallaşdırma\"nı seçin.\n\nAddım 5: \'Bitti\' düyməsini basın. + Doğrulama alınmadı. Zəhmət olmasa, yenidən daxil olun Yükləmə başladı! + Yükləmə növbədə (məhdud əlaqə rejimi aktivdir) %1$s yükləndi! Yükləmənizə baxmaq üçün toxunun - %1$s yüklənməsi başlanır + Fayl yüklənir: %s %1$s yüklənir %1$s yüklənməsi başa çatdı - %1$s faylının yüklənməsi alınmadı + %1$s yükləmək alınmadı + %1$s yüklənməsi dayandırıldı Baxmaq üçün toxun + Baxmaq üçün toxun Son Yükləmələrim Növbəyə alındı Uğursuz @@ -77,19 +110,26 @@ Foto çək Yaxınlıqdakılar Yükləmələrim + Keçidi kopiyala + Link kopyalandı. Paylaş + Faylın səhifəsinə bax Başlıq (Zəruri) + Zəhmət olmasa, bu fayl üçün başlıq təqdim et Açıqlama - Daxil olmaq olmur — şəbəkə xətası + Başlıq + Daxil olmaq mümkün deyil - şəbəkə xətası Çox sayda uğursuz daxil olma. Xahiş edirik bir neçə dəqiqə sonra yenidən cəhd edin. Bağışlayın, bu istifadəçi Vikianbardan bloklanıb Siz iki faktorlu autentifikasiya kodunuzu təqdim etməlisiniz. - Daxil olma uğursuz oldu + E-poçt ünvanınıza giriş doğrulama kodu göndərildi. Daxil olmaq üçün kodu daxil edin. + Daxil olma uğursuz oldu Yüklə Bu dəsti adlandırın Dəyişikliklər Yüklə Kateqoriyalarda axtar + Medianızın təsvir etdiyi elementləri axtarın (dağ, Tac Mahal və s.) Yadda saxla Yenilə Siyahı From 89436b0a753c8cde7eb3a3b4eabcbe155fd11182 Mon Sep 17 00:00:00 2001 From: Ritika Pahwa <83745993+RitikaPahwa4444@users.noreply.github.com> Date: Tue, 1 Jul 2025 11:52:08 +0530 Subject: [PATCH 042/162] Add v5.5.0 to CHANGELOG.md --- CHANGELOG.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index cd4e70b6c..72fda2f5d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,15 @@ # Wikimedia Commons for Android +## v5.5.0 + +### What's changed +* Explore images will now be shown based on the map location and not at your current location +* Enhanced Wikidata feedback message +* Green labels in Explore map will no longer be hidden by other pins thumbnails +* Upload wizard's language drop-down now reflects the language used in the pin label +* Users can now pick only one image at a time while using the custom selector +* Bug fixes and stability improvements + ## v5.4.1 ### What's changed From 4befff8f422efe335a09d784b3d754b8d2617536 Mon Sep 17 00:00:00 2001 From: "translatewiki.net" Date: Thu, 3 Jul 2025 14:02:08 +0200 Subject: [PATCH 043/162] Localisation updates from https://translatewiki.net. --- app/src/main/res/values-az/strings.xml | 235 +++++++++++++++++++++++++ app/src/main/res/values-ia/strings.xml | 1 + app/src/main/res/values-it/strings.xml | 2 +- app/src/main/res/values-mk/strings.xml | 3 +- app/src/main/res/values-sh/error.xml | 3 +- app/src/main/res/values-sh/strings.xml | 15 +- app/src/main/res/values-uk/strings.xml | 53 +++++- app/src/main/res/values-zh/strings.xml | 3 +- 8 files changed, 301 insertions(+), 14 deletions(-) diff --git a/app/src/main/res/values-az/strings.xml b/app/src/main/res/values-az/strings.xml index c498f23f5..b5f736415 100644 --- a/app/src/main/res/values-az/strings.xml +++ b/app/src/main/res/values-az/strings.xml @@ -135,31 +135,266 @@ Siyahı (Hələ yükləmə yoxdur) %1$s axtarışına uyğun kateqoriya tapılmadı + %1$s uyğun heç bir Vikidata elementi tapılmadı + %1$s alt sinifləri yoxdur + %1$s üst sinfi yoxdur + Şəkillərinizi Vikianbarda daha tapıla bilən etmək üçün kateqoriyalar əlavə edin.\nKateqoriyalar əlavə etmək üçün yazmağa başlayın. Kateqoriyalar Nizamlamalar Qeydiyyatdan keç Seçilmiş şəkillər + Xüsusi Seçici Kateqoriya + Yoxlanış Haqqında + Vikianbar proqramı Vikimedia icmasının qrant alanları və könüllüləri tərəfindən yaradılmış və dəstəklənən açıq mənbəli proqramdır. Vikimedia Fondu proqramın yaradılması, inkişafı və ya texniki xidmətində iştirak etmir. + Xəta hesabatları və təkliflər üçün yeni <a href=\"%1$s\">GitHub sorğusu</a> yaradın. Məxfilik siyasəti + Töhfə verənlər Haqqında + Rəy göndər (e-poçt vasitəsilə) + Heç bir e-poçt tətbiqi quraşdırılmayıb + Son istifadə olunan kateqoriyalar + İlk sinxronizasiya gözlənilir… + Siz hələ heç bir şəkil yükləməmisiniz. Yenidən cəhd edin + İmtina + Bu şəkli yükləməklə bildirirəm ki, bu mənim şəxsi işimdir, onda müəllif hüququ ilə qorunan material və ya selfilər yoxdur və <a href=\"https://commons.wikimedia.org/wiki/Commons:Policies_and_guidelines\">Vikianbar qaydalarına</a> riayət edir. Endir + Defolt lisenziya + Əvvəlki başlıq və təsvirdən istifadə et + Tema CC BY 3.0 + Vikianbar Vikipediyada istifadə olunan şəkillərin əksəriyyətinə ev sahibliyi edir. + Şəkilləriniz bütün dünyada insanları maarifləndirməyə kömək edir! + Tamamilə özünüz tərəfindən çəkilmiş və ya yaradılmış şəkilləri yükləyin: + Təbii obyektlər (çiçəklər, heyvanlar, dağlar) + Faydalı obyektlər (velosipedlər, qatar stansiyaları) + Məşhur insanlar (icra başçınız, tanış olduğunuz olimpiya idmançıları) + Zəhmət olmasa, YÜKLƏMƏYİN: + Selfi və ya dostlarınızın şəkilləri + İnternetdə tapdığınız şəkillər + Özəl proqramların ekran görüntüləri + Yükləmə nümunəsi: + Başlıq: Sidney Opera Evi + Təsvir: Sidney Opera Evinin körfəzdən görünüşü + Kateqoriyalar: Sidney Opera Evi Qərb istiqamətindən, Sidney Opera Evinin uzaqdan mənzərələri + Şəkilləriniz ilə töhfə verin. Vikipediya məqalələrinin canlanmasına kömək edin! + Vikipediyadakı şəkillər Vikianbardan götürülüb. + Şəkilləriniz bütün dünyada insanları maarifləndirməyə kömək edir. + İnternetdən tapdığınız müəllif hüquqları ilə qorunan materialları, eləcə də afişaların, kitab üzlüklərinin və s. şəkillərini yükləməkdən çəkinin. + Sizcə bunu başa düşdünüz? + Bəli! Əlavə məlumat Kateqoriyalar Yüklənir... Heç biri seçilməmişdir + Başlıq yoxdur + Təsvir yoxdur + Müzakirə yoxdur Naməlum lisenziya Yenilə + Yaddaşa giriş icazəsi tələb olunur + Tələb olunan icazə: Xarici yaddaşı oxumaq. Bu olmadan proqram qalereyanıza daxil ola bilməz. + Tələb olunan icazə: Xarici yaddaşa yazmaq. Bu olmadan proqram kameranıza/qalereyanıza daxil ola bilməz. + Məkan icazəsi tələb olunur + Tətbiqdaxili çəkilişlər üçün məkanı qeyd et + Cihaz kamerası onu qeyd etmədiyi halda, məkanı tətbiqdaxili çəkilişlərlə əlavə etmək üçün bunu aktiv edin + Oldu + Xəbərdarlıq + Dublikat fayl adı tapıldı + Yüklə Bəli Xeyr + Başlıq Başlıq + Təsvirlər + Təsvir Müzakirə Müəllif + Yüklənmə tarixi Lisenziya + Koordinatlar + Heç biri göstərilməyib + Beta Tester ol + Google Play-də beta kanalımıza qoşulun və yeni funksiyalara və xəta həllərinə erkən giriş əldə edin + 2FA kodu + E-poçt doğrulama kodu + Həqiqətən çıxış etmək istəyirsiniz? + Media şəkli uğursuz oldu + Heç bir alt kateqoriya tapılmadı + Heç bir üst kateqoriya tapılmadı + Zao dağı + Lamalar + Göy qurşağı körpüsü + Lalə + Vikipediyaya xoş gəlmisiniz + Müəlliflik hüquqlarına xoş gəlmisiniz + Sidney Opera Evi + İmtina + + Bağla + Ana səhifə + Yüklə + Yaxınlıqdakılar + Haqqında + Parametrlər + Rəy + GitHub vasitəsilə rəy + Çıxış + Təlimat + Bildirişlər + Yoxla + təsvir tapılmadı + Commons fayl səhifəsi + Vikidata elementi + Vikipediya məqaləsi + Zəhmət olmasa, medianı mümkün qədər təsvir edin: Harada çəkilib? Nəyi təsvir edir? Kontekst nədir? Obyektləri və ya şəxsləri təsvir edin. Asanlıqla təxmin edilə bilməyən məlumatları, məsələn, bir mənzərədirsə, günün saatını qeyd edin. Əgər media qeyri-adi bir şey göstərirsə, zəhmət olmasa, onu izah edin. + Zəhmət olmasa şəklin qısa təsvirini yazın. İlk başlıq şəkil üçün Başlıq kimi istifadə olunacaq. 255 simvolla məhdudlaşır. + Bu şəkil ilə bağlı potensial problemlər: + Şəkil çox qaranlıqdır. + Şəkil bulanıqdır. + Şəkil artıq Vikianbarda var. + Bu şəkil başqa yerdə çəkilib. + Zəhmət olmasa, yalnız özünüz çəkdiyiniz şəkilləri yükləyin. Başqalarının Facebook hesablarında tapdığınız şəkilləri yükləməyin. + Hələ də bu şəkli yükləmək istəyirsiniz? + Bağlantı xətası + Yükləmə prosesi aktiv internetə çıxış tələb edir. Şəbəkə bağlantınızı yoxlayın. + Şəkildə tapılan problemlər + Zəhmət olmasa, yalnız özünüz çəkdiyiniz şəkilləri yükləyin. İnternetdən tapdığınız şəkilləri yükləməyin. + Tətbiqdaxili kadrları yadda saxla + Tətbiqdaxili kamera ilə çəkilmiş şəkilləri cihazın yaddaşında saxla + Hesabınıza daxil olun + Jurnal faylını göndərin + Proqramla bağlı problemlərin aradan qaldırılmasına kömək etmək üçün jurnal faylını tərtibatçılara e-poçt vasitəsilə göndərin. Qeyd: jurnallar potensial olaraq şəxsi məlumatları ehtiva edə bilər + URL-i açmaq üçün heç bir veb brauzer tapılmadı + Xəta! URL tapılmadı + Silinməyə namizəd göstər + Bu şəkil silinməyə namizəddir. + Ətraflı məlumat üçün veb səhifəsinə bax + Ötür + Daxil ol + Daxil olma mərhələsini keçmək istədiyinizə əminsiniz? + Gələcəkdə şəkilləri yükləmək üçün daxil olmalısınız. + Bu funksiyadan istifadə etmək üçün zəhmət olmasa daxil olun + Vikimətni mübadilə buferinə köçür + Vikimətn mübadilə buferinə köçürüldü + Yaxınlıqdakılar düzgün işləməyə bilər, məkan əlçatan deyil. + İnternet əlçatan deyil. Yalnız keşlənmiş yerlər göstərilir. + Məkan girişi rədd edildi. Bu funksiyadan istifadə etmək üçün yerinizi manual təyin edin. + Yaxınlıqdakı yerlərin siyahısını göstərmək üçün icazə tələb olunur + Yaxınlıqdakı şəkillərin siyahısını göstərmək üçün icazə tələb olunur + İstiqamətlər Vikidata Vikipediya + Vikianbar + Bizi qiymətləndir + TSS + İstifadəçi təlimatı + Təlimatı ötür + İnternet əlçatan deyil + Bildirişləri əldə edərkən xəta baş verdi + Şəkli nəzərdən keçirmək üçün gətirilərkən xəta baş verdi. Yenidən cəhd etmək üçün yeniləmə düyməsini basın. + Heç bir bildiriş tapılmadı + Tərcümə et + Dillər + Tərcümələri təqdim etmək istədiyiniz dili seçin + Davam et + İmtina + Yenidən cəhd et + Bunlar sizə yaxın yerlərdir və onların Vikipediya məqalələrini təsvir etmək üçün şəkillərə ehtiyac duyurlar.\n\n\'BU SAHƏDƏ AXTAR\' düyməsinə klikləməklə, xəritə kilidləyib həmin məkan ətrafında yaxınlıqda axtarış başlaya bilərsiniz. + Bu yerə şəkil lazımdır. + Bu yerin artıq şəkli var. + Bu yer artıq mövcud deyil. + Şəkil tapılmadı! + Şəkillər yüklənərkən xəta baş verdi. + %1$s tərəfindən yüklənilib + Bloklanıb + Sizə Vikianbarı redaktə etmək qadağan edilib + Günün Şəkli + Axtar + Vikianbarda axtar + Axtar + Son axtarışlar: + Bu yaxınlarda axtarılanlar + Son dil sorğuları + Kateqoriyalar yüklənərkən xəta baş verdi. + Təsvirləri yükləyərkən xəta baş verdi. + Media + Kateqoriyalar + Elementlər + Seçilmiş + Mobil tətbiq vasitəsilə yüklənib + Xəritə + Şəkil Vikidatada %1$s elementinə əlavə edildi + Müvafiq Vikidata obyektini yeniləmək alınmadı! + Divar kağızı kimi təyin et + Divar kağızı uğurla təyin edildi! + Sorğu + Bu şəkli yükləmək olar? + Sual + Nəticə + Silinməyi tələb edilən şəkilləri yükləməyə davam etsəniz, hesabınız blok olunacaq. Sorğunu bitirmək istədiyinizə əminsiniz? + Yüklədiyiniz şəkillərin %1$s+ ədədi silinib. Silinməyi tələb edilən şəkilləri yükləməyə davam etsəniz, hesabınız blok olunacaq.\n\nTəlimata yenidən baxmaq və sonra hansı növ şəkilləri yükləməli və ya yükləməməli olduğunuzu öyrənməyə kömək etmək üçün testdən keçmək istəyirsiniz? + Selfielərin o qədər də məlumatlandırıcı dəyəri yoxdur. Haqqınızda Vikipediya məqaləsi yoxdursa, zəhmət olmasa, şəklinizi yükləməyin. + Abidələrin və mənzərələrin şəkillərini əksər ölkələrdə yükləmək olar. Nəzərə alın ki, xaricdəki müvəqqəti incəsənət abidələri tez-tez müəllif hüquqları ilə qorunur və yükləmək düzgün deyil. + Veb saytların skrinşotları törəmə əsərlər hesab edilir və veb-saytdakı müəllif hüququna tabedir. Bunlar müəllifin icazəsindən sonra istifadə edilə bilər. Belə icazə olmadan, onların işi əsasında yaratdığınız hər hansı əsər qanuni olaraq orijinal müəllifə məxsus lisenziyasız nüsxə sayılır. + Vikianbarın məqsədlərindən biri keyfiyyətli şəkillər toplamaqdır. Ona görə də bulanıq şəkillər yüklənməməlidir. Həmişə yaxşı işıqlandırma ilə gözəl şəkillər çəkməyə çalışın. + Texnologiya və ya mədəniyyəti təsvir edən şəkillər üçün Vikianbarda həmişə yer var. + Cavabların %1$s ədədi düzgündür. Təbriklər! + Suala cavab vermək üçün iki variantdan birini seçin + Giriş müddəti bitib. Zəhmət olmasa, yenidən daxil olun. + Bunu dostlarınızla paylaşın! + Davam et + Düzgün Cavab + Yanlış Cavab + Bu skrinşotu yükləmək olar? + Proqramı paylaş + Fırlat + Yaxınlıqdakı yerləri yükləmək mümkün olmadı + Bu ərazidə şəkillər yoxdur + Yaxınlıqda yer tapılmadı + Yaxınlıqdakı abidələri əldə edərkən xəta baş verdi. + Son axtarışlar yoxdur + Axtarış tarixçəsini silmək istədiyindən əminsiniz? + Bu yükləməni ləğv etmək istədiyinizə əminsiniz? + Bu axtarışı silmək istəyirsiniz? + Axtarış tarixçəsi silindi + Silinməyə namizəd göstər + Sil + Nailiyyətlər + Profil + Rozetlər + Statistika + Qəbul edilən təşəkkürlər + Seçilmiş şəkillər + \"Yaxınlıqdakı yerlər\" vasitəsilə şəkillər + Səviyyə %d + %s (Səviyyə %s) + Yüklənən şəkillər + Geri qaytarılan şəkillər + İstifadə olunan şəkillər + Nailiyyətlərinizi dostlarınızla paylaşın! + Bu tələbləri yerinə yetirdikcə səviyyəniz yüksəlir. \"Statistika\" bölməsindəki elementlər sizin səviyyənizi nəzərə almır. + minimum tələb olunur: + İstənilən yükləmə proqramı vasitəsilə Vikianbara yüklədiyiniz şəkillərin sayı + Vikianbara yüklədiyiniz və silinməyən şəkillərin faizi + Vikianbara yüklədiyiniz və Vikimedia məqalələrində istifadə olunan şəkillərin sayı + Xəta baş verdi! + Vikianbar bildirişi + Fərdi müəllif adından istifadə et + Fotoşəkilləri yükləyərkən istifadəçi adınız əvəzinə fərdi müəllif adından istifadə edin + Fərdi müəllif adı + Töhfələr + Yaxınlıqdakılar + Bildirişlər + Bildirişlər (oxunmuş) + Yaxınlıqdakı bildirişini göstər + Şəkillərə ehtiyacı olan ən yaxın yerlər üçün tətbiqdaxili bildiriş göstərin + Siyahı + Yaddaş icazəsi + Şəkilləri yükləmək üçün cihazınızın xarici yaddaşına giriş icazəsi lazımdır. + Artıq şəkillərə ehtiyacı olan ən yaxın yeri görməyəcəksiniz. Bununla belə, istəyirsinizsə, bu bildirişi Parametrlərdə yenidən aktivləşdirə bilərsiniz. Təşəkkür uğurla göndərildi Təşəkkür göndərilə bilmədi %1$s Təşəkkür göndərilir: Xəta diff --git a/app/src/main/res/values-ia/strings.xml b/app/src/main/res/values-ia/strings.xml index 452f4f9b6..9e169f8f6 100644 --- a/app/src/main/res/values-ia/strings.xml +++ b/app/src/main/res/values-ia/strings.xml @@ -816,4 +816,5 @@ Monstrar in A proximitate Create e incargate per: %1$s Create per %1$s e incargate per %2$s + Nominate pro deletion diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index 9ca05c344..ce121ab5d 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -772,7 +772,7 @@ Impara come scrivere una didascalia utile Vedi i tuoi risultati Modifica Immagine - Modifica Posizione + Modifica posizione Posizione aggiornata! Rimuovi posizione Rimuovi avviso di posizione diff --git a/app/src/main/res/values-mk/strings.xml b/app/src/main/res/values-mk/strings.xml index a0d1dd6ef..6a06f04e7 100644 --- a/app/src/main/res/values-mk/strings.xml +++ b/app/src/main/res/values-mk/strings.xml @@ -413,7 +413,7 @@ Сфатив дека ќе ми ја наруши приватноста Се премислив. Не сакам повеќе да биде видлива За жал, сликава не е соодветна за енциклопедија - Подигнато од мене %1$s, кое се користи во %2$d статии. + Подигнато од мене на %1$s, и се користи во барем {{PLURAL:%2$d|one=една статија|%2$d статии}}. Добре дојдовте на Ризницата!\n\nПодигнете ја вашата прва слика или снимка допирајќи го копчето за додавање. Нема избрано категории Некатегоризираните слики се слабо употребливи. Дали сигурно сакате да продолжите без да ставите категории? @@ -825,4 +825,5 @@ Прикажи во „Во близина“ Создал: %1$s Создал %1$s, а подигнал %2$s + Предложено за бришење diff --git a/app/src/main/res/values-sh/error.xml b/app/src/main/res/values-sh/error.xml index ea9b8e670..28d2bbe0a 100644 --- a/app/src/main/res/values-sh/error.xml +++ b/app/src/main/res/values-sh/error.xml @@ -1,9 +1,10 @@ - Commons se srušio + Aplikacija Ostava prestala je raditi Ups. Nešto nije u redu! Recite nam šta radite, pa podijelite s nama putem e-pošte. Pomoći će nam da ih popravimo! Hvala vam! diff --git a/app/src/main/res/values-sh/strings.xml b/app/src/main/res/values-sh/strings.xml index 5997677ef..97271b945 100644 --- a/app/src/main/res/values-sh/strings.xml +++ b/app/src/main/res/values-sh/strings.xml @@ -1,5 +1,6 @@ @@ -93,12 +94,12 @@ Pretraži kategorije Snimi Preučitaj - Popis + Lista (Još uvijek nema postavljenih datoteka) Nema kategorija što odgovoraju %1$s Stavite kategorije slikama kako biste olakšali korisnicima njihovo pronalaženje na Ostavi.\n\nDa biste stavili kategoriju, počnite sa pisanjem njenog imena. Kategorije - Podešavanja + Postavke Registracija Izabrane slike Kategorija @@ -125,7 +126,7 @@ Autorstvo 4.0 Autorstvo-Dijeliti pod istim uslovima 3.0 Autorstvo 3.0 - Ostava je udomljač najvećine slika što se koriste na Wikipediji. + Wikimedijina ostava skladišti većinu slika koje se upotrebljavaju na Wikipediji. Vaše slike pomažu u obrazovanju ljudi širom svijeta! Postavljajte slike koje su u potpunosti Vaše djelo: Objekti iz prirode (cvijeće, životinje, planine) @@ -188,7 +189,7 @@ Postavi U blizini O privitku - Podešavanja + Postavke Povratna informacija Odjava Uputstva @@ -214,7 +215,7 @@ U budućnosti ćete se morati prijaviti kako biste postavili slike. Prijavite se da biste koristili ovu funkciju „U blizini“ možda ne radi kako treba. Lokacija nije dostupna. - Potrebna je dozvola za popis liste lokacija u blizini + Potrebna je dozvola za prikaz liste lokacija u blizini Upute Wikidata Wikipedia @@ -226,7 +227,7 @@ Nema obavijesti Prevedi Jezici - Odaberite za koji jezik bi želeli da pravite prijevode + Izaberite jezik na koji biste željeli prevoditi Nastavi Otkaži Pokušaj ponovo @@ -261,6 +262,6 @@ Poništi Podaci o lokaciji pomažu Wikiurednicima da pronađu vašu sliku, čineći je mnogo korisnijom.\nVaše nedavne postavljene slike nemaju lokaciju.\nPredlažemo da uključite lokaciju u postavkama priloga kamere.\nHvala vam na učitavanju! Detalji - Razina priložnika + Nivo API-ja Android verzija diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index f005f2969..8eeceec22 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -132,6 +132,8 @@ Оберіть фото Поблизу Мої завантаження + Скопіювати посилання + Посилання скопійовано в буфер обміну Поширити Переглянути сторінку файлу Підпис (обов\'язково) @@ -142,6 +144,7 @@ Надто багато невдалих спроб. Будь ласка, спробуйте знову через кілька хвилин. Вибачте, цього користувача було заблоковано на Вікісховищі Ви повинні надати код двофакторної автентифікації. + Код підтвердження входу надіслано на вашу адресу електронної пошти. Будь ласка, введіть код для входу. Не вдалося увійти Завантажити Назвіть цю серію @@ -150,6 +153,7 @@ Пошук категорій Пошук об\'єктів, що зображено у цьому медіа (напр. гори, Тадж-Махал, тощо) Зберегти + Додаткове меню Оновити Список (Ще нема завантажень) @@ -246,6 +250,7 @@ Станьте бета-тестером Підпишіться на наш бета-канал на Google Play і отримайте ранній доступ до нових функцій та виправлень баґів Код 2FA + Код підтвердження електронної пошти Ви справді хочете вийти із системи? Помилка медіазображення Підкатегорій не знайдено @@ -306,6 +311,7 @@ Скопіювати вікі-текст у буфер обміну Вікі-текст скопійовано у буфер обміну Функція «Поблизу» може працювати некоректно, «Розташування» недоступне. + Інтернет недоступний. Показуються лише кешовані місця. Доступ до місцезнаходження заборонено. Щоб скористатися цією функцією, будь ласка, вкажіть своє місцезнаходження вручну. Потрібний дозвіл для показу списку місць поблизу Потрібний дозвіл для показу зображень місць поблизу @@ -389,11 +395,13 @@ Вилучити Досягнення Профіль + Значки Статистика Отримані подяки Вибрані зображення Зображення місць поблизу - Рівень + Рівень %d + %s (Рівень %s) Завантажені зображення Не відхилені зображення Використані зображення @@ -425,6 +433,7 @@ На Вашому пристрої не знайдено сумісного додатка з картами. Будь ласка, встановіть додаток з картами, якщо хочете скористатись цією функцією. Зображення Місця + Категорії Додати/вилучити закладки Закладки Ви не додали жодної закладки @@ -435,7 +444,7 @@ Мені стало зрозуміло, що це шкодить моїй приватності Моя думка змінилась, я не хочу, щоб це було доступно публічно Перепрошую, це зображення нецікаве для енциклопедії - Завантажено мною на сайт «%1$s» та використано у {{PLURAL:%2$d|one=одній статті|%2$d статтях}}. + Завантажено мною на сайт «%1$s» та використано у принаймні {{PLURAL:%2$d|one=одній статті|%2$d статтях}}. Ласкаво просимо до Вікісховища!\n\nЗавантажте Ваш перший медіафайл, натиснувши кнопку додавання. Жодної категорії не вибрано Зображення без категорій рідко використовуються. Ви впевнені, що хочете продовжити без вказаних категорій? @@ -506,6 +515,7 @@ У вас немає непрочитаних сповіщень Немає прочитаних сповіщень Поширення журналів + Перевірте свою скриньку електронної пошти Перегляд прочитаних Перегляд непрочитаних Сталася помилка при завантаженні зображень @@ -725,7 +735,7 @@ Для належної роботи мапи поблизу мають відображати стан PHONE STATE Внесок користувача: %s Досягнення користувача: %s - Переглянути сторінку користувача + Переглянути профіль користувача Редагувати описи Редагувати категорії Розширені параметри @@ -810,8 +820,45 @@ Повідомити у Вікідані про проблему з цим елементом Будь ласка, додайте якийсь коментар Обговорення + Напишіть щось про елемент «%1$s». Це буде видно публічно. «%1$s» більше не існує, фотографій цього більше не можливо зробити. + «%1$s» розташовано в іншому місці. «%1$s» — це інше місце. Будь ласка, вкажіть правильне місце нижче і, якщо можна, напишіть правильні широту і довготу. Інша проблема або інформація (поясніть нижче). Ваші відгуки розміщуються на ось цій вікісторінці: <a href=\"https://commons.wikimedia.org/wiki/Commons:Mobile_app/Feedback\">Commons:Mobile app/Feedback</a> + Ви впевнені, що бажаєте скасувати усі вивантаження? + Скасування усіх вивантажень… + Вивантаження + В очікуванні + Не вдалося + Не вдалося завантажити дані про місце + Вилучити папку + Підтвердити вилучення + Ви впевнені, що бажаєте вилучити папку %1$s, у якій міститься %2$d елемент(ів)? + Вилучити + Скасувати + Папку %1$s успішно вилучено + Не вдалося вилучити папку %1$s + Помилка при вилученні вмісту папки: %1$s + Не вдалося отримати шлях до папки для ID контейнера: %1$d + У цього місця ще немає зображень, сфотографуйте його! + Це місце уже має зображення. + Перевіряємо, чи це місце має зображення. + Помилка при завантаженні + Не знайдено використань + Вікісховище + Інші вікі + Використання файлу + Обліковий запис + Знищити обліковий запис + Попередження про знищення облікового запису + Зникнення є <b>останнім заходом</b>, і <b>його слід використовувати лише тоді, коли ви хочете назавжди припинити редагування</b>, а також щоб приховати якомога більше своїх минулих зв\'язків.<br/><br/>Вилучення облікового запису у Вікісховищі робиться шляхом зміни імені вашого облікового запису, щоб інші не могли розпізнати ваші внески; це називають зникненням облікового запису. <b>Зникнення не гарантує повної анонімності і не вилучає внесок у проєкти</b>. + Підпис + Підпис скопійовано до буферу обміну + Вітаємо, всі зображення в цьому альбомі або завантажені, або позначені як не для завантаження. + Показати в розділі «Дослідити» + Показати в розділі «Поблизу» + Створено та завантажено: %1$s + Створено %1$s та завантажено %2$s + Номіновано на вилучення diff --git a/app/src/main/res/values-zh/strings.xml b/app/src/main/res/values-zh/strings.xml index 452e54563..8244bdc30 100644 --- a/app/src/main/res/values-zh/strings.xml +++ b/app/src/main/res/values-zh/strings.xml @@ -470,7 +470,7 @@ 我意识到这对我的隐私不利 我改变了主意,我不想再让公众看到它了 对不起,这幅图对百科全书没什么意思 - 由我自己上传在%1$s,使用于%2$d个条目。 + 由我自己上传在%1$s,使用于至少%2$d个条目。 欢迎使用共享资源!\n\n通过点击添加按钮以上传您的首个媒体。 未提交分类 不带分类的图片很难有机会被利用到,您确定您要不选择分类来继续吗? @@ -880,4 +880,5 @@ 显示在附近 创建并上传者: %1$s 由%1$s创建并由%2$s上传 + 已提名删除 From 3bd0ec446610ab9df1ee17360a3840522382dd60 Mon Sep 17 00:00:00 2001 From: Paul Hawke Date: Fri, 4 Jul 2025 06:18:52 -0500 Subject: [PATCH 044/162] Convert top level "Utils" class to kotlin (#6364) * Unused class removed * Convert BasePresenter to kotlin * Removed redundent class * Move the Utils class into the utils package * Inline the creation of a page title object * Move license utilities into their own file * Inline app rating since its only ever used in 1 place * Moved GeoCoordinates utilities into their own class * Moved Monuments related utils into their own class * Moved screen capture into its own util class * Moved handleWebUrl to its own utility class * Moved fixExtension to its own class * Moved clipboard copy into its own utility class * Renames class to match remaining utility method * Convert UnderlineUtils to kotlin * Converted the copy-to-clipboard utility to kotlin * Converted license name and url lookup to kotlin * Converted fixExtension to kotlin * Convert handleGeoCoordinates to kotlin * Monument utils converted to kotlin * Convert then inline screeen capture in kotlin * Convert handleWebUrl to kotlin --- .../java/fr/free/nrw/commons/AboutActivity.kt | 66 ++--- .../fr/free/nrw/commons/BasePresenter.java | 18 -- .../java/fr/free/nrw/commons/BasePresenter.kt | 10 + .../java/fr/free/nrw/commons/License.java | 79 ------ .../main/java/fr/free/nrw/commons/Media.kt | 5 +- .../java/fr/free/nrw/commons/MvpView.java | 8 - .../main/java/fr/free/nrw/commons/Utils.java | 264 ------------------ .../free/nrw/commons/WelcomePagerAdapter.java | 7 +- .../fr/free/nrw/commons/auth/LoginActivity.kt | 6 +- .../nrw/commons/campaigns/CampaignView.kt | 4 +- .../commons/campaigns/CampaignsPresenter.kt | 2 +- .../nrw/commons/campaigns/ICampaignsView.kt | 3 +- .../category/CategoryDetailsActivity.kt | 10 +- .../contributions/ContributionsContract.kt | 1 - .../contributions/ContributionsFragment.kt | 14 +- .../ContributionsListContract.kt | 2 +- .../ContributionsListFragment.kt | 8 +- .../WikidataItemDetailsActivity.java | 9 +- .../explore/map/ExploreMapFragment.java | 7 +- .../locationpicker/LocationPickerActivity.kt | 6 +- .../nrw/commons/media/MediaDetailFragment.kt | 19 +- .../media/MediaDetailPagerFragment.java | 6 +- .../fragments/CommonPlaceClickActions.kt | 7 +- .../nearby/fragments/NearbyParentFragment.kt | 31 +- .../notification/NotificationActivity.kt | 4 +- .../nrw/commons/profile/ProfileActivity.kt | 28 +- .../achievements/AchievementsFragment.kt | 4 +- .../nrw/commons/settings/SettingsFragment.kt | 10 +- .../nrw/commons/upload/PageContentsCreator.kt | 4 +- .../fr/free/nrw/commons/upload/UploadItem.kt | 4 +- .../upload/license/MediaLicenseFragment.kt | 16 +- .../upload/license/MediaLicensePresenter.kt | 10 +- .../UploadMediaDetailsContract.kt | 2 +- .../free/nrw/commons/utils/ClipboardUtils.kt | 20 ++ .../fr/free/nrw/commons/utils/FixExtension.kt | 38 +++ .../free/nrw/commons/utils/GeoCoordinates.kt | 27 ++ .../fr/free/nrw/commons/utils/Licenses.kt | 31 ++ .../fr/free/nrw/commons/utils/Monuments.kt | 39 +++ .../free/nrw/commons/utils/UnderlineUtils.kt | 19 ++ .../fr/free/nrw/commons/utils/UrlUtils.kt | 33 +++ .../kotlin/fr/free/nrw/commons/UtilsTest.kt | 7 +- .../ContributionsFragmentUnitTests.kt | 7 - .../upload/MediaLicensePresenterTest.kt | 10 +- .../commons/utils/UtilsFixExtensionTest.kt | 1 - 44 files changed, 387 insertions(+), 519 deletions(-) delete mode 100644 app/src/main/java/fr/free/nrw/commons/BasePresenter.java create mode 100644 app/src/main/java/fr/free/nrw/commons/BasePresenter.kt delete mode 100644 app/src/main/java/fr/free/nrw/commons/License.java delete mode 100644 app/src/main/java/fr/free/nrw/commons/MvpView.java delete mode 100644 app/src/main/java/fr/free/nrw/commons/Utils.java create mode 100644 app/src/main/java/fr/free/nrw/commons/utils/ClipboardUtils.kt create mode 100644 app/src/main/java/fr/free/nrw/commons/utils/FixExtension.kt create mode 100644 app/src/main/java/fr/free/nrw/commons/utils/GeoCoordinates.kt create mode 100644 app/src/main/java/fr/free/nrw/commons/utils/Licenses.kt create mode 100644 app/src/main/java/fr/free/nrw/commons/utils/Monuments.kt create mode 100644 app/src/main/java/fr/free/nrw/commons/utils/UnderlineUtils.kt create mode 100644 app/src/main/java/fr/free/nrw/commons/utils/UrlUtils.kt diff --git a/app/src/main/java/fr/free/nrw/commons/AboutActivity.kt b/app/src/main/java/fr/free/nrw/commons/AboutActivity.kt index 143f5e569..ebbb4097a 100644 --- a/app/src/main/java/fr/free/nrw/commons/AboutActivity.kt +++ b/app/src/main/java/fr/free/nrw/commons/AboutActivity.kt @@ -1,7 +1,9 @@ package fr.free.nrw.commons import android.annotation.SuppressLint +import android.content.ActivityNotFoundException import android.content.Intent +import android.content.Intent.ACTION_VIEW import android.net.Uri import android.os.Bundle import android.view.Menu @@ -16,6 +18,9 @@ import fr.free.nrw.commons.theme.BaseActivity import fr.free.nrw.commons.utils.ConfigUtils.getVersionNameWithSha import fr.free.nrw.commons.utils.DialogUtil.showAlertDialog import java.util.Collections +import androidx.core.net.toUri +import fr.free.nrw.commons.utils.handleWebUrl +import fr.free.nrw.commons.utils.setUnderlinedText /** * Represents about screen of this app @@ -59,30 +64,12 @@ class AboutActivity : BaseActivity() { binding!!.aboutImprove.setHtmlText(improveText) binding!!.aboutVersion.text = applicationContext.getVersionNameWithSha() - Utils.setUnderlinedText( - binding!!.aboutFaq, R.string.about_faq, - applicationContext - ) - Utils.setUnderlinedText( - binding!!.aboutRateUs, R.string.about_rate_us, - applicationContext - ) - Utils.setUnderlinedText( - binding!!.aboutUserGuide, R.string.user_guide, - applicationContext - ) - Utils.setUnderlinedText( - binding!!.aboutPrivacyPolicy, R.string.about_privacy_policy, - applicationContext - ) - Utils.setUnderlinedText( - binding!!.aboutTranslate, R.string.about_translate, - applicationContext - ) - Utils.setUnderlinedText( - binding!!.aboutCredits, R.string.about_credits, - applicationContext - ) + binding!!.aboutFaq.setUnderlinedText(R.string.about_faq) + binding!!.aboutRateUs.setUnderlinedText(R.string.about_rate_us) + binding!!.aboutUserGuide.setUnderlinedText(R.string.user_guide) + binding!!.aboutPrivacyPolicy.setUnderlinedText(R.string.about_privacy_policy) + binding!!.aboutTranslate.setUnderlinedText(R.string.about_translate) + binding!!.aboutCredits.setUnderlinedText(R.string.about_credits) /* To set listeners, we can create a separate method and use lambda syntax. @@ -106,47 +93,56 @@ class AboutActivity : BaseActivity() { fun launchFacebook(view: View?) { val intent: Intent try { - intent = Intent(Intent.ACTION_VIEW, Uri.parse(Urls.FACEBOOK_APP_URL)) + intent = Intent(ACTION_VIEW, Urls.FACEBOOK_APP_URL.toUri()) intent.setPackage(Urls.FACEBOOK_PACKAGE_NAME) startActivity(intent) } catch (e: Exception) { - Utils.handleWebUrl(this, Uri.parse(Urls.FACEBOOK_WEB_URL)) + handleWebUrl(this, Urls.FACEBOOK_WEB_URL.toUri()) } } fun launchGithub(view: View?) { val intent: Intent try { - intent = Intent(Intent.ACTION_VIEW, Uri.parse(Urls.GITHUB_REPO_URL)) + intent = Intent(ACTION_VIEW, Urls.GITHUB_REPO_URL.toUri()) intent.setPackage(Urls.GITHUB_PACKAGE_NAME) startActivity(intent) } catch (e: Exception) { - Utils.handleWebUrl(this, Uri.parse(Urls.GITHUB_REPO_URL)) + handleWebUrl(this, Urls.GITHUB_REPO_URL.toUri()) } } fun launchWebsite(view: View?) { - Utils.handleWebUrl(this, Uri.parse(Urls.WEBSITE_URL)) + handleWebUrl(this, Urls.WEBSITE_URL.toUri()) } fun launchRatings(view: View?) { - Utils.rateApp(this) + try { + startActivity( + Intent( + ACTION_VIEW, + (Urls.PLAY_STORE_PREFIX + packageName).toUri() + ) + ) + } catch (_: ActivityNotFoundException) { + handleWebUrl(this, (Urls.PLAY_STORE_URL_PREFIX + packageName).toUri()) + } } fun launchCredits(view: View?) { - Utils.handleWebUrl(this, Uri.parse(Urls.CREDITS_URL)) + handleWebUrl(this, Urls.CREDITS_URL.toUri()) } fun launchUserGuide(view: View?) { - Utils.handleWebUrl(this, Uri.parse(Urls.USER_GUIDE_URL)) + handleWebUrl(this, Urls.USER_GUIDE_URL.toUri()) } fun launchPrivacyPolicy(view: View?) { - Utils.handleWebUrl(this, Uri.parse(BuildConfig.PRIVACY_POLICY_URL)) + handleWebUrl(this, BuildConfig.PRIVACY_POLICY_URL.toUri()) } fun launchFrequentlyAskedQuesions(view: View?) { - Utils.handleWebUrl(this, Uri.parse(Urls.FAQ_URL)) + handleWebUrl(this, Urls.FAQ_URL.toUri()) } override fun onCreateOptionsMenu(menu: Menu): Boolean { @@ -193,7 +189,7 @@ class AboutActivity : BaseActivity() { val positiveButtonRunnable = Runnable { val langCode = instance.languageLookUpTable!!.getCodes()[spinner.selectedItemPosition] - Utils.handleWebUrl(this@AboutActivity, Uri.parse(Urls.TRANSLATE_WIKI_URL + langCode)) + handleWebUrl(this@AboutActivity, (Urls.TRANSLATE_WIKI_URL + langCode).toUri()) } showAlertDialog( this, diff --git a/app/src/main/java/fr/free/nrw/commons/BasePresenter.java b/app/src/main/java/fr/free/nrw/commons/BasePresenter.java deleted file mode 100644 index 2653b3711..000000000 --- a/app/src/main/java/fr/free/nrw/commons/BasePresenter.java +++ /dev/null @@ -1,18 +0,0 @@ -package fr.free.nrw.commons; - -import androidx.annotation.NonNull; - -/** - * Base presenter, enforcing contracts to atach and detach view - */ -public interface BasePresenter { - /** - * Until a view is attached, it is open to listen events from the presenter - */ - void onAttachView(@NonNull T view); - - /** - * Detaching a view makes sure that the view no more receives events from the presenter - */ - void onDetachView(); -} diff --git a/app/src/main/java/fr/free/nrw/commons/BasePresenter.kt b/app/src/main/java/fr/free/nrw/commons/BasePresenter.kt new file mode 100644 index 000000000..085307c3e --- /dev/null +++ b/app/src/main/java/fr/free/nrw/commons/BasePresenter.kt @@ -0,0 +1,10 @@ +package fr.free.nrw.commons + +/** + * Base presenter, enforcing contracts to attach and detach view + */ +interface BasePresenter { + fun onAttachView(view: T) + + fun onDetachView() +} diff --git a/app/src/main/java/fr/free/nrw/commons/License.java b/app/src/main/java/fr/free/nrw/commons/License.java deleted file mode 100644 index 1fea236ee..000000000 --- a/app/src/main/java/fr/free/nrw/commons/License.java +++ /dev/null @@ -1,79 +0,0 @@ -package fr.free.nrw.commons; - -import androidx.annotation.Nullable; - -/** - * represents Licence object - */ -public class License { - private String key; - private String template; - private String url; - private String name; - - /** - * Constructs a new instance of License. - * - * @param key license key - * @param template license template - * @param url license URL - * @param name licence name - * - * @throws RuntimeException if License.key or Licence.template is null - */ - public License(String key, String template, String url, String name) { - if (key == null) { - throw new RuntimeException("License.key must not be null"); - } - if (template == null) { - throw new RuntimeException("License.template must not be null"); - } - this.key = key; - this.template = template; - this.url = url; - this.name = name; - } - - /** - * Gets the license key. - * @return license key as a String. - */ - public String getKey() { - return key; - } - - /** - * Gets the license template. - * @return license template as a String. - */ - public String getTemplate() { - return template; - } - - /** - * Gets the license name. If name is null, return license key. - * @return license name as string. if name null, license key as String - */ - public String getName() { - if (name == null) { - // hack - return getKey(); - } else { - return name; - } - } - - /** - * Gets the license URL - * - * @param language license language - * @return URL - */ - public @Nullable String getUrl(String language) { - if (url == null) { - return null; - } else { - return url.replace("$lang", language); - } - } -} diff --git a/app/src/main/java/fr/free/nrw/commons/Media.kt b/app/src/main/java/fr/free/nrw/commons/Media.kt index 7bd8e95fd..dbe722e91 100644 --- a/app/src/main/java/fr/free/nrw/commons/Media.kt +++ b/app/src/main/java/fr/free/nrw/commons/Media.kt @@ -1,7 +1,9 @@ package fr.free.nrw.commons import android.os.Parcelable +import fr.free.nrw.commons.BuildConfig.COMMONS_URL import fr.free.nrw.commons.location.LatLng +import fr.free.nrw.commons.wikidata.model.WikiSite import fr.free.nrw.commons.wikidata.model.page.PageTitle import kotlinx.parcelize.IgnoredOnParcel import kotlinx.parcelize.Parcelize @@ -173,7 +175,8 @@ class Media constructor( * Gets file page title * @return New media page title */ - val pageTitle: PageTitle get() = Utils.getPageTitle(filename!!) + val pageTitle: PageTitle + get() = PageTitle(filename!!, WikiSite(COMMONS_URL)) /** * Returns wikicode to use the media file on a MediaWiki site diff --git a/app/src/main/java/fr/free/nrw/commons/MvpView.java b/app/src/main/java/fr/free/nrw/commons/MvpView.java deleted file mode 100644 index 7485b2aaf..000000000 --- a/app/src/main/java/fr/free/nrw/commons/MvpView.java +++ /dev/null @@ -1,8 +0,0 @@ -package fr.free.nrw.commons; - -/** - * Base interface for all the views - */ -public interface MvpView { - void showMessage(String message); -} diff --git a/app/src/main/java/fr/free/nrw/commons/Utils.java b/app/src/main/java/fr/free/nrw/commons/Utils.java deleted file mode 100644 index 8d0f8b530..000000000 --- a/app/src/main/java/fr/free/nrw/commons/Utils.java +++ /dev/null @@ -1,264 +0,0 @@ -package fr.free.nrw.commons; - -import android.content.ClipData; -import android.content.ClipboardManager; -import android.content.Context; -import android.content.Intent; -import android.graphics.Bitmap; -import android.net.Uri; -import android.text.SpannableString; -import android.text.style.UnderlineSpan; -import android.view.View; -import android.widget.TextView; - -import androidx.annotation.NonNull; -import androidx.browser.customtabs.CustomTabColorSchemeParams; -import androidx.browser.customtabs.CustomTabsIntent; -import androidx.core.content.ContextCompat; - -import java.util.Calendar; -import java.util.Date; -import fr.free.nrw.commons.wikidata.model.WikiSite; -import fr.free.nrw.commons.wikidata.model.page.PageTitle; - -import java.util.Locale; -import java.util.regex.Pattern; - -import fr.free.nrw.commons.location.LatLng; -import fr.free.nrw.commons.settings.Prefs; -import fr.free.nrw.commons.utils.ViewUtil; -import timber.log.Timber; - -public class Utils { - - public static PageTitle getPageTitle(@NonNull String title) { - return new PageTitle(title, new WikiSite(BuildConfig.COMMONS_URL)); - } - - /** - * Generates licence name with given ID - * @param license License ID - * @return Name of license - */ - public static int licenseNameFor(String license) { - switch (license) { - case Prefs.Licenses.CC_BY_3: - return R.string.license_name_cc_by; - case Prefs.Licenses.CC_BY_4: - return R.string.license_name_cc_by_four; - case Prefs.Licenses.CC_BY_SA_3: - return R.string.license_name_cc_by_sa; - case Prefs.Licenses.CC_BY_SA_4: - return R.string.license_name_cc_by_sa_four; - case Prefs.Licenses.CC0: - return R.string.license_name_cc0; - } - throw new IllegalStateException("Unrecognized license value: " + license); - } - - /** - * Generates license url with given ID - * @param license License ID - * @return Url of license - */ - - - @NonNull - public static String licenseUrlFor(String license) { - switch (license) { - case Prefs.Licenses.CC_BY_3: - return "https://creativecommons.org/licenses/by/3.0/"; - case Prefs.Licenses.CC_BY_4: - return "https://creativecommons.org/licenses/by/4.0/"; - case Prefs.Licenses.CC_BY_SA_3: - return "https://creativecommons.org/licenses/by-sa/3.0/"; - case Prefs.Licenses.CC_BY_SA_4: - return "https://creativecommons.org/licenses/by-sa/4.0/"; - case Prefs.Licenses.CC0: - return "https://creativecommons.org/publicdomain/zero/1.0/"; - default: - throw new IllegalStateException("Unrecognized license value: " + license); - } - } - - /** - * Adds extension to filename. Converts to .jpg if system provides .jpeg, adds .jpg if no extension detected - * @param title File name - * @param extension Correct extension - * @return File with correct extension - */ - public static String fixExtension(String title, String extension) { - Pattern jpegPattern = Pattern.compile("\\.jpeg$", Pattern.CASE_INSENSITIVE); - - // People are used to ".jpg" more than ".jpeg" which the system gives us. - if (extension != null && extension.toLowerCase(Locale.ENGLISH).equals("jpeg")) { - extension = "jpg"; - } - title = jpegPattern.matcher(title).replaceFirst(".jpg"); - if (extension != null && !title.toLowerCase(Locale.getDefault()) - .endsWith("." + extension.toLowerCase(Locale.ENGLISH))) { - title += "." + extension; - } - - // If extension is still null, make it jpg. (Hotfix for https://github.com/commons-app/apps-android-commons/issues/228) - // If title has an extension in it, if won't be true - if (extension == null && title.lastIndexOf(".")<=0) { - extension = "jpg"; - title += "." + extension; - } - - return title; - } - - /** - * Launches intent to rate app - * @param context - */ - public static void rateApp(Context context) { - final String appPackageName = context.getPackageName(); - try { - context.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(Urls.PLAY_STORE_PREFIX + appPackageName))); - } - catch (android.content.ActivityNotFoundException anfe) { - handleWebUrl(context, Uri.parse(Urls.PLAY_STORE_URL_PREFIX + appPackageName)); - } - } - - /** - * Opens Custom Tab Activity with in-app browser for the specified URL. - * Launches intent for web URL - * @param context - * @param url - */ - public static void handleWebUrl(Context context, Uri url) { - Timber.d("Launching web url %s", url.toString()); - - final CustomTabColorSchemeParams color = new CustomTabColorSchemeParams.Builder() - .setToolbarColor(ContextCompat.getColor(context, R.color.primaryColor)) - .setSecondaryToolbarColor(ContextCompat.getColor(context, R.color.primaryDarkColor)) - .build(); - - CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder(); - builder.setDefaultColorSchemeParams(color); - builder.setExitAnimations(context, android.R.anim.slide_in_left, android.R.anim.slide_out_right); - CustomTabsIntent customTabsIntent = builder.build(); - // Clear previous browser tasks, so that back/exit buttons work as intended. - customTabsIntent.intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK); - customTabsIntent.launchUrl(context, url); - } - - /** - * Util function to handle geo coordinates. It no longer depends on google maps and any app - * capable of handling the map intent can handle it - * - * @param context The context for launching intent - * @param latLng The latitude and longitude of the location - */ - public static void handleGeoCoordinates(final Context context, final LatLng latLng) { - handleGeoCoordinates(context, latLng, 16); - } - - /** - * Util function to handle geo coordinates with specified zoom level. It no longer depends on - * google maps and any app capable of handling the map intent can handle it - * - * @param context The context for launching intent - * @param latLng The latitude and longitude of the location - * @param zoomLevel The zoom level - */ - public static void handleGeoCoordinates(final Context context, final LatLng latLng, - final double zoomLevel) { - final Intent mapIntent = new Intent(Intent.ACTION_VIEW, latLng.getGmmIntentUri(zoomLevel)); - if (mapIntent.resolveActivity(context.getPackageManager()) != null) { - context.startActivity(mapIntent); - } else { - ViewUtil.showShortToast(context, context.getString(R.string.map_application_missing)); - } - } - - /** - * To take screenshot of the screen and return it in Bitmap format - * - * @param view - * @return - */ - public static Bitmap getScreenShot(View view) { - View screenView = view.getRootView(); - screenView.setDrawingCacheEnabled(true); - Bitmap drawingCache = screenView.getDrawingCache(); - if (drawingCache != null) { - Bitmap bitmap = Bitmap.createBitmap(drawingCache); - screenView.setDrawingCacheEnabled(false); - return bitmap; - } - return null; - } - - /* - *Copies the content to the clipboard - * - */ - public static void copy(String label,String text, Context context){ - ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE); - ClipData clip = ClipData.newPlainText(label, text); - clipboard.setPrimaryClip(clip); - } - - /** - * This method sets underlined string text to a TextView - * - * @param textView TextView associated with string resource - * @param stringResourceName string resource name - * @param context - */ - public static void setUnderlinedText(TextView textView, int stringResourceName, Context context) { - SpannableString content = new SpannableString(context.getString(stringResourceName)); - content.setSpan(new UnderlineSpan(), 0, content.length(), 0); - textView.setText(content); - } - - /** - * For now we are enabling the monuments only when the date lies between 1 Sept & 31 OCt - * @param date - * @return - */ - public static boolean isMonumentsEnabled(final Date date) { - if (date.getMonth() == 8) { - return true; - } - return false; - } - - /** - * Util function to get the start date of wlm monument - * For this release we are hardcoding it to be 1st September - * @return - */ - public static String getWLMStartDate() { - return "1 Sep"; - } - - /*** - * Util function to get the end date of wlm monument - * For this release we are hardcoding it to be 31st October - * @return - */ - public static String getWLMEndDate() { - return "30 Sep"; - } - - /*** - * Function to get the current WLM year - * It increments at the start of September in line with the other WLM functions - * (No consideration of locales for now) - * @param calendar - * @return - */ - public static int getWikiLovesMonumentsYear(Calendar calendar) { - int year = calendar.get(Calendar.YEAR); - if (calendar.get(Calendar.MONTH) < Calendar.SEPTEMBER) { - year -= 1; - } - return year; - } -} diff --git a/app/src/main/java/fr/free/nrw/commons/WelcomePagerAdapter.java b/app/src/main/java/fr/free/nrw/commons/WelcomePagerAdapter.java index 8fd3fc704..a9b7381df 100644 --- a/app/src/main/java/fr/free/nrw/commons/WelcomePagerAdapter.java +++ b/app/src/main/java/fr/free/nrw/commons/WelcomePagerAdapter.java @@ -1,5 +1,7 @@ package fr.free.nrw.commons; +import static fr.free.nrw.commons.utils.UrlUtilsKt.handleWebUrl; + import android.net.Uri; import android.view.LayoutInflater; import android.view.View; @@ -7,6 +9,7 @@ import android.view.ViewGroup; import android.widget.TextView; import androidx.viewpager.widget.PagerAdapter; +import fr.free.nrw.commons.utils.UnderlineUtils; public class WelcomePagerAdapter extends PagerAdapter { private static final int[] PAGE_LAYOUTS = new int[]{ @@ -46,8 +49,8 @@ public class WelcomePagerAdapter extends PagerAdapter { if (position == PAGE_LAYOUTS.length - 1) { // Add link to more information TextView moreInfo = layout.findViewById(R.id.welcomeInfo); - Utils.setUnderlinedText(moreInfo, R.string.welcome_help_button_text, container.getContext()); - moreInfo.setOnClickListener(view -> Utils.handleWebUrl( + UnderlineUtils.setUnderlinedText(moreInfo, R.string.welcome_help_button_text); + moreInfo.setOnClickListener(view -> handleWebUrl( container.getContext(), Uri.parse("https://commons.wikimedia.org/wiki/Help:Contents") )); diff --git a/app/src/main/java/fr/free/nrw/commons/auth/LoginActivity.kt b/app/src/main/java/fr/free/nrw/commons/auth/LoginActivity.kt index 840bc7ca3..a606d639f 100644 --- a/app/src/main/java/fr/free/nrw/commons/auth/LoginActivity.kt +++ b/app/src/main/java/fr/free/nrw/commons/auth/LoginActivity.kt @@ -25,7 +25,6 @@ import androidx.core.content.ContextCompat import fr.free.nrw.commons.BuildConfig import fr.free.nrw.commons.CommonsApplication import fr.free.nrw.commons.R -import fr.free.nrw.commons.Utils import fr.free.nrw.commons.auth.login.LoginCallback import fr.free.nrw.commons.auth.login.LoginClient import fr.free.nrw.commons.auth.login.LoginResult @@ -38,6 +37,7 @@ import fr.free.nrw.commons.utils.ActivityUtils.startActivityWithFlags import fr.free.nrw.commons.utils.ConfigUtils.isBetaFlavour import fr.free.nrw.commons.utils.SystemThemeUtils import fr.free.nrw.commons.utils.ViewUtil.hideKeyboard +import fr.free.nrw.commons.utils.handleWebUrl import io.reactivex.disposables.CompositeDisposable import timber.log.Timber import java.util.Locale @@ -254,10 +254,10 @@ class LoginActivity : AccountAuthenticatorActivity() { } private fun forgotPassword() = - Utils.handleWebUrl(this, Uri.parse(BuildConfig.FORGOT_PASSWORD_URL)) + handleWebUrl(this, Uri.parse(BuildConfig.FORGOT_PASSWORD_URL)) private fun onPrivacyPolicyClicked() = - Utils.handleWebUrl(this, Uri.parse(BuildConfig.PRIVACY_POLICY_URL)) + handleWebUrl(this, Uri.parse(BuildConfig.PRIVACY_POLICY_URL)) private fun signUp() = startActivity(Intent(this, SignupActivity::class.java)) diff --git a/app/src/main/java/fr/free/nrw/commons/campaigns/CampaignView.kt b/app/src/main/java/fr/free/nrw/commons/campaigns/CampaignView.kt index 7a4720177..7a30ff5c4 100644 --- a/app/src/main/java/fr/free/nrw/commons/campaigns/CampaignView.kt +++ b/app/src/main/java/fr/free/nrw/commons/campaigns/CampaignView.kt @@ -7,7 +7,6 @@ import android.view.LayoutInflater import android.view.View import androidx.core.content.ContextCompat import fr.free.nrw.commons.R -import fr.free.nrw.commons.Utils import fr.free.nrw.commons.campaigns.models.Campaign import fr.free.nrw.commons.contributions.MainActivity import fr.free.nrw.commons.databinding.LayoutCampaginBinding @@ -16,6 +15,7 @@ import fr.free.nrw.commons.utils.CommonsDateUtil.getIso8601DateFormatShort import fr.free.nrw.commons.utils.DateUtil.getExtraShortDateString import fr.free.nrw.commons.utils.SwipableCardView import fr.free.nrw.commons.utils.ViewUtil.showLongToast +import fr.free.nrw.commons.utils.handleWebUrl import timber.log.Timber import java.text.ParseException @@ -74,7 +74,7 @@ class CampaignView : SwipableCardView { if (it.isWLMCampaign) { ((context) as MainActivity).showNearby() } else { - Utils.handleWebUrl(context, Uri.parse(it.link)) + handleWebUrl(context, Uri.parse(it.link)) } } } diff --git a/app/src/main/java/fr/free/nrw/commons/campaigns/CampaignsPresenter.kt b/app/src/main/java/fr/free/nrw/commons/campaigns/CampaignsPresenter.kt index 4743e0e54..53013c1ae 100644 --- a/app/src/main/java/fr/free/nrw/commons/campaigns/CampaignsPresenter.kt +++ b/app/src/main/java/fr/free/nrw/commons/campaigns/CampaignsPresenter.kt @@ -26,7 +26,7 @@ class CampaignsPresenter @Inject constructor( private val okHttpJsonApiClient: OkHttpJsonApiClient?, @param:Named(IO_THREAD) private val ioScheduler: Scheduler, @param:Named(MAIN_THREAD) private val mainThreadScheduler: Scheduler -) : BasePresenter { +) : BasePresenter { private var view: ICampaignsView? = null private var disposable: Disposable? = null private var campaign: Campaign? = null diff --git a/app/src/main/java/fr/free/nrw/commons/campaigns/ICampaignsView.kt b/app/src/main/java/fr/free/nrw/commons/campaigns/ICampaignsView.kt index 62a19aaac..1cbf7da1f 100644 --- a/app/src/main/java/fr/free/nrw/commons/campaigns/ICampaignsView.kt +++ b/app/src/main/java/fr/free/nrw/commons/campaigns/ICampaignsView.kt @@ -1,11 +1,10 @@ package fr.free.nrw.commons.campaigns -import fr.free.nrw.commons.MvpView import fr.free.nrw.commons.campaigns.models.Campaign /** * Interface which defines the view contracts of the campaign view */ -interface ICampaignsView : MvpView { +interface ICampaignsView { fun showCampaigns(campaign: Campaign?) } diff --git a/app/src/main/java/fr/free/nrw/commons/category/CategoryDetailsActivity.kt b/app/src/main/java/fr/free/nrw/commons/category/CategoryDetailsActivity.kt index a42d26fd6..e15d9baf3 100644 --- a/app/src/main/java/fr/free/nrw/commons/category/CategoryDetailsActivity.kt +++ b/app/src/main/java/fr/free/nrw/commons/category/CategoryDetailsActivity.kt @@ -13,9 +13,9 @@ import androidx.fragment.app.FragmentManager import androidx.lifecycle.Lifecycle import androidx.lifecycle.lifecycleScope import androidx.lifecycle.repeatOnLifecycle +import fr.free.nrw.commons.BuildConfig.COMMONS_URL import fr.free.nrw.commons.Media import fr.free.nrw.commons.R -import fr.free.nrw.commons.Utils import fr.free.nrw.commons.ViewPagerAdapter import fr.free.nrw.commons.databinding.ActivityCategoryDetailsBinding import fr.free.nrw.commons.explore.categories.media.CategoriesMediaFragment @@ -23,6 +23,9 @@ import fr.free.nrw.commons.explore.categories.parent.ParentCategoriesFragment import fr.free.nrw.commons.explore.categories.sub.SubCategoriesFragment import fr.free.nrw.commons.media.MediaDetailPagerFragment import fr.free.nrw.commons.theme.BaseActivity +import fr.free.nrw.commons.utils.handleWebUrl +import fr.free.nrw.commons.wikidata.model.WikiSite +import fr.free.nrw.commons.wikidata.model.page.PageTitle import kotlinx.coroutines.launch import javax.inject.Inject @@ -199,8 +202,9 @@ class CategoryDetailsActivity : BaseActivity(), override fun onOptionsItemSelected(item: MenuItem): Boolean { return when (item.itemId) { R.id.menu_browser_current_category -> { - val title = Utils.getPageTitle(CATEGORY_PREFIX + categoryName) - Utils.handleWebUrl(this, Uri.parse(title.canonicalUri)) + val title = PageTitle(CATEGORY_PREFIX + categoryName, WikiSite(COMMONS_URL)) + + handleWebUrl(this, Uri.parse(title.canonicalUri)) true } diff --git a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsContract.kt b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsContract.kt index 7027950e3..0e039729f 100644 --- a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsContract.kt +++ b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsContract.kt @@ -9,7 +9,6 @@ import fr.free.nrw.commons.BasePresenter interface ContributionsContract { interface View { - fun showMessage(localizedMessage: String) fun getContext(): Context? } diff --git a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsFragment.kt b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsFragment.kt index 3992d35dd..541cc6e56 100644 --- a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsFragment.kt +++ b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsFragment.kt @@ -30,7 +30,6 @@ import androidx.work.WorkManager import fr.free.nrw.commons.MapController.NearbyPlacesInfo import fr.free.nrw.commons.Media import fr.free.nrw.commons.R -import fr.free.nrw.commons.Utils import fr.free.nrw.commons.auth.SessionManager import fr.free.nrw.commons.campaigns.CampaignView import fr.free.nrw.commons.campaigns.CampaignsPresenter @@ -64,6 +63,9 @@ import fr.free.nrw.commons.utils.LengthUtils.formatDistanceBetween import fr.free.nrw.commons.utils.NetworkUtils.isInternetConnectionEstablished import fr.free.nrw.commons.utils.PermissionUtils.hasPermission import fr.free.nrw.commons.utils.ViewUtil.showLongToast +import fr.free.nrw.commons.utils.isMonumentsEnabled +import fr.free.nrw.commons.utils.wLMEndDate +import fr.free.nrw.commons.utils.wLMStartDate import io.reactivex.Observable import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.disposables.CompositeDisposable @@ -242,8 +244,8 @@ class ContributionsFragment : CommonsDaggerSupportFragment(), FragmentManager.On private fun initWLMCampaign() { wlmCampaign = Campaign( getString(R.string.wlm_campaign_title), - getString(R.string.wlm_campaign_description), Utils.getWLMStartDate().toString(), - Utils.getWLMEndDate().toString(), NearbyParentFragment.WLM_URL, true + getString(R.string.wlm_campaign_description), wLMStartDate, + wLMEndDate, NearbyParentFragment.WLM_URL, true ) } @@ -729,7 +731,7 @@ class ContributionsFragment : CommonsDaggerSupportFragment(), FragmentManager.On * of campaigns on the campaigns card */ private fun fetchCampaigns() { - if (Utils.isMonumentsEnabled(Date())) { + if (isMonumentsEnabled) { if (binding != null) { binding!!.campaignsView.setCampaign(wlmCampaign) binding!!.campaignsView.visibility = View.VISIBLE @@ -743,10 +745,6 @@ class ContributionsFragment : CommonsDaggerSupportFragment(), FragmentManager.On } } - override fun showMessage(message: String) { - Toast.makeText(context, message, Toast.LENGTH_SHORT).show() - } - override fun showCampaigns(campaign: Campaign?) { if (campaign != null && !isUserProfile) { if (binding != null) { diff --git a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsListContract.kt b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsListContract.kt index c6b8dd8a8..0c8c822ad 100644 --- a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsListContract.kt +++ b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsListContract.kt @@ -15,7 +15,7 @@ class ContributionsListContract { fun showNoContributionsUI(shouldShow: Boolean) } - interface UserActionListener : BasePresenter { + interface UserActionListener : BasePresenter { fun refreshList(swipeRefreshLayout: SwipeRefreshLayout?) } } diff --git a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsListFragment.kt b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsListFragment.kt index 9ecb35b24..b86cd6dc9 100644 --- a/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsListFragment.kt +++ b/app/src/main/java/fr/free/nrw/commons/contributions/ContributionsListFragment.kt @@ -29,7 +29,6 @@ import androidx.recyclerview.widget.SimpleItemAnimator import fr.free.nrw.commons.Media import fr.free.nrw.commons.MediaDataExtractor import fr.free.nrw.commons.R -import fr.free.nrw.commons.Utils import fr.free.nrw.commons.auth.SessionManager import fr.free.nrw.commons.contributions.WikipediaInstructionsDialogFragment.Companion.newInstance import fr.free.nrw.commons.databinding.FragmentContributionsListBinding @@ -41,6 +40,8 @@ import fr.free.nrw.commons.profile.ProfileActivity import fr.free.nrw.commons.utils.DialogUtil.showAlertDialog import fr.free.nrw.commons.utils.SystemThemeUtils import fr.free.nrw.commons.utils.ViewUtil.showShortToast +import fr.free.nrw.commons.utils.copyToClipboard +import fr.free.nrw.commons.utils.handleWebUrl import fr.free.nrw.commons.wikidata.model.WikiSite import org.apache.commons.lang3.StringUtils import javax.inject.Inject @@ -527,14 +528,13 @@ class ContributionsListFragment : CommonsDaggerSupportFragment(), ContributionsL */ override fun onConfirmClicked(contribution: Contribution?, copyWikicode: Boolean) { if (copyWikicode) { - val wikicode = contribution!!.media.wikiCode - Utils.copy("wikicode", wikicode, context) + requireContext().copyToClipboard("wikicode", contribution!!.media.wikiCode) } val url = languageWikipediaSite!!.mobileUrl() + "/wiki/" + (contribution!!.wikidataPlace ?.getWikipediaPageTitle()) - Utils.handleWebUrl(context, Uri.parse(url)) + handleWebUrl(requireContext(), Uri.parse(url)) } fun getContributionStateAt(position: Int): Int { diff --git a/app/src/main/java/fr/free/nrw/commons/explore/depictions/WikidataItemDetailsActivity.java b/app/src/main/java/fr/free/nrw/commons/explore/depictions/WikidataItemDetailsActivity.java index cf7269123..89593d07e 100644 --- a/app/src/main/java/fr/free/nrw/commons/explore/depictions/WikidataItemDetailsActivity.java +++ b/app/src/main/java/fr/free/nrw/commons/explore/depictions/WikidataItemDetailsActivity.java @@ -1,5 +1,7 @@ package fr.free.nrw.commons.explore.depictions; +import static fr.free.nrw.commons.utils.UrlUtilsKt.handleWebUrl; + import android.content.Context; import android.content.Intent; import android.net.Uri; @@ -8,16 +10,11 @@ import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; -import android.widget.FrameLayout; -import androidx.appcompat.widget.Toolbar; import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentManager; -import androidx.viewpager.widget.ViewPager; import com.google.android.material.snackbar.Snackbar; -import com.google.android.material.tabs.TabLayout; import fr.free.nrw.commons.Media; import fr.free.nrw.commons.R; -import fr.free.nrw.commons.Utils; import fr.free.nrw.commons.ViewPagerAdapter; import fr.free.nrw.commons.bookmarks.items.BookmarkItemsDao; import fr.free.nrw.commons.category.CategoryImagesCallback; @@ -249,7 +246,7 @@ public class WikidataItemDetailsActivity extends BaseActivity implements MediaDe case R.id.browser_actions_menu_items: String entityId=getIntent().getStringExtra("entityId"); Uri uri = Uri.parse("https://www.wikidata.org/wiki/" + entityId); - Utils.handleWebUrl(this, uri); + handleWebUrl(this, uri); return true; case R.id.menu_bookmark_current_item: diff --git a/app/src/main/java/fr/free/nrw/commons/explore/map/ExploreMapFragment.java b/app/src/main/java/fr/free/nrw/commons/explore/map/ExploreMapFragment.java index 2b3aa9f3c..364f4d53a 100644 --- a/app/src/main/java/fr/free/nrw/commons/explore/map/ExploreMapFragment.java +++ b/app/src/main/java/fr/free/nrw/commons/explore/map/ExploreMapFragment.java @@ -2,7 +2,9 @@ package fr.free.nrw.commons.explore.map; import static fr.free.nrw.commons.location.LocationServiceManager.LocationChangeType.LOCATION_SIGNIFICANTLY_CHANGED; import static fr.free.nrw.commons.location.LocationServiceManager.LocationChangeType.LOCATION_SLIGHTLY_CHANGED; +import static fr.free.nrw.commons.utils.GeoCoordinatesKt.handleGeoCoordinates; import static fr.free.nrw.commons.utils.MapUtils.ZOOM_LEVEL; +import static fr.free.nrw.commons.utils.UrlUtilsKt.handleWebUrl; import android.Manifest.permission; import android.annotation.SuppressLint; @@ -36,7 +38,6 @@ import fr.free.nrw.commons.BaseMarker; import fr.free.nrw.commons.MapController; import fr.free.nrw.commons.Media; import fr.free.nrw.commons.R; -import fr.free.nrw.commons.Utils; import fr.free.nrw.commons.bookmarks.locations.BookmarkLocationsDao; import fr.free.nrw.commons.contributions.MainActivity; import fr.free.nrw.commons.databinding.FragmentExploreMapBinding; @@ -639,13 +640,13 @@ public class ExploreMapFragment extends CommonsDaggerSupportFragment */ private void passInfoToSheet(final Place place) { binding.bottomSheetDetailsBinding.directionsButton.setOnClickListener( - view -> Utils.handleGeoCoordinates(getActivity(), + view -> handleGeoCoordinates(requireActivity(), place.getLocation(), binding.mapView.getZoomLevelDouble())); binding.bottomSheetDetailsBinding.commonsButton.setVisibility( place.hasCommonsLink() ? View.VISIBLE : View.GONE); binding.bottomSheetDetailsBinding.commonsButton.setOnClickListener( - view -> Utils.handleWebUrl(getContext(), place.siteLinks.getCommonsLink())); + view -> handleWebUrl(getContext(), place.siteLinks.getCommonsLink())); int index = 0; for (Media media : mediaList) { diff --git a/app/src/main/java/fr/free/nrw/commons/locationpicker/LocationPickerActivity.kt b/app/src/main/java/fr/free/nrw/commons/locationpicker/LocationPickerActivity.kt index 2a7b7713b..a8b6ddf26 100644 --- a/app/src/main/java/fr/free/nrw/commons/locationpicker/LocationPickerActivity.kt +++ b/app/src/main/java/fr/free/nrw/commons/locationpicker/LocationPickerActivity.kt @@ -30,7 +30,6 @@ import fr.free.nrw.commons.CameraPosition import fr.free.nrw.commons.CommonsApplication import fr.free.nrw.commons.Media import fr.free.nrw.commons.R -import fr.free.nrw.commons.Utils import fr.free.nrw.commons.auth.SessionManager import fr.free.nrw.commons.auth.csrf.CsrfTokenClient import fr.free.nrw.commons.coordinates.CoordinateEditHelper @@ -45,6 +44,7 @@ import fr.free.nrw.commons.upload.mediaDetails.UploadMediaDetailFragment.Compani import fr.free.nrw.commons.upload.mediaDetails.UploadMediaDetailFragment.Companion.LAST_ZOOM import fr.free.nrw.commons.utils.DialogUtil import fr.free.nrw.commons.utils.MapUtils.ZOOM_LEVEL +import fr.free.nrw.commons.utils.handleGeoCoordinates import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.schedulers.Schedulers import org.osmdroid.tileprovider.tilesource.TileSourceFactory @@ -432,8 +432,8 @@ class LocationPickerActivity : BaseActivity(), LocationPermissionCallback { position?.let { mapView?.zoomLevelDouble?.let { zoomLevel -> - Utils.handleGeoCoordinates(this, it, zoomLevel) - } ?: Utils.handleGeoCoordinates(this, it) + handleGeoCoordinates(this, it, zoomLevel) + } ?: handleGeoCoordinates(this, it) } } diff --git a/app/src/main/java/fr/free/nrw/commons/media/MediaDetailFragment.kt b/app/src/main/java/fr/free/nrw/commons/media/MediaDetailFragment.kt index f371b733f..5980e1fb5 100644 --- a/app/src/main/java/fr/free/nrw/commons/media/MediaDetailFragment.kt +++ b/app/src/main/java/fr/free/nrw/commons/media/MediaDetailFragment.kt @@ -77,7 +77,7 @@ import fr.free.nrw.commons.CommonsApplication.Companion.instance import fr.free.nrw.commons.Media import fr.free.nrw.commons.MediaDataExtractor import fr.free.nrw.commons.R -import fr.free.nrw.commons.Utils +import fr.free.nrw.commons.utils.UnderlineUtils import fr.free.nrw.commons.actions.ThanksClient import fr.free.nrw.commons.auth.SessionManager import fr.free.nrw.commons.auth.csrf.InvalidLoginTokenException @@ -119,6 +119,10 @@ import fr.free.nrw.commons.utils.PermissionUtils.hasPermission import fr.free.nrw.commons.utils.ViewUtil import fr.free.nrw.commons.utils.ViewUtil.showShortToast import fr.free.nrw.commons.utils.ViewUtilWrapper +import fr.free.nrw.commons.utils.copyToClipboard +import fr.free.nrw.commons.utils.handleGeoCoordinates +import fr.free.nrw.commons.utils.handleWebUrl +import fr.free.nrw.commons.utils.setUnderlinedText import fr.free.nrw.commons.wikidata.mwapi.MwQueryPage.Revision import io.reactivex.Observable import io.reactivex.Single @@ -316,8 +320,7 @@ class MediaDetailFragment : CommonsDaggerSupportFragment(), CategoryEditHelper.C _binding = FragmentMediaDetailBinding.inflate(inflater, container, false) val view: View = binding.root - - Utils.setUnderlinedText(binding.seeMore, R.string.nominated_see_more, requireContext()) + binding.seeMore.setUnderlinedText(R.string.nominated_see_more) if (isCategoryImage) { binding.authorLinearLayout.visibility = View.VISIBLE @@ -909,7 +912,7 @@ class MediaDetailFragment : CommonsDaggerSupportFragment(), CategoryEditHelper.C private fun onMediaDetailLicenceClicked() { val url: String? = media!!.licenseUrl if (!StringUtils.isBlank(url) && activity != null) { - Utils.handleWebUrl(activity, Uri.parse(url)) + handleWebUrl(requireContext(), Uri.parse(url)) } else { viewUtil.showShortToast(requireActivity(), getString(R.string.null_url)) } @@ -917,17 +920,17 @@ class MediaDetailFragment : CommonsDaggerSupportFragment(), CategoryEditHelper.C private fun onMediaDetailCoordinatesClicked() { if (media!!.coordinates != null && activity != null) { - Utils.handleGeoCoordinates(activity, media!!.coordinates) + handleGeoCoordinates(requireContext(), media!!.coordinates!!) } } private fun onCopyWikicodeClicked() { val data: String = "[[" + media!!.filename + "|thumb|" + media!!.fallbackDescription + "]]" - Utils.copy("wikiCode", data, context) + requireContext().copyToClipboard("wikiCode", data) Timber.d("Generated wikidata copy code: %s", data) - Toast.makeText(context, getString(R.string.wikicode_copied), Toast.LENGTH_SHORT) + Toast.makeText(requireContext(), getString(R.string.wikicode_copied), Toast.LENGTH_SHORT) .show() } @@ -1765,7 +1768,7 @@ class MediaDetailFragment : CommonsDaggerSupportFragment(), CategoryEditHelper.C private fun onSeeMoreClicked() { if (binding.nominatedDeletionBanner.visibility == View.VISIBLE && activity != null) { - Utils.handleWebUrl(activity, Uri.parse(media!!.pageTitle.mobileUri)) + handleWebUrl(requireContext(), Uri.parse(media!!.pageTitle.mobileUri)) } } diff --git a/app/src/main/java/fr/free/nrw/commons/media/MediaDetailPagerFragment.java b/app/src/main/java/fr/free/nrw/commons/media/MediaDetailPagerFragment.java index cba582a35..324d5867b 100644 --- a/app/src/main/java/fr/free/nrw/commons/media/MediaDetailPagerFragment.java +++ b/app/src/main/java/fr/free/nrw/commons/media/MediaDetailPagerFragment.java @@ -1,6 +1,6 @@ package fr.free.nrw.commons.media; -import static fr.free.nrw.commons.Utils.handleWebUrl; +import static fr.free.nrw.commons.utils.UrlUtilsKt.handleWebUrl; import android.os.Handler; import android.os.Looper; @@ -31,7 +31,7 @@ import com.google.android.material.snackbar.Snackbar; import fr.free.nrw.commons.CommonsApplication; import fr.free.nrw.commons.Media; import fr.free.nrw.commons.R; -import fr.free.nrw.commons.Utils; +import fr.free.nrw.commons.utils.ClipboardUtils; import fr.free.nrw.commons.auth.SessionManager; import fr.free.nrw.commons.bookmarks.models.Bookmark; import fr.free.nrw.commons.bookmarks.pictures.BookmarkPicturesContentProvider; @@ -216,7 +216,7 @@ public class MediaDetailPagerFragment extends CommonsDaggerSupportFragment imple return true; case R.id.menu_copy_link: String uri = m.getPageTitle().getCanonicalUri(); - Utils.copy("shareLink", uri, requireContext()); + ClipboardUtils.copy("shareLink", uri, requireContext()); Timber.d("Copied share link to clipboard: %s", uri); Toast.makeText(requireContext(), getString(R.string.menu_link_copied), Toast.LENGTH_SHORT).show(); diff --git a/app/src/main/java/fr/free/nrw/commons/nearby/fragments/CommonPlaceClickActions.kt b/app/src/main/java/fr/free/nrw/commons/nearby/fragments/CommonPlaceClickActions.kt index 202f2c305..5f4d0ab13 100644 --- a/app/src/main/java/fr/free/nrw/commons/nearby/fragments/CommonPlaceClickActions.kt +++ b/app/src/main/java/fr/free/nrw/commons/nearby/fragments/CommonPlaceClickActions.kt @@ -10,12 +10,13 @@ import androidx.activity.result.ActivityResultLauncher import androidx.appcompat.app.AlertDialog import androidx.appcompat.widget.PopupMenu import fr.free.nrw.commons.R -import fr.free.nrw.commons.Utils import fr.free.nrw.commons.auth.LoginActivity import fr.free.nrw.commons.contributions.ContributionController import fr.free.nrw.commons.kvstore.JsonKvStore import fr.free.nrw.commons.nearby.Place import fr.free.nrw.commons.utils.ActivityUtils +import fr.free.nrw.commons.utils.handleGeoCoordinates +import fr.free.nrw.commons.utils.handleWebUrl import fr.free.nrw.commons.wikidata.WikidataConstants import timber.log.Timber import javax.inject.Inject @@ -104,7 +105,7 @@ class CommonPlaceClickActions fun onDirectionsClicked(): (Place) -> Unit = { - Utils.handleGeoCoordinates(activity, it.getLocation()) + handleGeoCoordinates(activity, it.getLocation()) } private fun storeSharedPrefs(selectedPlace: Place) { @@ -113,7 +114,7 @@ class CommonPlaceClickActions } private fun openWebView(link: Uri): Boolean { - Utils.handleWebUrl(activity, link) + handleWebUrl(activity, link) return true } diff --git a/app/src/main/java/fr/free/nrw/commons/nearby/fragments/NearbyParentFragment.kt b/app/src/main/java/fr/free/nrw/commons/nearby/fragments/NearbyParentFragment.kt index 26875927e..a0dcead07 100644 --- a/app/src/main/java/fr/free/nrw/commons/nearby/fragments/NearbyParentFragment.kt +++ b/app/src/main/java/fr/free/nrw/commons/nearby/fragments/NearbyParentFragment.kt @@ -58,12 +58,10 @@ import fr.free.nrw.commons.CommonsApplication import fr.free.nrw.commons.MapController.NearbyPlacesInfo import fr.free.nrw.commons.Media import fr.free.nrw.commons.R -import fr.free.nrw.commons.Utils import fr.free.nrw.commons.bookmarks.locations.BookmarkLocationsDao import fr.free.nrw.commons.contributions.ContributionController import fr.free.nrw.commons.contributions.MainActivity import fr.free.nrw.commons.contributions.MainActivity.ActiveFragment -import fr.free.nrw.commons.customselector.ui.selector.ImageLoader import fr.free.nrw.commons.databinding.FragmentNearbyParentBinding import fr.free.nrw.commons.di.CommonsDaggerSupportFragment import fr.free.nrw.commons.filepicker.FilePicker @@ -76,7 +74,6 @@ import fr.free.nrw.commons.location.LocationServiceManager.LocationChangeType import fr.free.nrw.commons.location.LocationUpdateListener import fr.free.nrw.commons.media.MediaClient import fr.free.nrw.commons.media.MediaDetailPagerFragment -import fr.free.nrw.commons.media.MediaDetailPagerFragment.MediaDetailProvider import fr.free.nrw.commons.navtab.NavTab import fr.free.nrw.commons.nearby.BottomSheetAdapter import fr.free.nrw.commons.nearby.BottomSheetAdapter.ItemClickListener @@ -105,6 +102,10 @@ import fr.free.nrw.commons.utils.NearbyFABUtils.removeAnchorFromFAB import fr.free.nrw.commons.utils.NetworkUtils.isInternetConnectionEstablished import fr.free.nrw.commons.utils.SystemThemeUtils import fr.free.nrw.commons.utils.ViewUtil.showLongToast +import fr.free.nrw.commons.utils.copyToClipboard +import fr.free.nrw.commons.utils.handleGeoCoordinates +import fr.free.nrw.commons.utils.handleWebUrl +import fr.free.nrw.commons.utils.isMonumentsEnabled import fr.free.nrw.commons.wikidata.WikidataConstants import fr.free.nrw.commons.wikidata.WikidataEditListener import fr.free.nrw.commons.wikidata.WikidataEditListener.WikidataP18EditListener @@ -140,7 +141,6 @@ import java.util.UUID import java.util.concurrent.TimeUnit import javax.inject.Inject import javax.inject.Named -import javax.sql.DataSource import kotlin.concurrent.Volatile @@ -467,7 +467,7 @@ class NearbyParentFragment : CommonsDaggerSupportFragment(), } } _isDarkTheme = systemThemeUtils?.isDeviceInNightMode() == true - if (Utils.isMonumentsEnabled(Date())) { + if (isMonumentsEnabled) { binding?.rlContainerWlmMonthMessage?.visibility = View.VISIBLE } else { binding?.rlContainerWlmMonthMessage?.visibility = View.GONE @@ -836,7 +836,7 @@ class NearbyParentFragment : CommonsDaggerSupportFragment(), loadAnimations() setBottomSheetCallbacks() addActionToTitle() - if (!Utils.isMonumentsEnabled(Date())) { + if (!isMonumentsEnabled) { NearbyFilterState.setWlmSelected(false) } } @@ -1017,11 +1017,10 @@ class NearbyParentFragment : CommonsDaggerSupportFragment(), */ private fun addActionToTitle() { binding!!.bottomSheetDetails.title.setOnLongClickListener { view -> - Utils.copy( - "place", binding!!.bottomSheetDetails.title.text.toString(), - context + requireContext().copyToClipboard( + "place", binding!!.bottomSheetDetails.title.text.toString() ) - Toast.makeText(context, fr.free.nrw.commons.R.string.text_copy, Toast.LENGTH_SHORT) + Toast.makeText(requireContext(), fr.free.nrw.commons.R.string.text_copy, Toast.LENGTH_SHORT) .show() true } @@ -1580,7 +1579,7 @@ class NearbyParentFragment : CommonsDaggerSupportFragment(), searchLatLng, false, true, - Utils.isMonumentsEnabled(Date()), + isMonumentsEnabled, customQuery ) } @@ -1633,7 +1632,7 @@ class NearbyParentFragment : CommonsDaggerSupportFragment(), searchLatLng, false, true, - Utils.isMonumentsEnabled(Date()), + isMonumentsEnabled, customQuery ) } @@ -2854,14 +2853,14 @@ class NearbyParentFragment : CommonsDaggerSupportFragment(), R.drawable.ic_directions_black_24dp -> { selectedPlace?.let { - Utils.handleGeoCoordinates(this.context, it.getLocation()) + handleGeoCoordinates(requireContext(), it.getLocation()) binding?.map?.zoomLevelDouble ?: 0.0 } } R.drawable.ic_wikidata_logo_24dp -> { selectedPlace?.siteLinks?.wikidataLink?.let { - Utils.handleWebUrl(this.context, it) + handleWebUrl(requireContext(), it) } } @@ -2879,13 +2878,13 @@ class NearbyParentFragment : CommonsDaggerSupportFragment(), R.drawable.ic_wikipedia_logo_24dp -> { selectedPlace?.siteLinks?.wikipediaLink?.let { - Utils.handleWebUrl(this.context, it) + handleWebUrl(requireContext(), it) } } R.drawable.ic_commons_icon_vector -> { selectedPlace?.siteLinks?.commonsLink?.let { - Utils.handleWebUrl(this.context, it) + handleWebUrl(requireContext(), it) } } diff --git a/app/src/main/java/fr/free/nrw/commons/notification/NotificationActivity.kt b/app/src/main/java/fr/free/nrw/commons/notification/NotificationActivity.kt index 1547f89ad..76975964b 100644 --- a/app/src/main/java/fr/free/nrw/commons/notification/NotificationActivity.kt +++ b/app/src/main/java/fr/free/nrw/commons/notification/NotificationActivity.kt @@ -13,7 +13,6 @@ import androidx.recyclerview.widget.LinearLayoutManager import com.google.android.material.snackbar.Snackbar import fr.free.nrw.commons.CommonsApplication import fr.free.nrw.commons.R -import fr.free.nrw.commons.Utils import fr.free.nrw.commons.auth.SessionManager import fr.free.nrw.commons.auth.csrf.InvalidLoginTokenException import fr.free.nrw.commons.databinding.ActivityNotificationBinding @@ -22,6 +21,7 @@ import fr.free.nrw.commons.notification.models.NotificationType import fr.free.nrw.commons.theme.BaseActivity import fr.free.nrw.commons.utils.NetworkUtils import fr.free.nrw.commons.utils.ViewUtil +import fr.free.nrw.commons.utils.handleWebUrl import io.reactivex.Observable import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.schedulers.Schedulers @@ -197,7 +197,7 @@ class NotificationActivity : BaseActivity() { private fun handleUrl(url: String?) { if (url.isNullOrEmpty()) return - Utils.handleWebUrl(this, Uri.parse(url)) + handleWebUrl(this, Uri.parse(url)) } private fun setItems(notificationList: List?) { diff --git a/app/src/main/java/fr/free/nrw/commons/profile/ProfileActivity.kt b/app/src/main/java/fr/free/nrw/commons/profile/ProfileActivity.kt index 164842c9a..105cf1860 100644 --- a/app/src/main/java/fr/free/nrw/commons/profile/ProfileActivity.kt +++ b/app/src/main/java/fr/free/nrw/commons/profile/ProfileActivity.kt @@ -3,16 +3,16 @@ package fr.free.nrw.commons.profile import android.content.Context import android.content.Intent import android.graphics.Bitmap -import android.net.Uri import android.os.Bundle import android.util.Log -import android.view.* +import android.view.Menu +import android.view.MenuItem +import android.view.View import android.widget.ImageView import android.widget.TextView import androidx.core.content.FileProvider import androidx.fragment.app.Fragment import fr.free.nrw.commons.R -import fr.free.nrw.commons.Utils import fr.free.nrw.commons.ViewPagerAdapter import fr.free.nrw.commons.auth.SessionManager import fr.free.nrw.commons.contributions.ContributionsFragment @@ -23,7 +23,7 @@ import fr.free.nrw.commons.theme.BaseActivity import fr.free.nrw.commons.utils.DialogUtil import java.io.File import java.io.FileOutputStream -import java.util.* +import java.util.Locale import javax.inject.Inject /** @@ -133,7 +133,7 @@ class ProfileActivity : BaseActivity() { return when (item.itemId) { R.id.share_app_icon -> { val rootView = window.decorView.findViewById(android.R.id.content) - val screenShot = Utils.getScreenShot(rootView) + val screenShot = getScreenShot(rootView) if (screenShot == null) { Log.e("ERROR", "ScreenShot is null") return false @@ -212,6 +212,24 @@ class ProfileActivity : BaseActivity() { binding.tabLayout.visibility = if (isVisible) View.VISIBLE else View.GONE } + /** + * To take screenshot of the screen and return it in Bitmap format + * + * @param view + * @return + */ + fun getScreenShot(view: View): Bitmap? { + val screenView = view.rootView + screenView.isDrawingCacheEnabled = true + val drawingCache = screenView.drawingCache + if (drawingCache != null) { + val bitmap = Bitmap.createBitmap(drawingCache) + screenView.isDrawingCacheEnabled = false + return bitmap + } + return null + } + companion object { const val KEY_USERNAME = "username" const val KEY_SHOULD_SHOW_CONTRIBUTIONS = "shouldShowContributions" diff --git a/app/src/main/java/fr/free/nrw/commons/profile/achievements/AchievementsFragment.kt b/app/src/main/java/fr/free/nrw/commons/profile/achievements/AchievementsFragment.kt index f967b8619..8f23674ca 100644 --- a/app/src/main/java/fr/free/nrw/commons/profile/achievements/AchievementsFragment.kt +++ b/app/src/main/java/fr/free/nrw/commons/profile/achievements/AchievementsFragment.kt @@ -15,7 +15,6 @@ import com.google.android.material.badge.BadgeDrawable import com.google.android.material.badge.BadgeUtils import com.google.android.material.badge.ExperimentalBadgeUtils import fr.free.nrw.commons.R -import fr.free.nrw.commons.Utils import fr.free.nrw.commons.auth.SessionManager import fr.free.nrw.commons.databinding.FragmentAchievementsBinding import fr.free.nrw.commons.di.CommonsDaggerSupportFragment @@ -27,6 +26,7 @@ import fr.free.nrw.commons.utils.ConfigUtils.isBetaFlavour import fr.free.nrw.commons.utils.DialogUtil.showAlertDialog import fr.free.nrw.commons.utils.ViewUtil.showDismissibleSnackBar import fr.free.nrw.commons.utils.ViewUtil.showLongToast +import fr.free.nrw.commons.utils.handleWebUrl import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.schedulers.Schedulers import org.apache.commons.lang3.StringUtils @@ -524,7 +524,7 @@ class AchievementsFragment : CommonsDaggerSupportFragment(){ getString(R.string.ok), getString(R.string.read_help_link), {}, - { Utils.handleWebUrl(requireContext(), Uri.parse(helpLinkUrl)) }, + { handleWebUrl(requireContext(), Uri.parse(helpLinkUrl)) }, null ) } diff --git a/app/src/main/java/fr/free/nrw/commons/settings/SettingsFragment.kt b/app/src/main/java/fr/free/nrw/commons/settings/SettingsFragment.kt index 092f057e9..387dd4672 100644 --- a/app/src/main/java/fr/free/nrw/commons/settings/SettingsFragment.kt +++ b/app/src/main/java/fr/free/nrw/commons/settings/SettingsFragment.kt @@ -33,9 +33,7 @@ import com.karumi.dexter.MultiplePermissionsReport import com.karumi.dexter.PermissionToken import com.karumi.dexter.listener.PermissionRequest import com.karumi.dexter.listener.multi.MultiplePermissionsListener -import fr.free.nrw.commons.BuildConfig.MOBILE_META_URL import fr.free.nrw.commons.R -import fr.free.nrw.commons.Utils import fr.free.nrw.commons.activity.SingleWebViewActivity import fr.free.nrw.commons.campaigns.CampaignView import fr.free.nrw.commons.contributions.ContributionController @@ -53,6 +51,7 @@ import fr.free.nrw.commons.utils.DialogUtil import fr.free.nrw.commons.utils.PermissionUtils import fr.free.nrw.commons.utils.StringUtil import fr.free.nrw.commons.utils.ViewUtil +import fr.free.nrw.commons.utils.handleWebUrl import java.util.Locale import javax.inject.Inject import javax.inject.Named @@ -239,7 +238,10 @@ class SettingsFragment : PreferenceFragmentCompat() { val betaTesterPreference: Preference? = findPreference("becomeBetaTester") betaTesterPreference?.setOnPreferenceClickListener { - Utils.handleWebUrl(requireActivity(), Uri.parse(getString(R.string.beta_opt_in_link))) + handleWebUrl( + requireActivity(), + Uri.parse(getString(R.string.beta_opt_in_link)) + ) true } @@ -296,7 +298,7 @@ class SettingsFragment : PreferenceFragmentCompat() { getString(R.string.ok), getString(R.string.read_help_link), { }, - { Utils.handleWebUrl(requireContext(), Uri.parse(GET_CONTENT_PICKER_HELP_URL)) }, + { handleWebUrl(requireContext(), Uri.parse(GET_CONTENT_PICKER_HELP_URL)) }, null ) } diff --git a/app/src/main/java/fr/free/nrw/commons/upload/PageContentsCreator.kt b/app/src/main/java/fr/free/nrw/commons/upload/PageContentsCreator.kt index 0c4ded8b2..2de17f849 100644 --- a/app/src/main/java/fr/free/nrw/commons/upload/PageContentsCreator.kt +++ b/app/src/main/java/fr/free/nrw/commons/upload/PageContentsCreator.kt @@ -1,11 +1,11 @@ package fr.free.nrw.commons.upload import android.content.Context -import fr.free.nrw.commons.Utils import fr.free.nrw.commons.contributions.Contribution import fr.free.nrw.commons.filepicker.UploadableFile.DateTimeWithSource import fr.free.nrw.commons.settings.Prefs.Licenses import fr.free.nrw.commons.utils.ConfigUtils.getVersionNameWithSha +import fr.free.nrw.commons.utils.getWikiLovesMonumentsYear import org.apache.commons.lang3.StringUtils import java.text.SimpleDateFormat import java.util.Calendar @@ -49,7 +49,7 @@ class PageContentsCreator @Inject constructor(private val context: Context) { String.format( Locale.ENGLISH, "{{Wiki Loves Monuments %d|1= %s}}\n", - Utils.getWikiLovesMonumentsYear(Calendar.getInstance()), + getWikiLovesMonumentsYear(Calendar.getInstance()), contribution.countryCode ) ) diff --git a/app/src/main/java/fr/free/nrw/commons/upload/UploadItem.kt b/app/src/main/java/fr/free/nrw/commons/upload/UploadItem.kt index f357cd112..6d2321def 100644 --- a/app/src/main/java/fr/free/nrw/commons/upload/UploadItem.kt +++ b/app/src/main/java/fr/free/nrw/commons/upload/UploadItem.kt @@ -1,10 +1,10 @@ package fr.free.nrw.commons.upload import android.net.Uri -import fr.free.nrw.commons.Utils import fr.free.nrw.commons.filepicker.MimeTypeMapWrapper.Companion.getExtensionFromMimeType import fr.free.nrw.commons.nearby.Place import fr.free.nrw.commons.utils.ImageUtils +import fr.free.nrw.commons.utils.fixExtension class UploadItem( var mediaUri: Uri?, @@ -32,7 +32,7 @@ class UploadItem( * languages have been entered, the first language is used. */ val filename: String - get() = Utils.fixExtension( + get() = fixExtension( uploadMediaDetails[0].captionText, getExtensionFromMimeType(mimeType) ) diff --git a/app/src/main/java/fr/free/nrw/commons/upload/license/MediaLicenseFragment.kt b/app/src/main/java/fr/free/nrw/commons/upload/license/MediaLicenseFragment.kt index 0415d3270..65826a505 100644 --- a/app/src/main/java/fr/free/nrw/commons/upload/license/MediaLicenseFragment.kt +++ b/app/src/main/java/fr/free/nrw/commons/upload/license/MediaLicenseFragment.kt @@ -16,11 +16,13 @@ import android.widget.AdapterView import android.widget.ArrayAdapter import android.widget.TextView import fr.free.nrw.commons.R -import fr.free.nrw.commons.Utils import fr.free.nrw.commons.databinding.FragmentMediaLicenseBinding import fr.free.nrw.commons.upload.UploadActivity import fr.free.nrw.commons.upload.UploadBaseFragment import fr.free.nrw.commons.utils.DialogUtil.showAlertDialog +import fr.free.nrw.commons.utils.handleWebUrl +import fr.free.nrw.commons.utils.toLicenseName +import fr.free.nrw.commons.utils.toLicenseUrl import timber.log.Timber import javax.inject.Inject @@ -126,20 +128,20 @@ class MediaLicenseFragment : UploadBaseFragment(), MediaLicenseContract.View { } override fun setSelectedLicense(license: String?) { - var position = licenses!!.indexOf(getString(Utils.licenseNameFor(license))) + var position = license?.let { licenses!!.indexOf(getString(it.toLicenseName())) } ?: -1 // Check if position is valid if (position < 0) { Timber.d("Invalid position: %d. Using default licenses", position) position = licenses!!.size - 1 - } else { - Timber.d("Position: %d %s", position, getString(Utils.licenseNameFor(license))) } binding.spinnerLicenseList.setSelection(position) } override fun updateLicenseSummary(selectedLicense: String?, numberOfItems: Int) { - val licenseHyperLink = "" + - getString(Utils.licenseNameFor(selectedLicense)) + "
" + if (selectedLicense == null) return + + val licenseHyperLink = "" + + getString(selectedLicense.toLicenseName()) + "
" setTextViewHTML( binding.tvShareLicenseSummary, resources @@ -184,7 +186,7 @@ class MediaLicenseFragment : UploadBaseFragment(), MediaLicenseContract.View { } private fun launchBrowser(hyperLink: String) = - Utils.handleWebUrl(context, Uri.parse(hyperLink)) + handleWebUrl(requireContext(), Uri.parse(hyperLink)) override fun onDestroyView() { presenter.onDetachView() diff --git a/app/src/main/java/fr/free/nrw/commons/upload/license/MediaLicensePresenter.kt b/app/src/main/java/fr/free/nrw/commons/upload/license/MediaLicensePresenter.kt index 25d1a2324..df75019b2 100644 --- a/app/src/main/java/fr/free/nrw/commons/upload/license/MediaLicensePresenter.kt +++ b/app/src/main/java/fr/free/nrw/commons/upload/license/MediaLicensePresenter.kt @@ -1,9 +1,9 @@ package fr.free.nrw.commons.upload.license -import fr.free.nrw.commons.Utils import fr.free.nrw.commons.kvstore.JsonKvStore import fr.free.nrw.commons.repository.UploadRepository import fr.free.nrw.commons.settings.Prefs +import fr.free.nrw.commons.utils.toLicenseName import timber.log.Timber import java.lang.reflect.Method import java.lang.reflect.Proxy @@ -34,12 +34,14 @@ class MediaLicensePresenter @Inject constructor( val licenses = repository.getLicenses() view.setLicenses(licenses) - var selectedLicense = defaultKVStore.getString( + //CC_BY_SA_4 is the default one used by the commons web app + var selectedLicense: String = defaultKVStore.getString( Prefs.DEFAULT_LICENSE, Prefs.Licenses.CC_BY_SA_4 - ) //CC_BY_SA_4 is the default one used by the commons web app + ) ?: Prefs.Licenses.CC_BY_SA_4 + try { //I have to make sure that the stored default license was not one of the deprecated one's - Utils.licenseNameFor(selectedLicense) + selectedLicense.toLicenseName() } catch (exception: IllegalStateException) { Timber.e(exception) selectedLicense = Prefs.Licenses.CC_BY_SA_4 diff --git a/app/src/main/java/fr/free/nrw/commons/upload/mediaDetails/UploadMediaDetailsContract.kt b/app/src/main/java/fr/free/nrw/commons/upload/mediaDetails/UploadMediaDetailsContract.kt index c368b96ac..d6d774208 100644 --- a/app/src/main/java/fr/free/nrw/commons/upload/mediaDetails/UploadMediaDetailsContract.kt +++ b/app/src/main/java/fr/free/nrw/commons/upload/mediaDetails/UploadMediaDetailsContract.kt @@ -54,7 +54,7 @@ interface UploadMediaDetailsContract { fun showBadImagePopup(errorCode: Int, index: Int, uploadItem: UploadItem) } - interface UserActionListener : BasePresenter { + interface UserActionListener : BasePresenter { fun setupBasicKvStoreFactory(factory: (String) -> BasicKvStore) fun receiveImage( diff --git a/app/src/main/java/fr/free/nrw/commons/utils/ClipboardUtils.kt b/app/src/main/java/fr/free/nrw/commons/utils/ClipboardUtils.kt new file mode 100644 index 000000000..64d3636f0 --- /dev/null +++ b/app/src/main/java/fr/free/nrw/commons/utils/ClipboardUtils.kt @@ -0,0 +1,20 @@ +package fr.free.nrw.commons.utils + +import android.content.ClipData +import android.content.ClipboardManager +import android.content.Context +import android.content.Context.CLIPBOARD_SERVICE + +object ClipboardUtils { + // Convenience for Java usages - remove when they are converted. + @JvmStatic + fun copy(label: String?, text: String?, context: Context) { + context.copyToClipboard(label, text) + } +} + +fun Context.copyToClipboard(label: String?, text: String?) { + with(getSystemService(CLIPBOARD_SERVICE) as ClipboardManager) { + setPrimaryClip(ClipData.newPlainText(label, text)) + } +} \ No newline at end of file diff --git a/app/src/main/java/fr/free/nrw/commons/utils/FixExtension.kt b/app/src/main/java/fr/free/nrw/commons/utils/FixExtension.kt new file mode 100644 index 000000000..b9e3988a3 --- /dev/null +++ b/app/src/main/java/fr/free/nrw/commons/utils/FixExtension.kt @@ -0,0 +1,38 @@ +package fr.free.nrw.commons.utils + +import java.util.Locale +import java.util.regex.Pattern + +private val jpegPattern = Pattern.compile("\\.jpeg$", Pattern.CASE_INSENSITIVE) + +/** + * Adds extension to filename. Converts to .jpg if system provides .jpeg, adds .jpg if no extension detected + * @param theTitle File name + * @param ext Correct extension + * @return File with correct extension + */ +fun fixExtension(theTitle: String, ext: String?): String { + var result = theTitle + var extension = ext + + // People are used to ".jpg" more than ".jpeg" which the system gives us. + if (extension != null && extension.lowercase() == "jpeg") { + extension = "jpg" + } + + result = jpegPattern.matcher(result).replaceFirst(".jpg") + if (extension != null && + !result.lowercase(Locale.getDefault()).endsWith("." + extension.lowercase()) + ) { + result += ".$extension" + } + + // If extension is still null, make it jpg. (Hotfix for https://github.com/commons-app/apps-android-commons/issues/228) + // If title has an extension in it, if won't be true + if (extension == null && result.lastIndexOf(".") <= 0) { + extension = "jpg" + result += ".$extension" + } + + return result +} diff --git a/app/src/main/java/fr/free/nrw/commons/utils/GeoCoordinates.kt b/app/src/main/java/fr/free/nrw/commons/utils/GeoCoordinates.kt new file mode 100644 index 000000000..513e36f10 --- /dev/null +++ b/app/src/main/java/fr/free/nrw/commons/utils/GeoCoordinates.kt @@ -0,0 +1,27 @@ +package fr.free.nrw.commons.utils + +import android.content.Context +import android.content.Intent +import fr.free.nrw.commons.R +import fr.free.nrw.commons.location.LatLng +import fr.free.nrw.commons.utils.ViewUtil.showShortToast + +/** + * Util function to handle geo coordinates with specified zoom level. It no longer depends on + * google maps and any app capable of handling the map intent can handle it + * + * @param context The context for launching intent + * @param latLng The latitude and longitude of the location + * @param zoomLevel The zoom level + */ +fun handleGeoCoordinates( + context: Context, latLng: LatLng, + zoomLevel: Double = 16.0 +) { + val mapIntent = Intent(Intent.ACTION_VIEW, latLng.getGmmIntentUri(zoomLevel)) + if (mapIntent.resolveActivity(context.packageManager) != null) { + context.startActivity(mapIntent) + } else { + showShortToast(context, context.getString(R.string.map_application_missing)) + } +} diff --git a/app/src/main/java/fr/free/nrw/commons/utils/Licenses.kt b/app/src/main/java/fr/free/nrw/commons/utils/Licenses.kt new file mode 100644 index 000000000..065a14718 --- /dev/null +++ b/app/src/main/java/fr/free/nrw/commons/utils/Licenses.kt @@ -0,0 +1,31 @@ +package fr.free.nrw.commons.utils + +import fr.free.nrw.commons.R +import fr.free.nrw.commons.settings.Prefs + +/** + * Generates licence name with given ID + * @return Name of license + */ +fun String.toLicenseName(): Int = when (this) { + Prefs.Licenses.CC_BY_3 -> R.string.license_name_cc_by + Prefs.Licenses.CC_BY_4 -> R.string.license_name_cc_by_four + Prefs.Licenses.CC_BY_SA_3 -> R.string.license_name_cc_by_sa + Prefs.Licenses.CC_BY_SA_4 -> R.string.license_name_cc_by_sa_four + Prefs.Licenses.CC0 -> R.string.license_name_cc0 + else -> throw IllegalStateException("Unrecognized license value: $this") +} + +/** + * Generates license url with given ID + * @return Url of license + */ +fun String.toLicenseUrl(): String = when (this) { + Prefs.Licenses.CC_BY_3 -> "https://creativecommons.org/licenses/by/3.0/" + Prefs.Licenses.CC_BY_4 -> "https://creativecommons.org/licenses/by/4.0/" + Prefs.Licenses.CC_BY_SA_3 -> "https://creativecommons.org/licenses/by-sa/3.0/" + Prefs.Licenses.CC_BY_SA_4 -> "https://creativecommons.org/licenses/by-sa/4.0/" + Prefs.Licenses.CC0 -> "https://creativecommons.org/publicdomain/zero/1.0/" + else -> throw IllegalStateException("Unrecognized license value: $this") +} + diff --git a/app/src/main/java/fr/free/nrw/commons/utils/Monuments.kt b/app/src/main/java/fr/free/nrw/commons/utils/Monuments.kt new file mode 100644 index 000000000..d5f5736f5 --- /dev/null +++ b/app/src/main/java/fr/free/nrw/commons/utils/Monuments.kt @@ -0,0 +1,39 @@ +package fr.free.nrw.commons.utils + +import java.util.Calendar +import java.util.Date + +/** + * Get the start date of wlm monument + * For this release we are hardcoding it to be 1st September + * @return + */ +const val wLMStartDate: String = "1 Sep" + +/*** + * Get the end date of wlm monument + * For this release we are hardcoding it to be 31st October + * @return + */ +const val wLMEndDate: String = "30 Sep" + +/** + * For now we are enabling the monuments only when the date lies between 1 Sept & 31 OCt + */ +val isMonumentsEnabled: Boolean + get() = Date().month == 8 + +/*** + * Function to get the current WLM year + * It increments at the start of September in line with the other WLM functions + * (No consideration of locales for now) + * @param calendar + * @return + */ +fun getWikiLovesMonumentsYear(calendar: Calendar): Int { + var year = calendar[Calendar.YEAR] + if (calendar[Calendar.MONTH] < Calendar.SEPTEMBER) { + year -= 1 + } + return year +} diff --git a/app/src/main/java/fr/free/nrw/commons/utils/UnderlineUtils.kt b/app/src/main/java/fr/free/nrw/commons/utils/UnderlineUtils.kt new file mode 100644 index 000000000..75760d4ab --- /dev/null +++ b/app/src/main/java/fr/free/nrw/commons/utils/UnderlineUtils.kt @@ -0,0 +1,19 @@ +package fr.free.nrw.commons.utils + +import android.widget.TextView +import androidx.core.text.buildSpannedString +import androidx.core.text.underline + +object UnderlineUtils { + // Convenience method for Java usages - remove when those classes are converted + @JvmStatic + fun setUnderlinedText(textView: TextView, stringResourceName: Int) { + textView.setUnderlinedText(stringResourceName) + } +} + +fun TextView.setUnderlinedText(stringResourceName: Int) { + text = buildSpannedString { + underline { append(context.getString(stringResourceName)) } + } +} diff --git a/app/src/main/java/fr/free/nrw/commons/utils/UrlUtils.kt b/app/src/main/java/fr/free/nrw/commons/utils/UrlUtils.kt new file mode 100644 index 000000000..4843cf0aa --- /dev/null +++ b/app/src/main/java/fr/free/nrw/commons/utils/UrlUtils.kt @@ -0,0 +1,33 @@ +package fr.free.nrw.commons.utils + +import android.content.Context +import android.content.Intent +import android.net.Uri +import androidx.browser.customtabs.CustomTabColorSchemeParams +import androidx.browser.customtabs.CustomTabsIntent +import androidx.core.content.ContextCompat +import fr.free.nrw.commons.R +import timber.log.Timber + +/** + * Opens Custom Tab Activity with in-app browser for the specified URL. + * Launches intent for web URL + */ +fun handleWebUrl(context: Context, url: Uri) { + Timber.d("Launching web url %s", url.toString()) + + val color = CustomTabColorSchemeParams.Builder() + .setToolbarColor(ContextCompat.getColor(context, R.color.primaryColor)) + .setSecondaryToolbarColor(ContextCompat.getColor(context, R.color.primaryDarkColor)) + .build() + + val customTabsIntent = CustomTabsIntent.Builder() + .setDefaultColorSchemeParams(color) + .setExitAnimations( + context, android.R.anim.slide_in_left, android.R.anim.slide_out_right + ).build() + + // Clear previous browser tasks, so that back/exit buttons work as intended. + customTabsIntent.intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK) + customTabsIntent.launchUrl(context, url) +} diff --git a/app/src/test/kotlin/fr/free/nrw/commons/UtilsTest.kt b/app/src/test/kotlin/fr/free/nrw/commons/UtilsTest.kt index e9e68a3ad..d9151335a 100644 --- a/app/src/test/kotlin/fr/free/nrw/commons/UtilsTest.kt +++ b/app/src/test/kotlin/fr/free/nrw/commons/UtilsTest.kt @@ -1,5 +1,6 @@ package fr.free.nrw.commons +import fr.free.nrw.commons.utils.getWikiLovesMonumentsYear import org.junit.Test import org.junit.jupiter.api.Assertions import java.util.Calendar @@ -9,20 +10,20 @@ class UtilsTest { fun wikiLovesMonumentsYearBeforeSeptember() { val cal = Calendar.getInstance() cal.set(2022, Calendar.FEBRUARY, 1) - Assertions.assertEquals(2021, Utils.getWikiLovesMonumentsYear(cal)) + Assertions.assertEquals(2021, getWikiLovesMonumentsYear(cal)) } @Test fun wikiLovesMonumentsYearInSeptember() { val cal = Calendar.getInstance() cal.set(2022, Calendar.SEPTEMBER, 1) - Assertions.assertEquals(2022, Utils.getWikiLovesMonumentsYear(cal)) + Assertions.assertEquals(2022, getWikiLovesMonumentsYear(cal)) } @Test fun wikiLovesMonumentsYearAfterSeptember() { val cal = Calendar.getInstance() cal.set(2022, Calendar.DECEMBER, 1) - Assertions.assertEquals(2022, Utils.getWikiLovesMonumentsYear(cal)) + Assertions.assertEquals(2022, getWikiLovesMonumentsYear(cal)) } } diff --git a/app/src/test/kotlin/fr/free/nrw/commons/contributions/ContributionsFragmentUnitTests.kt b/app/src/test/kotlin/fr/free/nrw/commons/contributions/ContributionsFragmentUnitTests.kt index 4fd5689da..e3f1c86cc 100644 --- a/app/src/test/kotlin/fr/free/nrw/commons/contributions/ContributionsFragmentUnitTests.kt +++ b/app/src/test/kotlin/fr/free/nrw/commons/contributions/ContributionsFragmentUnitTests.kt @@ -248,13 +248,6 @@ class ContributionsFragmentUnitTests { fragment.onDestroyView() } - @Test - @Throws(Exception::class) - fun testShowMessage() { - Shadows.shadowOf(Looper.getMainLooper()).idle() - fragment.showMessage("") - } - @Test @Throws(Exception::class) fun testShowCampaigns() { diff --git a/app/src/test/kotlin/fr/free/nrw/commons/upload/MediaLicensePresenterTest.kt b/app/src/test/kotlin/fr/free/nrw/commons/upload/MediaLicensePresenterTest.kt index 68b1c95cb..b448df6d2 100644 --- a/app/src/test/kotlin/fr/free/nrw/commons/upload/MediaLicensePresenterTest.kt +++ b/app/src/test/kotlin/fr/free/nrw/commons/upload/MediaLicensePresenterTest.kt @@ -1,11 +1,12 @@ package fr.free.nrw.commons.upload import com.nhaarman.mockitokotlin2.verify -import fr.free.nrw.commons.Utils +import fr.free.nrw.commons.utils.UnderlineUtils import fr.free.nrw.commons.kvstore.JsonKvStore import fr.free.nrw.commons.repository.UploadRepository import fr.free.nrw.commons.upload.license.MediaLicenseContract import fr.free.nrw.commons.upload.license.MediaLicensePresenter +import fr.free.nrw.commons.utils.toLicenseName import org.junit.After import org.junit.Before import org.junit.Test @@ -25,7 +26,7 @@ import org.robolectric.RobolectricTestRunner */ @RunWith(RobolectricTestRunner::class) -@PrepareForTest(Utils::class) +@PrepareForTest(UnderlineUtils::class) class MediaLicensePresenterTest { @Mock internal lateinit var repository: UploadRepository @@ -39,7 +40,7 @@ class MediaLicensePresenterTest { @InjectMocks lateinit var mediaLicensePresenter: MediaLicensePresenter - private lateinit var mockedUtil: MockedStatic + private lateinit var mockedUtil: MockedStatic /** * initial setup test environemnt @@ -49,8 +50,7 @@ class MediaLicensePresenterTest { fun setUp() { MockitoAnnotations.openMocks(this) mediaLicensePresenter.onAttachView(view) - mockedUtil = Mockito.mockStatic(Utils::class.java) - `when`(Utils.licenseNameFor(ArgumentMatchers.anyString())).thenReturn(1) + mockedUtil = Mockito.mockStatic(UnderlineUtils::class.java) } @After diff --git a/app/src/test/kotlin/fr/free/nrw/commons/utils/UtilsFixExtensionTest.kt b/app/src/test/kotlin/fr/free/nrw/commons/utils/UtilsFixExtensionTest.kt index 24e9b233a..f4e6a771b 100644 --- a/app/src/test/kotlin/fr/free/nrw/commons/utils/UtilsFixExtensionTest.kt +++ b/app/src/test/kotlin/fr/free/nrw/commons/utils/UtilsFixExtensionTest.kt @@ -1,6 +1,5 @@ package fr.free.nrw.commons.utils -import fr.free.nrw.commons.Utils.fixExtension import org.junit.Assert.assertEquals import org.junit.Test From f98b49608e00331e9f659e104393b7cba35af525 Mon Sep 17 00:00:00 2001 From: Sonal Yadav Date: Sat, 5 Jul 2025 09:45:57 +0530 Subject: [PATCH 045/162] fix popup from appearing in nearby (#6359) Co-authored-by: Nicolas Raoul --- .../nrw/commons/upload/mediaDetails/UploadMediaPresenter.kt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/fr/free/nrw/commons/upload/mediaDetails/UploadMediaPresenter.kt b/app/src/main/java/fr/free/nrw/commons/upload/mediaDetails/UploadMediaPresenter.kt index 77999cf2f..4d565adb2 100644 --- a/app/src/main/java/fr/free/nrw/commons/upload/mediaDetails/UploadMediaPresenter.kt +++ b/app/src/main/java/fr/free/nrw/commons/upload/mediaDetails/UploadMediaPresenter.kt @@ -107,7 +107,10 @@ class UploadMediaPresenter @Inject constructor( view.showProgress(false) val gpsCoords = uploadItem.gpsCoords val hasImageCoordinates = gpsCoords != null && gpsCoords.imageCoordsExists - if (hasImageCoordinates && place == null) { + + // Only check for nearby places if image has coordinates AND no place was pre-selected + // This prevents the popup from appearing when uploading from Nearby feature + if (hasImageCoordinates && place == null && uploadItem.place == null) { checkNearbyPlaces(uploadItem) } }, { throwable: Throwable? -> From 65f41beed8247a8e2ba6986dc990fb238df820a3 Mon Sep 17 00:00:00 2001 From: VoidRaven Date: Sat, 5 Jul 2025 11:35:54 +0530 Subject: [PATCH 046/162] Update bug-report.yml to use Type:bug label as per issue #6356 (#6363) * Update bug-report.yml to use Type:bug label as per issue #6356 * Update bug-report.yml to use type: bug and labels: ['Type: bug'] as per issue #6356 * Update bug-report.yml to use type: Bug and revert labels to ['bug'] as per mentor's feedback for issue #6356 * Remove labels field from bug-report.yml as per feedback for issue #6356 --------- Co-authored-by: Ritika Pahwa <83745993+RitikaPahwa4444@users.noreply.github.com> --- .github/ISSUE_TEMPLATE/bug-report.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/bug-report.yml b/.github/ISSUE_TEMPLATE/bug-report.yml index f92f51a43..a4682fd3c 100644 --- a/.github/ISSUE_TEMPLATE/bug-report.yml +++ b/.github/ISSUE_TEMPLATE/bug-report.yml @@ -1,7 +1,7 @@ name: "\U0001F41E Bug report" description: Create a report to help us improve. title: "[Bug]: " -labels: ["bug"] +type: Bug # Retained to categorize the issue as per organization-level type body: - type: markdown attributes: From 66395b98719e76d3c6f6546678a361486cc27a97 Mon Sep 17 00:00:00 2001 From: Paul Hawke Date: Sun, 6 Jul 2025 19:50:16 -0500 Subject: [PATCH 047/162] convert top level classes to kotlin (#6368) * Converted welcome activity / pager to kotlin * Removed unused interface * Convert ViewPagerAdapter to kotlin and enforce that all tabs must have a title that comes from strings.xml * Convert OkHttpConnectionFactory and remove an exception class nobody was using * Convert MapController to kotlin along with fixing nullability in a few places --- .idea/codeStyles/Project.xml | 1 + .../fr/free/nrw/commons/MapController.java | 30 ---- .../java/fr/free/nrw/commons/MapController.kt | 46 ++++++ .../nrw/commons/OkHttpConnectionFactory.java | 154 ------------------ .../nrw/commons/OkHttpConnectionFactory.kt | 122 ++++++++++++++ .../java/fr/free/nrw/commons/ViewHolder.java | 7 - .../fr/free/nrw/commons/ViewPagerAdapter.java | 68 -------- .../fr/free/nrw/commons/ViewPagerAdapter.kt | 44 +++++ .../fr/free/nrw/commons/WelcomeActivity.java | 109 ------------- .../fr/free/nrw/commons/WelcomeActivity.kt | 78 +++++++++ .../free/nrw/commons/WelcomePagerAdapter.java | 77 --------- .../free/nrw/commons/WelcomePagerAdapter.kt | 70 ++++++++ .../category/CategoryDetailsActivity.kt | 17 +- .../nrw/commons/contributions/MainActivity.kt | 4 +- .../nrw/commons/explore/ExploreFragment.java | 22 +-- .../nrw/commons/explore/SearchActivity.java | 20 +-- .../WikidataItemDetailsActivity.java | 20 +-- .../commons/explore/map/ExploreMapCalls.java | 3 + .../explore/map/ExploreMapPresenter.java | 9 +- .../free/nrw/commons/media/MediaInterface.kt | 2 +- .../commons/navtab/MoreBottomSheetFragment.kt | 4 +- .../free/nrw/commons/nearby/NearbyPlaces.java | 26 ++- .../nrw/commons/profile/ProfileActivity.kt | 35 ++-- .../commons/upload/UploadProgressActivity.kt | 13 +- app/src/main/res/values/strings.xml | 2 + .../free/nrw/commons/MockWebServerTest.java | 110 ------------- .../fr/free/nrw/commons/MockWebServerTest.kt | 110 +++++++++++++ .../free/nrw/commons/TestConnectionFactory.kt | 3 +- .../commons/auth/csrf/CsrfTokenClientTest.kt | 4 +- 29 files changed, 555 insertions(+), 655 deletions(-) delete mode 100644 app/src/main/java/fr/free/nrw/commons/MapController.java create mode 100644 app/src/main/java/fr/free/nrw/commons/MapController.kt delete mode 100644 app/src/main/java/fr/free/nrw/commons/OkHttpConnectionFactory.java create mode 100644 app/src/main/java/fr/free/nrw/commons/OkHttpConnectionFactory.kt delete mode 100644 app/src/main/java/fr/free/nrw/commons/ViewHolder.java delete mode 100644 app/src/main/java/fr/free/nrw/commons/ViewPagerAdapter.java create mode 100644 app/src/main/java/fr/free/nrw/commons/ViewPagerAdapter.kt delete mode 100644 app/src/main/java/fr/free/nrw/commons/WelcomeActivity.java create mode 100644 app/src/main/java/fr/free/nrw/commons/WelcomeActivity.kt delete mode 100644 app/src/main/java/fr/free/nrw/commons/WelcomePagerAdapter.java create mode 100644 app/src/main/java/fr/free/nrw/commons/WelcomePagerAdapter.kt delete mode 100644 app/src/test/kotlin/fr/free/nrw/commons/MockWebServerTest.java create mode 100644 app/src/test/kotlin/fr/free/nrw/commons/MockWebServerTest.kt diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml index 5c297a65e..ea0cb3b07 100644 --- a/.idea/codeStyles/Project.xml +++ b/.idea/codeStyles/Project.xml @@ -16,6 +16,7 @@