diff --git a/OsmAnd-telegram/res/values-uk/strings.xml b/OsmAnd-telegram/res/values-uk/strings.xml index 8e706abe85..40c91d4ed3 100644 --- a/OsmAnd-telegram/res/values-uk/strings.xml +++ b/OsmAnd-telegram/res/values-uk/strings.xml @@ -93,9 +93,9 @@ Поділитися Назад Оберіть час - Оберіть контакти та групи, з якими ви бажаєте поділитися своїм місцезнаходженням. + Виберіть контакти та групи, з якими ви бажаєте поділитися своїм місцеперебуванням. Пошук: Група або контакт - Поділитися місцезнаходженням + Поділитися розташуванням Показати на карті OsmAnd онлайн GPS Tracker Номер телефону @@ -111,7 +111,7 @@ Запуск Вихід із системи Закриття - Служба визначення місцезнаходження вимкнена. Увімкнути\? + Служба визначення розташування вимкнена. Увімкнути\? Ви не увійшли до системи Продовжити Скасувати @@ -225,8 +225,8 @@ Дата початку - кінця Налаштування GPX Ми не збирали дані за вибраний день - Надіслати місцезнаходження як - Виберіть, як виглядатимуть повідомлення з вашим місцезнаходженням. + Надіслати місцеперебування як + Виберіть, як виглядатимуть повідомлення з вашим місцеперебуванням. Час руху Показати кількість зібраних та відправлених GPS-точок. Виберіть час для відображення @@ -234,7 +234,7 @@ Не рухається Встановити денний час для всіх Видимий час для всіх - Встановіть час, коли вибрані контакти та групи будуть бачити ваше місцезнаходження в режимі реального часу. + Встановіть час, коли вибрані контакти та групи бачитимуть ваше місцеперебування в режимі реального часу. Виберіть одного з локальних постачальників, щоб поділитися своїм місцеположенням. Пошук контактів Пошук у всіх своїх групах та контактах. diff --git a/OsmAnd/res/layout/bottom_sheet_item_progress.xml b/OsmAnd/res/layout/bottom_sheet_item_progress.xml new file mode 100644 index 0000000000..6fcb6e1286 --- /dev/null +++ b/OsmAnd/res/layout/bottom_sheet_item_progress.xml @@ -0,0 +1,10 @@ + + diff --git a/OsmAnd/res/layout/bottom_sheet_with_progress_bar.xml b/OsmAnd/res/layout/bottom_sheet_with_progress_bar.xml new file mode 100644 index 0000000000..258489706b --- /dev/null +++ b/OsmAnd/res/layout/bottom_sheet_with_progress_bar.xml @@ -0,0 +1,48 @@ + + + + + + + + + + \ No newline at end of file diff --git a/OsmAnd/res/layout/bottom_sheet_with_switch_divider_and_additional_button.xml b/OsmAnd/res/layout/bottom_sheet_with_switch_divider_and_additional_button.xml index 681c03e560..6953783885 100644 --- a/OsmAnd/res/layout/bottom_sheet_with_switch_divider_and_additional_button.xml +++ b/OsmAnd/res/layout/bottom_sheet_with_switch_divider_and_additional_button.xml @@ -1,80 +1,83 @@ + xmlns:app="http://schemas.android.com/apk/res-auto" + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:baselineAligned="false" + android:gravity="center_vertical" + android:minHeight="@dimen/bottom_sheet_selected_item_title_height"> - + - + - + - + - + - + - + - + - + - + diff --git a/OsmAnd/res/layout/context_menu_controls.xml b/OsmAnd/res/layout/context_menu_controls.xml new file mode 100644 index 0000000000..0132153f4f --- /dev/null +++ b/OsmAnd/res/layout/context_menu_controls.xml @@ -0,0 +1,30 @@ + + + + + + + + \ No newline at end of file diff --git a/OsmAnd/res/layout/dialog_edit_gpx_description.xml b/OsmAnd/res/layout/dialog_edit_gpx_description.xml index 52b5f97bdc..1d2428f82b 100644 --- a/OsmAnd/res/layout/dialog_edit_gpx_description.xml +++ b/OsmAnd/res/layout/dialog_edit_gpx_description.xml @@ -42,25 +42,31 @@ android:textSize="@dimen/dialog_header_text_size" osmand:typeface="@string/font_roboto_medium" /> - + android:background="@drawable/btn_border_active"> + + + @@ -69,17 +75,26 @@ android:layout_height="1dp" android:background="?attr/divider_color" /> - + android:layout_height="match_parent"> + + + + \ No newline at end of file diff --git a/OsmAnd/res/layout/dialog_read_gpx_description.xml b/OsmAnd/res/layout/dialog_read_gpx_description.xml index f4cf390af5..d065868ab1 100644 --- a/OsmAnd/res/layout/dialog_read_gpx_description.xml +++ b/OsmAnd/res/layout/dialog_read_gpx_description.xml @@ -56,32 +56,40 @@ android:id="@+id/divider" android:layout_width="match_parent" android:layout_height="1dp" - android:background="?attr/divider_color" + android:background="?attr/ctx_menu_info_divider" android:visibility="gone" tools:visibility="visible"/> - + android:background="@drawable/rounded_background_3dp"> + + + + - - - - - - - + + + - + android:orientation="vertical"> + + + + + + + + + + + + + + + + + + + + + android:layout_marginStart="@dimen/card_padding" + android:layout_marginLeft="@dimen/card_padding" + android:layout_marginTop="@dimen/content_padding" + android:background="@drawable/rounded_background_3dp" + android:visibility="gone" + tools:visibility="visible"> - - @@ -110,6 +160,7 @@ - - - - - - - diff --git a/OsmAnd/res/layout/item_gpx_action.xml b/OsmAnd/res/layout/item_gpx_action.xml index dce94e951b..8b68dd681b 100644 --- a/OsmAnd/res/layout/item_gpx_action.xml +++ b/OsmAnd/res/layout/item_gpx_action.xml @@ -1,13 +1,15 @@ + android:minHeight="@dimen/context_menu_controller_height" + android:minWidth="@dimen/context_menu_top_right_button_min_width" + android:layout_width="@dimen/fab_recycler_view_padding_bottom" + android:layout_height="@dimen/setting_list_item_small_height"> diff --git a/OsmAnd/res/layout/item_gpx_stat_block.xml b/OsmAnd/res/layout/item_gpx_stat_block.xml index fcb3e604cb..18dfa5cdde 100644 --- a/OsmAnd/res/layout/item_gpx_stat_block.xml +++ b/OsmAnd/res/layout/item_gpx_stat_block.xml @@ -3,42 +3,62 @@ xmlns:osmand="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:orientation="vertical"> + android:layout_height="@dimen/list_header_height" + android:layout_marginStart="@dimen/content_padding" + android:layout_marginLeft="@dimen/content_padding" + android:gravity="center_vertical" + android:orientation="horizontal"> + android:layout_width="match_parent" + android:layout_height="match_parent" + android:layout_marginEnd="@dimen/content_padding" + android:layout_marginRight="@dimen/content_padding" + android:orientation="vertical"> - + + + + + + + + - - + tools:text="@string/distance" /> - + \ No newline at end of file diff --git a/OsmAnd/res/layout/track_appearance.xml b/OsmAnd/res/layout/track_appearance.xml index 074c5f8a86..3356a7f3f3 100644 --- a/OsmAnd/res/layout/track_appearance.xml +++ b/OsmAnd/res/layout/track_appearance.xml @@ -90,34 +90,7 @@ - - - - - - - + + + + xmlns:app="http://schemas.android.com/apk/res-auto" + xmlns:osmand="http://schemas.android.com/apk/res-auto" + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical"> - + - + - + - + - + - - + + - + - + - - + + - + diff --git a/OsmAnd/res/values-de/strings.xml b/OsmAnd/res/values-de/strings.xml index 434aa506d8..620e4a10ea 100644 --- a/OsmAnd/res/values-de/strings.xml +++ b/OsmAnd/res/values-de/strings.xml @@ -3998,4 +3998,14 @@ Mountainbike Server-Fehler: %1$s Der Name ist bereits vorhanden + Beim Passieren + Abweichung von der Route + Ankunft am Ziel + Annährung ans Ziel + Vollständig lesen + Dieses Online-Routingmodul löschen\? + Beschreibung bearbeiten + Wegpunkte löschen + In Favoriten kopieren + In Kartenmarkierungen kopieren \ No newline at end of file diff --git a/OsmAnd/res/values-eo/strings.xml b/OsmAnd/res/values-eo/strings.xml index 59164b63aa..349175b810 100644 --- a/OsmAnd/res/values-eo/strings.xml +++ b/OsmAnd/res/values-eo/strings.xml @@ -4000,4 +4000,10 @@ Interspacoj distancaj kaj tempaj Tempo de anonco de diversaj voĉaj sciigoj dependas de ilia specoj, nuna naviga kaj implicita naviga rapido. Tempo de anonco + Kopii al ŝatataj + Ĉu forigi tiun ĉi enretan navigilon\? + Legi pli + Redakti priskribon + Forigi navigadpunktojn + Kopii al map‑markoj \ No newline at end of file diff --git a/OsmAnd/res/values-fr/strings.xml b/OsmAnd/res/values-fr/strings.xml index 27659178d3..e9c1c87b65 100644 --- a/OsmAnd/res/values-fr/strings.xml +++ b/OsmAnd/res/values-fr/strings.xml @@ -3990,4 +3990,10 @@ Vélo tout terrain Vélo électrique Vélo + Copier vers les marques de carte + Copier vers les favoris + Supprimer ce moteur de routage en ligne \? + Lire la suite + Modifier la description + Supprimer les points de passage \ No newline at end of file diff --git a/OsmAnd/res/values-gl/strings.xml b/OsmAnd/res/values-gl/strings.xml index 9ee8d8b590..c39329ec8e 100644 --- a/OsmAnd/res/values-gl/strings.xml +++ b/OsmAnd/res/values-gl/strings.xml @@ -3976,4 +3976,26 @@ Lon %2$s Selecionar cartafol ou engadir un novo Seleccionar cartafol Baleiro + Chegar ao destino + Xiro + Intres de tempo e distancia + A hora do anuncio das diferentes indicacións por voz depende do tipo de mensaxe, a velocidade de navegación actual e a velocidade de navegación predefinida. + Hora do anuncio + Comezar gravación + Amosar pista no mapa + Cadeira de rodas + Sendeirismo + Camiñando + Ciclismo eléctrico + Ciclismo de montaña + Ciclismo de estrada + Ciclismo regular + Vehículos pesados + Camión pequeno + Camión + Scooter + Bicicleta de carreiras + Bicicleta de montaña + Erro do servidor: %1$s + O nome xa existe \ No newline at end of file diff --git a/OsmAnd/res/values-hu/strings.xml b/OsmAnd/res/values-hu/strings.xml index ba55ac197f..d883e7189b 100644 --- a/OsmAnd/res/values-hu/strings.xml +++ b/OsmAnd/res/values-hu/strings.xml @@ -312,7 +312,7 @@ \n \nÁtmenetileg átállítva online CloudMade-re. Nem sikerült megtalálni a megadott mappát. - Adatok tárolási helye + Adatok tárolási mappája {0} verzió telepítve ({1}). Összeállítás letöltése… OsmAnd {0} – {1}, {2} MB. Telepíted? @@ -362,7 +362,7 @@ Tömegközlekedés keresésének alaphelyzetbe állítása Felvett hang Nincs betöltött vektoros térkép - Nem található GPX fálj a tracks könyvtárban + Nem található GPX-fálj a tracks mappában Nem sikerült beolvasni a GPX-adatokat. Vektoros OSM térkép Közlekedés keresése megállónál @@ -491,7 +491,7 @@ Teljes távolság %1$s, utazási idő %2$d óra %3$d perc. Online vagy offline útvonaltervező szolgáltatás. Útvonaltervező szolgáltatás - A tárolási könyvtár nem érhető el a memóriakártyán! + A tárolási mappa nem érhető el a memóriakártyán! Letöltés {0} - {1} ? {0} régióhoz már le van töltve offline adat ({1}). Frissíted ({2})? Cím @@ -547,7 +547,7 @@ Jelenlegi nyomvonal mentése A navigáció alatti nyomvonalfelvételhez adja meg a naplózási intervallumot Naplózási intervallum navigáció közben - Navigáció közben a GPX útvonal automatikusan mentésre kerül az OsmAnd „tracks” könyvtárába. + Navigáció közben a GPX útvonal automatikusan mentésre kerül az OsmAnd „tracks” mappájába. Térképcsempe újratöltése Célpont Hozzáadás a „Kedvencek”-hez @@ -661,7 +661,7 @@ \n \nA csempés térképek letölthetők internetes forrásokból, vagy előkészíthetők kapcsolat nélküli használathoz (kézzel átmásolva az OsmAnd adatmappájába) SQLite adatbázisként, amely különféle harmadik féltől származó térkép-előkészítő eszközökkel állítható elő. Megjeleníti a háttérben futó nyomvonalrögzítés és navigáció beállításait, ami periodikusan felébreszti a GPS modult (kikapcsolt képernyőnél). - Elérhetővé teszi az eszköz akadálymentesítési lehetőségeit közvetlenül az OsmAndban. Ez megkönnyíti például a szövegfelolvasó (TTS) hangok beszédsebességének állítását, az irányító gombok képernyő navigációjának beállítását, egy görgető használatát a nagyítás vezérléséhez, vagy szövegfelolvasó visszajelzés használatát, például a pozíció automatikus bejelentésénél. + Elérhetővé teszi az eszköz akadálymentesítési lehetőségeit közvetlenül az OsmAndban. Ez megkönnyíti például a szövegfelolvasó (TTS) hangok beszédsebességének állítását, az irányító gombok képernyő navigációjának beállítását, egy görgető használatát a nagyítás vezérléséhez, vagy szövegfelolvasó visszajelzés használatát, például a pozíció automatikus bemondásánál. Beállítások fejlesztői és hibakeresési szolgáltatásokhoz, mint például navigáció szimulálása, a megjelenítés teljesítménye vagy hangutasítások. Fejlesztőknek szánt funkciók, nem szükségesek a normál használathoz. Bővítmények A bővítmények speciális beállításokat és kiegészítő funkciókat aktiválnak. @@ -1178,7 +1178,7 @@ Útvonal megosztása GPX-ben OsmAnd segítségével megosztott útvonal Érkezés bemondása - Milyen korán szeretnéd hallani az érkezés bejelentését\? + Milyen korán szeretné hallani az érkezés bemondását\? Csak kézzel (koppintás a nyílra) Navigációs utasítások újra bemondása rendszeres időközönként. Navigációs utasítások ismétlése @@ -1818,7 +1818,7 @@ Éjjel Hónap és ország: Eltávolítás - Az alkalmazás átváltott belső memóriára, mert a kijelölt adattároló mappa írásvédett. Kérjük, jelöljön ki egy írható tárolási mappát. + Az alkalmazás átváltott belső memóriára, mert a kijelölt adattároló mappa írásvédett. Kérjük, jelöljön ki egy írható tárolómappát. Osztott memória Felső sáv Útvonal újraszámítása @@ -1948,10 +1948,10 @@ Hanggal jelölje a célpont irányát. Rezgő irányjelzés Rezgéssel jelölje a célpont irányát. - Okos automatikus bejelentés + Intelligens automatikus bemondás Figyelmeztetés, csak ha a célpont iránya megváltozott. - Automatikus bejelentések időköz - A bejelentések közötti legkisebb időköz. + Bemondások gyakorisága + A bemondások közötti legkisebb időköz. magyar (magázó) Jelenlegi nyomvonal Jelölő helyének módosítása @@ -2157,7 +2157,7 @@ Érvényes teljes OLC \nA következő területet jeleníti meg: %1$s x %2$s Gomb, amely lépteti az alábbi listát. - GPX fájlok könyvtárának kijelölése + GPX-fájlok mappájának kijelölése Nem sikerült áthelyezni a fájlt. Áthelyezés Nyomvonalak @@ -2191,7 +2191,7 @@ Mellékutak előnyben részesítése Előnyben részesített terep: sík vagy dombos. Lejtő - Új mappa létrehozása + Új mappa hozzáadása Pont(ok) törölve. Biztosan törli ez(eke)t a ponto(ka)t: %1$d\? Érintendő fordulók az útvonalon @@ -3051,7 +3051,7 @@ Tömeg, magasság, hossz, sebesség Jármű paraméterek A hangbemondások csak navigáció közben kerülnek lejátszásra. - Navigációs utasítások és bejelentések + Navigációs utasítások és bemondások Hangutasítások Képernyő riasztások Útvonal paraméterek testreszabása @@ -3059,7 +3059,7 @@ Bővítménybeállítások Töltsd le a részletes %s térképet a terület megtekintéséhez. Az OsmAnd belső tárolója (felhasználók és más alkalmazások számára rejtett). - Tárolás mappájának módosítása + Tároló mappa módosítása Szélességkorlátozás Adja meg az útvonalakon a járművekre vonatkozó szélességkorlátozást. Bizonyos útvonalak és úttípusok elkerülése @@ -3086,10 +3086,10 @@ Szövegfelolvasó motor indítása sikertelen. %1$s • %2$s %1$s GB szabad (%2$s GB-ból) - Add meg a könyvtár elérési útvonalát - Könyvtár… - OsmAnd adatok elérési útvonalának beillesztése - Módosítod az OsmAnd adatokat tároló könyvtárat\? + Add meg a mappa elérési útvonalát + Mappa… + Az OsmAnd-adatokat tartalmazó mappa elérési útvonalának beillesztése + Módosítod az OsmAnd adatok mappáját\? Áthelyezés az új helyre %1$s TB %1$s GB @@ -3103,11 +3103,11 @@ Domborzatárnyékolás megjelenítése Domborzatárnyékolás elrejtése Domborzatárnyékolás megjelenítése/elrejtése - Nyomvonal tárolási könyvtára - A nyomvonalak a \'rec\' könyvtárban tárolhatók, havi vagy napi bontás szerinti könyvtárakban. + Nyomvonal tárolási mappája + A nyomvonalak tárolhatók a \'rec\' mappában, illetve havi vagy napi bontás szerinti mappákban. Nyomvonalak felvétele a \'rec\' mappába Nyomvonalak felvétele napi bontású mappákba - Nyomvonalak rögzítése a rögzítés napja szerinti almappákba (pl. 2018-01-01). + Nyomvonalak felvétele a felvétel napja szerinti almappákba (pl. 2018-01-01). Profil exportálása OsmAnd profil: %1$s \'%1$s\' már létezik. Felülírja\? @@ -3340,7 +3340,7 @@ Videojegyzetek Fényképes jegyzetek Útvonal újraszámítása - Bejelentés + Bemondás Felhasználónév és jelszó Ezek a bővítménybeállítások globálisak, és minden profilra vonatkoznak OSM-szerkesztés @@ -3986,9 +3986,18 @@ Hegyi kerékpározás Verenykerékpározás Rendes kerékpározás - Tgk. - Nehéz tgk. + Teherautó + Nehéz teherautó Kisteherautó Szerverhiba: %1$s Ez a név már létezik + A különféle hangutasítások bemondási ideje függ az utasítás típusától, az aktuális navigációs sebességtől és az alapértelmezett navigációs sebességtől. + Bemondás ideje + Roller + Törli ezt az online útvonaltervezőt\? + Az egész elolvasása + Leírás szerkesztése + Útpontok törlése + Másolás a térképjelölők közé + Másolás a kedvencek közé \ No newline at end of file diff --git a/OsmAnd/res/values-is/strings.xml b/OsmAnd/res/values-is/strings.xml index 168f905c8b..ebb0385e37 100644 --- a/OsmAnd/res/values-is/strings.xml +++ b/OsmAnd/res/values-is/strings.xml @@ -3966,4 +3966,43 @@ Hjólandi Bíll Afrita heimilisfang + Leiðagerð af netinu + Leiðagerð af netinu + Möppur + Veldu möppu + Veldu möppu eða bættu við nýrri + Tómt + Greina eftir millibilum (uppskipting millibila) + Senda inn í OpenStreetMap + Breyta ferli + Endurnefna feril + Skipta um möppu + sek + Framhjá + Aðkoma + Langur undirbúningur + Undirbúa + Utan leiðar + Koma á áfangastað + Beygja + Millibil tíma og vegalengda + Tilkynningar mismunandi talskilaboða fara eftir tegund skilaboða, fyrirliggjandi hraða leiðsagnar og sjálfgefnum hraða leiðsagnar. + Tími tilkynninga + Hefja upptöku + Birta feril á korti + Hjólastólar + Gönguferðir + Gangandi + Rafmagnshjól + Fjallahjól + Götuhjól + Venjulegar hjólreiðar + Þyngri vöruflutningabifreiðar + Litlar vöruflutningabifreiðar + Flutningabifreiðar + Skellinöðrur + Götukeppnishjól + Fjallahjól + Villa í netþjóni: %1$s + Nafnið er þegar til staðar \ No newline at end of file diff --git a/OsmAnd/res/values-it/strings.xml b/OsmAnd/res/values-it/strings.xml index bbe3202bf0..7a3d6ee245 100644 --- a/OsmAnd/res/values-it/strings.xml +++ b/OsmAnd/res/values-it/strings.xml @@ -543,7 +543,7 @@ Circolazione a sinistra Per i paesi in cui si guida nella parte sinistra della strada. Posizione di partenza non ancora determinata. - Annulla il download del file\? + Annulla il download\? La mappa di base necessaria per il funzionamento è in coda per il download. Abilita il plugin \'Mappe Online\' per scegliere altre sorgenti di mappe Mappe online e a tasselli @@ -929,7 +929,7 @@ Seleziona Preferito Modifiche OSM Non connesso al Wi-Fi. Usare la connessione a Internet attuale per il download\? - Cancellare il percorso\? + Ignora il percorso\? Interrompere la navigazione Cancella la destinazione Altra @@ -1399,7 +1399,7 @@ Ok Annulla - Annulla + Ignora No Acceso @@ -1989,7 +1989,7 @@ Ottieni indicazioni e scopri nuovi luoghi senza una connessione a Internet Scegli un\'altra regione Non hai mappe offline installate. Si può scegliere una mappa dalla lista o scaricarle in seguito andando su \'Menù - %1$s\'. - Il costo della sottoscrizione verrà addebitato ogni mese. Puoi scegliere di annullare la sottoscrizione su Google Play in ogni momento. + La sottoscrizione viene addebitata ogni mese. Puoi annullarla su Google Play in ogni momento. Donazione per la comunità di OpenStreetMap Parte della tua donazione verrà inviata agli utenti che fanno modifiche su OpenStreetMap. Il costo della sottoscrizione rimane inalterato. La sottoscrizione attiva aggiornamenti orari, quotidiani e settimanali e la possibilità di scaricare senza limiti tutte le mappe del mondo. @@ -3134,7 +3134,7 @@ Il formato selezionato sarà applicato per tutta l\'app. Questa impostazione è selezionata di default per i profili: %s Cambia impostazioni - Annulla cambiamenti + Annulla modifiche Applica solo a \"%1$s\" Applica a tutti i profili Messaggio di avvio @@ -3704,7 +3704,7 @@ Abilita per controllare il livello di zoom della mappa con i pulsanti del volume del dispositivo. Pulsanti volume come zoom Per favore indica un nome per il punto - Il punto di destinazione corrente sul percorso verrà eliminato. Se sarà la Destinazione, la navigazione verrà interrotta. + Elimina la destinazione successiva nel percorso. Se questa è la destinazione finale, la navigazione si fermerà. Scarica mappe Wikipedia Ottieni informazioni sui punti di interesse da Wikipedia. È la tua guida tascabile offline - basta abilitare il plugin Wikipedia e goderti gli articoli sugli oggetti intorno a te. Moto da enduro diff --git a/OsmAnd/res/values-iw/strings.xml b/OsmAnd/res/values-iw/strings.xml index 2d8c31ec67..4915811995 100644 --- a/OsmAnd/res/values-iw/strings.xml +++ b/OsmAnd/res/values-iw/strings.xml @@ -3986,4 +3986,19 @@ אופני הרים שגיאת שרת: %1$s השם כבר קיים + סטייה ממסלול + הגעה ליעד + הצגת המסלול על המפה + רכיבה חשמלית + רכיבת הרים + רכיבת כביש + רכיבה רגילה + טיול שטח + משאית כבדה + למחוק את מנוע הניווט המקוון הזה\? + להציג במלואו + עריכת תיאור + מחיקת נקודות דרך + העתקה לסמני המפה + העתקה למועדפים \ No newline at end of file diff --git a/OsmAnd/res/values-pt-rBR/strings.xml b/OsmAnd/res/values-pt-rBR/strings.xml index 2d9bc87624..44ac4e79b6 100644 --- a/OsmAnd/res/values-pt-rBR/strings.xml +++ b/OsmAnd/res/values-pt-rBR/strings.xml @@ -3995,4 +3995,10 @@ MTB Erro de servidor: %1$s O nome já existe + Editar descrição + Apagar ponto fixo + Copiar para marcadores de mapa + Copiar para favoritos + Excluir este mecanismo de roteamento online\? + Ler na íntegra \ No newline at end of file diff --git a/OsmAnd/res/values-sc/strings.xml b/OsmAnd/res/values-sc/strings.xml index c4b514317b..c0caa235d6 100644 --- a/OsmAnd/res/values-sc/strings.xml +++ b/OsmAnd/res/values-sc/strings.xml @@ -3964,4 +3964,22 @@ Ischerta sa cartella Ischerta una cartella o crea·nde una noa Bòidu + Intervallos de tempus e de distàntzia + Incumintza a registrare + Ammustra sa rasta in sa mapa + Cadira a rodas + Escursionismu + A pee + Tziclismu elètricu + Tziclismu de monte + Tziclismu in carreras + Tziclismu regulare + Veìculu de trasportu + Camioneta + Càmion + Motorinu (Scooter) + Bitzicleta de cursa + MTB (motosilurante) + Errore de su serbidore: %1$s + Su nùmene esistit giai \ No newline at end of file diff --git a/OsmAnd/res/values-sk/strings.xml b/OsmAnd/res/values-sk/strings.xml index e89e617204..95f34a3db1 100644 --- a/OsmAnd/res/values-sk/strings.xml +++ b/OsmAnd/res/values-sk/strings.xml @@ -160,7 +160,7 @@ Vymazať úpravu Asynchrónne upravovanie OSM: OSM POI/poznámky uložené v zariadení - Zobraziť a spravovať OSM bodu záujmu/poznámky uložené v databáze v zariadení. + Zobraziť a spravovať OSM body záujmu/poznámky uložené v databáze v zariadení. Určiť interval stopovania naživo. Interval stopovania naživo Zadajte webovú adresu stopovania naživo so syntaxom parametrov: lat={0}, lon={1}, timestamp={2}, hdop={3}, altitude={4}, speed={5}, bearing={6}. @@ -698,7 +698,7 @@ Filter \'%1$s\' bol vytvorený Východzí bod nebol zatiaľ zistený. Zrušiť sťahovanie\? - Základná potrebná pre základné funkcie aplikácie bola zaradená na stiahnutie. + Základná mapa potrebná pre základné funkcie aplikácie bola zaradená na stiahnutie. Názov Kategória DDD.DDDDD @@ -1091,7 +1091,7 @@ Svetové korekcie nadmorskej výšky Svetové námorné značky Svetové platby bitcoinom - Svetová základná mapa + Svetová prehľadová mapa Svetová lyžiarska mapa Chorvátsky (Hrvatski) Čínsky (中国的) @@ -2696,7 +2696,7 @@ Záložka Skryť celý popis Zobraziť celý popis - Pre jazdenie mimo cesty v teréne (off-road) založený na štýle \'Topo\' a pre použitie s podkladovou mapou zo zelených satelitných snímok. Znížená hrúbka ciest, zvýšená hrúbka poľných ciest, chorníkov, cyklistických a iných trás. + Pre jazdenie mimo cesty v teréne (off-road) založený na štýle \'Topo\' a pre použitie s podkladovou mapou zo zelených satelitných snímok. Znížená hrúbka ciest, zvýšená hrúbka poľných ciest, chodníkov, cyklistických a iných trás. Pre námornú navigáciu. Obsahuje bóje, majáky, vodné cesty, morské trasy a značky, prístavy, námorné služby a hĺbkové vrstevnice. Pre lyžovanie. Obsahuje zjazdovky, lyžiarske vleky a iné objekty pre lyžiarov. Druhoradé objekty na mape sú menej výrazné. Jednoduchý štýl pre navigáciu auta. Príjemný nočný režim, vrstevnice, kontrastné oranžové cesty, druhoradé objekty na mape sú menej výrazné. diff --git a/OsmAnd/res/values-sl/strings.xml b/OsmAnd/res/values-sl/strings.xml index 9a0e2bec9b..89091ce1d4 100644 --- a/OsmAnd/res/values-sl/strings.xml +++ b/OsmAnd/res/values-sl/strings.xml @@ -3271,4 +3271,38 @@ Ustvari novo pot Končano Prepiši sled + Mape + Izberi mapo + Izberi mapo ali dodaj novo + Prazno + Analiziraj po intervalih (razdelitveni interval) + Naloži v OpenStreetMap + Uredi sled + Preimenuj sled + Spremeni mapo + sek + Pristop + Pripravi se + Izven poti + Prihod na cilj + Zavoj + Intervali časa in razdalje + Čas objave različnih glasovnih pozivov je odvisen od vrste poziva, trenutne hitrosti navigacije in privzete hitrosti navigacije. + Čas objave + Začni snemanje + Invalidski voziček + Hoja + Pohodništvo + Električno kolesarjenje + Gorsko kolesarjenje + Cestno kolesarjenje + Redno kolesarjenje + Težko tovorno vozilo + Majhno tovorno vozilo + Tovorno vozilo + Skuter + Dirkalno kolo + MTB + Napaka strežnika: %1$s + To ime že obstaja \ No newline at end of file diff --git a/OsmAnd/res/values-tr/strings.xml b/OsmAnd/res/values-tr/strings.xml index 9b7d3c4972..02664a0a1e 100644 --- a/OsmAnd/res/values-tr/strings.xml +++ b/OsmAnd/res/values-tr/strings.xml @@ -4001,4 +4001,10 @@ Yarış bisikleti Sunucu hatası: %1$s Ad zaten var + Ara noktaları sil + Harita işaretleyicilerine kopyala + Sık kullanılanlara kopyala + Bu çevrim içi yönlendirme motoru silinsin mi\? + Tamamını oku + Açıklamayı düzenle \ No newline at end of file diff --git a/OsmAnd/res/values-uk/phrases.xml b/OsmAnd/res/values-uk/phrases.xml index 759b53b5f9..9464312798 100644 --- a/OsmAnd/res/values-uk/phrases.xml +++ b/OsmAnd/res/values-uk/phrases.xml @@ -2790,7 +2790,7 @@ Вирощується культура: рис Вид вибуху: неглибокого закладення Послуги надаються дорослим: так - Різдво: нотатка + Різдво: примітка Крильця Ямайська Місця на відкритому повітрі: пішохідна зона @@ -3019,7 +3019,7 @@ Вино: так Напої і закуски Болото, періодично затоплюване морською водою - Нотатка + Примітка Вирощується культура: квіти Водонагрівач: відсутній Орієнтація майданчика для вільного польоту: схід (E) diff --git a/OsmAnd/res/values-uk/strings.xml b/OsmAnd/res/values-uk/strings.xml index 843c7adc62..f180654a56 100644 --- a/OsmAnd/res/values-uk/strings.xml +++ b/OsmAnd/res/values-uk/strings.xml @@ -22,12 +22,12 @@ Автономна навігація OsmAnd тимчасово не доступна. Лівосторонній рух Для країн з лівостороннім рухом. - Початкове місцезнаходження ще не визначено. + Початкове місцеперебування ще не визначено. Розташування ще не визначено. Встановити прозорість (0 – прозорий, 255 – непрозорий) Скасувати завантаження\? Дякуємо за користування OsmAnd. Завантажуйте регіональні дані для користування в автономному режимі за допомогою пункту меню \'Налаштування\' → \'Керування мапами\' для перегляду мап, пошуку адрес, POI, громадського транспорту тощо. - Основна мапа, необхідна для забезпечення основних можливостей, знаходиться у черзі завантаження. + Основна мапа, необхідна для забезпечення основних можливостей, перебуває у черзі завантаження. Нічого не знайдено. Якщо Ви не знайшли свій регіон, Ви можете створити його самостійно (див. https://osmand.net). Мережеві та кешовані растрові мапи Звичайні мапи (векторні) @@ -57,7 +57,7 @@ Для поточної місцевості відсутні векторні автономні мапи. Завантажте їх у \'Налаштуваннях\' (\'Керування файлами мап\') або перемкніться на втулок \'Мережеві мапи\'. Відправити GPX файли в OSM? Видимість - Теги + Мітки Для вивантаження GPX-файлів вкажіть ваше ім\'я користувача і пароль в OSM. Підтримка Підтримати розробку нових функцій @@ -121,13 +121,13 @@ Якщо ввімкнено редагування в автономному режимі, тоді зміни буде збережено спочатку локально та завантажено за запитом, інакше зміни буде завантажено негайно. Зміни POI всередині застосунку не впливають на завантажені файли мап - вони зберігаються в окремий файл на Вашому пристрої. Вивантаження… - {0} POI/нотатки вивантажено + {0} POI/примітки вивантажено Вивантажити усе Вивантажити правки в OSM Видалити редагування Асинхронне редагування OSM: - OSM-POI/Нотатки, збережено на пристрої - Перегляд і керування OSM-POI/нотатками, збереженими у базі даних на пристрої. + OSM-POI/примітки, збережено на пристрої + Перегляд і керування OSM-POI/примітками, збереженими у базі даних пристрою. Вкажіть інтервал надсилання даних. Інтервал надсилання даних Вкажіть веб-адресу з наступними параметрами: lat={0}, lon={1}, timestamp={2}, hdop={3}, altitude={4}, speed={5}, bearing={6}. @@ -312,8 +312,8 @@ Поділитись, використовуючи Координати: %1$s\n%2$s Щоб побачити розташування, перейдіть за веб-посиланням %1$s або intent-посиланням Android %2$s - Надіслати місцезнаходження - Поділитись місцезнаходженням + Надіслати місцеперебування + Поділитись місцеперебуванням Маршрутну точку GPX \"{0}\" додано Додати точку до записаного треку Адміністративні @@ -435,7 +435,7 @@ Яндекс Пробки Маршрут Закладки - Нотатки OSM (мережеві) + Примітки OSM (мережеві) POI-накладення… Джерело мапи… Шари мапи @@ -575,7 +575,7 @@ Закрити Дані завантажуються… Зчитування даних… - Помилка у роботі застосунку. Файл журналу знаходиться тут {0}. Будь ласка, напишіть розробнику про помилку (з вкладеним журнальним файлом). + Помилка роботи застосунку. Файл журналу розміщено тут {0}. Повідомте розробника про помилку (з вкладеним файлом журналу). Збереження GPX-файлу… Закінчено Використовувати Інтернет для прокладання маршруту. @@ -597,7 +597,7 @@ Оновити мапу Оновити частину мапи Точка - Додати в закладки + Додати до закладок Вибір між місцевими та англійськими назвами. Використовувати англійські назви на мапах Налаштування програми @@ -657,7 +657,7 @@ Застосувати Додати Ні - Введіть ім’я Закладки + Введіть назву Закладки Закладка Точку Закладки \'\'{0}\'\' додано. Редагувати Закладку @@ -683,7 +683,7 @@ Відкрити Коментар Зміна POI - Наступні теги POI не можуть бути змінені + Всі інші мітки POI не буде змінено Зберегти Очистити Фільтр @@ -776,7 +776,7 @@ Світлина %1$s %2$s Зробити світлину Зробити світлину - Взаємозберігайте треки та звуко/відео-нотатки з Вашим обліковим записом Dropbox. + Синхронізуйте треки та звуко/відеопримітки з вашим обліковим записом Dropbox. Втулок Dropbox Змінити порядок Будь ласка, зверніть увагу на оплату втулка \"Горизонталі\" для підтримки подальшого розвитку. @@ -795,7 +795,7 @@ недоступно Зупинити Почати - Звуко/відео-нотатки + Звуко/відеопримітки Втулок OsmAnd для показу горизонталей в автономному режимі Використовувати програму Камера Налаштування аудіо/відео запису. @@ -805,8 +805,8 @@ Запис За запитом\? Аудіо/відео зараз записується. Для зупинки натисніть на AV-віджет. - Створити аудіо-нотатку - Створити відео-нотатку + Створити аудіопримітку + Створити відеопримітку Вилучити запис Грати Проміжний пункт призначення @@ -820,9 +820,9 @@ \n \nВсесвітні дані (між 70° на півночі і 70° на півдні) базуються на вимірюваннях SRTM (Shuttle Radar Topography Mission) і ASTER (Advanced Spaceborne Thermal Emission and Reflection Radiometer), даних інструменту відмальовуванню Terra, флагманського супутника системи спостереження Землі від NASA. ASTER — це підсумок спільної роботи NASA, міністерства економіки Японії, міністерства торгівлі і промисловості Японії (METI), агенції космічних систем Японії (J-spacesystems). Вимірювання відстаней - Звуко-нотатки - Зробіть звуко/світлино/відео нотатки під час подорожі, використовуючи або кнопку мапи, або контекстне меню розташування. - Звуко/відео-нотатки + Аудіопримітки + Робіть звуко/світлино/відео примітки під час подорожі використовуючи кнопку мапи або контекстне меню розташування. + Звуко/відеопримітки частин Горизонталі Цей втулок показує як шар горизонталей, так і шар рельєфу поверх усталених мап OsmAnd. Ця функціональність стане в пригоді спортсменам, туристам, мандрівникам та будь-кому, хто цікавиться структурою рельєфу місцевості. (Зверніть увагу, що дані про горизонталі є окремими від даних про рельєф; додаткові завантаження доступні після задіювання втулку.) @@ -843,7 +843,7 @@ Запустити програму в безпечному режимі (використовує повільніші Android-функції замість власних). Безпечний режим Програму запущено в безпечному режимі (вимкніть його в \'Налаштуваннях\'). - Оберіть \"Використати місцезнаходження...\" для прив\'язки нотатки до даного місцезнаходження. + Виберіть \"Використати місцеперебування...\" для прив\'язки примітки до поточного розташування. Службу OsmAnd у тлі досі запущено. Зупинити її роботу також\? Закрити набір змін Програма \'ZXing Barcode Scanner\' не встановлена. Шукати в Google Play? @@ -1370,8 +1370,8 @@ Північної широти Відхилити Аудіо - Поділитись нотаткою - A/V нотатки + Поділитись приміткою + A/V примітки Мережева мапа Тільки дороги Вільно %1$s @@ -1382,7 +1382,7 @@ Завантажте спеціальну безмережеву мапу, щоб відобразити морські подробиці. Редагувати групу Місце для стоянки - ВИЛУЧИТИ ТЕҐ + ВИЛУЧИТИ МІТКУ Стан GPS Завантажити нічні збірки. Збірки @@ -1589,7 +1589,7 @@ Себуанська У Вас є старі несумісні дані з Вікіпедії. Заархівувати їх? Завантажити додаткові дані з Вікіпедії (%1$s Мб)\? - Служба визначення місцезнаходження вимкнена. Увімкнути? + Служба визначення розташування вимкнена. Увімкнути\? Запобігти самостійному логуваню Імпортувати до OsmAnd Читати повну статтю (мережево) @@ -1624,19 +1624,19 @@ Зберегти локально OSM POI відредаговано OSM POI видалено - Відкрити OSM-нотатку - Відкрити заново OSM-нотатку - До OSM-нотатки додано коментар - Створено OSM-нотатку - OSM-нотатка - Створити нотатку + Відкрити примітку OSM + Повторно відкрити примітку OSM + До примітки OSM додано коментар + Створено примітку OSM + Примітка OSM + Створити примітку Додати коментар - Перевідкрити нотатку - Закрити нотатку - Нотатку створено - Не вдалося створити нотатку. - Нотатку закрито - Не вдалося закрити нотатку. + Перевідкрити примітку + Закрити примітку + Примітку створено + Не вдалося створити примітку. + Примітку закрито + Не вдалося закрити примітку. Підтвердити Вилучити GPX точку? Редагувати GPX точку @@ -1656,7 +1656,7 @@ Показати мапу Імітувати перший запуск застосунку гео: - Поділитись місцезнаходженням + Поділитись місцеперебуванням Надіслати Будь ласка, використовуйте назву категорії, яка ще не існує. Назва категорії @@ -1790,7 +1790,7 @@ OSM правки, поширені через OsmAnd Заплановані обʼєкти Ви дійсно хочете зберегти POI, не вказавши його тип? - Надання доступу до даних про місцезнаходження. + Надання доступу до даних про місцеперебування. Надання доступу до камери. Надання доступу до мікрофона. Відстань: @@ -1947,8 +1947,8 @@ Передплата дозволяє щогодини отримувати оновлення для мап по всьому світу. \nЧастина від передплати переводиться спільноті OSM та виплачується кожному землеписцю за його внесок. \nЯкщо Вам подобається OsmAnd та OSM, і хочете підтримати і бути підтриманими ними, це ідеальний спосіб зробити це. - Надішліть Вашу OSM-нотатку таємно, або скориставшись обліковим записом на OSM.org. - Надіслати нотатку в OSM + Надішліть примітку OSM знеособлено чи скориставшись профілем OpenStreetMap.org. + Надіслати примітку в OSM Неприпустимі знаки в назві файлу Слідкуйте за нами Звукові напрямки @@ -2039,7 +2039,7 @@ Неможливо визначити місце розташування З’єднання з Інтернетом відсутнє Необхідно завантажити мапи. - Визначення місцезнаходження… + Визначення місцеперебування… Вільне місце Сховище даних OsmAnd (мапи, файли з треками, тощо): %1$s. Дати дозвіл @@ -2162,19 +2162,19 @@ Додати підкладку Змінити джерело мапи Довге натискання з перетягуванням кнопки змінює її розташування на екрані. - Додати нотатку OSM + Додати примітку OSM Дуже тонкий Відкритий код розташування (OLC) - Нова аудіонотатка - Нова відеонотатка - Нова фотонотатка + Нова аудіопримітка + Нова відеопримітка + Нова фотопримітка Найменування Кнопка для додавання позначки мапи посередині екрану. Натискання на цю кнопку додасть маршрутну точку GPX посередині екрану. - Натискання цієї кнопки додає аудіонотатку посередині екрану. - Натискання цієї кнопки додає відеонотатку посередині екрану. - Натискання цієї кнопки додає фотонотатку посередині екрану. - Натискання цієї кнопки додає OSM-нотатку посередині екрану. + Натискання цієї кнопки додає аудіопримітку посередині екрана. + Натискання цієї кнопки додає відеопримітку посередині екрана. + Натискання цієї кнопки додає фотопримітку посередині екрана. + Натискання цієї кнопки додає примітку OSM посередині екрану. Натискання цієї кнопки додає POI посередині екрану. Перемикач, щоб вимкнути або увімкнути голосові підказки під час навігації. Кнопка для додавання місця паркування посередині екрана. @@ -2210,12 +2210,12 @@ Шукати знову Збільшити радіус пошуку Нічого не знайдено - Місце призначення знаходиться в області з приватним доступом. Дозволити доступ по приватних дорогах для цієї подорожі\? + Місце призначення розташовано в області з приватним доступом. Дозволити доступ до приватних доріг у цій подорожі\? Змініть пошуковий запит або ж розширте пошуковий радіус. - Показати/приховати OSM-нотатки - Показати OSM-нотатки - Приховати OSM-нотатки - Натискання на кнопку дії покаже чи приховає OSM-нотатки на мапі. + Показати/приховати примітки OSM + Показати примітки OSM + Приховати примітки OSM + Натискання на кнопку дії покаже чи приховає примітки OSM на мапі. Відсортоване за відстанню Пошук у закладках Завантажте шар мапи «Пагорби», щоб показати вертикальне затінення. @@ -2304,12 +2304,12 @@ \n Катання на лижах \nOsmAnd-втулок лижних мап дозволяє бачити лижні траси з рівнем складності та деякою додатковими відомостями на зразок розташування підйомників та інших об’єктів. - Їзда на велосипеді -\n• Знаходьте велосипедні доріжки на мапі -\n• GPS-навігація у велосипедному режимі будує маршрут з використанням велосипедних доріжок -\n• Ви можете бачити свою швидкість та висотне положення -\n• Опція запису GPX дозволяє вам записувати Вашу подорож та ділитися нею -\n• Через додатковий втулок Ви можете увімкнути відображення горизонталей та рельєфу + Їзда на велосипеді +\n• Знаходьте велосипедні доріжки на мапі +\n• GPS-навігація у велосипедному режимі будує маршрут з використанням велосипедних доріжок +\n• Ви можете бачити свою швидкість та висотне положення +\n• Параметр запису GPX дозволяє вам записувати вашу подорож та ділитися нею +\n• Через додатковий втулок ви можете увімкнути показ горизонталей та рельєфу Прогулянки, походи, екскурсія по місту \n• Мапа показує доріжки для прогулянок та походів \n• Вікіпедія Вашою обраною мовою може багато розповісти під час екскурсії містом @@ -2382,9 +2382,9 @@ Безпосередній вклад у OSM \n• Звітуйте про помилки в даних \n• Вивантажуйте GPX-треки в OSM безпосередньо з програми -\n• Додавайте POI (цікаві точки) та безпосередньо вивантажуйте їх в OSM (чи пізніше, якщо зараз Ви в офлайні) -\n• Опція запису подорожі також і в режимі тла (в той час як пристрій знаходиться в сплячому режимі) -\nOsmAnd — вільне й відкрите програмне забезпечення, що активно розвивається. Кожен може внести свій вклад, звітуючи про помилки, поліпшуючи переклад чи розробляючи нові функції. Також проєкт покладається на фінансові внески для оплати розробки та тестування нових функціональних можливостей. +\n• Додавайте POI (цікаві точки) та безпосередньо вивантажуйте їх в OSM (чи пізніше, якщо зараз ви в автономному режимі) +\n• Параметр запису подорожі також і в тлі (коли пристрій перебуває в режимі сну) +\nOsmAnd — вільне й відкрите програмне забезпечення, що активно розвивається. Кожен може допомогти, звітуючи про помилки, поліпшуючи переклад чи розробляючи нові функції. Також проєкт покладається на фінансові внески для оплати розробки та тестування нових функціональних можливостей. \n Приблизне охоплення мап та якість: \n • Західна Європа: **** @@ -2505,7 +2505,7 @@ Сортувати за: Використовувати розташування Додати Ваше місце розташування як точку початку при плануванні маршруту. - Моє місцезнаходження + Моє місцеперебування Фініш Планувати маршрут Впорядкувати @@ -2526,9 +2526,9 @@ Уникає льодових доріг і бродів. Додати копію початкової точки як місце призначення. Зробити кругову подорож - Не вдалося змінити нотатку. - Змінити нотатку - Змінити OSM-нотатку + Не вдалося змінити примітку. + Змінити примітку + Змінити примітку OSM Неправильний ввід Неправильний формат Дорога @@ -2576,15 +2576,15 @@ Пошук треків з шляховими точками Більше Створити або змінити OSM-об\'єкти - Створюйте або змінюйте цікаві точки в OSM, відкривайте або коментуйте OSM-нотатки, а також надсилайте записані GPX-файли. + Створюйте або змінюйте OSM POI, відкривайте або коментуйте примітки OSM та надсилайте записані GPX-файли. Вилучено Відредаговано Додано Позначку %s задіяно. Натискання на позначку на мапі перемістить її на перше місце в списку задіяних позначок, не відкриваючи контекстне меню. Задіювання одним натисненням - Робіть нотатки! - Додайте аудіо, відео або фотонотатку в будь-яку точку на мапі, використовуючи віджет або контекстне меню. + Робіть примітки! + Додайте аудіо, відео або фотопримітку в будь-яку точку на мапі використовуючи віджет або контекстне меню. Примітки за датою За датою За типом @@ -2620,14 +2620,14 @@ Додає проміжну зупинку Додає першу зупинку Пересунути призначення далі і створити його - Показати закриті нотатки + Показати закриті примітки Показати чи приховати примітки OSM на мапі. GPX — підходить для експорту в JOSM та інші OSM-редактори. OSC — підходить для експорту в OSM. GPX-файл OSC-файл Виберіть тип файлу - Виберіть вид експорту: OSM-нотатки, POI чи і те і те. + Виберіть вид експорту: примітки OSM, POI чи і те і те. Усі дані Примітки OSM Відкриється завтра о @@ -2844,7 +2844,7 @@ Крутість Запустити OsmAnd\? Пішки - Довжина тегу \"%s\" має бути менше 255 символів. + Довжина мітки \"%s\" має бути менше 255 символів. Докладніше про те, як OsmAnd розраховує маршрути, читайте в нашому деннику. Навігація громадським транспортом на даний час проходить тестування, можливі помилки та неточності. Додати проміжну точку @@ -3339,13 +3339,13 @@ Розмір зображення, якість звуку та відео Логін, пароль, редагування в безмережному режимі Оберіть значок, колір та назву - Дозволяє ділитися поточним місцезнаходженням, використовуючи запис поїздки. + Дозволяє ділитися поточним місцеперебуванням, використовуючи запис поїздки. Мережеве відстеження Точність журналювання Ви можете знайти всі записи в %1$s або в теці OsmAnd за допомогою файлового провідника. - Ваші нотатки OSM знаходяться в %1$s. - Відеонотатки - Фотонотатки + Ваші примітки OSM розміщено в %1$s. + Відеопримітки + Фотопримітки Перерахунок маршруту Оголошення Ім\'я користувача і пароль @@ -3617,7 +3617,7 @@ Показати чи приховати громадський транспорт Кнопка показу або приховування громадського транспорту на мапі. Створити чи змінити POI - Додати чи змінити вибране + Додати чи змінити закладку Відновити усталене впорядкування Повернутися до редагування Ви можете отримати доступ до цих дій, торкнувшись кнопки “%1$s”. @@ -3999,4 +3999,10 @@ Гірський велосипед Помилка сервера: %1$s Назва вже існує + Видалити цей рушій мережної маршрутизації\? + Читати повністю + Змінити опис + Видалити маршрутні точки + Копіювати до позначок мапи + Копіювати до закладок \ No newline at end of file diff --git a/OsmAnd/res/values-zh-rCN/strings.xml b/OsmAnd/res/values-zh-rCN/strings.xml index 97d64f7faf..6b188df900 100644 --- a/OsmAnd/res/values-zh-rCN/strings.xml +++ b/OsmAnd/res/values-zh-rCN/strings.xml @@ -491,7 +491,7 @@ 靠右行驶 隐藏多边形 渲染模式 - + 显示等高线 显示更多地图细节 路线规划数据 格式 @@ -1120,7 +1120,7 @@ 不要发送匿名应用使用统计信息 恢复购买内容 可见性 - OsmAnd 会搜集您打开应用的哪一部分的信息。您的位置永远不会被发送至服务器,您输入进应用的任何数据或者浏览的区域、搜索内容和下载内容同样不会被搜集。 + OsmAnd 只会搜集您打开应用的那一部分的信息。您的位置永远不会被发送至服务器,您输入进应用的任何数据或者浏览的区域、搜索内容和下载内容同样不会被搜集。 不要在启动时显示信息 感谢您购买完整版本的 OsmAnd! 操作名称 @@ -1915,7 +1915,7 @@ 音频/视频注记 轻触\"使用位置 …\"以在此添加注记。 音频注记 - + 高山远足表(SAC) 依据 SAC 分级计算路径 徒步旅行符号叠加层 根据 OSMC 轨迹渲染路径。 @@ -3112,4 +3112,16 @@ 添加地址 输入地址 REC + OsmAnd将为选择的配置文件连接路线点。 + 在之前添加点 + 在之后添加点 + 路线点 + 保存为路线点 + 路线点1 + 保存路线点 + 用于在线跟踪的时间缓冲区 + 添加轨迹航点 + 添加轨迹航点 + 将轨迹记录到GPX文件 + 当应用程序被杀死时,跟踪日志将被暂停(通过最近的应用程序)。(OsmAnd背景指示会从Android通知栏中消失)。 \ No newline at end of file diff --git a/OsmAnd/res/values/strings.xml b/OsmAnd/res/values/strings.xml index 79d3a211b4..7cd16f7f7e 100644 --- a/OsmAnd/res/values/strings.xml +++ b/OsmAnd/res/values/strings.xml @@ -12,6 +12,11 @@ --> + Select edits for upload + Uploaded %1$d of %2$d + Uploading %1$d of %2$d + Upload completed + Uploading Copy to favorites Copy to map markers Delete waypoints diff --git a/OsmAnd/src/net/osmand/plus/GpxSelectionHelper.java b/OsmAnd/src/net/osmand/plus/GpxSelectionHelper.java index f23320d091..5dd44bf989 100644 --- a/OsmAnd/src/net/osmand/plus/GpxSelectionHelper.java +++ b/OsmAnd/src/net/osmand/plus/GpxSelectionHelper.java @@ -153,12 +153,12 @@ public class GpxSelectionHelper { return followTrackListener; } - private static class GpxFileLoaderTask extends AsyncTask { + public static class GpxFileLoaderTask extends AsyncTask { private File fileToLoad; private CallbackWithObject callback; - GpxFileLoaderTask(File fileToLoad, CallbackWithObject callback) { + public GpxFileLoaderTask(File fileToLoad, CallbackWithObject callback) { this.fileToLoad = fileToLoad; this.callback = callback; } diff --git a/OsmAnd/src/net/osmand/plus/UiUtilities.java b/OsmAnd/src/net/osmand/plus/UiUtilities.java index 94bd3c4bcb..8d3a6d35bf 100644 --- a/OsmAnd/src/net/osmand/plus/UiUtilities.java +++ b/OsmAnd/src/net/osmand/plus/UiUtilities.java @@ -636,7 +636,7 @@ public class UiUtilities { int activeDisableColor = getColorWithAlpha(activeColor, 0.25f); ColorStateList activeCsl = new ColorStateList(states, new int[] {activeColor, activeDisableColor}); int inactiveColor = ContextCompat.getColor(ctx, nightMode ? R.color.icon_color_default_dark : R.color.icon_color_secondary_light); - ColorStateList inactiveCsl = new ColorStateList(states, new int[] {inactiveColor, inactiveColor}); + ColorStateList inactiveCsl = new ColorStateList(states, new int[] {activeDisableColor, inactiveColor}); slider.setTrackActiveTintList(activeCsl); slider.setTrackInactiveTintList(inactiveCsl); slider.setHaloTintList(activeCsl); diff --git a/OsmAnd/src/net/osmand/plus/activities/MapActivity.java b/OsmAnd/src/net/osmand/plus/activities/MapActivity.java index eb6dcbfbb7..0de562fa2b 100644 --- a/OsmAnd/src/net/osmand/plus/activities/MapActivity.java +++ b/OsmAnd/src/net/osmand/plus/activities/MapActivity.java @@ -70,7 +70,6 @@ import net.osmand.plus.GpxSelectionHelper.GpxDisplayItem; import net.osmand.plus.GpxSelectionHelper.SelectedGpxFile; import net.osmand.plus.OnDismissDialogFragmentListener; import net.osmand.plus.OsmAndConstants; -import net.osmand.plus.OsmAndLocationProvider; import net.osmand.plus.OsmAndLocationProvider.OsmAndLocationListener; import net.osmand.plus.OsmAndLocationSimulation; import net.osmand.plus.OsmandApplication; @@ -1568,6 +1567,17 @@ public class MapActivity extends OsmandActionBarActivity implements DownloadEven } } + public boolean shouldHideTopControls() { + boolean hideTopControls = !mapContextMenu.shouldShowTopControls(); + + TrackMenuFragment fragment = getTrackMenuFragment(); + if (fragment != null) { + hideTopControls = hideTopControls || !fragment.shouldShowTopControls(); + } + + return hideTopControls; + } + public OsmandMapTileView getMapView() { return mapView; } @@ -1628,8 +1638,8 @@ public class MapActivity extends OsmandActionBarActivity implements DownloadEven launchMapActivityMoveToTop(activity, null); } - public static void launchMapActivityMoveToTop(Context activity, Bundle intentParams) { - launchMapActivityMoveToTop(activity, intentParams, null, null); + public static void launchMapActivityMoveToTop(Context activity, Bundle prevIntentParams) { + launchMapActivityMoveToTop(activity, prevIntentParams, null, null); } public static void clearPrevActivityIntent() { diff --git a/OsmAnd/src/net/osmand/plus/base/ContextMenuFragment.java b/OsmAnd/src/net/osmand/plus/base/ContextMenuFragment.java index 4f6097897f..4cc90afd96 100644 --- a/OsmAnd/src/net/osmand/plus/base/ContextMenuFragment.java +++ b/OsmAnd/src/net/osmand/plus/base/ContextMenuFragment.java @@ -103,7 +103,7 @@ public abstract class ContextMenuFragment extends BaseOsmAndFragment public interface ContextMenuFragmentListener { void onContextMenuYPosChanged(@NonNull ContextMenuFragment fragment, int y, boolean needMapAdjust, boolean animated); - void onContextMenuStateChanged(@NonNull ContextMenuFragment fragment, int menuState); + void onContextMenuStateChanged(@NonNull ContextMenuFragment fragment, int menuState, int previousMenuState); void onContextMenuDismiss(@NonNull ContextMenuFragment fragment); } @@ -815,7 +815,7 @@ public abstract class ContextMenuFragment extends BaseOsmAndFragment ContextMenuFragmentListener listener = this.listener; if (listener != null) { - listener.onContextMenuStateChanged(this, newMenuState); + listener.onContextMenuStateChanged(this, newMenuState, currentMenuState); } } @@ -971,7 +971,8 @@ public abstract class ContextMenuFragment extends BaseOsmAndFragment ContextMenuFragmentListener listener = ContextMenuFragment.this.listener; if (listener != null) { - listener.onContextMenuStateChanged(ContextMenuFragment.this, getCurrentMenuState()); + int menuState = getCurrentMenuState(); + listener.onContextMenuStateChanged(ContextMenuFragment.this, menuState, menuState); } } } diff --git a/OsmAnd/src/net/osmand/plus/base/ContextMenuScrollFragment.java b/OsmAnd/src/net/osmand/plus/base/ContextMenuScrollFragment.java index 51f4278948..5ba853e147 100644 --- a/OsmAnd/src/net/osmand/plus/base/ContextMenuScrollFragment.java +++ b/OsmAnd/src/net/osmand/plus/base/ContextMenuScrollFragment.java @@ -82,7 +82,7 @@ public abstract class ContextMenuScrollFragment extends ContextMenuFragment impl } @Override - public void onContextMenuStateChanged(@NonNull ContextMenuFragment fragment, int menuState) { + public void onContextMenuStateChanged(@NonNull ContextMenuFragment fragment, int menuState, int previousMenuState) { updateMapControlsVisibility(menuState); } diff --git a/OsmAnd/src/net/osmand/plus/base/MenuBottomSheetDialogFragment.java b/OsmAnd/src/net/osmand/plus/base/MenuBottomSheetDialogFragment.java index 2af2d9673b..e4f0c6fa58 100644 --- a/OsmAnd/src/net/osmand/plus/base/MenuBottomSheetDialogFragment.java +++ b/OsmAnd/src/net/osmand/plus/base/MenuBottomSheetDialogFragment.java @@ -268,6 +268,18 @@ public abstract class MenuBottomSheetDialogFragment extends BottomSheetDialogFra dismissButtonStringRes = stringRes; } + protected int getDismissButtonHeight(){ + return getResources().getDimensionPixelSize(R.dimen.bottom_sheet_cancel_button_height_small); + } + + protected int getRightButtonHeight(){ + return getResources().getDimensionPixelSize(R.dimen.bottom_sheet_cancel_button_height_small); + } + + protected int getThirdButtonHeight(){ + return getResources().getDimensionPixelSize(R.dimen.bottom_sheet_cancel_button_height_small); + } + protected DialogButtonType getDismissButtonType() { return DialogButtonType.SECONDARY; } @@ -360,6 +372,7 @@ public abstract class MenuBottomSheetDialogFragment extends BottomSheetDialogFra private void setupDismissButton() { dismissButton = buttonsContainer.findViewById(R.id.dismiss_button); + dismissButton.getLayoutParams().height = getDismissButtonHeight(); int buttonTextId = getDismissButtonTextId(); if (buttonTextId != DEFAULT_VALUE) { UiUtilities.setupDialogButton(nightMode, dismissButton, getDismissButtonType(), buttonTextId); @@ -376,6 +389,7 @@ public abstract class MenuBottomSheetDialogFragment extends BottomSheetDialogFra private void setupRightButton() { rightButton = buttonsContainer.findViewById(R.id.right_bottom_button); + rightButton.getLayoutParams().height = getRightButtonHeight(); int buttonTextId = getRightBottomButtonTextId(); if (buttonTextId != DEFAULT_VALUE) { UiUtilities.setupDialogButton(nightMode, rightButton, getRightBottomButtonType(), buttonTextId); @@ -398,6 +412,7 @@ public abstract class MenuBottomSheetDialogFragment extends BottomSheetDialogFra protected void setupThirdButton() { thirdButton = buttonsContainer.findViewById(R.id.third_button); + thirdButton.getLayoutParams().height = getThirdButtonHeight(); int buttonTextId = getThirdBottomButtonTextId(); if (buttonTextId != DEFAULT_VALUE) { UiUtilities.setupDialogButton(nightMode, thirdButton, getThirdBottomButtonType(), buttonTextId); diff --git a/OsmAnd/src/net/osmand/plus/base/bottomsheetmenu/simpleitems/ProgressItem.java b/OsmAnd/src/net/osmand/plus/base/bottomsheetmenu/simpleitems/ProgressItem.java new file mode 100644 index 0000000000..ec3724b9d3 --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/base/bottomsheetmenu/simpleitems/ProgressItem.java @@ -0,0 +1,11 @@ +package net.osmand.plus.base.bottomsheetmenu.simpleitems; + +import net.osmand.plus.R; +import net.osmand.plus.base.bottomsheetmenu.SimpleBottomSheetItem; + +public class ProgressItem extends SimpleBottomSheetItem { + + public ProgressItem() { + this.layoutId = R.layout.bottom_sheet_item_progress; + } +} diff --git a/OsmAnd/src/net/osmand/plus/dialogs/RenameFileBottomSheet.java b/OsmAnd/src/net/osmand/plus/dialogs/RenameFileBottomSheet.java index af26533607..f2bfe0e6e7 100644 --- a/OsmAnd/src/net/osmand/plus/dialogs/RenameFileBottomSheet.java +++ b/OsmAnd/src/net/osmand/plus/dialogs/RenameFileBottomSheet.java @@ -99,7 +99,9 @@ public class RenameFileBottomSheet extends MenuBottomSheetDialogFragment { } private void updateFileName(String name) { - if (!Algorithms.isEmpty(name) && ILLEGAL_FILE_NAME_CHARACTERS.matcher(name).find()) { + if (Algorithms.isBlank(name)) { + nameTextBox.setError(getString(R.string.empty_filename)); + } else if (ILLEGAL_FILE_NAME_CHARACTERS.matcher(name).find()) { nameTextBox.setError(getString(R.string.file_name_containes_illegal_char)); } else { selectedFileName = name; diff --git a/OsmAnd/src/net/osmand/plus/dialogs/UploadPhotoProgressBottomSheet.java b/OsmAnd/src/net/osmand/plus/dialogs/UploadPhotoProgressBottomSheet.java new file mode 100644 index 0000000000..f1c37a55ee --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/dialogs/UploadPhotoProgressBottomSheet.java @@ -0,0 +1,118 @@ +package net.osmand.plus.dialogs; + +import android.content.Context; +import android.content.DialogInterface; +import android.content.DialogInterface.OnDismissListener; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.ProgressBar; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.fragment.app.FragmentActivity; +import androidx.fragment.app.FragmentManager; + +import net.osmand.plus.R; +import net.osmand.plus.UiUtilities; +import net.osmand.plus.base.MenuBottomSheetDialogFragment; +import net.osmand.plus.base.bottomsheetmenu.BaseBottomSheetItem; +import net.osmand.plus.base.bottomsheetmenu.BottomSheetItemWithDescription; +import net.osmand.plus.base.bottomsheetmenu.simpleitems.DividerSpaceItem; +import net.osmand.plus.mapcontextmenu.UploadPhotosAsyncTask.UploadPhotosListener; + +public class UploadPhotoProgressBottomSheet extends MenuBottomSheetDialogFragment implements UploadPhotosListener { + + public static final String TAG = UploadPhotoProgressBottomSheet.class.getSimpleName(); + + private ProgressBar progressBar; + private TextView uploadedPhotosTitle; + private TextView uploadedPhotosCounter; + + private OnDismissListener onDismissListener; + + private int progress; + private int maxProgress; + + @Override + public void createMenuItems(Bundle savedInstanceState) { + Context context = requireContext(); + LayoutInflater inflater = UiUtilities.getInflater(context, nightMode); + View view = inflater.inflate(R.layout.bottom_sheet_with_progress_bar, null); + + uploadedPhotosTitle = view.findViewById(R.id.title); + uploadedPhotosCounter = view.findViewById(R.id.description); + progressBar = view.findViewById(R.id.progress_bar); + progressBar.setMax(maxProgress); + String titleProgress = getString(progress == maxProgress? R.string.upload_photo_completed: R.string.upload_photo); + String descriptionProgress; + if (progress == maxProgress) { + descriptionProgress = getString(R.string.uploaded_count, progress, maxProgress); + } else { + descriptionProgress = getString(R.string.uploading_count, progress, maxProgress); + } + + BaseBottomSheetItem descriptionItem = new BottomSheetItemWithDescription.Builder() + .setDescription(descriptionProgress) + .setTitle(titleProgress) + .setCustomView(view) + .create(); + items.add(descriptionItem); + + updateProgress(progress); + + int padding = getResources().getDimensionPixelSize(R.dimen.content_padding_small); + items.add(new DividerSpaceItem(context, padding)); + } + + public void setMaxProgress(int maxProgress) { + this.maxProgress = maxProgress; + } + + public void setOnDismissListener(OnDismissListener onDismissListener) { + this.onDismissListener = onDismissListener; + } + + private void updateProgress(int progress) { + progressBar.setProgress(progress); + uploadedPhotosCounter.setText((getString(R.string.uploading_count, progress, maxProgress))); + uploadedPhotosTitle.setText(progress == maxProgress ? R.string.upload_photo_completed : R.string.upload_photo); + } + + @Override + public void uploadPhotosProgressUpdate(int progress) { + this.progress = progress; + updateProgress(progress); + } + + @Override + public void uploadPhotosFinished() { + updateProgress(maxProgress); + if (progress == maxProgress) { + uploadedPhotosCounter.setText((getString(R.string.uploaded_count, progress, maxProgress))); + setDismissButtonTextId(R.string.shared_string_close); + UiUtilities.setupDialogButton(nightMode, dismissButton, getDismissButtonType(), getDismissButtonTextId()); + } + } + + @Override + public void onDismiss(@NonNull DialogInterface dialog) { + super.onDismiss(dialog); + FragmentActivity activity = getActivity(); + if (onDismissListener != null && activity != null && !activity.isChangingConfigurations()) { + onDismissListener.onDismiss(dialog); + } + } + + public static UploadPhotosListener showInstance(@NonNull FragmentManager fragmentManager, int maxProgress, OnDismissListener listener) { + UploadPhotoProgressBottomSheet fragment = new UploadPhotoProgressBottomSheet(); + fragment.setRetainInstance(true); + fragment.setMaxProgress(maxProgress); + fragment.setOnDismissListener(listener); + fragmentManager.beginTransaction() + .add(fragment, UploadPhotoProgressBottomSheet.TAG) + .commitAllowingStateLoss(); + + return fragment; + } +} \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/download/DownloadResources.java b/OsmAnd/src/net/osmand/plus/download/DownloadResources.java index 4f820bac2a..56d137a696 100644 --- a/OsmAnd/src/net/osmand/plus/download/DownloadResources.java +++ b/OsmAnd/src/net/osmand/plus/download/DownloadResources.java @@ -13,6 +13,7 @@ import net.osmand.plus.OsmandApplication; import net.osmand.plus.OsmandPlugin; import net.osmand.plus.download.DownloadOsmandIndexesHelper.AssetIndexItem; import net.osmand.plus.inapp.InAppPurchaseHelper; +import net.osmand.plus.wikivoyage.data.TravelDbHelper; import net.osmand.util.Algorithms; import org.apache.commons.logging.Log; @@ -358,7 +359,9 @@ public class DownloadResources extends DownloadResourceGroup { continue; } if (ii.getType() == DownloadActivityType.WIKIVOYAGE_FILE) { - wikivoyageMaps.addItem(ii); + if (app.getTravelHelper() instanceof TravelDbHelper) { + wikivoyageMaps.addItem(ii); + } continue; } if (ii.getType() == DownloadActivityType.TRAVEL_FILE) { diff --git a/OsmAnd/src/net/osmand/plus/helpers/IntentHelper.java b/OsmAnd/src/net/osmand/plus/helpers/IntentHelper.java index e4e6fac9dd..0d569ba880 100644 --- a/OsmAnd/src/net/osmand/plus/helpers/IntentHelper.java +++ b/OsmAnd/src/net/osmand/plus/helpers/IntentHelper.java @@ -27,6 +27,7 @@ import net.osmand.plus.settings.backend.ApplicationMode; import net.osmand.plus.settings.backend.OsmandSettings; import net.osmand.plus.settings.fragments.BaseSettingsFragment; import net.osmand.plus.settings.fragments.BaseSettingsFragment.SettingsScreenType; +import net.osmand.plus.track.TrackMenuFragment; import net.osmand.util.Algorithms; import org.apache.commons.logging.Log; @@ -37,6 +38,8 @@ import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; +import static net.osmand.plus.activities.TrackActivity.CURRENT_RECORDING; +import static net.osmand.plus.activities.TrackActivity.TRACK_FILE_NAME; import static net.osmand.plus.osmedit.oauth.OsmOAuthHelper.OsmAuthorizationListener; public class IntentHelper { @@ -250,6 +253,12 @@ public class IntentHelper { } mapActivity.setIntent(null); } + if (intent.hasExtra(TrackMenuFragment.OPEN_TRACK_MENU)) { + String path = intent.getStringExtra(TRACK_FILE_NAME); + boolean currentRecording = intent.getBooleanExtra(CURRENT_RECORDING, false); + TrackMenuFragment.showInstance(mapActivity, path, currentRecording); + mapActivity.setIntent(null); + } } } diff --git a/OsmAnd/src/net/osmand/plus/importfiles/ImportHelper.java b/OsmAnd/src/net/osmand/plus/importfiles/ImportHelper.java index a46ae659b8..3f1456a659 100644 --- a/OsmAnd/src/net/osmand/plus/importfiles/ImportHelper.java +++ b/OsmAnd/src/net/osmand/plus/importfiles/ImportHelper.java @@ -29,7 +29,6 @@ import net.osmand.plus.OsmandApplication; import net.osmand.plus.R; import net.osmand.plus.activities.ActivityResultListener; import net.osmand.plus.activities.MapActivity; -import net.osmand.plus.activities.TrackActivity; import net.osmand.plus.dialogs.ImportGpxBottomSheetDialogFragment; import net.osmand.plus.helpers.GpxUiHelper; import net.osmand.plus.helpers.GpxUiHelper.GPXInfo; @@ -37,6 +36,7 @@ import net.osmand.plus.measurementtool.MeasurementToolFragment; import net.osmand.plus.settings.backend.ExportSettingsType; import net.osmand.plus.settings.backend.backup.SettingsHelper; import net.osmand.plus.settings.backend.backup.SettingsItem; +import net.osmand.plus.track.TrackMenuFragment; import net.osmand.plus.views.OsmandMapTileView; import net.osmand.util.Algorithms; @@ -596,10 +596,7 @@ public class ImportHelper { private void showGpxInDetailsActivity(String gpxFilePath) { if (!Algorithms.isEmpty(gpxFilePath)) { - Intent newIntent = new Intent(activity, app.getAppCustomization().getTrackActivity()); - newIntent.putExtra(TrackActivity.TRACK_FILE_NAME, gpxFilePath); - newIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); - activity.startActivity(newIntent); + TrackMenuFragment.openTrack(activity, new File(gpxFilePath), null); } } diff --git a/OsmAnd/src/net/osmand/plus/mapcontextmenu/MapContextMenu.java b/OsmAnd/src/net/osmand/plus/mapcontextmenu/MapContextMenu.java index c1a6a6cc0a..cd035da4bb 100644 --- a/OsmAnd/src/net/osmand/plus/mapcontextmenu/MapContextMenu.java +++ b/OsmAnd/src/net/osmand/plus/mapcontextmenu/MapContextMenu.java @@ -22,18 +22,17 @@ import net.osmand.data.FavouritePoint; import net.osmand.data.LatLon; import net.osmand.data.PointDescription; import net.osmand.data.TransportStop; -import net.osmand.plus.settings.backend.ApplicationMode; import net.osmand.plus.ContextMenuAdapter; import net.osmand.plus.GpxSelectionHelper.SelectedGpxFile; -import net.osmand.plus.mapmarkers.MapMarker; -import net.osmand.plus.mapmarkers.MapMarkersHelper.MapMarkerChangedListener; import net.osmand.plus.OsmandApplication; import net.osmand.plus.OsmandPlugin; import net.osmand.plus.R; import net.osmand.plus.TargetPointsHelper.TargetPoint; import net.osmand.plus.TargetPointsHelper.TargetPointChangedListener; import net.osmand.plus.activities.MapActivity; +import net.osmand.plus.helpers.AndroidUiHelper; import net.osmand.plus.helpers.GpxUiHelper; +import net.osmand.plus.mapcontextmenu.AdditionalActionsBottomSheetDialogFragment.ContextMenuItemClickListener; import net.osmand.plus.mapcontextmenu.MenuController.ContextMenuToolbarController; import net.osmand.plus.mapcontextmenu.MenuController.MenuState; import net.osmand.plus.mapcontextmenu.MenuController.MenuType; @@ -47,12 +46,14 @@ import net.osmand.plus.mapcontextmenu.editors.RtePtEditor; import net.osmand.plus.mapcontextmenu.editors.WptPtEditor; import net.osmand.plus.mapcontextmenu.other.MapMultiSelectionMenu; import net.osmand.plus.mapcontextmenu.other.ShareMenu; -import net.osmand.plus.mapcontextmenu.AdditionalActionsBottomSheetDialogFragment.ContextMenuItemClickListener; +import net.osmand.plus.mapmarkers.MapMarker; +import net.osmand.plus.mapmarkers.MapMarkersHelper.MapMarkerChangedListener; import net.osmand.plus.monitoring.OsmandMonitoringPlugin; import net.osmand.plus.routing.RoutingHelper; +import net.osmand.plus.settings.backend.ApplicationMode; import net.osmand.plus.transport.TransportStopRoute; -import net.osmand.plus.views.layers.ContextMenuLayer; import net.osmand.plus.views.OsmandMapLayer; +import net.osmand.plus.views.layers.ContextMenuLayer; import net.osmand.plus.views.mapwidgets.MapInfoWidgetsFactory.TopToolbarController; import net.osmand.plus.views.mapwidgets.MapInfoWidgetsFactory.TopToolbarControllerType; import net.osmand.util.Algorithms; @@ -570,18 +571,21 @@ public class MapContextMenu extends MenuTitleController implements StateChangedL public void updateControlsVisibility(boolean menuVisible) { MapActivity mapActivity = getMapActivity(); if (mapActivity != null) { - int topControlsVisibility = shouldShowTopControls(menuVisible) ? View.VISIBLE : View.GONE; - mapActivity.findViewById(R.id.map_center_info).setVisibility(topControlsVisibility); - mapActivity.findViewById(R.id.map_left_widgets_panel).setVisibility(topControlsVisibility); - mapActivity.findViewById(R.id.map_right_widgets_panel).setVisibility(topControlsVisibility); - - int bottomControlsVisibility = shouldShowBottomControls(menuVisible) ? View.VISIBLE : View.GONE; - mapActivity.findViewById(R.id.bottom_controls_container).setVisibility(bottomControlsVisibility); - - mapActivity.refreshMap(); + boolean topControlsVisible = shouldShowTopControls(menuVisible); + boolean bottomControlsVisible = shouldShowBottomControls(menuVisible); + updateControlsVisibility(mapActivity, topControlsVisible, bottomControlsVisible); } } + public static void updateControlsVisibility(@NonNull MapActivity mapActivity, boolean topControlsVisible, boolean bottomControlsVisible) { + AndroidUiHelper.updateVisibility(mapActivity.findViewById(R.id.map_center_info), topControlsVisible); + AndroidUiHelper.updateVisibility(mapActivity.findViewById(R.id.map_left_widgets_panel), topControlsVisible); + AndroidUiHelper.updateVisibility(mapActivity.findViewById(R.id.map_right_widgets_panel), topControlsVisible); + AndroidUiHelper.updateVisibility(mapActivity.findViewById(R.id.bottom_controls_container), bottomControlsVisible); + + mapActivity.refreshMap(); + } + public boolean shouldShowTopControls() { return shouldShowTopControls(isVisible()); } diff --git a/OsmAnd/src/net/osmand/plus/mapcontextmenu/MenuBuilder.java b/OsmAnd/src/net/osmand/plus/mapcontextmenu/MenuBuilder.java index 3890046fac..183e41a84f 100644 --- a/OsmAnd/src/net/osmand/plus/mapcontextmenu/MenuBuilder.java +++ b/OsmAnd/src/net/osmand/plus/mapcontextmenu/MenuBuilder.java @@ -1,22 +1,19 @@ package net.osmand.plus.mapcontextmenu; import android.app.Activity; +import android.content.ClipData; import android.content.ClipboardManager; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.res.ColorStateList; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; import android.graphics.Color; -import android.graphics.Matrix; import android.graphics.PorterDuff; import android.graphics.drawable.Drawable; import android.graphics.drawable.GradientDrawable; import android.net.Uri; import android.os.AsyncTask; -import android.os.Handler; -import android.os.Looper; +import android.os.Build; import android.text.SpannableStringBuilder; import android.text.Spanned; import android.text.TextUtils; @@ -39,14 +36,12 @@ import androidx.core.content.ContextCompat; import androidx.core.graphics.drawable.DrawableCompat; import net.osmand.AndroidUtils; -import net.osmand.PlatformUtil; import net.osmand.data.Amenity; import net.osmand.data.LatLon; import net.osmand.data.PointDescription; import net.osmand.data.QuadRect; import net.osmand.osm.PoiCategory; import net.osmand.osm.PoiType; -import net.osmand.osm.io.NetworkUtils; import net.osmand.plus.OsmAndFormatter; import net.osmand.plus.OsmandApplication; import net.osmand.plus.OsmandPlugin; @@ -54,6 +49,7 @@ import net.osmand.plus.R; import net.osmand.plus.UiUtilities; import net.osmand.plus.Version; import net.osmand.plus.activities.ActivityResultListener; +import net.osmand.plus.activities.ActivityResultListener.OnActivityResultListener; import net.osmand.plus.activities.MapActivity; import net.osmand.plus.helpers.FontCache; import net.osmand.plus.mapcontextmenu.builders.cards.AbstractCard; @@ -79,13 +75,6 @@ import net.osmand.plus.widgets.tools.ClickableSpanTouchListener; import net.osmand.util.Algorithms; import net.osmand.util.MapUtils; -import org.apache.commons.logging.Log; -import org.openplacereviews.opendb.util.exception.FailedVerificationException; - -import java.io.BufferedInputStream; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.InputStream; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; @@ -99,8 +88,6 @@ import static net.osmand.plus.mapcontextmenu.builders.cards.ImageCard.GetImageCa public class MenuBuilder { private static final int PICK_IMAGE = 1231; - private static final int MAX_IMAGE_LENGTH = 2048; - private static final Log LOG = PlatformUtil.getLog(MenuBuilder.class); public static final float SHADOW_HEIGHT_TOP_DP = 17f; public static final int TITLE_LIMIT = 60; protected static final String[] arrowChars = new String[] {"=>", " - "}; @@ -133,7 +120,6 @@ public class MenuBuilder { private String preferredMapLang; private String preferredMapAppLang; private boolean transliterateNames; - private View view; private View photoButton; private final OpenDBAPI openDBAPI = new OpenDBAPI(); @@ -270,7 +256,6 @@ public class MenuBuilder { } public void build(View view) { - this.view = view; firstRow = true; hidden = false; buildTopInternal(view); @@ -425,7 +410,7 @@ public class MenuBuilder { if (false) { AddPhotosBottomSheetDialogFragment.showInstance(mapActivity.getSupportFragmentManager()); } else { - registerResultListener(view); + registerResultListener(); final String baseUrl = OPRConstants.getBaseUrl(app); final String name = app.getSettings().OPR_USERNAME.get(); final String privateKey = app.getSettings().OPR_ACCESS_TOKEN.get(); @@ -443,6 +428,9 @@ public class MenuBuilder { Intent intent = new Intent(); intent.setType("image/*"); intent.setAction(Intent.ACTION_GET_CONTENT); + if (Build.VERSION.SDK_INT > 18) { + intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true); + } mapActivity.startActivityForResult(Intent.createChooser(intent, mapActivity.getString(R.string.select_picture)), PICK_IMAGE); } @@ -472,132 +460,33 @@ public class MenuBuilder { false, null, false); } - private void registerResultListener(final View view) { - mapActivity.registerActivityResultListener(new ActivityResultListener(PICK_IMAGE, new ActivityResultListener. - OnActivityResultListener() { + private void registerResultListener() { + mapActivity.registerActivityResultListener(new ActivityResultListener(PICK_IMAGE, new OnActivityResultListener() { @Override public void onResult(int resultCode, Intent resultData) { if (resultData != null) { - handleSelectedImage(view, resultData.getData()); + List imagesUri = new ArrayList<>(); + Uri data = resultData.getData(); + if (data != null) { + imagesUri.add(data); + } + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { + ClipData clipData = resultData.getClipData(); + if (clipData != null) { + for (int i = 0; i < clipData.getItemCount(); i++) { + Uri uri = resultData.getClipData().getItemAt(i).getUri(); + if (uri != null) { + imagesUri.add(uri); + } + } + } + } + execute(new UploadPhotosAsyncTask(mapActivity, imagesUri, getLatLon(), placeId, getAdditionalCardParams(), imageCardListener)); } } })); } - private void handleSelectedImage(final View view, final Uri uri) { - Thread t = new Thread(new Runnable() { - @Override - public void run() { - InputStream inputStream = null; - try { - inputStream = app.getContentResolver().openInputStream(uri); - if (inputStream != null) { - uploadImageToPlace(inputStream); - } - } catch (Exception e) { - LOG.error(e); - String str = app.getString(R.string.cannot_upload_image); - showToastMessage(str); - } finally { - Algorithms.closeStream(inputStream); - } - } - }); - t.start(); - } - - private void uploadImageToPlace(InputStream image) { - InputStream serverData = new ByteArrayInputStream(compressImageToJpeg(image)); - final String baseUrl = OPRConstants.getBaseUrl(app); - // all these should be constant - String url = baseUrl + "api/ipfs/image"; - String response = NetworkUtils.sendPostDataRequest(url, "file", "compressed.jpeg", serverData); - if (response != null) { - int res = 0; - try { - StringBuilder error = new StringBuilder(); - String privateKey = app.getSettings().OPR_ACCESS_TOKEN.get(); - String username = app.getSettings().OPR_USERNAME.get(); - res = openDBAPI.uploadImage( - placeId, - baseUrl, - privateKey, - username, - response, error); - if (res != 200) { - showToastMessage(error.toString()); - } else { - //ok, continue - } - } catch (FailedVerificationException e) { - LOG.error(e); - checkTokenAndShowScreen(); - } - if (res != 200) { - //image was uploaded but not added to blockchain - checkTokenAndShowScreen(); - } else { - String str = app.getString(R.string.successfully_uploaded_pattern, 1, 1); - showToastMessage(str); - //refresh the image - execute(new GetImageCardsTask(mapActivity, getLatLon(), getAdditionalCardParams(), imageCardListener)); - } - } else { - checkTokenAndShowScreen(); - } - } - - private void showToastMessage(final String str) { - new Handler(Looper.getMainLooper()).post(new Runnable() { - @Override - public void run() { - Toast.makeText(mapActivity.getBaseContext(), str, Toast.LENGTH_LONG).show(); - } - }); - } - - //This method runs on non main thread - private void checkTokenAndShowScreen() { - final String baseUrl = OPRConstants.getBaseUrl(app); - final String name = app.getSettings().OPR_USERNAME.get(); - final String privateKey = app.getSettings().OPR_ACCESS_TOKEN.get(); - if (openDBAPI.checkPrivateKeyValid(baseUrl, name, privateKey)) { - String str = app.getString(R.string.cannot_upload_image); - showToastMessage(str); - } else { - app.runInUIThread(new Runnable() { - @Override - public void run() { - OprStartFragment.showInstance(mapActivity.getSupportFragmentManager()); - } - }); - } - } - - private byte[] compressImageToJpeg(InputStream image) { - BufferedInputStream bufferedInputStream = new BufferedInputStream(image); - Bitmap bmp = BitmapFactory.decodeStream(bufferedInputStream); - ByteArrayOutputStream os = new ByteArrayOutputStream(); - int h = bmp.getHeight(); - int w = bmp.getWidth(); - boolean scale = false; - while (w > MAX_IMAGE_LENGTH || h > MAX_IMAGE_LENGTH) { - w = w / 2; - h = h / 2; - scale = true; - } - if (scale) { - Matrix matrix = new Matrix(); - matrix.postScale(w, h); - Bitmap resizedBitmap = Bitmap.createBitmap( - bmp, 0, 0, w, h, matrix, false); - bmp.recycle(); - bmp = resizedBitmap; - } - bmp.compress(Bitmap.CompressFormat.JPEG, 90, os); - return os.toByteArray(); - } - private void startLoadingImages() { if (onlinePhotoCardsRow == null) { return; diff --git a/OsmAnd/src/net/osmand/plus/mapcontextmenu/UploadPhotosAsyncTask.java b/OsmAnd/src/net/osmand/plus/mapcontextmenu/UploadPhotosAsyncTask.java new file mode 100644 index 0000000000..30932e8b42 --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/mapcontextmenu/UploadPhotosAsyncTask.java @@ -0,0 +1,220 @@ +package net.osmand.plus.mapcontextmenu; + +import android.content.DialogInterface; +import android.content.DialogInterface.OnDismissListener; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.Matrix; +import android.net.Uri; +import android.os.AsyncTask; + +import androidx.fragment.app.FragmentActivity; +import androidx.fragment.app.FragmentManager; + +import net.osmand.AndroidUtils; +import net.osmand.PlatformUtil; +import net.osmand.data.LatLon; +import net.osmand.osm.io.NetworkUtils; +import net.osmand.plus.OsmandApplication; +import net.osmand.plus.R; +import net.osmand.plus.activities.MapActivity; +import net.osmand.plus.dialogs.UploadPhotoProgressBottomSheet; +import net.osmand.plus.mapcontextmenu.builders.cards.ImageCard.GetImageCardsTask; +import net.osmand.plus.mapcontextmenu.builders.cards.ImageCard.GetImageCardsTask.GetImageCardsListener; +import net.osmand.plus.openplacereviews.OPRConstants; +import net.osmand.plus.openplacereviews.OprStartFragment; +import net.osmand.plus.osmedit.opr.OpenDBAPI; +import net.osmand.util.Algorithms; + +import org.apache.commons.logging.Log; +import org.openplacereviews.opendb.util.exception.FailedVerificationException; + +import java.io.BufferedInputStream; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.lang.ref.WeakReference; +import java.util.List; +import java.util.Map; + +public class UploadPhotosAsyncTask extends AsyncTask { + + private static final Log LOG = PlatformUtil.getLog(UploadPhotosAsyncTask.class); + + private static final int MAX_IMAGE_LENGTH = 2048; + + private final OsmandApplication app; + private final WeakReference activityRef; + private UploadPhotosListener listener; + + private final OpenDBAPI openDBAPI = new OpenDBAPI(); + private final LatLon latLon; + private final List data; + private final String[] placeId; + private final Map params; + private final GetImageCardsListener imageCardListener; + + public UploadPhotosAsyncTask(MapActivity activity, List data, LatLon latLon, String[] placeId, + Map params, GetImageCardsListener imageCardListener) { + app = (OsmandApplication) activity.getApplicationContext(); + activityRef = new WeakReference<>(activity); + this.data = data; + this.latLon = latLon; + this.params = params; + this.placeId = placeId; + this.imageCardListener = imageCardListener; + } + + @Override + protected void onPreExecute() { + FragmentActivity activity = activityRef.get(); + if (AndroidUtils.isActivityNotDestroyed(activity)) { + FragmentManager manager = activity.getSupportFragmentManager(); + listener = UploadPhotoProgressBottomSheet.showInstance(manager, data.size(), new OnDismissListener() { + @Override + public void onDismiss(DialogInterface dialog) { + cancel(false); + } + }); + } + } + + @Override + protected void onProgressUpdate(Integer... values) { + if (listener != null) { + listener.uploadPhotosProgressUpdate(values[0]); + } + } + + protected Void doInBackground(Void... uris) { + for (int i = 0; i < data.size(); i++) { + if (isCancelled()) { + break; + } + Uri uri = data.get(i); + handleSelectedImage(uri); + publishProgress(i + 1); + } + return null; + } + + @Override + protected void onPostExecute(Void aVoid) { + if (listener != null) { + listener.uploadPhotosFinished(); + } + } + + private void handleSelectedImage(final Uri uri) { + InputStream inputStream = null; + try { + inputStream = app.getContentResolver().openInputStream(uri); + if (inputStream != null) { + uploadImageToPlace(inputStream); + } + } catch (Exception e) { + LOG.error(e); + app.showToastMessage(R.string.cannot_upload_image); + } finally { + Algorithms.closeStream(inputStream); + } + } + + private void uploadImageToPlace(InputStream image) { + InputStream serverData = new ByteArrayInputStream(compressImageToJpeg(image)); + final String baseUrl = OPRConstants.getBaseUrl(app); + // all these should be constant + String url = baseUrl + "api/ipfs/image"; + String response = NetworkUtils.sendPostDataRequest(url, "file", "compressed.jpeg", serverData); + if (response != null) { + int res = 0; + try { + StringBuilder error = new StringBuilder(); + String privateKey = app.getSettings().OPR_ACCESS_TOKEN.get(); + String username = app.getSettings().OPR_USERNAME.get(); + res = openDBAPI.uploadImage( + placeId, + baseUrl, + privateKey, + username, + response, error); + if (res != 200) { + app.showToastMessage(error.toString()); + } else { + //ok, continue + } + } catch (FailedVerificationException e) { + LOG.error(e); + checkTokenAndShowScreen(); + } + if (res != 200) { + //image was uploaded but not added to blockchain + checkTokenAndShowScreen(); + } else { + String str = app.getString(R.string.successfully_uploaded_pattern, 1, 1); + app.showToastMessage(str); + //refresh the image + + MapActivity activity = activityRef.get(); + if (activity != null) { + MenuBuilder.execute(new GetImageCardsTask(activity, latLon, params, imageCardListener)); + } + } + } else { + checkTokenAndShowScreen(); + } + } + + //This method runs on non main thread + private void checkTokenAndShowScreen() { + String baseUrl = OPRConstants.getBaseUrl(app); + String name = app.getSettings().OPR_USERNAME.get(); + String privateKey = app.getSettings().OPR_ACCESS_TOKEN.get(); + if (openDBAPI.checkPrivateKeyValid(baseUrl, name, privateKey)) { + app.showToastMessage(R.string.cannot_upload_image); + } else { + app.runInUIThread(new Runnable() { + @Override + public void run() { + MapActivity activity = activityRef.get(); + if (activity != null) { + OprStartFragment.showInstance(activity.getSupportFragmentManager()); + } + } + }); + } + } + + private byte[] compressImageToJpeg(InputStream image) { + BufferedInputStream bufferedInputStream = new BufferedInputStream(image); + Bitmap bmp = BitmapFactory.decodeStream(bufferedInputStream); + ByteArrayOutputStream os = new ByteArrayOutputStream(); + int h = bmp.getHeight(); + int w = bmp.getWidth(); + boolean scale = false; + while (w > MAX_IMAGE_LENGTH || h > MAX_IMAGE_LENGTH) { + w = w / 2; + h = h / 2; + scale = true; + } + if (scale) { + Matrix matrix = new Matrix(); + matrix.postScale(w, h); + Bitmap resizedBitmap = Bitmap.createBitmap( + bmp, 0, 0, w, h, matrix, false); + bmp.recycle(); + bmp = resizedBitmap; + } + bmp.compress(Bitmap.CompressFormat.JPEG, 90, os); + return os.toByteArray(); + } + + + public interface UploadPhotosListener { + + void uploadPhotosProgressUpdate(int progress); + + void uploadPhotosFinished(); + + } +} \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/mapcontextmenu/builders/WptPtMenuBuilder.java b/OsmAnd/src/net/osmand/plus/mapcontextmenu/builders/WptPtMenuBuilder.java index 2a4912f232..c6a287f86b 100644 --- a/OsmAnd/src/net/osmand/plus/mapcontextmenu/builders/WptPtMenuBuilder.java +++ b/OsmAnd/src/net/osmand/plus/mapcontextmenu/builders/WptPtMenuBuilder.java @@ -1,7 +1,6 @@ package net.osmand.plus.mapcontextmenu.builders; import android.content.Context; -import android.content.Intent; import android.view.View; import android.widget.LinearLayout; @@ -16,13 +15,12 @@ import net.osmand.data.LatLon; import net.osmand.data.PointDescription; import net.osmand.plus.GpxSelectionHelper; import net.osmand.plus.GpxSelectionHelper.SelectedGpxFile; -import net.osmand.plus.settings.backend.OsmAndAppCustomization; import net.osmand.plus.OsmAndFormatter; import net.osmand.plus.R; import net.osmand.plus.activities.MapActivity; -import net.osmand.plus.activities.TrackActivity; -import net.osmand.plus.mapcontextmenu.MenuBuilder; import net.osmand.plus.mapcontextmenu.CollapsableView; +import net.osmand.plus.mapcontextmenu.MenuBuilder; +import net.osmand.plus.track.TrackMenuFragment; import net.osmand.plus.views.layers.POIMapLayer; import net.osmand.plus.widgets.TextViewEx; import net.osmand.util.Algorithms; @@ -181,12 +179,7 @@ public class WptPtMenuBuilder extends MenuBuilder { button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { - OsmAndAppCustomization appCustomization = app.getAppCustomization(); - final Intent intent = new Intent(context, appCustomization.getTrackActivity()); - intent.putExtra(TrackActivity.TRACK_FILE_NAME, gpxFile.path); - intent.putExtra(TrackActivity.OPEN_POINTS_TAB, true); - intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); - context.startActivity(intent); + TrackMenuFragment.openTrack(mapActivity, new File(gpxFile.path), null); } }); view.addView(button); diff --git a/OsmAnd/src/net/osmand/plus/mapcontextmenu/controllers/SelectedGpxMenuController.java b/OsmAnd/src/net/osmand/plus/mapcontextmenu/controllers/SelectedGpxMenuController.java index 8a86fbe134..427e0cce35 100644 --- a/OsmAnd/src/net/osmand/plus/mapcontextmenu/controllers/SelectedGpxMenuController.java +++ b/OsmAnd/src/net/osmand/plus/mapcontextmenu/controllers/SelectedGpxMenuController.java @@ -1,7 +1,6 @@ package net.osmand.plus.mapcontextmenu.controllers; import android.app.ProgressDialog; -import android.content.Intent; import android.graphics.drawable.Drawable; import android.os.AsyncTask; @@ -17,9 +16,7 @@ import net.osmand.plus.GpxSelectionHelper; import net.osmand.plus.GpxSelectionHelper.SelectedGpxFile; import net.osmand.plus.OsmandApplication; import net.osmand.plus.R; -import net.osmand.plus.Version; import net.osmand.plus.activities.MapActivity; -import net.osmand.plus.activities.TrackActivity; import net.osmand.plus.helpers.GpxUiHelper; import net.osmand.plus.mapcontextmenu.MenuController; import net.osmand.plus.mapcontextmenu.builders.SelectedGpxMenuBuilder; @@ -45,21 +42,9 @@ public class SelectedGpxMenuController extends MenuController { leftTitleButtonController = new TitleButtonController() { @Override public void buttonPressed() { - OsmandApplication app = mapActivity.getMyApplication(); SelectedGpxFile selectedGpxFile = selectedGpxPoint.getSelectedGpxFile(); - if (Version.isDeveloperVersion(app)) { - mapActivity.getContextMenu().hide(false); - TrackMenuFragment.showInstance(mapActivity, selectedGpxFile.getGpxFile().path, selectedGpxFile.isShowCurrentTrack()); - } else { - Intent intent = new Intent(mapActivity, mapActivity.getMyApplication().getAppCustomization().getTrackActivity()); - if (selectedGpxFile.isShowCurrentTrack()) { - intent.putExtra(TrackActivity.CURRENT_RECORDING, true); - } else { - intent.putExtra(TrackActivity.TRACK_FILE_NAME, selectedGpxFile.getGpxFile().path); - } - intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); - mapActivity.startActivity(intent); - } + mapActivity.getContextMenu().hide(false); + TrackMenuFragment.showInstance(mapActivity, selectedGpxFile.getGpxFile().path, selectedGpxFile.isShowCurrentTrack()); } }; leftTitleButtonController.caption = mapActivity.getString(R.string.shared_string_open_track); diff --git a/OsmAnd/src/net/osmand/plus/mapmarkers/CoordinateInputDialogFragment.java b/OsmAnd/src/net/osmand/plus/mapmarkers/CoordinateInputDialogFragment.java index 09eef3d06c..32e045948d 100644 --- a/OsmAnd/src/net/osmand/plus/mapmarkers/CoordinateInputDialogFragment.java +++ b/OsmAnd/src/net/osmand/plus/mapmarkers/CoordinateInputDialogFragment.java @@ -5,7 +5,6 @@ import android.app.Dialog; import android.content.ClipData; import android.content.ClipboardManager; import android.content.Context; -import android.content.Intent; import android.content.res.ColorStateList; import android.graphics.Rect; import android.graphics.drawable.Drawable; @@ -66,7 +65,6 @@ import net.osmand.plus.GpxSelectionHelper; import net.osmand.plus.OsmAndLocationProvider.OsmAndCompassListener; import net.osmand.plus.OsmAndLocationProvider.OsmAndLocationListener; import net.osmand.plus.OsmandApplication; -import net.osmand.plus.settings.backend.OsmandPreference; import net.osmand.plus.R; import net.osmand.plus.UiUtilities; import net.osmand.plus.Version; @@ -78,6 +76,8 @@ import net.osmand.plus.mapmarkers.CoordinateInputFormats.DDM; import net.osmand.plus.mapmarkers.CoordinateInputFormats.DMS; import net.osmand.plus.mapmarkers.CoordinateInputFormats.Format; import net.osmand.plus.mapmarkers.adapters.CoordinateInputAdapter; +import net.osmand.plus.settings.backend.OsmandPreference; +import net.osmand.plus.track.TrackMenuFragment; import net.osmand.plus.widgets.EditTextEx; import net.osmand.util.Algorithms; import net.osmand.util.LocationParser; @@ -1097,11 +1097,7 @@ public class CoordinateInputDialogFragment extends DialogFragment implements Osm .setAction(R.string.shared_string_show, new View.OnClickListener() { @Override public void onClick(View view) { - Intent intent = new Intent(app, app.getAppCustomization().getTrackActivity()); - intent.putExtra(TrackActivity.OPEN_POINTS_TAB, true); - intent.putExtra(TrackActivity.TRACK_FILE_NAME, getGpx().path); - intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); - startActivity(intent); + TrackMenuFragment.openTrack(app, new File(getGpx().path), null); } }); UiUtilities.setupSnackbar(snackbar, !lightTheme); diff --git a/OsmAnd/src/net/osmand/plus/mapmarkers/MapMarkersDialogFragment.java b/OsmAnd/src/net/osmand/plus/mapmarkers/MapMarkersDialogFragment.java index 2a50192d03..f0b226dd1e 100644 --- a/OsmAnd/src/net/osmand/plus/mapmarkers/MapMarkersDialogFragment.java +++ b/OsmAnd/src/net/osmand/plus/mapmarkers/MapMarkersDialogFragment.java @@ -1,7 +1,6 @@ package net.osmand.plus.mapmarkers; import android.app.Dialog; -import android.content.Intent; import android.graphics.drawable.Drawable; import android.os.Build; import android.os.Bundle; @@ -29,19 +28,20 @@ import net.osmand.AndroidUtils; import net.osmand.Location; import net.osmand.data.LatLon; import net.osmand.plus.LockableViewPager; -import net.osmand.plus.mapmarkers.MapMarkersHelper.MapMarkersSortByDef; -import net.osmand.plus.mapmarkers.MapMarkersHelper.OnGroupSyncedListener; import net.osmand.plus.OsmandApplication; import net.osmand.plus.R; import net.osmand.plus.UiUtilities; import net.osmand.plus.activities.MapActivity; -import net.osmand.plus.activities.TrackActivity; import net.osmand.plus.mapmarkers.CoordinateInputDialogFragment.OnPointsSavedListener; import net.osmand.plus.mapmarkers.DirectionIndicationDialogFragment.DirectionIndicationFragmentListener; +import net.osmand.plus.mapmarkers.MapMarkersHelper.MapMarkersSortByDef; +import net.osmand.plus.mapmarkers.MapMarkersHelper.OnGroupSyncedListener; import net.osmand.plus.mapmarkers.OptionsBottomSheetDialogFragment.MarkerOptionsFragmentListener; import net.osmand.plus.mapmarkers.OrderByBottomSheetDialogFragment.OrderByFragmentListener; import net.osmand.plus.mapmarkers.SaveAsTrackBottomSheetDialogFragment.MarkerSaveAsTrackFragmentListener; +import net.osmand.plus.track.TrackMenuFragment; +import java.io.File; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -167,7 +167,7 @@ public class MapMarkersDialogFragment extends DialogFragment implements OnGroupS viewPager.setAdapter(adapter); progressBar = (ProgressBar) mainView.findViewById(R.id.progress_bar); - + TextView toolbarTitle = mainView.findViewById(R.id.map_markers_toolbar_title); bottomNav = mainView.findViewById(R.id.map_markers_bottom_navigation); toolbarTitle.setTextColor(ContextCompat.getColor(getContext(), lightTheme ? R.color.active_buttons_and_links_text_light : R.color.text_color_primary_dark)); @@ -486,11 +486,7 @@ public class MapMarkersDialogFragment extends DialogFragment implements OnGroupS .setAction(R.string.shared_string_show, new View.OnClickListener() { @Override public void onClick(View view) { - Intent intent = new Intent(mapActivity, getMyApplication().getAppCustomization().getTrackActivity()); - intent.putExtra(TrackActivity.TRACK_FILE_NAME, gpxPath); - intent.putExtra(TrackActivity.OPEN_POINTS_TAB, true); - intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); - startActivity(intent); + TrackMenuFragment.openTrack(mapActivity, new File(gpxPath), null); } }); UiUtilities.setupSnackbar(snackbar, !lightTheme); diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementToolFragment.java b/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementToolFragment.java index 6fb7aa7cab..cc17d2ac9f 100644 --- a/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementToolFragment.java +++ b/OsmAnd/src/net/osmand/plus/measurementtool/MeasurementToolFragment.java @@ -47,7 +47,6 @@ import net.osmand.plus.UiUtilities; import net.osmand.plus.Version; import net.osmand.plus.activities.MapActivity; import net.osmand.plus.activities.MapActivityActions; -import net.osmand.plus.activities.TrackActivity; import net.osmand.plus.base.BaseOsmAndFragment; import net.osmand.plus.base.ContextMenuFragment.MenuState; import net.osmand.plus.helpers.AndroidUiHelper; @@ -76,6 +75,7 @@ import net.osmand.plus.routepreparationmenu.RouteOptionsBottomSheet.DialogMode; import net.osmand.plus.routepreparationmenu.cards.BaseCard; import net.osmand.plus.settings.backend.ApplicationMode; import net.osmand.plus.settings.backend.OsmandSettings; +import net.osmand.plus.track.TrackMenuFragment; import net.osmand.plus.views.layers.MapControlsLayer.MapControlsThemeInfoProvider; import net.osmand.plus.views.mapwidgets.MapInfoWidgetsFactory.TopToolbarController; import net.osmand.plus.views.mapwidgets.MapInfoWidgetsFactory.TopToolbarControllerType; @@ -1914,11 +1914,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route GpxData gpxData = editingCtx.getGpxData(); GPXFile gpx = gpxData != null ? gpxData.getGpxFile() : null; if (gpx != null) { - Intent newIntent = new Intent(mapActivity, app.getAppCustomization().getTrackActivity()); - newIntent.putExtra(TrackActivity.TRACK_FILE_NAME, gpx.path); - newIntent.putExtra(TrackActivity.OPEN_TRACKS_LIST, true); - newIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); - startActivity(newIntent); + TrackMenuFragment.openTrack(mapActivity, new File(gpx.path), null); } } editingCtx.resetRouteSettingsListener(); diff --git a/OsmAnd/src/net/osmand/plus/measurementtool/SavedTrackBottomSheetDialogFragment.java b/OsmAnd/src/net/osmand/plus/measurementtool/SavedTrackBottomSheetDialogFragment.java index fc4f5aeece..8a2b558c60 100644 --- a/OsmAnd/src/net/osmand/plus/measurementtool/SavedTrackBottomSheetDialogFragment.java +++ b/OsmAnd/src/net/osmand/plus/measurementtool/SavedTrackBottomSheetDialogFragment.java @@ -1,7 +1,6 @@ package net.osmand.plus.measurementtool; import android.app.Activity; -import android.content.Intent; import android.os.Bundle; import android.view.View; import android.widget.TextView; @@ -10,16 +9,15 @@ import androidx.annotation.NonNull; import androidx.fragment.app.FragmentActivity; import androidx.fragment.app.FragmentManager; -import net.osmand.plus.OsmandApplication; import net.osmand.plus.R; import net.osmand.plus.UiUtilities; import net.osmand.plus.activities.MapActivity; -import net.osmand.plus.activities.TrackActivity; import net.osmand.plus.base.MenuBottomSheetDialogFragment; import net.osmand.plus.base.bottomsheetmenu.BottomSheetItemButton; import net.osmand.plus.base.bottomsheetmenu.SimpleBottomSheetItem; import net.osmand.plus.base.bottomsheetmenu.simpleitems.DividerItem; import net.osmand.plus.helpers.GpxUiHelper; +import net.osmand.plus.track.TrackMenuFragment; import net.osmand.util.Algorithms; import java.io.File; @@ -60,11 +58,7 @@ public class SavedTrackBottomSheetDialogFragment extends MenuBottomSheetDialogFr public void onClick(View v) { FragmentActivity activity = getActivity(); if (activity != null && !Algorithms.isEmpty(fileName)) { - OsmandApplication app = ((OsmandApplication) activity.getApplication()); - Intent newIntent = new Intent(activity, app.getAppCustomization().getTrackActivity()); - newIntent.putExtra(TrackActivity.TRACK_FILE_NAME, fileName); - newIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); - activity.startActivity(newIntent); + TrackMenuFragment.openTrack(activity, new File(fileName), null); } dismiss(); } diff --git a/OsmAnd/src/net/osmand/plus/monitoring/DashTrackFragment.java b/OsmAnd/src/net/osmand/plus/monitoring/DashTrackFragment.java index 7b1a4cb26a..28211e5682 100644 --- a/OsmAnd/src/net/osmand/plus/monitoring/DashTrackFragment.java +++ b/OsmAnd/src/net/osmand/plus/monitoring/DashTrackFragment.java @@ -13,16 +13,14 @@ import android.widget.LinearLayout; import android.widget.TextView; import android.widget.Toast; -import net.osmand.IndexConstants; import net.osmand.GPXUtilities; import net.osmand.GPXUtilities.GPXFile; +import net.osmand.IndexConstants; import net.osmand.plus.GpxSelectionHelper; import net.osmand.plus.GpxSelectionHelper.SelectedGpxFile; -import net.osmand.plus.settings.backend.OsmAndAppCustomization; import net.osmand.plus.OsmAndFormatter; import net.osmand.plus.OsmandApplication; import net.osmand.plus.OsmandPlugin; -import net.osmand.plus.settings.backend.OsmandSettings; import net.osmand.plus.R; import net.osmand.plus.activities.MapActivity; import net.osmand.plus.activities.SavingTrackHelper; @@ -33,6 +31,9 @@ import net.osmand.plus.helpers.GpxUiHelper; import net.osmand.plus.helpers.GpxUiHelper.GPXInfo; import net.osmand.plus.myplaces.AvailableGPXFragment; import net.osmand.plus.myplaces.FavoritesActivity; +import net.osmand.plus.settings.backend.OsmAndAppCustomization; +import net.osmand.plus.settings.backend.OsmandSettings; +import net.osmand.plus.track.TrackMenuFragment; import java.io.File; import java.util.ArrayList; @@ -153,7 +154,7 @@ public class DashTrackFragment extends DashBaseFragment { view.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - AvailableGPXFragment.openTrack(getActivity(), null); + TrackMenuFragment.openTrack(getActivity(), null, null); } }); view.findViewById(R.id.divider_dash).setVisibility(View.VISIBLE); @@ -172,7 +173,7 @@ public class DashTrackFragment extends DashBaseFragment { v.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - AvailableGPXFragment.openTrack(getActivity(), f); + TrackMenuFragment.openTrack(getActivity(), f, null); } }); ImageButton showOnMap = ((ImageButton) v.findViewById(R.id.show_on_map)); diff --git a/OsmAnd/src/net/osmand/plus/monitoring/SaveGPXBottomSheetFragment.java b/OsmAnd/src/net/osmand/plus/monitoring/SaveGPXBottomSheetFragment.java index 0b38cb6853..4bd5e6bcda 100644 --- a/OsmAnd/src/net/osmand/plus/monitoring/SaveGPXBottomSheetFragment.java +++ b/OsmAnd/src/net/osmand/plus/monitoring/SaveGPXBottomSheetFragment.java @@ -29,6 +29,7 @@ import net.osmand.plus.activities.MapActivity; import net.osmand.plus.base.MenuBottomSheetDialogFragment; import net.osmand.plus.base.bottomsheetmenu.SimpleBottomSheetItem; import net.osmand.plus.myplaces.AvailableGPXFragment; +import net.osmand.plus.track.TrackMenuFragment; import net.osmand.plus.views.OsmandMapTileView; import net.osmand.plus.widgets.OsmandTextFieldBoxes; import net.osmand.util.Algorithms; @@ -167,7 +168,7 @@ public class SaveGPXBottomSheetFragment extends MenuBottomSheetDialogFragment { } FragmentActivity activity = getActivity(); if (openTrack && activity != null) { - AvailableGPXFragment.openTrack(activity, file); + TrackMenuFragment.openTrack(activity, file, null); } } } diff --git a/OsmAnd/src/net/osmand/plus/monitoring/TripRecordingBottomSheet.java b/OsmAnd/src/net/osmand/plus/monitoring/TripRecordingBottomSheet.java index 54b444ff30..789fc0aeb0 100644 --- a/OsmAnd/src/net/osmand/plus/monitoring/TripRecordingBottomSheet.java +++ b/OsmAnd/src/net/osmand/plus/monitoring/TripRecordingBottomSheet.java @@ -9,6 +9,7 @@ import android.os.Bundle; import android.text.SpannableString; import android.view.LayoutInflater; import android.view.View; +import android.view.ViewGroup; import android.widget.CompoundButton; import android.widget.CompoundButton.OnCheckedChangeListener; import android.widget.ImageView; @@ -18,10 +19,12 @@ import android.widget.TextView; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.appcompat.widget.SwitchCompat; +import androidx.core.content.ContextCompat; import androidx.fragment.app.FragmentManager; import com.google.android.material.slider.RangeSlider; +import net.osmand.AndroidUtils; import net.osmand.plus.GpxSelectionHelper.SelectedGpxFile; import net.osmand.plus.NavigationService; import net.osmand.plus.OsmandApplication; @@ -49,9 +52,9 @@ public class TripRecordingBottomSheet extends MenuBottomSheetDialogFragment { private ImageView upDownBtn; private SwitchCompat confirmEveryRun; - private RangeSlider intervalSlider; private TextView intervalValueView; private LinearLayout container; + private View divider; private boolean infoExpanded; @Override @@ -92,8 +95,10 @@ public class TripRecordingBottomSheet extends MenuBottomSheetDialogFragment { } }); + divider = itemView.findViewById(R.id.second_divider); + LinearLayout expandHideIntervalContainer = itemView.findViewById(R.id.interval_view_container); upDownBtn = itemView.findViewById(R.id.up_down_button); - upDownBtn.setOnClickListener(new View.OnClickListener() { + expandHideIntervalContainer.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { @@ -108,8 +113,11 @@ public class TripRecordingBottomSheet extends MenuBottomSheetDialogFragment { updateIntervalLegend(); container = itemView.findViewById(R.id.always_ask_and_range_slider_container); - intervalSlider = itemView.findViewById(R.id.interval_slider); + RangeSlider intervalSlider = itemView.findViewById(R.id.interval_slider); intervalSlider.setValueTo(secondsLength + minutesLength - 1); + int currentModeColorRes = app.getSettings().getApplicationMode().getIconColorInfo().getColor(nightMode); + int currentModeColor = ContextCompat.getColor(app, currentModeColorRes); + UiUtilities.setupSlider(intervalSlider, nightMode, currentModeColor, true); container.setVisibility(View.GONE); intervalSlider.addOnChangeListener(new RangeSlider.OnChangeListener() { @@ -126,6 +134,7 @@ public class TripRecordingBottomSheet extends MenuBottomSheetDialogFragment { updateIntervalLegend(); } }); + for (int i = 0; i < secondsLength + minutesLength; i++) { if (i < secondsLength) { if (settings.SAVE_GLOBAL_TRACK_INTERVAL.get() <= SECONDS[i] * 1000) { @@ -151,13 +160,15 @@ public class TripRecordingBottomSheet extends MenuBottomSheetDialogFragment { } }); - SwitchCompat showTrackOnMapButton = showTrackOnMapView.findViewById(R.id.switch_button); + final SwitchCompat showTrackOnMapButton = showTrackOnMapView.findViewById(R.id.switch_button); showTrackOnMapButton.setChecked(app.getSelectedGpxHelper().getSelectedCurrentRecordingTrack() != null); - showTrackOnMapButton.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { - + View basicItem = itemView.findViewById(R.id.basic_item_body); + basicItem.setOnClickListener(new View.OnClickListener() { @Override - public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { - app.getSelectedGpxHelper().selectGpxFile(app.getSavingTrackHelper().getCurrentGpx(), isChecked, false); + public void onClick(View v) { + boolean checked = !showTrackOnMapButton.isChecked(); + showTrackOnMapButton.setChecked(checked); + app.getSelectedGpxHelper().selectGpxFile(app.getSavingTrackHelper().getCurrentGpx(), checked, false); } }); UiUtilities.setupCompoundButton(showTrackOnMapButton, nightMode, PROFILE_DEPENDENT); @@ -217,6 +228,14 @@ public class TripRecordingBottomSheet extends MenuBottomSheetDialogFragment { private void toggleInfoView() { infoExpanded = !infoExpanded; + ViewGroup.MarginLayoutParams marginParams = (ViewGroup.MarginLayoutParams) divider.getLayoutParams(); + final int dp8 = AndroidUtils.dpToPx(app, 8f); + final int dp16 = AndroidUtils.dpToPx(app, 16f); + if (infoExpanded) { + AndroidUtils.setMargins(marginParams, 0, dp16, 0, dp8); + } else { + AndroidUtils.setMargins(marginParams, 0, 0, 0, dp8); + } AndroidUiHelper.updateVisibility(container, infoExpanded); updateUpDownBtn(); } @@ -226,6 +245,16 @@ public class TripRecordingBottomSheet extends MenuBottomSheetDialogFragment { return true; } + @Override + protected int getRightButtonHeight(){ + return getResources().getDimensionPixelSize(R.dimen.bottom_sheet_cancel_button_height); + } + + @Override + protected int getDismissButtonHeight(){ + return getResources().getDimensionPixelSize(R.dimen.bottom_sheet_cancel_button_height); + } + @Override protected int getRightBottomButtonTextId() { return R.string.start_recording; diff --git a/OsmAnd/src/net/osmand/plus/myplaces/AvailableGPXFragment.java b/OsmAnd/src/net/osmand/plus/myplaces/AvailableGPXFragment.java index 06a38d3ef2..1bde2f3c61 100644 --- a/OsmAnd/src/net/osmand/plus/myplaces/AvailableGPXFragment.java +++ b/OsmAnd/src/net/osmand/plus/myplaces/AvailableGPXFragment.java @@ -13,8 +13,6 @@ import android.os.AsyncTask; import android.os.Build; import android.os.Bundle; import android.os.Handler; -import android.text.Editable; -import android.text.TextWatcher; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; @@ -27,7 +25,6 @@ import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.CheckBox; import android.widget.CompoundButton; -import android.widget.EditText; import android.widget.ExpandableListView; import android.widget.Filter; import android.widget.Filterable; @@ -75,7 +72,6 @@ import net.osmand.plus.UiUtilities; import net.osmand.plus.activities.MapActivity; import net.osmand.plus.activities.OsmandBaseExpandableListAdapter; import net.osmand.plus.activities.SavingTrackHelper; -import net.osmand.plus.activities.TrackActivity; import net.osmand.plus.base.OsmandExpandableListFragment; import net.osmand.plus.helpers.AndroidUiHelper; import net.osmand.plus.helpers.GpxUiHelper.GPXDataSetType; @@ -103,14 +99,12 @@ import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; -import java.util.regex.Pattern; import static net.osmand.plus.GpxSelectionHelper.CURRENT_TRACK; import static net.osmand.plus.myplaces.FavoritesActivity.GPX_TAB; -import static net.osmand.plus.myplaces.FavoritesActivity.OPEN_GPX_REQUEST; import static net.osmand.plus.myplaces.FavoritesActivity.TAB_ID; +import static net.osmand.plus.track.TrackMenuFragment.openTrack; import static net.osmand.util.Algorithms.capitalizeFirstLetter; -import static net.osmand.util.Algorithms.collectDirs; import static net.osmand.util.Algorithms.formatDuration; import static net.osmand.util.Algorithms.objectEquals; import static net.osmand.util.Algorithms.removeAllFiles; @@ -348,10 +342,10 @@ public class AvailableGPXFragment extends OsmandExpandableListFragment implement currentGpxView.findViewById(R.id.current_track_info).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - Intent newIntent = new Intent(getActivity(), getMyApplication().getAppCustomization().getTrackActivity()); - newIntent.putExtra(TrackActivity.CURRENT_RECORDING, true); - newIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); - startActivity(newIntent); + FragmentActivity activity = getActivity(); + if (activity != null) { + openTrack(activity, null, storeState()); + } } }); listView.addHeaderView(currentGpxView); @@ -419,18 +413,6 @@ public class AvailableGPXFragment extends OsmandExpandableListFragment implement updateCurrentTrack(); } - public static void openTrack(Activity a, final File f) { - Intent newIntent = new Intent(a, ((OsmandApplication) a.getApplication()).getAppCustomization().getTrackActivity()); - // causes wrong position caching: newIntent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); - if (f == null) { - newIntent.putExtra(TrackActivity.CURRENT_RECORDING, true); - } else { - newIntent.putExtra(TrackActivity.TRACK_FILE_NAME, f.getAbsolutePath()); - } - newIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); - a.startActivityForResult(newIntent, OPEN_GPX_REQUEST); - } - public void reloadTracks() { asyncLoader = new LoadGpxTask(); asyncLoader.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, getActivity()); @@ -840,7 +822,7 @@ public class AvailableGPXFragment extends OsmandExpandableListFragment implement app.showToastMessage(R.string.file_can_not_be_moved); } } - + public void renamedTo(File file) { reloadTracks(); } @@ -1615,7 +1597,7 @@ public class AvailableGPXFragment extends OsmandExpandableListFragment implement GpxInfo item = allGpxAdapter.getChild(groupPosition, childPosition); if (!selectionMode) { - openTrack(getActivity(), item.file); + openTrack(getActivity(), item.file, storeState()); } else { if (!selectedItems.contains(item)) { selectedItems.add(item); diff --git a/OsmAnd/src/net/osmand/plus/myplaces/EditTrackGroupDialogFragment.java b/OsmAnd/src/net/osmand/plus/myplaces/EditTrackGroupDialogFragment.java index a38c9e993c..19c398685c 100644 --- a/OsmAnd/src/net/osmand/plus/myplaces/EditTrackGroupDialogFragment.java +++ b/OsmAnd/src/net/osmand/plus/myplaces/EditTrackGroupDialogFragment.java @@ -81,11 +81,15 @@ public class EditTrackGroupDialogFragment extends MenuBottomSheetDialogFragment } items.add(new TitleItem(getCategoryName(app, group.getName()))); + boolean trackPoints = group.getType() == GpxDisplayItemType.TRACK_POINTS; SelectedGpxFile selectedGpxFile = app.getSelectedGpxHelper().getSelectedFileByPath(group.getGpx().path); - if (group.getType() == GpxDisplayItemType.TRACK_POINTS && selectedGpxFile != null) { + if (trackPoints && selectedGpxFile != null) { items.add(createShowOnMapItem(selectedGpxFile)); } items.add(createEditNameItem()); + if (trackPoints) { + items.add(createChangeColorItem()); + } items.add(new OptionsDividerItem(app)); // items.add(createCopyToMarkersItem()); @@ -272,8 +276,10 @@ public class EditTrackGroupDialogFragment extends MenuBottomSheetDialogFragment final int themeRes = nightMode ? R.style.OsmandDarkTheme : R.style.OsmandLightTheme; final View changeColorView = View.inflate(new ContextThemeWrapper(getContext(), themeRes), R.layout.change_fav_color, null); - ((ImageView) changeColorView.findViewById(R.id.change_color_icon)) - .setImageDrawable(getContentIcon(R.drawable.ic_action_appearance)); + ImageView icon = ((ImageView) changeColorView.findViewById(R.id.change_color_icon)); + icon.setImageDrawable(getContentIcon(R.drawable.ic_action_appearance)); + int margin = getResources().getDimensionPixelSize(R.dimen.bottom_sheet_icon_margin_large); + UiUtilities.setMargins(icon, 0, 0, margin, 0); updateColorView((ImageView) changeColorView.findViewById(R.id.colorImage)); return new BaseBottomSheetItem.Builder() .setCustomView(changeColorView) diff --git a/OsmAnd/src/net/osmand/plus/myplaces/TrackActivityFragmentAdapter.java b/OsmAnd/src/net/osmand/plus/myplaces/TrackActivityFragmentAdapter.java index b1ae49fc43..2d30551927 100644 --- a/OsmAnd/src/net/osmand/plus/myplaces/TrackActivityFragmentAdapter.java +++ b/OsmAnd/src/net/osmand/plus/myplaces/TrackActivityFragmentAdapter.java @@ -429,7 +429,7 @@ public class TrackActivityFragmentAdapter implements TrackBitmapDrawerListener { String title = metadata.getArticleTitle(); String lang = metadata.getArticleLang(); if (!TextUtils.isEmpty(title) && !TextUtils.isEmpty(lang)) { - return app.getTravelHelper().getArticleByTitle(title, gpx.getRect(), lang); + return app.getTravelHelper().getArticleByTitle(title, gpx.getRect(), lang, false, null); } return null; } diff --git a/OsmAnd/src/net/osmand/plus/onlinerouting/ui/OnlineRoutingCard.java b/OsmAnd/src/net/osmand/plus/onlinerouting/ui/OnlineRoutingCard.java index b18ee19fdb..39951b4c2c 100644 --- a/OsmAnd/src/net/osmand/plus/onlinerouting/ui/OnlineRoutingCard.java +++ b/OsmAnd/src/net/osmand/plus/onlinerouting/ui/OnlineRoutingCard.java @@ -2,6 +2,7 @@ package net.osmand.plus.onlinerouting.ui; import android.text.Editable; import android.text.TextWatcher; +import android.view.Gravity; import android.view.View; import android.view.View.OnClickListener; import android.view.View.OnFocusChangeListener; @@ -79,6 +80,7 @@ public class OnlineRoutingCard extends BaseCard { int activeColor = ContextCompat.getColor(app, appMode.getIconColorInfo().getColor(nightMode)); textFieldBoxes.setPrimaryColor(activeColor); + textFieldBoxes.setGravityFloatingLabel(Gravity.START); editText.addTextChangedListener(new TextWatcher() { @Override diff --git a/OsmAnd/src/net/osmand/plus/osmedit/OsmEditsFragment.java b/OsmAnd/src/net/osmand/plus/osmedit/OsmEditsFragment.java index e61520188d..cacc1ed125 100644 --- a/OsmAnd/src/net/osmand/plus/osmedit/OsmEditsFragment.java +++ b/OsmAnd/src/net/osmand/plus/osmedit/OsmEditsFragment.java @@ -295,8 +295,12 @@ public class OsmEditsFragment extends OsmAndListFragment implements ProgressDial item.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() { @Override public boolean onMenuItemClick(MenuItem item) { - uploadItems(osmEditsSelected.toArray(new OsmPoint[0])); - mode.finish(); + if (Algorithms.isEmpty(osmEditsSelected)) { + app.showToastMessage(R.string.toast_select_edits_for_upload); + } else { + uploadItems(osmEditsSelected.toArray(new OsmPoint[0])); + mode.finish(); + } return true; } }); diff --git a/OsmAnd/src/net/osmand/plus/routepreparationmenu/ChooseRouteFragment.java b/OsmAnd/src/net/osmand/plus/routepreparationmenu/ChooseRouteFragment.java index 5c283c670d..99d6a5c0cd 100644 --- a/OsmAnd/src/net/osmand/plus/routepreparationmenu/ChooseRouteFragment.java +++ b/OsmAnd/src/net/osmand/plus/routepreparationmenu/ChooseRouteFragment.java @@ -815,7 +815,7 @@ public class ChooseRouteFragment extends BaseOsmAndFragment implements ContextMe } @Override - public void onContextMenuStateChanged(@NonNull ContextMenuFragment fragment, int menuState) { + public void onContextMenuStateChanged(@NonNull ContextMenuFragment fragment, int menuState, int previousMenuState) { LockableViewPager viewPager = this.viewPager; RouteDetailsFragment current = getCurrentFragment(); if (viewPager != null && fragment == current) { diff --git a/OsmAnd/src/net/osmand/plus/settings/backend/OsmAndAppCustomization.java b/OsmAnd/src/net/osmand/plus/settings/backend/OsmAndAppCustomization.java index 2a7158ac11..485ada9072 100644 --- a/OsmAnd/src/net/osmand/plus/settings/backend/OsmAndAppCustomization.java +++ b/OsmAnd/src/net/osmand/plus/settings/backend/OsmAndAppCustomization.java @@ -178,10 +178,6 @@ public class OsmAndAppCustomization { return MapActivity.class; } - public Class getTrackActivity() { - return TrackActivity.class; - } - public Class getFavoritesActivity() { return FavoritesActivity.class; } diff --git a/OsmAnd/src/net/osmand/plus/track/DescriptionCard.java b/OsmAnd/src/net/osmand/plus/track/DescriptionCard.java index 0eea4abd1c..8195c8d417 100644 --- a/OsmAnd/src/net/osmand/plus/track/DescriptionCard.java +++ b/OsmAnd/src/net/osmand/plus/track/DescriptionCard.java @@ -1,14 +1,14 @@ package net.osmand.plus.track; import android.view.View; - -import androidx.annotation.NonNull; -import androidx.appcompat.widget.AppCompatImageView; +import android.widget.FrameLayout; +import android.widget.LinearLayout; import com.squareup.picasso.Callback; import com.squareup.picasso.Picasso; import com.squareup.picasso.RequestCreator; +import net.osmand.GPXUtilities; import net.osmand.GPXUtilities.GPXFile; import net.osmand.PicassoUtils; import net.osmand.plus.R; @@ -19,6 +19,9 @@ import net.osmand.plus.widgets.TextViewEx; import net.osmand.plus.wikipedia.WikiArticleHelper; import net.osmand.util.Algorithms; +import androidx.annotation.NonNull; +import androidx.appcompat.widget.AppCompatImageView; + import static net.osmand.plus.myplaces.TrackActivityFragmentAdapter.getMetadataImageLink; public class DescriptionCard extends BaseCard { @@ -37,11 +40,8 @@ public class DescriptionCard extends BaseCard { @Override protected void updateContent() { - if (gpxFile.metadata == null || gpxFile.metadata.getDescription() == null) { - AndroidUiHelper.updateVisibility(view, false); - return; - } else { - AndroidUiHelper.updateVisibility(view, true); + if (gpxFile.metadata == null) { + gpxFile.metadata = new GPXUtilities.Metadata(); } final String title = gpxFile.metadata.getArticleTitle(); @@ -50,6 +50,34 @@ public class DescriptionCard extends BaseCard { setupImage(imageUrl); + if (Algorithms.isBlank(descriptionHtml)) { + showAddBtn(); + } else { + showDescription(title, imageUrl, descriptionHtml); + } + } + + private void showAddBtn() { + LinearLayout descriptionContainer = view.findViewById(R.id.description_container); + FrameLayout addBtn = view.findViewById(R.id.btn_add); + + addBtn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + GpxEditDescriptionDialogFragment.showInstance(getMapActivity(), "", null); + } + }); + AndroidUiHelper.updateVisibility(descriptionContainer, false); + AndroidUiHelper.updateVisibility(addBtn, true); + } + + private void showDescription(final String title, final String imageUrl, final String descriptionHtml) { + LinearLayout descriptionContainer = view.findViewById(R.id.description_container); + FrameLayout addBtn = view.findViewById(R.id.btn_add); + + AndroidUiHelper.updateVisibility(descriptionContainer, true); + AndroidUiHelper.updateVisibility(addBtn, false); + TextViewEx tvDescription = view.findViewById(R.id.description); tvDescription.setText(getFirstParagraph(descriptionHtml)); @@ -60,6 +88,7 @@ public class DescriptionCard extends BaseCard { GpxReadDescriptionDialogFragment.showInstance(mapActivity, title, imageUrl, descriptionHtml); } }); + TextViewEx editBtn = view.findViewById(R.id.btn_edit); editBtn.setOnClickListener(new View.OnClickListener() { @Override diff --git a/OsmAnd/src/net/osmand/plus/track/GpxEditDescriptionDialogFragment.java b/OsmAnd/src/net/osmand/plus/track/GpxEditDescriptionDialogFragment.java index ca868bc3bc..a79a392f8e 100644 --- a/OsmAnd/src/net/osmand/plus/track/GpxEditDescriptionDialogFragment.java +++ b/OsmAnd/src/net/osmand/plus/track/GpxEditDescriptionDialogFragment.java @@ -1,5 +1,7 @@ package net.osmand.plus.track; +import android.content.Context; +import android.content.DialogInterface; import android.os.AsyncTask; import android.os.Bundle; import android.text.Editable; @@ -7,12 +9,6 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.fragment.app.Fragment; -import androidx.fragment.app.FragmentActivity; -import androidx.fragment.app.FragmentManager; - import net.osmand.GPXUtilities.GPXFile; import net.osmand.PlatformUtil; import net.osmand.plus.OsmandApplication; @@ -22,12 +18,18 @@ import net.osmand.plus.activities.MapActivity; import net.osmand.plus.base.BaseOsmAndDialogFragment; import net.osmand.plus.track.SaveGpxAsyncTask.SaveGpxListener; import net.osmand.plus.widgets.EditTextEx; -import net.osmand.util.Algorithms; import org.apache.commons.logging.Log; import java.io.File; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.app.AlertDialog; +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentActivity; +import androidx.fragment.app.FragmentManager; + public class GpxEditDescriptionDialogFragment extends BaseOsmAndDialogFragment { public static final String TAG = GpxEditDescriptionDialogFragment.class.getSimpleName(); @@ -37,6 +39,8 @@ public class GpxEditDescriptionDialogFragment extends BaseOsmAndDialogFragment { private EditTextEx editableHtml; + private String htmlCode; + @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { @@ -46,11 +50,16 @@ public class GpxEditDescriptionDialogFragment extends BaseOsmAndDialogFragment { View view = themedInflater.inflate(R.layout.dialog_edit_gpx_description, container, false); editableHtml = view.findViewById(R.id.description); + editableHtml.requestFocus(); view.findViewById(R.id.btn_close).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - dismiss(); + if (shouldClose()) { + dismiss(); + } else { + showDismissDialog(); + } } }); @@ -58,7 +67,7 @@ public class GpxEditDescriptionDialogFragment extends BaseOsmAndDialogFragment { @Override public void onClick(View v) { Editable editable = editableHtml.getText(); - if (!Algorithms.isEmpty(editable) && !saveGpx(editable.toString())) { + if (editable != null && !saveGpx(editable.toString())) { dismiss(); } } @@ -66,15 +75,38 @@ public class GpxEditDescriptionDialogFragment extends BaseOsmAndDialogFragment { Bundle args = getArguments(); if (args != null) { - String html = args.getString(CONTENT_KEY); - if (html != null) { - editableHtml.setText(html); + htmlCode = args.getString(CONTENT_KEY); + if (htmlCode != null) { + editableHtml.setText(htmlCode); } } return view; } + private boolean shouldClose() { + Editable editable = editableHtml.getText(); + if (htmlCode == null || editable == null || editable.toString() == null) { + return true; + } + return htmlCode.equals(editable.toString()); + } + + private void showDismissDialog() { + Context themedContext = UiUtilities.getThemedContext(getMapActivity(), isNightMode(false)); + AlertDialog.Builder dismissDialog = new AlertDialog.Builder(themedContext); + dismissDialog.setTitle(getString(R.string.shared_string_dismiss)); + dismissDialog.setMessage(getString(R.string.exit_without_saving)); + dismissDialog.setNegativeButton(R.string.shared_string_cancel, null); + dismissDialog.setPositiveButton(R.string.shared_string_exit, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + dismiss(); + } + }); + dismissDialog.show(); + } + private boolean saveGpx(final String html) { MapActivity mapActivity = getMapActivity(); if (mapActivity == null || mapActivity.getTrackMenuFragment() == null) { diff --git a/OsmAnd/src/net/osmand/plus/track/GpxReadDescriptionDialogFragment.java b/OsmAnd/src/net/osmand/plus/track/GpxReadDescriptionDialogFragment.java index 42a4441cdc..b652c7a3bd 100644 --- a/OsmAnd/src/net/osmand/plus/track/GpxReadDescriptionDialogFragment.java +++ b/OsmAnd/src/net/osmand/plus/track/GpxReadDescriptionDialogFragment.java @@ -3,6 +3,7 @@ package net.osmand.plus.track; import android.content.Context; import android.graphics.Color; import android.graphics.drawable.Drawable; +import android.os.Build; import android.os.Bundle; import android.util.Base64; import android.view.LayoutInflater; @@ -15,14 +16,6 @@ import android.webkit.WebSettings; import android.webkit.WebView; import android.webkit.WebViewClient; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.appcompat.widget.AppCompatImageView; -import androidx.appcompat.widget.Toolbar; -import androidx.core.content.ContextCompat; -import androidx.fragment.app.FragmentActivity; -import androidx.fragment.app.FragmentManager; - import com.squareup.picasso.Callback; import com.squareup.picasso.Picasso; import com.squareup.picasso.RequestCreator; @@ -39,6 +32,14 @@ import net.osmand.plus.widgets.WebViewEx; import net.osmand.plus.wikivoyage.WikivoyageUtils; import net.osmand.util.Algorithms; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.widget.AppCompatImageView; +import androidx.appcompat.widget.Toolbar; +import androidx.core.content.ContextCompat; +import androidx.fragment.app.FragmentActivity; +import androidx.fragment.app.FragmentManager; + public class GpxReadDescriptionDialogFragment extends BaseOsmAndDialogFragment { public static final String TAG = GpxReadDescriptionDialogFragment.class.getSimpleName(); @@ -181,10 +182,16 @@ public class GpxReadDescriptionDialogFragment extends BaseOsmAndDialogFragment { private void setupWebView(final View view) { webView = view.findViewById(R.id.content); + webView.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE); + if (Build.VERSION.SDK_INT >= 19) { + webView.setLayerType(View.LAYER_TYPE_HARDWARE, null); + } + else { + webView.setLayerType(View.LAYER_TYPE_SOFTWARE, null); + } webView.setScrollbarFadingEnabled(true); webView.setVerticalScrollBarEnabled(false); webView.setBackgroundColor(Color.TRANSPARENT); - webView.setLayerType(WebView.LAYER_TYPE_HARDWARE, null); webView.getSettings().setTextZoom((int) (getResources().getConfiguration().fontScale * 100f)); webView.getSettings().setDomStorageEnabled(true); webView.getSettings().setLoadWithOverviewMode(true); diff --git a/OsmAnd/src/net/osmand/plus/track/OptionsCard.java b/OsmAnd/src/net/osmand/plus/track/OptionsCard.java index e042a6ab6b..fef9f34f0b 100644 --- a/OsmAnd/src/net/osmand/plus/track/OptionsCard.java +++ b/OsmAnd/src/net/osmand/plus/track/OptionsCard.java @@ -74,7 +74,9 @@ public class OptionsCard extends BaseCard { items.add(createDirectionsItem()); } items.add(createDividerItem()); - items.add(createJoinGapsItem()); + if (gpxFile.getGeneralTrack() != null) { + items.add(createJoinGapsItem()); + } items.add(createAnalyzeOnMapItem()); items.add(createAnalyzeByIntervalsItem()); diff --git a/OsmAnd/src/net/osmand/plus/track/OverviewCard.java b/OsmAnd/src/net/osmand/plus/track/OverviewCard.java index d5d8e44ce4..e43b6d139f 100644 --- a/OsmAnd/src/net/osmand/plus/track/OverviewCard.java +++ b/OsmAnd/src/net/osmand/plus/track/OverviewCard.java @@ -1,10 +1,6 @@ package net.osmand.plus.track; import android.annotation.SuppressLint; -import android.content.Context; -import android.content.res.TypedArray; -import android.graphics.Canvas; -import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.view.LayoutInflater; import android.view.MotionEvent; @@ -17,18 +13,20 @@ import androidx.annotation.ColorRes; import androidx.annotation.DrawableRes; import androidx.annotation.NonNull; import androidx.appcompat.widget.AppCompatImageView; -import androidx.recyclerview.widget.DefaultItemAnimator; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; -import androidx.recyclerview.widget.RecyclerView.ItemDecoration; +import net.osmand.AndroidUtils; import net.osmand.GPXUtilities.GPXFile; import net.osmand.GPXUtilities.GPXTrackAnalysis; +import net.osmand.plus.GpxSelectionHelper.GpxDisplayGroup; import net.osmand.plus.GpxSelectionHelper.GpxDisplayItem; import net.osmand.plus.GpxSelectionHelper.GpxDisplayItemType; import net.osmand.plus.OsmAndFormatter; import net.osmand.plus.R; +import net.osmand.plus.UiUtilities; import net.osmand.plus.activities.MapActivity; +import net.osmand.plus.helpers.AndroidUiHelper; import net.osmand.plus.helpers.GpxUiHelper.GPXDataSetType; import net.osmand.plus.myplaces.SegmentActionsListener; import net.osmand.plus.routepreparationmenu.cards.BaseCard; @@ -36,7 +34,6 @@ import net.osmand.plus.widgets.TextViewEx; import net.osmand.util.Algorithms; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; import static net.osmand.plus.myplaces.TrackActivityFragmentAdapter.isGpxFileSelected; @@ -44,6 +41,7 @@ import static net.osmand.plus.track.OptionsCard.APPEARANCE_BUTTON_INDEX; import static net.osmand.plus.track.OptionsCard.DIRECTIONS_BUTTON_INDEX; import static net.osmand.plus.track.OptionsCard.EDIT_BUTTON_INDEX; import static net.osmand.plus.track.OptionsCard.SHOW_ON_MAP_BUTTON_INDEX; +import static net.osmand.plus.track.OverviewCard.StatBlock.ItemType.*; public class OverviewCard extends BaseCard { @@ -55,15 +53,22 @@ public class OverviewCard extends BaseCard { private final TrackDisplayHelper displayHelper; private final GPXFile gpxFile; - private final GpxDisplayItemType[] filterTypes = new GpxDisplayItemType[] {GpxDisplayItemType.TRACK_SEGMENT}; + private final GpxDisplayItemType[] filterTypes = {GpxDisplayItemType.TRACK_SEGMENT}; private final SegmentActionsListener listener; + private boolean gpxFileSelected; + private GpxDisplayItem gpxItem; public OverviewCard(@NonNull MapActivity mapActivity, @NonNull TrackDisplayHelper displayHelper, @NonNull SegmentActionsListener listener) { super(mapActivity); this.displayHelper = displayHelper; - this.gpxFile = displayHelper.getGpx(); this.listener = listener; + gpxFile = displayHelper.getGpx(); + gpxFileSelected = isGpxFileSelected(app, gpxFile); + List groups = displayHelper.getOriginalGroups(filterTypes); + if (!Algorithms.isEmpty(groups)) { + gpxItem = TrackDisplayHelper.flatten(displayHelper.getOriginalGroups(filterTypes)).get(0); + } } @Override @@ -73,7 +78,7 @@ public class OverviewCard extends BaseCard { @Override protected void updateContent() { - int iconColorDef = R.color.icon_color_active_light; + int iconColorDef = nightMode ? R.color.icon_color_active_dark : R.color.icon_color_active_light; int iconColorPres = R.color.active_buttons_and_links_text_dark; boolean fileAvailable = gpxFile.path != null && !gpxFile.showCurrentTrack; @@ -93,101 +98,94 @@ public class OverviewCard extends BaseCard { } void initStatBlocks() { - GpxDisplayItem gpxItem = TrackDisplayHelper.flatten(displayHelper.getOriginalGroups(filterTypes)).get(0); - GPXTrackAnalysis analysis = gpxItem.analysis; - boolean joinSegments = displayHelper.isJoinSegments(); - float totalDistance = !joinSegments && gpxItem.isGeneralTrack() ? analysis.totalDistanceWithoutGaps : analysis.totalDistance; - float timeSpan = !joinSegments && gpxItem.isGeneralTrack() ? analysis.timeSpanWithoutGaps : analysis.timeSpan; - String asc = OsmAndFormatter.getFormattedAlt(analysis.diffElevationUp, app); - String desc = OsmAndFormatter.getFormattedAlt(analysis.diffElevationDown, app); - String avg = OsmAndFormatter.getFormattedSpeed(analysis.avgSpeed, app); - String max = OsmAndFormatter.getFormattedSpeed(analysis.maxSpeed, app); + if (gpxItem != null) { + GPXTrackAnalysis analysis = gpxItem.analysis; + boolean joinSegments = displayHelper.isJoinSegments(); + float totalDistance = !joinSegments && gpxItem.isGeneralTrack() ? analysis.totalDistanceWithoutGaps : analysis.totalDistance; + float timeSpan = !joinSegments && gpxItem.isGeneralTrack() ? analysis.timeSpanWithoutGaps : analysis.timeSpan; + String asc = OsmAndFormatter.getFormattedAlt(analysis.diffElevationUp, app); + String desc = OsmAndFormatter.getFormattedAlt(analysis.diffElevationDown, app); + String avg = OsmAndFormatter.getFormattedSpeed(analysis.avgSpeed, app); + String max = OsmAndFormatter.getFormattedSpeed(analysis.maxSpeed, app); + List items = new ArrayList<>(); - StatBlock sDistance = new StatBlock(app.getString(R.string.distance), OsmAndFormatter.getFormattedDistance(totalDistance, app), - R.drawable.ic_action_track_16, R.color.icon_color_default_light, GPXDataSetType.ALTITUDE, GPXDataSetType.SPEED); - StatBlock sAscent = new StatBlock(app.getString(R.string.altitude_ascent), asc, - R.drawable.ic_action_arrow_up_16, R.color.gpx_chart_red, GPXDataSetType.SLOPE, null); - StatBlock sDescent = new StatBlock(app.getString(R.string.altitude_descent), desc, - R.drawable.ic_action_arrow_down_16, R.color.gpx_pale_green, GPXDataSetType.ALTITUDE, GPXDataSetType.SLOPE); - StatBlock sAvSpeed = new StatBlock(app.getString(R.string.average_speed), avg, - R.drawable.ic_action_speed_16, R.color.icon_color_default_light, GPXDataSetType.SPEED, null); - StatBlock sMaxSpeed = new StatBlock(app.getString(R.string.max_speed), max, - R.drawable.ic_action_max_speed_16, R.color.icon_color_default_light, GPXDataSetType.SPEED, null); - StatBlock sTimeSpan = new StatBlock(app.getString(R.string.shared_string_time_span), - Algorithms.formatDuration((int) (timeSpan / 1000), app.accessibilityEnabled()), - R.drawable.ic_action_time_span_16, R.color.icon_color_default_light, GPXDataSetType.SPEED, null); + StatBlock.prepareData(analysis, items, app.getString(R.string.distance), OsmAndFormatter.getFormattedDistance(totalDistance, app), + R.drawable.ic_action_track_16, R.color.icon_color_default_light, GPXDataSetType.ALTITUDE, GPXDataSetType.SPEED, ITEM_DISTANCE); + StatBlock.prepareData(analysis, items, app.getString(R.string.altitude_ascent), asc, + R.drawable.ic_action_arrow_up_16, R.color.gpx_chart_red, GPXDataSetType.SLOPE, null, ITEM_ALTITUDE); + StatBlock.prepareData(analysis, items, app.getString(R.string.altitude_descent), desc, + R.drawable.ic_action_arrow_down_16, R.color.gpx_pale_green, GPXDataSetType.ALTITUDE, GPXDataSetType.SLOPE, ITEM_ALTITUDE); + StatBlock.prepareData(analysis, items, app.getString(R.string.average_speed), avg, + R.drawable.ic_action_speed_16, R.color.icon_color_default_light, GPXDataSetType.SPEED, null, ITEM_SPEED); + StatBlock.prepareData(analysis, items, app.getString(R.string.max_speed), max, + R.drawable.ic_action_max_speed_16, R.color.icon_color_default_light, GPXDataSetType.SPEED, null, ITEM_SPEED); + StatBlock.prepareData(analysis, items, app.getString(R.string.shared_string_time_span), + Algorithms.formatDuration((int) (timeSpan / 1000), app.accessibilityEnabled()), + R.drawable.ic_action_time_span_16, R.color.icon_color_default_light, GPXDataSetType.SPEED, null, ITEM_TIME); - LinearLayoutManager llManager = new LinearLayoutManager(app); - llManager.setOrientation(LinearLayoutManager.HORIZONTAL); - rvOverview.setLayoutManager(llManager); - rvOverview.setItemAnimator(new DefaultItemAnimator()); - List items = Arrays.asList(sDistance, sAscent, sDescent, sAvSpeed, sMaxSpeed, sTimeSpan); - final StatBlockAdapter siAdapter = new StatBlockAdapter(items); - rvOverview.setAdapter(siAdapter); - rvOverview.addItemDecoration(new HorizontalDividerDecoration(app)); + if (Algorithms.isEmpty(items)) { + AndroidUiHelper.updateVisibility(rvOverview, false); + } else { + final StatBlockAdapter sbAdapter = new StatBlockAdapter(items); + rvOverview.setLayoutManager(new LinearLayoutManager(app, LinearLayoutManager.HORIZONTAL, false)); + rvOverview.setAdapter(sbAdapter); + } + } else { + AndroidUiHelper.updateVisibility(rvOverview, false); + } + } + + @DrawableRes + private int getActiveShowHideIcon() { + gpxFileSelected = isGpxFileSelected(app, gpxFile); + return gpxFileSelected ? R.drawable.ic_action_view : R.drawable.ic_action_hide; } private void initShowButton(final int iconColorDef, final int iconColorPres) { - final AppCompatImageView image = showButton.findViewById(R.id.image); - final AppCompatImageView filled = showButton.findViewById(R.id.filled); - final int iconShowResId = R.drawable.ic_action_view; - final int iconHideResId = R.drawable.ic_action_hide; - final boolean[] gpxFileSelected = {isGpxFileSelected(app, gpxFile)}; - filled.setImageResource(R.drawable.bg_topbar_shield_exit_ref); - filled.setAlpha(gpxFileSelected[0] ? 1f : 0.1f); - setImageDrawable(image, gpxFileSelected[0] ? iconShowResId : iconHideResId, - gpxFileSelected[0] ? iconColorPres : iconColorDef); - showButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - gpxFileSelected[0] = !gpxFileSelected[0]; - filled.setAlpha(gpxFileSelected[0] ? 1f : 0.1f); - setImageDrawable(image, gpxFileSelected[0] ? iconShowResId : iconHideResId, - gpxFileSelected[0] ? iconColorPres : iconColorDef); - CardListener listener = getListener(); - if (listener != null) { - listener.onCardButtonPressed(OverviewCard.this, SHOW_ON_MAP_BUTTON_INDEX); - } - } - }); + initButton(showButton, SHOW_ON_MAP_BUTTON_INDEX, getActiveShowHideIcon(), iconColorDef, iconColorPres); } - private void initAppearanceButton(int iconColorDef, int iconColorPres) { + private void initAppearanceButton(@ColorRes int iconColorDef, @ColorRes int iconColorPres) { initButton(appearanceButton, APPEARANCE_BUTTON_INDEX, R.drawable.ic_action_appearance, iconColorDef, iconColorPres); } - private void initEditButton(int iconColorDef, int iconColorPres) { + private void initEditButton(@ColorRes int iconColorDef, @ColorRes int iconColorPres) { initButton(editButton, EDIT_BUTTON_INDEX, R.drawable.ic_action_edit_dark, iconColorDef, iconColorPres); } - private void initDirectionsButton(int iconColorDef, int iconColorPres) { + private void initDirectionsButton(@ColorRes int iconColorDef, @ColorRes int iconColorPres) { initButton(directionsButton, DIRECTIONS_BUTTON_INDEX, R.drawable.ic_action_gdirections_dark, iconColorDef, iconColorPres); } - private void initButton(View item, final int buttonIndex, int iconResId, int iconColorDef, int iconColorPres) { - final AppCompatImageView image = item.findViewById(R.id.image); + private void initButton(View item, final int buttonIndex, @DrawableRes Integer iconResId, + @ColorRes final int iconColorDef, @ColorRes int iconColorPres) { + final AppCompatImageView icon = item.findViewById(R.id.image); final AppCompatImageView filled = item.findViewById(R.id.filled); - filled.setImageResource(R.drawable.bg_topbar_shield_exit_ref); + filled.setImageResource(nightMode ? R.drawable.bg_plugin_logo_enabled_dark : R.drawable.bg_topbar_shield_exit_ref); filled.setAlpha(0.1f); - setImageDrawable(image, iconResId, iconColorDef); - setOnTouchItem(item, image, filled, iconResId, iconColorDef, iconColorPres); + setImageDrawable(icon, iconResId, iconColorDef); + setOnTouchItem(item, icon, filled, iconResId, iconColorDef, iconColorPres); item.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { CardListener listener = getListener(); if (listener != null) { listener.onCardButtonPressed(OverviewCard.this, buttonIndex); + if (buttonIndex == SHOW_ON_MAP_BUTTON_INDEX) { + setImageDrawable(icon, getActiveShowHideIcon(), iconColorDef); + } } } }); } - private void setImageDrawable(ImageView iv, @DrawableRes int resId, @ColorRes int color) { - Drawable icon = app.getUIUtilities().getIcon(resId, color); + private void setImageDrawable(ImageView iv, @DrawableRes Integer resId, @ColorRes int color) { + Drawable icon = resId != null ? app.getUIUtilities().getIcon(resId, color) + : UiUtilities.tintDrawable(iv.getDrawable(), getResolvedColor(color)); iv.setImageDrawable(icon); } - private void setOnTouchItem(View item, final ImageView image, final ImageView filled, @DrawableRes final int resId, @ColorRes final int colorDef, @ColorRes final int colorPres) { + private void setOnTouchItem(View item, final ImageView image, final ImageView filled, @DrawableRes final Integer resId, @ColorRes final int colorDef, @ColorRes final int colorPres) { item.setOnTouchListener(new View.OnTouchListener() { @SuppressLint("ClickableViewAccessibility") @Override @@ -234,26 +232,24 @@ public class OverviewCard extends BaseCard { @Override public void onBindViewHolder(StatBlockViewHolder holder, int position) { final StatBlock item = statBlocks.get(position); - holder.valueText.setText(item.value); holder.titleText.setText(item.title); - holder.valueText.setTextColor(app.getResources().getColor(R.color.active_color_primary_light)); + holder.valueText.setTextColor(getActiveColor()); holder.titleText.setTextColor(app.getResources().getColor(R.color.text_color_secondary_light)); holder.itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - GpxDisplayItem gpxItem = TrackDisplayHelper.flatten(displayHelper.getOriginalGroups(filterTypes)).get(0); if (gpxItem != null && gpxItem.analysis != null) { ArrayList list = new ArrayList<>(); - if (item.firstType != null) { - list.add(item.firstType); - } - if (item.secondType != null) { - list.add(item.secondType); - } - if (list.size() > 0) { - gpxItem.chartTypes = list.toArray(new GPXDataSetType[0]); + if (gpxItem.analysis.hasElevationData || gpxItem.analysis.isSpeedSpecified() || gpxItem.analysis.hasSpeedData) { + if (item.firstType != null) { + list.add(item.firstType); + } + if (item.secondType != null) { + list.add(item.secondType); + } } + gpxItem.chartTypes = list.size() > 0 ? list.toArray(new GPXDataSetType[0]) : null; gpxItem.locationOnMap = gpxItem.locationStart; listener.openAnalyzeOnMap(gpxItem); @@ -261,6 +257,8 @@ public class OverviewCard extends BaseCard { } }); setImageDrawable(holder.imageView, item.imageResId, item.imageColorId); + AndroidUtils.setBackgroundColor(view.getContext(), holder.divider, nightMode, R.color.divider_color_light, R.color.divider_color_dark); + AndroidUiHelper.updateVisibility(holder.divider, position != statBlocks.size() - 1); } } @@ -269,55 +267,18 @@ public class OverviewCard extends BaseCard { private final TextViewEx valueText; private final TextView titleText; private final AppCompatImageView imageView; + private final View divider; StatBlockViewHolder(View view) { super(view); valueText = view.findViewById(R.id.value); titleText = view.findViewById(R.id.title); imageView = view.findViewById(R.id.image); + divider = view.findViewById(R.id.divider); } } - private static class HorizontalDividerDecoration extends ItemDecoration { - - private final Drawable divider; - private final int marginV; - private final int marginH; - - public HorizontalDividerDecoration(Context context) { - int[] ATTRS = new int[] {android.R.attr.listDivider}; - final TypedArray ta = context.obtainStyledAttributes(ATTRS); - divider = ta.getDrawable(0); -// DrawableCompat.setTint(divider, context.getResources().getColor(R.color.divider_color_light)); //todo change drawable color - ta.recycle(); - marginV = context.getResources().getDimensionPixelSize(R.dimen.map_small_button_margin); - marginH = context.getResources().getDimensionPixelSize(R.dimen.content_padding); - } - - @Override - public void onDraw(@NonNull Canvas c, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) { - drawHorizontal(c, parent); - } - - public void drawHorizontal(Canvas c, RecyclerView parent) { - for (int i = 0; i < parent.getChildCount(); i++) { - final View child = parent.getChildAt(i); - final int left = child.getRight() - divider.getIntrinsicWidth() + marginH; - final int right = left + divider.getIntrinsicHeight(); - final int top = child.getTop() + marginV; - final int bottom = child.getBottom() - marginV; - divider.setBounds(left, top, right, bottom); - divider.draw(c); - } - } - - @Override - public void getItemOffsets(Rect outRect, @NonNull View view, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) { - outRect.set(marginH - divider.getIntrinsicWidth(), marginV, marginH + divider.getIntrinsicWidth(), marginV); - } - } - - private static class StatBlock { + protected static class StatBlock { private final String title; private final String value; @@ -325,15 +286,56 @@ public class OverviewCard extends BaseCard { private final int imageColorId; private final GPXDataSetType firstType; private final GPXDataSetType secondType; + private final ItemType itemType; public StatBlock(String title, String value, @DrawableRes int imageResId, @ColorRes int imageColorId, - GPXDataSetType firstType, GPXDataSetType secondType) { + GPXDataSetType firstType, GPXDataSetType secondType, ItemType itemType) { this.title = title; this.value = value; this.imageResId = imageResId; this.imageColorId = imageColorId; this.firstType = firstType; this.secondType = secondType; + this.itemType = itemType; + } + + public static void prepareData(GPXTrackAnalysis analysis, List listItems, String title, + String value, @DrawableRes int imageResId, @ColorRes int imageColorId, + GPXDataSetType firstType, GPXDataSetType secondType, ItemType itemType) { + StatBlock statBlock = new StatBlock(title, value, imageResId, imageColorId, firstType, secondType, itemType); + switch (statBlock.itemType) { + case ITEM_DISTANCE: { + if (analysis.totalDistance != 0f) { + listItems.add(statBlock); + } + break; + } + case ITEM_ALTITUDE: { + if (analysis.hasElevationData) { + listItems.add(statBlock); + } + break; + } + case ITEM_SPEED: { + if (analysis.isSpeedSpecified()) { + listItems.add(statBlock); + } + break; + } + case ITEM_TIME: { + if (analysis.hasSpeedData) { + listItems.add(statBlock); + } + break; + } + } + } + + public enum ItemType { + ITEM_DISTANCE, + ITEM_ALTITUDE, + ITEM_SPEED, + ITEM_TIME; } } } \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/track/TrackMenuFragment.java b/OsmAnd/src/net/osmand/plus/track/TrackMenuFragment.java index f169248511..a551ba2330 100644 --- a/OsmAnd/src/net/osmand/plus/track/TrackMenuFragment.java +++ b/OsmAnd/src/net/osmand/plus/track/TrackMenuFragment.java @@ -2,6 +2,8 @@ package net.osmand.plus.track; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; +import android.app.ProgressDialog; +import android.content.Context; import android.content.DialogInterface; import android.content.res.ColorStateList; import android.os.AsyncTask; @@ -22,6 +24,7 @@ import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.TextView; +import androidx.activity.OnBackPressedCallback; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.StringRes; @@ -32,6 +35,7 @@ import androidx.fragment.app.FragmentManager; import com.google.android.material.bottomnavigation.BottomNavigationView; import net.osmand.AndroidUtils; +import net.osmand.CallbackWithObject; import net.osmand.FileUtils; import net.osmand.FileUtils.RenameCallback; import net.osmand.GPXUtilities.GPXFile; @@ -42,10 +46,10 @@ import net.osmand.data.LatLon; import net.osmand.data.PointDescription; import net.osmand.data.QuadRect; import net.osmand.data.RotatedTileBox; -import net.osmand.plus.GpxDbHelper; import net.osmand.plus.GpxSelectionHelper.GpxDisplayGroup; import net.osmand.plus.GpxSelectionHelper.GpxDisplayItem; import net.osmand.plus.GpxSelectionHelper.GpxDisplayItemType; +import net.osmand.plus.GpxSelectionHelper.GpxFileLoaderTask; import net.osmand.plus.GpxSelectionHelper.SelectedGpxFile; import net.osmand.plus.OsmAndLocationProvider.OsmAndCompassListener; import net.osmand.plus.OsmAndLocationProvider.OsmAndLocationListener; @@ -86,6 +90,7 @@ import net.osmand.util.MapUtils; import org.apache.commons.logging.Log; import java.io.File; +import java.lang.ref.WeakReference; import java.util.List; import static net.osmand.plus.activities.TrackActivity.CURRENT_RECORDING; @@ -110,6 +115,8 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card SegmentActionsListener, RenameCallback, OnTrackFileMoveListener, OnPointsDeleteListener, OsmAndLocationListener, OsmAndCompassListener { + public static final String OPEN_TRACK_MENU = "open_track_menu"; + public static final String TAG = TrackMenuFragment.class.getName(); private static final Log log = PlatformUtil.getLog(TrackMenuFragment.class); @@ -144,6 +151,7 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card private int menuTitleHeight; private int toolbarHeightPx; + private boolean mapPositionAdjusted; public enum TrackMenuType { OVERVIEW(R.id.action_overview, R.string.shared_string_overview), @@ -202,33 +210,39 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); app = requireMyApplication(); - GpxDbHelper gpxDbHelper = app.getGpxDbHelper(); displayHelper = new TrackDisplayHelper(app); updateLocationViewCache = app.getUIUtilities().getUpdateLocationViewCache(); - Bundle arguments = getArguments(); - if (arguments != null) { - String gpxFilePath = arguments.getString(TRACK_FILE_NAME); - boolean currentRecording = arguments.getBoolean(CURRENT_RECORDING, false); - if (currentRecording) { - selectedGpxFile = app.getSavingTrackHelper().getCurrentTrack(); - } else { - File file = new File(gpxFilePath); - displayHelper.setFile(file); - displayHelper.setGpxDataItem(gpxDbHelper.getItem(file)); - selectedGpxFile = app.getSelectedGpxHelper().getSelectedFileByPath(gpxFilePath); - } - displayHelper.setGpx(selectedGpxFile.getGpxFile()); - String fileName = Algorithms.getFileWithoutDirs(getGpx().path); - gpxTitle = GpxUiHelper.getGpxTitle(fileName); + if (!selectedGpxFile.isShowCurrentTrack()) { + File file = new File(selectedGpxFile.getGpxFile().path); + displayHelper.setFile(file); + displayHelper.setGpxDataItem(app.getGpxDbHelper().getItem(file)); } + displayHelper.setGpx(selectedGpxFile.getGpxFile()); + String fileName = Algorithms.getFileWithoutDirs(getGpx().path); + gpxTitle = GpxUiHelper.getGpxTitle(fileName); toolbarHeightPx = getResources().getDimensionPixelSize(R.dimen.dashboard_map_toolbar); + + FragmentActivity activity = requireMyActivity(); + activity.getOnBackPressedDispatcher().addCallback(this, new OnBackPressedCallback(true) { + public void handleOnBackPressed() { + MapActivity mapActivity = getMapActivity(); + if (mapActivity != null) { + mapActivity.launchPrevActivityIntent(); + } + dismiss(); + } + }); } public GPXFile getGpx() { return displayHelper.getGpx(); } + public void setSelectedGpxFile(SelectedGpxFile selectedGpxFile) { + this.selectedGpxFile = selectedGpxFile; + } + @Override public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = super.onCreateView(inflater, container, savedInstanceState); @@ -244,6 +258,7 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card if (isPortrait()) { AndroidUiHelper.updateVisibility(getTopShadow(), true); + AndroidUiHelper.updateVisibility(view.findViewById(R.id.map_my_location_button), false); } else { int widthNoShadow = getLandscapeNoShadowWidth(); FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(widthNoShadow, ViewGroup.LayoutParams.WRAP_CONTENT); @@ -255,7 +270,6 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card setupToolbar(); updateHeader(); setupButtons(view); - enterTrackAppearanceMode(); runLayoutListener(); } return view; @@ -441,15 +455,21 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card } @Override - public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - super.onViewCreated(view, savedInstanceState); - adjustMapPosition(getHeight()); + public void onContextMenuStateChanged(@NonNull ContextMenuFragment fragment, int currentMenuState, int previousMenuState) { + super.onContextMenuStateChanged(fragment, currentMenuState, previousMenuState); + + boolean changed = currentMenuState != previousMenuState; + if (changed) { + updateControlsVisibility(true); + } + if (currentMenuState != MenuState.FULL_SCREEN && (changed || !mapPositionAdjusted)) { + adjustMapPosition(getViewY()); + } } @Override public void onDestroyView() { super.onDestroyView(); - exitTrackAppearanceMode(); updateStatusBarColor(); } @@ -460,6 +480,7 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card if (mapActivity != null && trackChartPoints != null) { mapActivity.getMapLayers().getGpxLayer().setTrackChartPoints(trackChartPoints); } + updateControlsVisibility(true); startLocationUpdate(); } @@ -470,6 +491,7 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card if (mapActivity != null) { mapActivity.getMapLayers().getGpxLayer().setTrackChartPoints(null); } + updateControlsVisibility(false); stopLocationUpdate(); } @@ -555,26 +577,25 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card updateContent(); } - private void enterTrackAppearanceMode() { + public void updateControlsVisibility(boolean menuVisible) { MapActivity mapActivity = getMapActivity(); if (mapActivity != null) { - boolean portrait = AndroidUiHelper.isOrientationPortrait(mapActivity); - AndroidUiHelper.setVisibility(mapActivity, portrait ? View.INVISIBLE : View.GONE, - R.id.map_left_widgets_panel, - R.id.map_right_widgets_panel, - R.id.map_center_info); + boolean topControlsVisible = shouldShowTopControls(menuVisible); + boolean bottomControlsVisible = shouldShowBottomControls(menuVisible); + MapContextMenu.updateControlsVisibility(mapActivity, topControlsVisible, bottomControlsVisible); } } - private void exitTrackAppearanceMode() { - MapActivity mapActivity = getMapActivity(); - if (mapActivity != null) { - AndroidUiHelper.setVisibility(mapActivity, View.VISIBLE, - R.id.map_left_widgets_panel, - R.id.map_right_widgets_panel, - R.id.map_center_info, - R.id.map_search_button); - } + public boolean shouldShowTopControls() { + return shouldShowTopControls(isVisible()); + } + + public boolean shouldShowTopControls(boolean menuVisible) { + return !menuVisible || !isPortrait() || getCurrentMenuState() == MenuState.HEADER_ONLY; + } + + public boolean shouldShowBottomControls(boolean menuVisible) { + return !menuVisible || !isPortrait(); } @Override @@ -746,15 +767,6 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card } } - @Override - protected int applyPosY(int currentY, boolean needCloseMenu, boolean needMapAdjust, int previousMenuState, int newMenuState, int dZoom, boolean animated) { - int y = super.applyPosY(currentY, needCloseMenu, needMapAdjust, previousMenuState, newMenuState, dZoom, animated); - if (needMapAdjust) { - adjustMapPosition(y); - } - return y; - } - public void updateToolbar(int y, boolean animated) { final MapActivity mapActivity = getMapActivity(); if (mapActivity != null) { @@ -807,6 +819,7 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card if (r.left != 0 && r.right != 0) { mapActivity.getMapView().fitRectToMap(r.left, r.right, r.top, r.bottom, tileBoxWidthPx, tileBoxHeightPx, 0); } + mapPositionAdjusted = true; } } @@ -996,7 +1009,7 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card @Override public void gpxSavingFinished(Exception errorMessage) { if (selectedGpxFile != null) { - List groups = displayHelper.getDisplayGroups(new GpxDisplayItemType[]{GpxDisplayItemType.TRACK_SEGMENT}); + List groups = displayHelper.getDisplayGroups(new GpxDisplayItemType[] {GpxDisplayItemType.TRACK_SEGMENT}); selectedGpxFile.setDisplayGroups(groups, app); selectedGpxFile.processPoints(app); } @@ -1029,16 +1042,63 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card } } - public static boolean showInstance(@NonNull MapActivity mapActivity, String path, boolean showCurrentTrack) { + public static void openTrack(@NonNull Context context, @Nullable File file, Bundle prevIntentParams) { + boolean currentRecording = file == null; + String path = file != null ? file.getAbsolutePath() : null; + if (context instanceof MapActivity) { + TrackMenuFragment.showInstance((MapActivity) context, path, currentRecording); + } else { + Bundle bundle = new Bundle(); + bundle.putString(TRACK_FILE_NAME, path); + bundle.putBoolean(OPEN_TRACK_MENU, true); + bundle.putBoolean(CURRENT_RECORDING, currentRecording); + MapActivity.launchMapActivityMoveToTop(context, prevIntentParams, null, bundle); + } + } + + public static void showInstance(@NonNull final MapActivity mapActivity, @Nullable String path, boolean showCurrentTrack) { + OsmandApplication app = mapActivity.getMyApplication(); + SelectedGpxFile selectedGpxFile; + if (showCurrentTrack) { + selectedGpxFile = app.getSavingTrackHelper().getCurrentTrack(); + } else { + selectedGpxFile = app.getSelectedGpxHelper().getSelectedFileByPath(path); + } + if (selectedGpxFile != null) { + showInstance(mapActivity, selectedGpxFile); + } else if (!Algorithms.isEmpty(path)) { + String title = app.getString(R.string.loading_smth, ""); + final ProgressDialog progress = ProgressDialog.show(mapActivity, title, app.getString(R.string.loading_data)); + final WeakReference mapActivityRef = new WeakReference<>(mapActivity); + + GpxFileLoaderTask gpxFileLoaderTask = new GpxFileLoaderTask(new File(path), new CallbackWithObject() { + @Override + public boolean processResult(GPXFile result) { + MapActivity mapActivity = mapActivityRef.get(); + if (mapActivity != null) { + OsmandApplication app = mapActivity.getMyApplication(); + SelectedGpxFile selectedGpxFile = app.getSelectedGpxHelper().selectGpxFile(result, true, false); + showInstance(mapActivity, selectedGpxFile); + } + if (progress != null && AndroidUtils.isActivityNotDestroyed(mapActivity)) { + progress.dismiss(); + } + return true; + } + }); + gpxFileLoaderTask.execute(); + } + } + + public static boolean showInstance(@NonNull MapActivity mapActivity, SelectedGpxFile selectedGpxFile) { try { Bundle args = new Bundle(); - args.putString(TRACK_FILE_NAME, path); - args.putBoolean(CURRENT_RECORDING, showCurrentTrack); args.putInt(ContextMenuFragment.MENU_STATE_KEY, MenuState.HEADER_ONLY); TrackMenuFragment fragment = new TrackMenuFragment(); fragment.setArguments(args); fragment.setRetainInstance(true); + fragment.setSelectedGpxFile(selectedGpxFile); mapActivity.getSupportFragmentManager() .beginTransaction() diff --git a/OsmAnd/src/net/osmand/plus/views/AddGpxPointBottomSheetHelper.java b/OsmAnd/src/net/osmand/plus/views/AddGpxPointBottomSheetHelper.java index a317fece3f..f525c60fbd 100644 --- a/OsmAnd/src/net/osmand/plus/views/AddGpxPointBottomSheetHelper.java +++ b/OsmAnd/src/net/osmand/plus/views/AddGpxPointBottomSheetHelper.java @@ -1,6 +1,5 @@ package net.osmand.plus.views; -import android.content.Intent; import android.graphics.PointF; import android.view.View; import android.widget.ImageView; @@ -14,7 +13,6 @@ import net.osmand.data.RotatedTileBox; import net.osmand.plus.R; import net.osmand.plus.UiUtilities; import net.osmand.plus.activities.MapActivity; -import net.osmand.plus.activities.TrackActivity; import net.osmand.plus.mapcontextmenu.MapContextMenu; import net.osmand.plus.mapcontextmenu.editors.RtePtEditor; import net.osmand.plus.mapcontextmenu.editors.WptPtEditor; @@ -22,6 +20,8 @@ import net.osmand.plus.mapcontextmenu.editors.WptPtEditor.OnDismissListener; import net.osmand.plus.track.TrackMenuFragment; import net.osmand.plus.views.layers.ContextMenuLayer; +import java.io.File; + public class AddGpxPointBottomSheetHelper implements OnDismissListener { private final View view; private final TextView title; @@ -149,18 +149,10 @@ public class AddGpxPointBottomSheetHelper implements OnDismissListener { if (fragment != null) { fragment.show(); } else { - openTrackActivity(); + TrackMenuFragment.openTrack(mapActivity, new File(newGpxPoint.getGpx().path), null); } } - private void openTrackActivity() { - Intent newIntent = new Intent(mapActivity, mapActivity.getMyApplication().getAppCustomization().getTrackActivity()); - newIntent.putExtra(TrackActivity.TRACK_FILE_NAME, newGpxPoint.getGpx().path); - newIntent.putExtra(TrackActivity.OPEN_POINTS_TAB, true); - newIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); - mapActivity.startActivity(newIntent); - } - public static class NewGpxPoint { private PointDescription pointDescription; private GPXFile gpx; diff --git a/OsmAnd/src/net/osmand/plus/views/layers/MapControlsLayer.java b/OsmAnd/src/net/osmand/plus/views/layers/MapControlsLayer.java index e4fe3a484c..22eb448670 100644 --- a/OsmAnd/src/net/osmand/plus/views/layers/MapControlsLayer.java +++ b/OsmAnd/src/net/osmand/plus/views/layers/MapControlsLayer.java @@ -859,30 +859,30 @@ public class MapControlsLayer extends OsmandMapLayer { } boolean routeFollowingMode = !routePlanningMode && rh.isFollowingMode(); boolean trackDialogOpened = mapActivity.getTrackDetailsMenu().isVisible(); - boolean contextMenuOpened = !mapActivity.getContextMenu().shouldShowTopControls(); + boolean shouldHideTopControls = mapActivity.shouldHideTopControls(); boolean showRouteCalculationControls = routePlanningMode || ((app.accessibilityEnabled() || (System.currentTimeMillis() - touchEvent < TIMEOUT_TO_SHOW_BUTTONS)) && routeFollowingMode); boolean routeDialogOpened = mapRouteInfoMenu.isVisible() || (showRouteCalculationControls && mapRouteInfoMenu.needShowMenu()); - updateMyLocationVisibility(backToLocationControl, rh, routeDialogOpened || contextMenuOpened); + updateMyLocationVisibility(backToLocationControl, rh, routeDialogOpened || shouldHideTopControls); //routePlanningBtn.setIconResId(routeFollowingMode ? R.drawable.ic_action_info_dark : R.drawable.ic_action_gdirections_dark); updateRoutePlaningButton(rh, routePlanningMode); boolean showBottomMenuButtons = (showRouteCalculationControls || !routeFollowingMode) && !isInMovingMarkerMode() && !isInGpxDetailsMode() && !isInMeasurementToolMode() - && !isInPlanRouteMode() && !contextMenuOpened && !isInChoosingRoutesMode() + && !isInPlanRouteMode() && !shouldHideTopControls && !isInChoosingRoutesMode() && !isInWaypointsChoosingMode() && !isInFollowTrackMode() && !isInTrackAppearanceMode(); routePlanningBtn.updateVisibility(showBottomMenuButtons); menuControl.updateVisibility(showBottomMenuButtons); - boolean showZoomButtons = !routeDialogOpened && !contextMenuOpened && !isInTrackAppearanceMode() + boolean showZoomButtons = !routeDialogOpened && !shouldHideTopControls && !isInTrackAppearanceMode() && (!isInGpxApproximationMode() || !isPotrait()) && !isInFollowTrackMode() && (!isInChoosingRoutesMode() || !isInWaypointsChoosingMode() || !portrait); mapZoomIn.updateVisibility(showZoomButtons); mapZoomOut.updateVisibility(showZoomButtons); boolean forceHideCompass = routeDialogOpened || trackDialogOpened || isInMeasurementToolMode() - || isInPlanRouteMode() || contextMenuOpened || isInChoosingRoutesMode() + || isInPlanRouteMode() || shouldHideTopControls || isInChoosingRoutesMode() || isInTrackAppearanceMode() || isInWaypointsChoosingMode() || isInFollowTrackMode(); compassHud.forceHideCompass = forceHideCompass; compassHud.updateVisibility(!forceHideCompass && shouldShowCompass()); @@ -892,7 +892,7 @@ public class MapControlsLayer extends OsmandMapLayer { if (layersHud.setIconResId(appMode.getIconRes())) { layersHud.update(app, isNight); } - boolean showTopButtons = !routeDialogOpened && !trackDialogOpened && !contextMenuOpened + boolean showTopButtons = !routeDialogOpened && !trackDialogOpened && !shouldHideTopControls && !isInMeasurementToolMode() && !isInPlanRouteMode() && !isInChoosingRoutesMode() && !isInTrackAppearanceMode() && !isInWaypointsChoosingMode() && !isInFollowTrackMode(); layersHud.updateVisibility(showTopButtons); diff --git a/OsmAnd/src/net/osmand/plus/views/layers/MapQuickActionLayer.java b/OsmAnd/src/net/osmand/plus/views/layers/MapQuickActionLayer.java index fe4b73dfba..4ba977235e 100644 --- a/OsmAnd/src/net/osmand/plus/views/layers/MapQuickActionLayer.java +++ b/OsmAnd/src/net/osmand/plus/views/layers/MapQuickActionLayer.java @@ -425,6 +425,7 @@ public class MapQuickActionLayer extends OsmandMapLayer implements QuickActionRe measurementToolLayer.isInMeasurementMode() || mapMarkersLayer.isInPlanRouteMode() || gpxLayer.isInTrackAppearanceMode() || + mapControlsLayer.isInTrackMenuMode() || mapRouteInfoMenu.isVisible() || MapRouteInfoMenu.chooseRoutesVisible || MapRouteInfoMenu.waypointsVisible || diff --git a/OsmAnd/src/net/osmand/plus/views/mapwidgets/MapInfoWidgetsFactory.java b/OsmAnd/src/net/osmand/plus/views/mapwidgets/MapInfoWidgetsFactory.java index fca0ae429e..63c4c93ab9 100644 --- a/OsmAnd/src/net/osmand/plus/views/mapwidgets/MapInfoWidgetsFactory.java +++ b/OsmAnd/src/net/osmand/plus/views/mapwidgets/MapInfoWidgetsFactory.java @@ -974,7 +974,7 @@ public class MapInfoWidgetsFactory { } } } - if (map.isTopToolbarActive() || !map.getContextMenu().shouldShowTopControls() || MapRouteInfoMenu.chooseRoutesVisible || MapRouteInfoMenu.waypointsVisible) { + if (map.isTopToolbarActive() || map.shouldHideTopControls() || MapRouteInfoMenu.chooseRoutesVisible || MapRouteInfoMenu.waypointsVisible) { updateVisibility(false); } else if (showClosestWaypointFirstInAddress && updateWaypoint()) { updateVisibility(true); @@ -1232,7 +1232,7 @@ public class MapInfoWidgetsFactory { @SuppressLint("SetTextI18n") public boolean updateInfo() { - boolean visible = settings.SHOW_COORDINATES_WIDGET.get() && map.getContextMenu().shouldShowTopControls() + boolean visible = settings.SHOW_COORDINATES_WIDGET.get() && !map.shouldHideTopControls() && map.getMapRouteInfoMenu().shouldShowTopControls() && !map.isTopToolbarActive() && !map.getMapLayers().getGpxLayer().isInTrackAppearanceMode() && !MapRouteInfoMenu.chooseRoutesVisible && !MapRouteInfoMenu.waypointsVisible diff --git a/OsmAnd/src/net/osmand/plus/views/mapwidgets/MapMarkersWidgetsFactory.java b/OsmAnd/src/net/osmand/plus/views/mapwidgets/MapMarkersWidgetsFactory.java index f47c0f8bd6..ac0765cee5 100644 --- a/OsmAnd/src/net/osmand/plus/views/mapwidgets/MapMarkersWidgetsFactory.java +++ b/OsmAnd/src/net/osmand/plus/views/mapwidgets/MapMarkersWidgetsFactory.java @@ -191,7 +191,7 @@ public class MapMarkersWidgetsFactory { || map.getMapRouteInfoMenu().isVisible() || addressTopBar.getVisibility() == View.VISIBLE || map.isTopToolbarActive() - || !map.getContextMenu().shouldShowTopControls() + || map.shouldHideTopControls() || map.getMapLayers().getGpxLayer().isInTrackAppearanceMode() || map.getMapLayers().getMapMarkersLayer().isInPlanRouteMode()) { updateVisibility(false); diff --git a/OsmAnd/src/net/osmand/plus/widgets/OsmandTextFieldBoxes.java b/OsmAnd/src/net/osmand/plus/widgets/OsmandTextFieldBoxes.java index 612d293271..64cae466c4 100644 --- a/OsmAnd/src/net/osmand/plus/widgets/OsmandTextFieldBoxes.java +++ b/OsmAnd/src/net/osmand/plus/widgets/OsmandTextFieldBoxes.java @@ -26,7 +26,30 @@ public class OsmandTextFieldBoxes extends TextFieldBoxes { floatingLabel.setVisibility(View.GONE); labelSpace.setVisibility(View.GONE); labelSpaceBelow.setVisibility(View.GONE); - int paddingH = getResources().getDimensionPixelSize(R.dimen.route_info_card_details_margin); - inputLayout.setPadding(0, paddingH, 0, paddingH); + int paddingV = getResources().getDimensionPixelSize(R.dimen.route_info_card_details_margin); + inputLayout.setPadding(0, paddingV, 0, paddingV); + } + + public void setGravityFloatingLabel(int gravity) { + floatingLabel.setGravity(gravity); + } + + @Override + public void setLabelText(String labelText) { + super.setLabelText(labelText); + floatingLabel.post(new Runnable() { + @Override + public void run() { + if (floatingLabel.getLineCount() > 1) { + inputLayout.setPadding( + inputLayout.getPaddingLeft(), + getResources().getDimensionPixelOffset(useDenseSpacing ? R.dimen.dense_editTextLayout_padding_top : R.dimen.editTextLayout_padding_top) + + getResources().getDimensionPixelSize(useDenseSpacing ? R.dimen.context_menu_first_line_top_margin : R.dimen.content_padding_small), + inputLayout.getPaddingRight(), + inputLayout.getPaddingBottom() + ); + } + } + }); } } diff --git a/OsmAnd/src/net/osmand/plus/wikivoyage/article/WikivoyageArticleDialogFragment.java b/OsmAnd/src/net/osmand/plus/wikivoyage/article/WikivoyageArticleDialogFragment.java index 9e2339f3ee..4ee8099c26 100644 --- a/OsmAnd/src/net/osmand/plus/wikivoyage/article/WikivoyageArticleDialogFragment.java +++ b/OsmAnd/src/net/osmand/plus/wikivoyage/article/WikivoyageArticleDialogFragment.java @@ -15,6 +15,7 @@ import android.view.ViewGroup; import android.webkit.JavascriptInterface; import android.webkit.WebSettings; import android.webkit.WebView; +import android.widget.ProgressBar; import android.widget.TextView; import androidx.annotation.NonNull; @@ -27,14 +28,12 @@ import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentManager.BackStackEntry; import net.osmand.AndroidUtils; -import net.osmand.GPXUtilities; import net.osmand.GPXUtilities.GPXFile; import net.osmand.IndexConstants; import net.osmand.plus.OsmandApplication; import net.osmand.plus.OsmandPlugin; import net.osmand.plus.R; import net.osmand.plus.UiUtilities; -import net.osmand.plus.activities.TrackActivity; import net.osmand.plus.development.OsmandDevelopmentPlugin; import net.osmand.plus.helpers.FileNameTranslationHelper; import net.osmand.plus.settings.backend.OsmandSettings; @@ -45,7 +44,9 @@ import net.osmand.plus.wikivoyage.WikivoyageWebViewClient; import net.osmand.plus.wikivoyage.data.TravelArticle; import net.osmand.plus.wikivoyage.data.TravelArticle.TravelArticleIdentifier; import net.osmand.plus.wikivoyage.data.TravelHelper; +import net.osmand.plus.wikivoyage.data.TravelHelper.GpxReadCallback; import net.osmand.plus.wikivoyage.data.TravelLocalDataHelper; +import net.osmand.plus.wikivoyage.explore.WikivoyageExploreActivity; import net.osmand.util.Algorithms; import java.io.File; @@ -53,6 +54,7 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.Map; +import static net.osmand.plus.track.TrackMenuFragment.openTrack; import static net.osmand.plus.wikipedia.WikiArticleShowImages.OFF; @@ -75,6 +77,7 @@ public class WikivoyageArticleDialogFragment extends WikiArticleBaseDialogFragme private TravelArticle article; private TextView trackButton; + private ProgressBar gpxProgress; private TextView saveBtn; private WikivoyageWebViewClient webViewClient; @@ -150,14 +153,18 @@ public class WikivoyageArticleDialogFragment extends WikiArticleBaseDialogFragme if (article == null || activity == null || fm == null) { return; } + if (activity instanceof WikivoyageExploreActivity) { + WikivoyageExploreActivity exploreActivity = (WikivoyageExploreActivity) activity; + exploreActivity.setArticle(article); + } TravelHelper travelHelper = getMyApplication().getTravelHelper(); - File path = travelHelper.createGpxFile(article); - Intent newIntent = new Intent(activity, getMyApplication().getAppCustomization().getTrackActivity()); - newIntent.putExtra(TrackActivity.TRACK_FILE_NAME, path.getAbsolutePath()); - newIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); - startActivity(newIntent); + File file = travelHelper.createGpxFile(article); + openTrack(activity, new File(file.getAbsolutePath()), null); } }); + trackButton.setVisibility(View.GONE); + gpxProgress = mainView.findViewById(R.id.gpx_progress); + gpxProgress.setVisibility(View.GONE); saveBtn = (TextView) mainView.findViewById(R.id.save_button); @@ -305,19 +312,23 @@ public class WikivoyageArticleDialogFragment extends WikiArticleBaseDialogFragme selectedLang = langs.get(0); } articleToolbarText.setText(""); - article = getMyApplication().getTravelHelper().getArticleById(articleId, selectedLang); + article = getMyApplication().getTravelHelper().getArticleById(articleId, selectedLang, true, + new GpxReadCallback() { + @Override + public void onGpxFileReading() { + updateTrackButton(true, null); + } + + @Override + public void onGpxFileRead(@Nullable GPXFile gpxFile) { + updateTrackButton(false, gpxFile); + } + }); if (article == null) { return; } webViewClient.setArticle(article); articleToolbarText.setText(article.getTitle()); - GPXFile gpxFile = article.getGpxFile(); - if (gpxFile != null && gpxFile.getPointsSize() > 0) { - trackButton.setVisibility(View.VISIBLE); - trackButton.setText(getString(R.string.shared_string_gpx_points) + " (" + gpxFile.getPointsSize() + ")"); - } else { - trackButton.setVisibility(View.GONE); - } TravelLocalDataHelper ldh = getMyApplication().getTravelHelper().getBookmarksHelper(); ldh.addToHistory(article); @@ -327,6 +338,21 @@ public class WikivoyageArticleDialogFragment extends WikiArticleBaseDialogFragme contentWebView.loadDataWithBaseURL(getBaseUrl(), createHtmlContent(), "text/html", "UTF-8", null); } + private void updateTrackButton(boolean processing, @Nullable GPXFile gpxFile) { + if (processing) { + trackButton.setVisibility(View.GONE); + gpxProgress.setVisibility(View.VISIBLE); + } else { + if (gpxFile != null && gpxFile.getPointsSize() > 0) { + trackButton.setVisibility(View.VISIBLE); + trackButton.setText(getString(R.string.shared_string_gpx_points) + " (" + gpxFile.getPointsSize() + ")"); + } else { + trackButton.setVisibility(View.GONE); + } + gpxProgress.setVisibility(View.GONE); + } + } + @NonNull @Override protected String createHtmlContent() { diff --git a/OsmAnd/src/net/osmand/plus/wikivoyage/article/WikivoyageArticleNavigationFragment.java b/OsmAnd/src/net/osmand/plus/wikivoyage/article/WikivoyageArticleNavigationFragment.java index 1018874d26..d99937cce8 100644 --- a/OsmAnd/src/net/osmand/plus/wikivoyage/article/WikivoyageArticleNavigationFragment.java +++ b/OsmAnd/src/net/osmand/plus/wikivoyage/article/WikivoyageArticleNavigationFragment.java @@ -1,7 +1,9 @@ package net.osmand.plus.wikivoyage.article; +import android.app.Activity; import android.content.Context; import android.graphics.drawable.Drawable; +import android.os.AsyncTask; import android.os.Bundle; import android.text.TextUtils; import android.view.LayoutInflater; @@ -20,10 +22,13 @@ import androidx.core.content.ContextCompat; import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentManager; +import net.osmand.plus.OsmandApplication; import net.osmand.plus.R; import net.osmand.plus.activities.OsmandBaseExpandableListAdapter; import net.osmand.plus.base.MenuBottomSheetDialogFragment; +import net.osmand.plus.base.bottomsheetmenu.BaseBottomSheetItem; import net.osmand.plus.base.bottomsheetmenu.SimpleBottomSheetItem; +import net.osmand.plus.base.bottomsheetmenu.simpleitems.ProgressItem; import net.osmand.plus.base.bottomsheetmenu.simpleitems.TitleItem; import net.osmand.plus.wikivoyage.data.TravelArticle; import net.osmand.plus.wikivoyage.data.TravelArticle.TravelArticleIdentifier; @@ -52,6 +57,7 @@ public class WikivoyageArticleNavigationFragment extends MenuBottomSheetDialogFr private List parentsList; private ExpandableListView expListView; + private Map> navigationMap; @Override public void createMenuItems(Bundle savedInstanceState) { @@ -75,61 +81,28 @@ public class WikivoyageArticleNavigationFragment extends MenuBottomSheetDialogFr return; } - article = getMyApplication().getTravelHelper().getArticleById(articleId, selectedLang); + OsmandApplication app = requiredMyApplication(); + article = app.getTravelHelper().getArticleById(articleId, selectedLang, false, null); if (article == null) { return; } parentsList = new ArrayList<>(Arrays.asList(article.getAggregatedPartOf().split(","))); - Map> navigationMap - = getMyApplication().getTravelHelper().getNavigationMap(article); - items.add(new TitleItem(getString(R.string.shared_string_navigation))); - expListView = new ExpandableListView(ctx); - final ExpandableListAdapter listAdapter = new ExpandableListAdapter(ctx, navigationMap); + if (navigationMap == null) { + items.add(new ProgressItem()); + new BuildNavigationTask(app).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + } else { + final ExpandableListAdapter listAdapter = createNavigationListView(navigationMap); + LinearLayout container = new LinearLayout(ctx); + container.addView(expListView); - expListView.setAdapter(listAdapter); - Drawable transparent = AppCompatResources.getDrawable(ctx, R.color.color_transparent); - expListView.setDivider(transparent); - expListView.setGroupIndicator(transparent); - expListView.setSelector(transparent); - expListView.setLayoutParams(new LinearLayout.LayoutParams( - LinearLayout.LayoutParams.MATCH_PARENT, - LinearLayout.LayoutParams.MATCH_PARENT) - ); + items.add(new SimpleBottomSheetItem.Builder().setCustomView(container).create()); - expListView.setOnChildClickListener(new ExpandableListView.OnChildClickListener() { - @Override - public boolean onChildClick(ExpandableListView parent, View v, - int groupPosition, int childPosition, long id) { - WikivoyageSearchResult articleItem = listAdapter.getArticleItem(groupPosition, childPosition); - sendResults(articleItem.getArticleTitle()); - dismiss(); - return true; + if (listAdapter.getGroupCount() > 0) { + expListView.expandGroup(listAdapter.getGroupCount() - 1); } - }); - expListView.setOnGroupClickListener(new ExpandableListView.OnGroupClickListener() { - @Override - public boolean onGroupClick(ExpandableListView parent, View v, int groupPosition, long id) { - WikivoyageSearchResult articleItem = (WikivoyageSearchResult) listAdapter.getGroup(groupPosition); - if (Algorithms.isEmpty(articleItem.getArticleTitle())) { - Toast.makeText(getContext(), R.string.wiki_article_not_found, Toast.LENGTH_LONG).show(); - } else { - sendResults(articleItem.getArticleTitle()); - dismiss(); - } - return true; - } - }); - - LinearLayout container = new LinearLayout(ctx); - container.addView(expListView); - - items.add(new SimpleBottomSheetItem.Builder().setCustomView(container).create()); - - if (listAdapter.getGroupCount() > 0) { - expListView.expandGroup(listAdapter.getGroupCount() - 1); } } @@ -307,4 +280,84 @@ public class WikivoyageArticleNavigationFragment extends MenuBottomSheetDialogFr return true; } } + + public void updateMenu() { + Activity activity = getActivity(); + View mainView = getView(); + if (activity != null && mainView != null) { + LinearLayout itemsContainer = (LinearLayout) mainView.findViewById(useScrollableItemsContainer() + ? R.id.scrollable_items_container : R.id.non_scrollable_items_container); + if (itemsContainer != null) { + itemsContainer.removeAllViews(); + } + items.clear(); + createMenuItems(null); + for (BaseBottomSheetItem item : items) { + item.inflate(activity, itemsContainer, nightMode); + } + setupHeightAndBackground(mainView); + } + } + + private ExpandableListAdapter createNavigationListView(Map> navigationMap) { + final Context ctx = requireContext(); + + expListView = new ExpandableListView(ctx); + final ExpandableListAdapter listAdapter = new ExpandableListAdapter(ctx, navigationMap); + + expListView.setAdapter(listAdapter); + Drawable transparent = AppCompatResources.getDrawable(ctx, R.color.color_transparent); + expListView.setDivider(transparent); + expListView.setGroupIndicator(transparent); + expListView.setSelector(transparent); + expListView.setLayoutParams(new LinearLayout.LayoutParams( + LinearLayout.LayoutParams.MATCH_PARENT, + LinearLayout.LayoutParams.MATCH_PARENT) + ); + + expListView.setOnChildClickListener(new ExpandableListView.OnChildClickListener() { + @Override + public boolean onChildClick(ExpandableListView parent, View v, + int groupPosition, int childPosition, long id) { + WikivoyageSearchResult articleItem = listAdapter.getArticleItem(groupPosition, childPosition); + sendResults(articleItem.getArticleTitle()); + dismiss(); + return true; + } + }); + expListView.setOnGroupClickListener(new ExpandableListView.OnGroupClickListener() { + @Override + public boolean onGroupClick(ExpandableListView parent, View v, int groupPosition, long id) { + WikivoyageSearchResult articleItem = (WikivoyageSearchResult) listAdapter.getGroup(groupPosition); + if (Algorithms.isEmpty(articleItem.getArticleTitle())) { + Toast.makeText(ctx, R.string.wiki_article_not_found, Toast.LENGTH_LONG).show(); + } else { + sendResults(articleItem.getArticleTitle()); + dismiss(); + } + return true; + } + }); + return listAdapter; + } + + private class BuildNavigationTask extends AsyncTask>> { + + private final OsmandApplication app; + + public BuildNavigationTask(@NonNull OsmandApplication app) { + this.app = app; + } + + @Override + protected Map> doInBackground(Void... voids) { + return app.getTravelHelper().getNavigationMap(article); + } + + @Override + protected void onPostExecute(Map> navigationMap) { + WikivoyageArticleNavigationFragment.this.navigationMap = navigationMap; + updateMenu(); + } + } } diff --git a/OsmAnd/src/net/osmand/plus/wikivoyage/data/TravelArticle.java b/OsmAnd/src/net/osmand/plus/wikivoyage/data/TravelArticle.java index cf38b7265f..952b85be4d 100644 --- a/OsmAnd/src/net/osmand/plus/wikivoyage/data/TravelArticle.java +++ b/OsmAnd/src/net/osmand/plus/wikivoyage/data/TravelArticle.java @@ -44,6 +44,7 @@ public class TravelArticle { String aggregatedPartOf; long lastModified; + boolean gpxFileReading; boolean gpxFileRead; @NonNull diff --git a/OsmAnd/src/net/osmand/plus/wikivoyage/data/TravelDbHelper.java b/OsmAnd/src/net/osmand/plus/wikivoyage/data/TravelDbHelper.java index 38380015c3..b53605a0bb 100644 --- a/OsmAnd/src/net/osmand/plus/wikivoyage/data/TravelDbHelper.java +++ b/OsmAnd/src/net/osmand/plus/wikivoyage/data/TravelDbHelper.java @@ -549,7 +549,7 @@ public class TravelDbHelper implements TravelHelper { @Override @Nullable - public TravelArticle getArticleById(@NonNull TravelArticleIdentifier articleId, @NonNull String lang) { + public TravelArticle getArticleById(@NonNull TravelArticleIdentifier articleId, @NonNull String lang, boolean readGpx, @Nullable GpxReadCallback callback) { TravelArticle res = null; SQLiteConnection conn = openConnection(); String routeId = articleId.routeId; @@ -566,24 +566,27 @@ public class TravelDbHelper implements TravelHelper { if (res == null) { res = localDataHelper.getSavedArticle(articleId.file, articleId.routeId, lang); } + if (res != null && callback != null) { + callback.onGpxFileRead(res.gpxFile); + } return res; } @Nullable @Override - public TravelArticle getArticleByTitle(@NonNull final String title, @NonNull final String lang) { - return getArticleByTitle(title, new QuadRect(), lang); + public TravelArticle getArticleByTitle(@NonNull final String title, @NonNull final String lang, boolean readGpx, @Nullable GpxReadCallback callback) { + return getArticleByTitle(title, new QuadRect(), lang, readGpx, callback); } @Nullable @Override - public TravelArticle getArticleByTitle(@NonNull final String title, @NonNull LatLon latLon, @NonNull final String lang) { - return getArticleByTitle(title, new QuadRect(), lang); + public TravelArticle getArticleByTitle(@NonNull final String title, @NonNull LatLon latLon, @NonNull final String lang, boolean readGpx, @Nullable GpxReadCallback callback) { + return getArticleByTitle(title, new QuadRect(), lang, readGpx, callback); } @Nullable @Override - public TravelArticle getArticleByTitle(@NonNull final String title, @NonNull QuadRect rect, @NonNull final String lang) { + public TravelArticle getArticleByTitle(@NonNull final String title, @NonNull QuadRect rect, @NonNull final String lang, boolean readGpx, @Nullable GpxReadCallback callback) { TravelArticle res = null; SQLiteConnection conn = openConnection(); if (conn != null) { @@ -596,6 +599,9 @@ public class TravelDbHelper implements TravelHelper { cursor.close(); } } + if (res != null && callback != null) { + callback.onGpxFileRead(res.gpxFile); + } return res; } diff --git a/OsmAnd/src/net/osmand/plus/wikivoyage/data/TravelHelper.java b/OsmAnd/src/net/osmand/plus/wikivoyage/data/TravelHelper.java index 87b5bc1e95..967138b0bd 100644 --- a/OsmAnd/src/net/osmand/plus/wikivoyage/data/TravelHelper.java +++ b/OsmAnd/src/net/osmand/plus/wikivoyage/data/TravelHelper.java @@ -3,6 +3,8 @@ package net.osmand.plus.wikivoyage.data; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import net.osmand.GPXUtilities; +import net.osmand.GPXUtilities.GPXFile; import net.osmand.data.LatLon; import net.osmand.data.QuadRect; import net.osmand.plus.wikivoyage.data.TravelArticle.TravelArticleIdentifier; @@ -14,6 +16,11 @@ import java.util.Map; public interface TravelHelper { + interface GpxReadCallback { + void onGpxFileReading(); + void onGpxFileRead(@Nullable GPXFile gpxFile); + } + TravelLocalDataHelper getBookmarksHelper(); void initializeDataOnAppStartup(); @@ -29,19 +36,19 @@ public interface TravelHelper { List getPopularArticles(); @NonNull - Map> getNavigationMap(@NonNull final TravelArticle article); + Map> getNavigationMap(@NonNull TravelArticle article); @Nullable - TravelArticle getArticleById(@NonNull TravelArticleIdentifier articleId, @NonNull String lang); + TravelArticle getArticleById(@NonNull TravelArticleIdentifier articleId, @NonNull String lang, boolean readGpx, @Nullable GpxReadCallback callback); @Nullable - public TravelArticle getArticleByTitle(@NonNull final String title, @NonNull final String lang); + TravelArticle getArticleByTitle(@NonNull String title, @NonNull String lang, boolean readGpx, @Nullable GpxReadCallback callback); @Nullable - public TravelArticle getArticleByTitle(@NonNull final String title, @NonNull LatLon latLon, @NonNull final String lang); + TravelArticle getArticleByTitle(@NonNull String title, @NonNull LatLon latLon, @NonNull String lang, boolean readGpx, @Nullable GpxReadCallback callback); @Nullable - TravelArticle getArticleByTitle(@NonNull String title, @NonNull QuadRect rect, @NonNull String lang); + TravelArticle getArticleByTitle(@NonNull String title, @NonNull QuadRect rect, @NonNull String lang, boolean readGpx, @Nullable GpxReadCallback callback); @Nullable TravelArticleIdentifier getArticleId(@NonNull String title, @NonNull String lang); @@ -50,10 +57,10 @@ public interface TravelHelper { ArrayList getArticleLangs(@NonNull TravelArticleIdentifier articleId); @NonNull - String getGPXName(@NonNull final TravelArticle article); + String getGPXName(@NonNull TravelArticle article); @NonNull - File createGpxFile(@NonNull final TravelArticle article); + File createGpxFile(@NonNull TravelArticle article); // TODO: this method should be deleted once TravelDBHelper is deleted @Nullable diff --git a/OsmAnd/src/net/osmand/plus/wikivoyage/data/TravelLocalDataHelper.java b/OsmAnd/src/net/osmand/plus/wikivoyage/data/TravelLocalDataHelper.java index 2c59c16ed2..02ee5a32c8 100644 --- a/OsmAnd/src/net/osmand/plus/wikivoyage/data/TravelLocalDataHelper.java +++ b/OsmAnd/src/net/osmand/plus/wikivoyage/data/TravelLocalDataHelper.java @@ -420,7 +420,7 @@ public class TravelLocalDataHelper { if (cursor.moveToFirst()) { do { TravelArticle dbArticle = readSavedArticle(cursor); - TravelArticle article = context.getTravelHelper().getArticleById(dbArticle.generateIdentifier(), dbArticle.lang); + TravelArticle article = context.getTravelHelper().getArticleById(dbArticle.generateIdentifier(), dbArticle.lang, false, null); if (article != null && article.getLastModified() > dbArticle.getLastModified()) { updateSavedArticle(dbArticle, article); res.add(article); diff --git a/OsmAnd/src/net/osmand/plus/wikivoyage/data/TravelObfHelper.java b/OsmAnd/src/net/osmand/plus/wikivoyage/data/TravelObfHelper.java index 65f2da58a8..0f14896a94 100644 --- a/OsmAnd/src/net/osmand/plus/wikivoyage/data/TravelObfHelper.java +++ b/OsmAnd/src/net/osmand/plus/wikivoyage/data/TravelObfHelper.java @@ -1,5 +1,6 @@ package net.osmand.plus.wikivoyage.data; +import android.os.AsyncTask; import android.text.TextUtils; import androidx.annotation.NonNull; @@ -56,7 +57,7 @@ public class TravelObfHelper implements TravelHelper { public static final String ROUTE_ARTICLE_POINT = "route_article_point"; public static final int POPULAR_ARTICLES_SEARCH_RADIUS = 100000; public static final int ARTICLE_SEARCH_RADIUS = 50000; - public static final int MAX_POPULAR_ARTICLES_COUNT = 100; + public static final int MAX_POPULAR_ARTICLES_COUNT = 30; private final OsmandApplication app; private final Collator collator; @@ -97,9 +98,19 @@ public class TravelObfHelper implements TravelHelper { location, POPULAR_ARTICLES_SEARCH_RADIUS, -1, getSearchFilter(false), null); List amenities = reader.searchPoi(req); if (amenities.size() > 0) { + Collections.sort(amenities, new Comparator() { + @Override + public int compare(Amenity a1, Amenity a2) { + int d1 = (int) (MapUtils.getDistance(a1.getLocation().getLatitude(), a1.getLocation().getLongitude(), + location.getLatitude(), location.getLongitude())); + int d2 = (int) (MapUtils.getDistance(a2.getLocation().getLatitude(), a2.getLocation().getLongitude(), + location.getLatitude(), location.getLongitude())); + return d1 < d2 ? -1 : (d1 == d2 ? 0 : 1); + } + }); for (Amenity amenity : amenities) { if (!Algorithms.isEmpty(amenity.getName(lang))) { - TravelArticle article = cacheTravelArticles(reader.getFile(), amenity, lang, false); + TravelArticle article = cacheTravelArticles(reader.getFile(), amenity, lang, false, null); if (article != null) { popularArticles.add(article); if (popularArticles.size() >= MAX_POPULAR_ARTICLES_COUNT) { @@ -108,16 +119,6 @@ public class TravelObfHelper implements TravelHelper { } } } - Collections.sort(popularArticles, new Comparator() { - @Override - public int compare(TravelArticle article1, TravelArticle article2) { - int d1 = (int) (MapUtils.getDistance(article1.getLat(), article1.getLon(), - location.getLatitude(), location.getLongitude())); - int d2 = (int) (MapUtils.getDistance(article2.getLat(), article2.getLon(), - location.getLatitude(), location.getLongitude())); - return d1 < d2 ? -1 : (d1 == d2 ? 0 : 1); - } - }); } } catch (Exception e) { LOG.error(e.getMessage(), e); @@ -128,13 +129,13 @@ public class TravelObfHelper implements TravelHelper { } @Nullable - private TravelArticle cacheTravelArticles(File file, Amenity amenity, String lang, boolean readPoints) { + private TravelArticle cacheTravelArticles(File file, Amenity amenity, String lang, boolean readPoints, @Nullable GpxReadCallback callback) { TravelArticle article = null; - Map articles = readArticles(file, amenity, false); + Map articles = readArticles(file, amenity); if (!Algorithms.isEmpty(articles)) { TravelArticleIdentifier newArticleId = articles.values().iterator().next().generateIdentifier(); cachedArticles.put(newArticleId, articles); - article = getCachedArticle(newArticleId, lang, readPoints); + article = getCachedArticle(newArticleId, lang, readPoints, callback); } return article; } @@ -155,17 +156,17 @@ public class TravelObfHelper implements TravelHelper { } @NonNull - private Map readArticles(@NonNull File file, @NonNull Amenity amenity, boolean readPoints) { + private Map readArticles(@NonNull File file, @NonNull Amenity amenity) { Map articles = new HashMap<>(); Set langs = getLanguages(amenity); for (String lang : langs) { - articles.put(lang, readArticle(file, amenity, lang, readPoints)); + articles.put(lang, readArticle(file, amenity, lang)); } return articles; } @NonNull - private TravelArticle readArticle(@NonNull File file, @NonNull Amenity amenity, @NonNull String lang, boolean readPoints) { + private TravelArticle readArticle(@NonNull File file, @NonNull Amenity amenity, @NonNull String lang) { TravelArticle res = new TravelArticle(); res.file = file; String title = amenity.getName(lang); @@ -182,29 +183,11 @@ public class TravelObfHelper implements TravelHelper { res.lang = lang; res.contentsJson = Algorithms.emptyIfNull(amenity.getTagContent(Amenity.CONTENT_JSON, lang)); res.aggregatedPartOf = Algorithms.emptyIfNull(amenity.getTagContent(Amenity.IS_AGGR_PART, lang)); - if (readPoints) { - res.gpxFile = buildGpxFile(res); - res.gpxFileRead = true; - } return res; } - private GPXFile buildGpxFile(@NonNull TravelArticle article) { - GPXFile gpxFile = null; - List pointList = getPointList(article); - if (!Algorithms.isEmpty(pointList)) { - gpxFile = new GPXFile(article.getTitle(), article.getLang(), article.getContent()); - gpxFile.metadata.link = TravelArticle.getImageUrl(article.getImageTitle(), false); - for (Amenity amenity : pointList) { - WptPt wptPt = createWptPt(amenity, article.getLang()); - gpxFile.addPoint(wptPt); - } - } - return gpxFile; - } - @NonNull - private List getPointList(@NonNull final TravelArticle article) { + private synchronized List getPointList(@NonNull final TravelArticle article) { final List pointList = new ArrayList<>(); final String lang = article.getLang(); for (BinaryMapIndexReader reader : getReaders()) { @@ -312,7 +295,7 @@ public class TravelObfHelper implements TravelHelper { for (Amenity amenity : entry.getValue()) { Set nameLangs = getLanguages(amenity); if (nameLangs.contains(appLang)) { - TravelArticle article = readArticle(file, amenity, appLang, false); + TravelArticle article = readArticle(file, amenity, appLang); ArrayList langs = new ArrayList<>(nameLangs); Collections.sort(langs, new Comparator() { @Override @@ -379,7 +362,7 @@ public class TravelObfHelper implements TravelHelper { @NonNull @Override - public Map> getNavigationMap(@NonNull final TravelArticle article) { + public synchronized Map> getNavigationMap(@NonNull final TravelArticle article) { final String lang = article.getLang(); final String title = article.getTitle(); if (TextUtils.isEmpty(lang) || TextUtils.isEmpty(title)) { @@ -481,20 +464,28 @@ public class TravelObfHelper implements TravelHelper { LOG.error(e.getMessage()); } if (!Algorithms.isEmpty(amenities)) { - article = readArticle(reader.getFile(), amenities.get(0), lang, false); + article = readArticle(reader.getFile(), amenities.get(0), lang); } } return article; } @Override - public TravelArticle getArticleById(@NonNull TravelArticleIdentifier articleId, @NonNull String lang) { - TravelArticle article = getCachedArticle(articleId, lang, true); - return article == null ? localDataHelper.getSavedArticle(articleId.file, articleId.routeId, lang) : article; + public TravelArticle getArticleById(@NonNull TravelArticleIdentifier articleId, @NonNull String lang, + boolean readGpx, @Nullable GpxReadCallback callback) { + TravelArticle article = getCachedArticle(articleId, lang, readGpx, callback); + if (article == null) { + article = localDataHelper.getSavedArticle(articleId.file, articleId.routeId, lang); + if (article != null && callback != null && readGpx) { + callback.onGpxFileRead(article.gpxFile); + } + } + return article; } @Nullable - private TravelArticle getCachedArticle(@NonNull TravelArticleIdentifier articleId, @NonNull String lang, boolean forceReadPoints) { + private TravelArticle getCachedArticle(@NonNull TravelArticleIdentifier articleId, @NonNull String lang, + boolean forceReadPoints, @Nullable GpxReadCallback callback) { TravelArticle article = null; Map articles = cachedArticles.get(articleId); if (articles != null) { @@ -510,17 +501,25 @@ public class TravelObfHelper implements TravelHelper { } } } - if (article == null) { - article = findArticleById(articleId, lang); + if (article == null && articles == null) { + article = findArticleById(articleId, lang, callback); } - if (article != null && !article.gpxFileRead && forceReadPoints) { - article.gpxFile = buildGpxFile(article); - article.gpxFileRead = true; + if (article != null && forceReadPoints && !Algorithms.isEmpty(lang)) { + readGpxFile(article, callback); } return article; } - private TravelArticle findArticleById(@NonNull final TravelArticleIdentifier articleId, final String lang) { + private void readGpxFile(@NonNull TravelArticle article, @Nullable GpxReadCallback callback) { + if (!article.gpxFileRead) { + new GpxFileReader(article, callback).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + } else if (callback != null) { + callback.onGpxFileRead(article.gpxFile); + } + } + + private TravelArticle findArticleById(@NonNull final TravelArticleIdentifier articleId, + final String lang, @Nullable GpxReadCallback callback) { TravelArticle article = null; final boolean isDbArticle = articleId.file != null && articleId.file.getName().endsWith(IndexConstants.BINARY_WIKIVOYAGE_MAP_INDEX_EXT); final List amenities = new ArrayList<>(); @@ -563,7 +562,7 @@ public class TravelObfHelper implements TravelHelper { LOG.error(e.getMessage()); } if (!Algorithms.isEmpty(amenities)) { - article = cacheTravelArticles(reader.getFile(), amenities.get(0), lang, true); + article = cacheTravelArticles(reader.getFile(), amenities.get(0), lang, true, callback); } } return article; @@ -571,20 +570,23 @@ public class TravelObfHelper implements TravelHelper { @Nullable @Override - public TravelArticle getArticleByTitle(@NonNull final String title, @NonNull final String lang) { - return getArticleByTitle(title, new QuadRect(), lang); + public TravelArticle getArticleByTitle(@NonNull final String title, @NonNull final String lang, + boolean readGpx, @Nullable GpxReadCallback callback) { + return getArticleByTitle(title, new QuadRect(), lang, readGpx, callback); } @Nullable @Override - public TravelArticle getArticleByTitle(@NonNull final String title, @NonNull LatLon latLon, @NonNull final String lang) { - QuadRect rect = latLon != null ? MapUtils.calculateLatLonBbox(latLon.getLatitude(), latLon.getLongitude(), ARTICLE_SEARCH_RADIUS) : new QuadRect(); - return getArticleByTitle(title, rect, lang); + public TravelArticle getArticleByTitle(@NonNull final String title, @NonNull LatLon latLon, + @NonNull final String lang, boolean readGpx, @Nullable GpxReadCallback callback) { + QuadRect rect = MapUtils.calculateLatLonBbox(latLon.getLatitude(), latLon.getLongitude(), ARTICLE_SEARCH_RADIUS); + return getArticleByTitle(title, rect, lang, readGpx, callback); } @Nullable @Override - public TravelArticle getArticleByTitle(@NonNull final String title, @NonNull QuadRect rect, @NonNull final String lang) { + public TravelArticle getArticleByTitle(@NonNull final String title, @NonNull QuadRect rect, + @NonNull final String lang, boolean readGpx, @Nullable GpxReadCallback callback) { TravelArticle article = null; final List amenities = new ArrayList<>(); int x = 0; @@ -627,7 +629,7 @@ public class TravelObfHelper implements TravelHelper { LOG.error(e.getMessage()); } if (!Algorithms.isEmpty(amenities)) { - article = cacheTravelArticles(reader.getFile(), amenities.get(0), lang, true); + article = cacheTravelArticles(reader.getFile(), amenities.get(0), lang, readGpx, callback); } } return article; @@ -654,7 +656,7 @@ public class TravelObfHelper implements TravelHelper { } } if (a == null) { - TravelArticle article = getArticleByTitle(title, lang); + TravelArticle article = getArticleByTitle(title, lang, false, null); if (article != null) { a = article; } @@ -666,7 +668,7 @@ public class TravelObfHelper implements TravelHelper { @Override public ArrayList getArticleLangs(@NonNull TravelArticleIdentifier articleId) { ArrayList res = new ArrayList<>(); - TravelArticle article = getArticleById(articleId, ""); + TravelArticle article = getArticleById(articleId, "", false, null); if (article != null) { Map articles = cachedArticles.get(article.generateIdentifier()); if (articles != null) { @@ -683,14 +685,14 @@ public class TravelObfHelper implements TravelHelper { @NonNull @Override - public String getGPXName(@NonNull final TravelArticle article) { + public String getGPXName(@NonNull TravelArticle article) { return article.getTitle().replace('/', '_').replace('\'', '_') .replace('\"', '_') + IndexConstants.GPX_FILE_EXT; } @NonNull @Override - public File createGpxFile(@NonNull final TravelArticle article) { + public File createGpxFile(@NonNull TravelArticle article) { final GPXFile gpx = article.getGpxFile(); File file = app.getAppPath(IndexConstants.GPX_TRAVEL_DIR + getGPXName(article)); writeGpxFile(file, gpx); @@ -706,4 +708,46 @@ public class TravelObfHelper implements TravelHelper { public String getWikivoyageFileName() { return WORLD_WIKIVOYAGE_FILE_NAME; } + + private class GpxFileReader extends AsyncTask { + + private final TravelArticle article; + private final GpxReadCallback callback; + + public GpxFileReader(@NonNull TravelArticle article, @Nullable GpxReadCallback callback) { + this.article = article; + this.callback = callback; + } + + @Override + protected void onPreExecute() { + if (callback != null) { + callback.onGpxFileReading(); + } + } + + @Override + protected GPXFile doInBackground(Void... voids) { + GPXFile gpxFile = null; + List pointList = getPointList(article); + if (!Algorithms.isEmpty(pointList)) { + gpxFile = new GPXFile(article.getTitle(), article.getLang(), article.getContent()); + gpxFile.metadata.link = TravelArticle.getImageUrl(article.getImageTitle(), false); + for (Amenity amenity : pointList) { + WptPt wptPt = createWptPt(amenity, article.getLang()); + gpxFile.addPoint(wptPt); + } + } + return gpxFile; + } + + @Override + protected void onPostExecute(GPXFile gpxFile) { + article.gpxFileRead = true; + article.gpxFile = gpxFile; + if (callback != null) { + callback.onGpxFileRead(gpxFile); + } + } + } } \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/wikivoyage/menu/WikivoyageWptPtMenuController.java b/OsmAnd/src/net/osmand/plus/wikivoyage/menu/WikivoyageWptPtMenuController.java index 6f3ee2fd43..84507da899 100644 --- a/OsmAnd/src/net/osmand/plus/wikivoyage/menu/WikivoyageWptPtMenuController.java +++ b/OsmAnd/src/net/osmand/plus/wikivoyage/menu/WikivoyageWptPtMenuController.java @@ -10,6 +10,7 @@ import net.osmand.GPXUtilities.WptPt; import net.osmand.data.LatLon; import net.osmand.data.PointDescription; import net.osmand.plus.GpxSelectionHelper.SelectedGpxFile; +import net.osmand.plus.OsmandApplication; import net.osmand.plus.R; import net.osmand.plus.activities.MapActivity; import net.osmand.plus.mapcontextmenu.controllers.WptPtMenuController; @@ -38,13 +39,14 @@ public class WikivoyageWptPtMenuController extends WptPtMenuController { } private static TravelArticle getTravelArticle(@NonNull MapActivity mapActivity, @NonNull WptPt wpt) { - SelectedGpxFile selectedGpxFile = mapActivity.getMyApplication().getSelectedGpxHelper().getSelectedGPXFile(wpt); + OsmandApplication app = mapActivity.getMyApplication(); + SelectedGpxFile selectedGpxFile = app.getSelectedGpxHelper().getSelectedGPXFile(wpt); GPXFile gpxFile = selectedGpxFile != null ? selectedGpxFile.getGpxFile() : null; Metadata metadata = gpxFile != null ? gpxFile.metadata : null; String title = metadata != null ? metadata.getArticleTitle() : null; String lang = metadata != null ? metadata.getArticleLang() : null; if (!TextUtils.isEmpty(title) && !TextUtils.isEmpty(lang)) { - return mapActivity.getMyApplication().getTravelHelper().getArticleByTitle(title, new LatLon(wpt.lat, wpt.lon), lang); + return app.getTravelHelper().getArticleByTitle(title, new LatLon(wpt.lat, wpt.lon), lang, false, null); } return null; } diff --git a/gradle.properties b/gradle.properties index c80fef2728..dffb2e0a79 100644 --- a/gradle.properties +++ b/gradle.properties @@ -21,4 +21,4 @@ # UPDATE 3: Turn on D8 to recover builds with new gradle 6.5 and pluigin 4.1.1 #android.enableD8=false android.enableJetifier=true -android.useAndroidX=true +android.useAndroidX=true \ No newline at end of file