Compare commits
71 Commits
v2025.10.0
...
release/20
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2601ec854a | ||
|
|
3fbecd00d5 | ||
|
|
26cdde144a | ||
|
|
f9a0dd1cb2 | ||
|
|
bdde42ce4e | ||
|
|
633896854d | ||
|
|
37a518cb9b | ||
|
|
dd3b6faa42 | ||
|
|
fceb6e0b8a | ||
|
|
ad07875b88 | ||
|
|
db1e5131b7 | ||
|
|
ba7addc504 | ||
|
|
d168855ef5 | ||
|
|
509ff4de72 | ||
|
|
340b5ae3f9 | ||
|
|
f5afe7f363 | ||
|
|
51bfa3d372 | ||
|
|
91d523a6fa | ||
|
|
1c8eeeeee2 | ||
|
|
034098f5ef | ||
|
|
3fcf653deb | ||
|
|
5035aa3f79 | ||
|
|
c887abfd80 | ||
|
|
707415a788 | ||
|
|
832273f928 | ||
|
|
1947a32007 | ||
|
|
e73c37a5dd | ||
|
|
9912d19302 | ||
|
|
30f624a070 | ||
|
|
428ff30af7 | ||
|
|
f514606ebe | ||
|
|
e0351b26ba | ||
|
|
64f8d751cf | ||
|
|
d145f3b51b | ||
|
|
f42014cf37 | ||
|
|
66fae205c2 | ||
|
|
54ba143bbe | ||
|
|
c685b8bed3 | ||
|
|
bb94621cdc | ||
|
|
17f34d155e | ||
|
|
175e971064 | ||
|
|
533e34f390 | ||
|
|
24ec765a00 | ||
|
|
e5b6d882bf | ||
|
|
a74ae0fa3a | ||
|
|
431852f8cc | ||
|
|
a21a717bec | ||
|
|
d7221bdfc9 | ||
|
|
efc8e44350 | ||
|
|
e3c287db53 | ||
|
|
0748e4c9a4 | ||
|
|
7739329cb4 | ||
|
|
2619738882 | ||
|
|
2217db002a | ||
|
|
00be9a536d | ||
|
|
ed37b6595e | ||
|
|
e670bef0a2 | ||
|
|
ccd3f9813a | ||
|
|
db6ad05406 | ||
|
|
8520f32f2d | ||
|
|
47f16c5b89 | ||
|
|
056711f4bd | ||
|
|
2eccbba26e | ||
|
|
8101d50f50 | ||
|
|
8a0a069195 | ||
|
|
a26f4933dc | ||
|
|
aa2d35759f | ||
|
|
233f5b4c33 | ||
|
|
284972ad60 | ||
|
|
0c0e9ab5f6 | ||
|
|
e7f766084f |
@@ -0,0 +1,9 @@
|
||||
• Vylepšena viditelnost a uživatelské rozhraní pokynů v navigaci
|
||||
• Přidána možnost vynechat kroky
|
||||
• Vylepšeno vyhledávání ve více jazycích
|
||||
• Přidána specifická ikona pro autobusové zastávky
|
||||
• Opraveny problémy s Android Auto (prostřednictvím projektu OM)
|
||||
• Vylepšen editor a opraveny drobné problémy
|
||||
• Vylepšeny styly map (prostřednictvím projektu OM)
|
||||
• Vylepšeny překlady aplikace
|
||||
Další změny najdete v našich poznámkách k vydání Codeberg!
|
||||
@@ -1,10 +1,9 @@
|
||||
• Karten-Daten vom 6. September
|
||||
• Zeitstrafen für Radrouting
|
||||
• Farbige POI-Beschriftungen in Autonavigation
|
||||
• POI-Suche nach Filialnamen
|
||||
• Abspannportale, Sicherheitskabinen & Büros hinzugefügt
|
||||
• Aktualisierte Symbole für Türme, Nachtclubs, Apotheken und Fahnenmasten
|
||||
• Lesezeichen-Farbe in GPX-Exporten
|
||||
• Farbfüllung von Fußgängerbereiche auf Plätzen
|
||||
• Android Auto: Anzeige Ausfahrtsnummern in Kreisverkehren
|
||||
Weitere Änderungen in Codeberg-Versionshinweisen!
|
||||
• Verbesserte Sichtbarkeit & Benutzeroberfläche für Navigationsanweisungen
|
||||
• Option um Treppen zu vermeiden
|
||||
• Verbesserte Suche in mehreren Sprachen
|
||||
• Spezifisches Symbol für Busbahnöfe hinzugefügt
|
||||
• Probleme mit Android Auto behoben (via OM)
|
||||
• Verbesserter Editor mit kleinere Bugfixes
|
||||
• Kartenstile verbessert (via OM)
|
||||
• Verbesserte Übersetzungen
|
||||
Für weitere Änderungen siehe Codeberg-Versionshinweise
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
• OpenStreetMap data as of September 6
|
||||
• Turn penalties for bicycle routing
|
||||
• Colored POI labels for car navigation map style
|
||||
• Search POIs by branch name
|
||||
• Added power portals, security booths and offices
|
||||
• Update icons for towers, nightclubs, chemists, flagpoles
|
||||
• Save bookmark color to GPX exports
|
||||
• Color fill pedestrian parts of squares
|
||||
• Android Auto: display roundabout exit numbers
|
||||
• Improved visibility and UI of instructions in navigation
|
||||
• Added option to avoid steps
|
||||
• Improved search in multiple languages
|
||||
• Added specific icon for bus stations
|
||||
• Fixed Android Auto issues (via OM project)
|
||||
• Improved editor and fix minor issues
|
||||
• Improved map styles (via OM project)
|
||||
• Improved app translations
|
||||
Check our Codeberg release notes for more changes!
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
• Datos a 6 de septiembre
|
||||
• Penalizaciones de giros en rutas de bici
|
||||
• Etiquetas de puntos de interés en color en navegación
|
||||
• Buscar por nombre de sucursal
|
||||
• Añadir portales de energía, cabinas de seguridad y oficinas
|
||||
• Nuevos iconos: torres, discotecas, parafarmacias y mástiles
|
||||
• Guardar color en exportaciones GPX
|
||||
• Colorear áreas peatonales de plazas
|
||||
• Android Auto: mostrar números de salida de rotondas
|
||||
• Mejora de la visibilidad y la interfaz de usuario de las instrucciones de navegación
|
||||
• Se ha añadido la opción de evitar escaleras
|
||||
• Mejora de la búsqueda en varios idiomas como ES
|
||||
• Se ha añadido un icono específico para las estaciones de autobús
|
||||
• Se han solucionado los problemas de Android Auto (a través del proyecto OM)
|
||||
• Se ha mejorado el editor y se han solucionado pequeños problemas
|
||||
• Se han mejorado los estilos de los mapas (a través del proyecto OM)
|
||||
Más detalles en Codeberg
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
• Données OSM du 06 septembre
|
||||
• Pénalités dans les calculs d'itinéraires vélos
|
||||
• Ajout de labels colorés en mode navigation
|
||||
• Support du tag branch dans la recherche
|
||||
• Ajout des portiques électriques, postes de sécurité
|
||||
• Mise à jour des icônes de tours, boîtes de nuits, chimiste et mat
|
||||
• Enregistrement de la couleur des signets dans les exports GPX
|
||||
• Android Auto: Affichage du numéro de sortie des ronds-points
|
||||
• Interface utilisateur et visibilité des instructions en navigation améliorée
|
||||
• Option pour éviter les escaliers ajoutée
|
||||
• Recherche améliorée dans différents languages
|
||||
• Icône pour les gares routières ajoutée
|
||||
• Corrections de bugs liées à Android Auto (via OM)
|
||||
• Editeur amélioré et corrections de bugs
|
||||
• Style de la carte amélioré (via OM)
|
||||
• Traductions améliorées
|
||||
Plus d'informations sur notre Codeberg
|
||||
|
||||
32
android/app/src/fdroid/play/listings/id/full-description.txt
Normal file
@@ -0,0 +1,32 @@
|
||||
Aplikasi peta gratis & sumber terbuka yang dipimpin komunitas, berbasis data OpenStreetMap dan diperkuat dengan komitmen terhadap transparansi, privasi, serta non-profit. CoMaps adalah turunan dari Organic Maps, yang merupakan turunan dari Maps.ME.
|
||||
|
||||
Baca lebih lanjut tentang alasan proyek ini dan arahnya di <b><i>codeberg.org/comaps</i></b>.
|
||||
Bergabunglah dengan komunitas dan bantu menjadikan aplikasi peta terbaik
|
||||
• Gunakan aplikasi ini dan sebarkan
|
||||
• Beri masukan dan laporkan masalah
|
||||
• Perbarui data peta di aplikasi atau di situs OpenStreetMap
|
||||
|
||||
‣ <b>Fokus Offline</b>: Rencanakan dan navigasikan perjalananmu di luar negeri tanpa perlu layanan seluler, cari titik saat hiking jauh, dll. Semua fungsi aplikasi dirancang untuk bekerja offline.
|
||||
‣ <b>Menghormati Privasi</b>: Aplikasi ini dirancang dengan privasi sebagai prioritas – tidak mengidentifikasi orang, tidak melacak, dan tidak mengumpulkan informasi pribadi. Bebas iklan.
|
||||
‣ <b>Sederhana dan Rapi</b>: fitur penting yang mudah digunakan dan langsung berfungsi.
|
||||
‣ <b>Hemat Baterai dan Ruang</b>: Tidak menguras baterai seperti aplikasi navigasi lain. Peta ringkas menghemat ruang berharga di ponselmu.
|
||||
‣ <b>Gratis dan Dibangun oleh Komunitas</b>: Orang seperti kamu membantu membangun aplikasi ini dengan menambahkan tempat ke OpenStreetMap, menguji serta memberi masukan fitur, dan menyumbangkan keterampilan pengembangan maupun dana.
|
||||
‣ <b>Terbuka dan Transparan</b>: Pengambilan keputusan dan keuangan transparan, non-profit, dan sepenuhnya sumber terbuka.
|
||||
|
||||
<b>Fitur Utama</b>:
|
||||
• Peta detail yang bisa diunduh, dengan tempat yang tidak ada di Google Maps
|
||||
• Mode outdoor dengan sorotan jalur hiking, area berkemah, sumber air, puncak, garis kontur, dll
|
||||
• Jalur pejalan kaki dan jalur sepeda
|
||||
• Titik menarik seperti restoran, SPBU, hotel, toko, tempat wisata, dan banyak lagi
|
||||
• Pencarian berdasarkan nama, alamat, atau kategori titik menarik
|
||||
• Navigasi dengan suara untuk berjalan, bersepeda, atau berkendara
|
||||
• Tandai tempat favoritmu dengan sekali tap
|
||||
• Artikel Wikipedia offline
|
||||
• Layer dan rute transportasi subway
|
||||
• Rekaman jejak
|
||||
• Ekspor dan impor bookmark serta jejak dalam format KML, KMZ, GPX
|
||||
• Mode gelap untuk digunakan saat malam
|
||||
• Tingkatkan data peta untuk semua orang dengan editor bawaan sederhana
|
||||
|
||||
<b>Kebebasan Ada di Sini</b>
|
||||
Temukan perjalananmu, jelajahi dunia dengan privasi dan komunitas di garis depan!
|
||||
@@ -0,0 +1 @@
|
||||
Navigasi peta mudah – Temukan lebih banyak – Didukung oleh komunitas
|
||||
@@ -1,10 +0,0 @@
|
||||
• OpenStreetMap aggiornato al 6 Settembre
|
||||
• Bici: miglior stima del tempo di percorrenza
|
||||
• Auto: punti d'interesse colorati
|
||||
• Cerca i punti d'interesse tramite filiale
|
||||
• Aggiunte strutture alta tensione, cabine di sicurezza e uffici
|
||||
• Aggiornate le icone per torri, discoteche, farmacie e aste per bandiere
|
||||
• Salva il colore dei Preferiti nel GPX
|
||||
• Evidenziate le aree pedonali nelle piazze
|
||||
• AndroidAuto: aggiunto il numero dell'uscita nelle rotonde
|
||||
Visita Codeberg per ulteriori dettagli
|
||||
|
||||
@@ -1 +1 @@
|
||||
Lett kart navigasjon - Opplev mere på din reise - Drevet av felleskapet
|
||||
Enkel kartnavigering - Opplev mere på din reise - Drevet av felleskapet
|
||||
|
||||
@@ -1 +1 @@
|
||||
CoMaps - Gå tur, sykkel, kjør - med personvern
|
||||
CoMaps - Gå, sykle, kjøre offline med personvern
|
||||
|
||||
@@ -1 +1 @@
|
||||
Łatwa nawigacja – Odkryj więcej ze swojej podróży – Wspierane przez społeczność
|
||||
Łatwa nawigacja po mapie - Odkryj więcej z podróży - Wspierane przez społeczność
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
• Dados OSM de 6/09
|
||||
• Penalidades de conversão para bicicleta
|
||||
• Etiquetas de POI coloridas para o estilo do mapa de navegação de carros
|
||||
• Busca de POIs por nome de filial
|
||||
• Adição de portais de energia, guaritas e escritórios
|
||||
• Atualização de ícones para torres, discotecas, farmácias e mastros
|
||||
• Salva a cor dos favoritos nas exportações GPX
|
||||
• Preenchimento de praças pavimentadas
|
||||
• Android Auto: exibe números de saída de rotatória
|
||||
Confira nossas notas de lançamento do Codeberg para mais mudanças
|
||||
• Visibilidade e interface do usuário aprimoradas para instruções na navegação
|
||||
• Opção adicionada para evitar degraus
|
||||
• Busca aprimorada em vários idiomas
|
||||
• Adição de ícone específico para rodoviárias
|
||||
• Problemas corrigidos no Android Auto (via projeto OM)
|
||||
• Editor aprimorado e correção de problemas menores
|
||||
• Estilos de mapa aprimorados (via projeto OM)
|
||||
• Traduções aprimoradas
|
||||
Confira nossas notas de lançamento do Codeberg para mais mudanças!
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
• Данные на 6 сентября
|
||||
• Предупреждения на веломаршруте
|
||||
• Цветные метки POI при автонавигации
|
||||
• Поиск POI по названию ветки
|
||||
• Добавлены высоковольтные опоры, помещения охраны и офисы
|
||||
• Обновлены значки башен,вышек,мачт,ночных клубов,аптек
|
||||
• Сохранение цвета закладок при экспорте в GPX (через OM)
|
||||
• Отображение цветом пешеходных зон
|
||||
• Android Auto: отображение номеров съездов на кольцевых развязках
|
||||
Посмотрите примечания к выпуску Codeberg, чтобы узнать о других изменениях!
|
||||
• Лучшая видимость и интерфейс при навигации
|
||||
• Добавлена возможность пропускать шаги
|
||||
• Улучшен поиск на нескольких языках
|
||||
• Новый значок автостанций
|
||||
• Исправлены проблемы с Android Auto (через OM)
|
||||
• Улучшен редактор и исправлены мелкие недочёты
|
||||
• Улучшены стили карт (через OM)
|
||||
• Улучшены переводы приложения
|
||||
Ознакомьтесь с примечаниями к выпуску Codeberg, чтобы узнать изменениях!
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
Navigasi peta mudah – Temukan lebih banyak – Didukung oleh komunitas
|
||||
1
android/app/src/google/play/listings/id/title.txt
Normal file
@@ -0,0 +1 @@
|
||||
CoMaps - Jelajah dengan Privat
|
||||
@@ -0,0 +1 @@
|
||||
Enkel kartnavigering - Opplev mere på din reise - Drevet av felleskapet
|
||||
1
android/app/src/google/play/listings/no-NO/title.txt
Normal file
@@ -0,0 +1 @@
|
||||
CoMaps -Naviger med personvern
|
||||
@@ -0,0 +1 @@
|
||||
Łatwa nawigacja po mapie - Odkryj więcej z podróży - Wspierane przez społeczność
|
||||
@@ -89,6 +89,7 @@
|
||||
<!-- Allows for config and orientation change without killing/restarting main activity -->
|
||||
<activity
|
||||
android:name="app.organicmaps.SplashActivity"
|
||||
android:theme="@style/MwmTheme.Splash"
|
||||
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation"
|
||||
android:screenOrientation="fullUser"
|
||||
android:exported="true">
|
||||
@@ -349,6 +350,7 @@
|
||||
|
||||
<activity
|
||||
android:name="app.organicmaps.DownloadResourcesLegacyActivity"
|
||||
android:theme="@style/MwmTheme.DownloadResourcesLegacy"
|
||||
android:configChanges="orientation|screenLayout|screenSize"
|
||||
android:screenOrientation="fullUser"/>
|
||||
|
||||
@@ -365,6 +367,7 @@
|
||||
|
||||
<activity
|
||||
android:name="app.organicmaps.MwmActivity"
|
||||
android:theme="@style/MwmTheme.MainActivity"
|
||||
android:launchMode="singleTask"
|
||||
android:configChanges="uiMode"
|
||||
android:screenOrientation="fullUser"
|
||||
@@ -386,6 +389,7 @@
|
||||
|
||||
<activity
|
||||
android:name="app.organicmaps.search.SearchActivity"
|
||||
android:theme="@style/MwmTheme.CardBg"
|
||||
android:configChanges="orientation|screenLayout|screenSize"
|
||||
android:screenOrientation="fullUser"
|
||||
android:label="@string/search_map"
|
||||
@@ -412,6 +416,7 @@
|
||||
|
||||
<activity
|
||||
android:name="app.organicmaps.bookmarks.BookmarkCategoriesActivity"
|
||||
android:theme="@style/MwmTheme.WindowBg"
|
||||
android:configChanges="orientation|screenLayout|screenSize"
|
||||
android:screenOrientation="fullUser"
|
||||
android:label="@string/bookmarks_and_tracks"
|
||||
@@ -420,6 +425,7 @@
|
||||
|
||||
<activity
|
||||
android:name="app.organicmaps.bookmarks.BookmarkListActivity"
|
||||
android:theme="@style/MwmTheme.CardBg"
|
||||
android:configChanges="orientation|screenLayout|screenSize"
|
||||
android:screenOrientation="fullUser"
|
||||
android:label="@string/bookmarks"
|
||||
|
||||
@@ -24,7 +24,6 @@ import androidx.annotation.CallSuper;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.annotation.StyleRes;
|
||||
import androidx.core.view.ViewCompat;
|
||||
import app.organicmaps.base.BaseMwmFragmentActivity;
|
||||
import app.organicmaps.downloader.MapManagerHelper;
|
||||
@@ -438,11 +437,4 @@ public class DownloadResourcesLegacyActivity extends BaseMwmFragmentActivity
|
||||
.setOnDismissListener(dialog -> mAlertDialog = null)
|
||||
.show();
|
||||
}
|
||||
|
||||
@Override
|
||||
@StyleRes
|
||||
public int getThemeResourceId(@NonNull String theme)
|
||||
{
|
||||
return R.style.MwmTheme_DownloadResourcesLegacy;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,210 +0,0 @@
|
||||
package app.organicmaps;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.SurfaceHolder;
|
||||
import android.view.SurfaceView;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.content.res.ConfigurationHelper;
|
||||
import app.organicmaps.base.BaseMwmFragment;
|
||||
import app.organicmaps.sdk.Map;
|
||||
import app.organicmaps.sdk.MapRenderingListener;
|
||||
import app.organicmaps.sdk.display.DisplayType;
|
||||
import app.organicmaps.sdk.util.log.Logger;
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||
|
||||
public class MapFragment extends BaseMwmFragment implements View.OnTouchListener, SurfaceHolder.Callback
|
||||
{
|
||||
private static final String TAG = MapFragment.class.getSimpleName();
|
||||
|
||||
@NonNull
|
||||
private final Map mMap = new Map(DisplayType.Device);
|
||||
|
||||
public void updateCompassOffset(int offsetX, int offsetY)
|
||||
{
|
||||
mMap.updateCompassOffset(requireContext(), offsetX, offsetY, true);
|
||||
}
|
||||
|
||||
public void updateBottomWidgetsOffset(int offsetX, int offsetY)
|
||||
{
|
||||
mMap.updateBottomWidgetsOffset(requireContext(), offsetX, offsetY);
|
||||
}
|
||||
|
||||
public void updateMyPositionRoutingOffset(int offsetY)
|
||||
{
|
||||
mMap.updateMyPositionRoutingOffset(offsetY);
|
||||
}
|
||||
|
||||
public void destroySurface(boolean activityIsChangingConfigurations)
|
||||
{
|
||||
mMap.onSurfaceDestroyed(activityIsChangingConfigurations, isAdded());
|
||||
}
|
||||
|
||||
public boolean isContextCreated()
|
||||
{
|
||||
return mMap.isContextCreated();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void surfaceCreated(@NonNull SurfaceHolder surfaceHolder)
|
||||
{
|
||||
Logger.d(TAG);
|
||||
int densityDpi;
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R)
|
||||
densityDpi = ConfigurationHelper.getDensityDpi(requireContext().getResources());
|
||||
else
|
||||
densityDpi = getDensityDpiOld();
|
||||
|
||||
mMap.onSurfaceCreated(requireContext(), surfaceHolder.getSurface(), surfaceHolder.getSurfaceFrame(), densityDpi);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void surfaceChanged(SurfaceHolder surfaceHolder, int format, int width, int height)
|
||||
{
|
||||
Logger.d(TAG);
|
||||
mMap.onSurfaceChanged(requireContext(), surfaceHolder.getSurface(), surfaceHolder.getSurfaceFrame(),
|
||||
surfaceHolder.isCreating());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void surfaceDestroyed(@NonNull SurfaceHolder surfaceHolder)
|
||||
{
|
||||
Logger.d(TAG);
|
||||
mMap.onSurfaceDestroyed(requireActivity().isChangingConfigurations(), true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttach(Context context)
|
||||
{
|
||||
Logger.d(TAG);
|
||||
super.onAttach(context);
|
||||
|
||||
mMap.setLocationHelper(MwmApplication.from(requireContext()).getLocationHelper());
|
||||
mMap.setMapRenderingListener((MapRenderingListener) context);
|
||||
mMap.setCallbackUnsupported(this::reportUnsupported);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDetach()
|
||||
{
|
||||
Logger.d(TAG);
|
||||
super.onDetach();
|
||||
mMap.setMapRenderingListener(null);
|
||||
mMap.setCallbackUnsupported(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle b)
|
||||
{
|
||||
Logger.d(TAG);
|
||||
super.onCreate(b);
|
||||
setRetainInstance(true);
|
||||
boolean launchByDeepLink = false;
|
||||
Bundle args = getArguments();
|
||||
if (args != null)
|
||||
launchByDeepLink = args.getBoolean(Map.ARG_LAUNCH_BY_DEEP_LINK);
|
||||
mMap.onCreate(launchByDeepLink);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart()
|
||||
{
|
||||
Logger.d(TAG);
|
||||
super.onStart();
|
||||
mMap.onStart();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStop()
|
||||
{
|
||||
Logger.d(TAG);
|
||||
super.onStop();
|
||||
mMap.onStop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause()
|
||||
{
|
||||
Logger.d(TAG);
|
||||
super.onPause();
|
||||
mMap.onPause(requireContext());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume()
|
||||
{
|
||||
Logger.d(TAG);
|
||||
super.onResume();
|
||||
mMap.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState)
|
||||
{
|
||||
Logger.d(TAG);
|
||||
final View view = inflater.inflate(R.layout.fragment_map, container, false);
|
||||
final SurfaceView mSurfaceView = view.findViewById(R.id.map_surfaceview);
|
||||
mSurfaceView.getHolder().addCallback(this);
|
||||
return view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouch(View view, MotionEvent event)
|
||||
{
|
||||
int action = event.getActionMasked();
|
||||
int pointerIndex = event.getActionIndex();
|
||||
switch (action)
|
||||
{
|
||||
case MotionEvent.ACTION_POINTER_UP -> action = Map.NATIVE_ACTION_UP;
|
||||
case MotionEvent.ACTION_UP ->
|
||||
{
|
||||
action = Map.NATIVE_ACTION_UP;
|
||||
pointerIndex = 0;
|
||||
}
|
||||
case MotionEvent.ACTION_POINTER_DOWN -> action = Map.NATIVE_ACTION_DOWN;
|
||||
case MotionEvent.ACTION_DOWN ->
|
||||
{
|
||||
action = Map.NATIVE_ACTION_DOWN;
|
||||
pointerIndex = 0;
|
||||
}
|
||||
case MotionEvent.ACTION_MOVE ->
|
||||
{
|
||||
action = Map.NATIVE_ACTION_MOVE;
|
||||
pointerIndex = Map.INVALID_POINTER_MASK;
|
||||
}
|
||||
case MotionEvent.ACTION_CANCEL -> action = Map.NATIVE_ACTION_CANCEL;
|
||||
}
|
||||
Map.onTouch(action, event, pointerIndex);
|
||||
return true;
|
||||
}
|
||||
|
||||
public void notifyOnSurfaceDestroyed(@NonNull Runnable task)
|
||||
{
|
||||
mMap.onSurfaceDestroyed(false, true);
|
||||
task.run();
|
||||
}
|
||||
|
||||
private void reportUnsupported()
|
||||
{
|
||||
new MaterialAlertDialogBuilder(requireContext(), R.style.MwmTheme_AlertDialog)
|
||||
.setMessage(R.string.unsupported_phone)
|
||||
.setCancelable(false)
|
||||
.setPositiveButton(R.string.close, (dlg, which) -> requireActivity().moveTaskToBack(true))
|
||||
.show();
|
||||
}
|
||||
|
||||
private int getDensityDpiOld()
|
||||
{
|
||||
final DisplayMetrics metrics = new DisplayMetrics();
|
||||
requireActivity().getWindowManager().getDefaultDisplay().getMetrics(metrics);
|
||||
return metrics.densityDpi;
|
||||
}
|
||||
}
|
||||
@@ -42,7 +42,6 @@ import androidx.annotation.CallSuper;
|
||||
import androidx.annotation.Keep;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.StyleRes;
|
||||
import androidx.annotation.UiThread;
|
||||
import androidx.core.app.ActivityCompat;
|
||||
import androidx.core.content.ContextCompat;
|
||||
@@ -85,6 +84,7 @@ import app.organicmaps.routing.RoutingPlanInplaceController;
|
||||
import app.organicmaps.sdk.ChoosePositionMode;
|
||||
import app.organicmaps.sdk.Framework;
|
||||
import app.organicmaps.sdk.Map;
|
||||
import app.organicmaps.sdk.MapController;
|
||||
import app.organicmaps.sdk.MapRenderingListener;
|
||||
import app.organicmaps.sdk.PlacePageActivationListener;
|
||||
import app.organicmaps.sdk.Router;
|
||||
@@ -138,10 +138,10 @@ import java.util.ArrayList;
|
||||
import java.util.Objects;
|
||||
|
||||
public class MwmActivity extends BaseMwmFragmentActivity
|
||||
implements PlacePageActivationListener, View.OnTouchListener, MapRenderingListener, RoutingController.Container,
|
||||
LocationListener, SensorListener, LocationState.ModeChangeListener,
|
||||
RoutingPlanInplaceController.RoutingPlanListener, RoutingBottomMenuListener,
|
||||
BookmarkManager.BookmarksLoadingListener, FloatingSearchToolbarController.SearchToolbarListener,
|
||||
implements PlacePageActivationListener, MapRenderingListener, RoutingController.Container, LocationListener,
|
||||
SensorListener, LocationState.ModeChangeListener, RoutingPlanInplaceController.RoutingPlanListener,
|
||||
RoutingBottomMenuListener, BookmarkManager.BookmarksLoadingListener,
|
||||
FloatingSearchToolbarController.SearchToolbarListener,
|
||||
MenuBottomSheetFragment.MenuBottomSheetInterfaceWithHeader,
|
||||
PlacePageController.PlacePageRouteSettingsListener, MapButtonsController.MapButtonClickListener,
|
||||
DisplayChangedListener
|
||||
@@ -171,8 +171,9 @@ public class MwmActivity extends BaseMwmFragmentActivity
|
||||
|
||||
private static final String POWER_SAVE_DISCLAIMER_SHOWN = "POWER_SAVE_DISCLAIMER_SHOWN";
|
||||
|
||||
@Nullable
|
||||
private MapFragment mMapFragment;
|
||||
@SuppressWarnings("NotNullFieldNotInitialized")
|
||||
@NonNull
|
||||
private MapController mMapController;
|
||||
|
||||
private View mPointChooser;
|
||||
private MaterialToolbar mPointChooserToolbar;
|
||||
@@ -245,7 +246,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
|
||||
ManageRouteBottomSheet mManageRouteBottomSheet;
|
||||
|
||||
private boolean mRemoveDisplayListener = true;
|
||||
private int mLastUiMode = Configuration.UI_MODE_TYPE_UNDEFINED;
|
||||
private static int mLastUiMode = Configuration.UI_MODE_TYPE_UNDEFINED;
|
||||
|
||||
public interface LeftAnimationTrackListener
|
||||
{
|
||||
@@ -455,25 +456,12 @@ public class MwmActivity extends BaseMwmFragmentActivity
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@StyleRes
|
||||
protected int getThemeResourceId(@NonNull String theme)
|
||||
{
|
||||
if (Config.UiTheme.isDefault(theme))
|
||||
return R.style.MwmTheme_MainActivity;
|
||||
|
||||
if (Config.UiTheme.isNight(theme))
|
||||
return R.style.MwmTheme_Night_MainActivity;
|
||||
|
||||
return super.getThemeResourceId(theme);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisplayChangedToCar(@NonNull Runnable onTaskFinishedCallback)
|
||||
{
|
||||
mRemoveDisplayListener = false;
|
||||
startActivity(new Intent(this, MapPlaceholderActivity.class));
|
||||
Objects.requireNonNull(mMapFragment).notifyOnSurfaceDestroyed(onTaskFinishedCallback);
|
||||
mMapController.setOnDestroyListener(onTaskFinishedCallback);
|
||||
finish();
|
||||
}
|
||||
|
||||
@@ -482,13 +470,15 @@ public class MwmActivity extends BaseMwmFragmentActivity
|
||||
{
|
||||
super.onConfigurationChanged(newConfig);
|
||||
|
||||
final int newUiMode = newConfig.uiMode & Configuration.UI_MODE_TYPE_MASK;
|
||||
final boolean newUiModeIsCarConnected = newUiMode == Configuration.UI_MODE_TYPE_CAR;
|
||||
final boolean newUiModeIsCarDisconnected =
|
||||
mLastUiMode == Configuration.UI_MODE_TYPE_CAR && newUiMode == Configuration.UI_MODE_TYPE_NORMAL;
|
||||
mLastUiMode = newUiMode;
|
||||
final int newType = newConfig.uiMode & Configuration.UI_MODE_TYPE_MASK;
|
||||
final int oldType = mLastUiMode & Configuration.UI_MODE_TYPE_MASK;
|
||||
|
||||
if (newUiModeIsCarConnected || newUiModeIsCarDisconnected)
|
||||
mLastUiMode = newConfig.uiMode;
|
||||
|
||||
final boolean carModeChanged =
|
||||
newType != oldType && (newType == Configuration.UI_MODE_TYPE_CAR || oldType == Configuration.UI_MODE_TYPE_CAR);
|
||||
|
||||
if (carModeChanged)
|
||||
return;
|
||||
|
||||
makeNavigationBarTransparentInLightMode();
|
||||
@@ -550,7 +540,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
|
||||
updateViewsInsets();
|
||||
|
||||
if (getIntent().getBooleanExtra(EXTRA_UPDATE_THEME, false))
|
||||
ThemeSwitcher.INSTANCE.restart(isMapRendererActive());
|
||||
ThemeSwitcher.INSTANCE.restart(mMapController.isRenderingActive());
|
||||
|
||||
/*
|
||||
* onRenderingInitializationFinished() hook is not called when MwmActivity is recreated with the already
|
||||
@@ -618,7 +608,10 @@ public class MwmActivity extends BaseMwmFragmentActivity
|
||||
|
||||
private void initViews(boolean isLaunchByDeeplink)
|
||||
{
|
||||
initMap(isLaunchByDeeplink);
|
||||
mMapController = new MapController(findViewById(R.id.map), MwmApplication.from(this).getLocationHelper(), this,
|
||||
this::reportUnsupported, isLaunchByDeeplink);
|
||||
getLifecycle().addObserver(mMapController);
|
||||
|
||||
initNavigationButtons();
|
||||
|
||||
if (!mIsTabletLayout)
|
||||
@@ -732,16 +725,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
|
||||
private void showPositionChooser(ChoosePositionMode mode, boolean isBusiness, boolean applyPosition)
|
||||
{
|
||||
closeFloatingToolbarsAndPanels(false);
|
||||
if (mMapFragment != null)
|
||||
{
|
||||
final View mapView = mMapFragment.getView();
|
||||
if (mapView != null)
|
||||
{
|
||||
int width = mapView.getWidth();
|
||||
int height = mapView.getHeight();
|
||||
Framework.nativeSetVisibleRect(0, 0, width, height);
|
||||
}
|
||||
}
|
||||
|
||||
UiUtils.show(mPointChooser);
|
||||
mMapButtonsViewModel.setButtonsHidden(true);
|
||||
ChoosePositionMode.set(mode, isBusiness, applyPosition);
|
||||
@@ -760,29 +744,6 @@ public class MwmActivity extends BaseMwmFragmentActivity
|
||||
finish();
|
||||
}
|
||||
|
||||
private void initMap(boolean isLaunchByDeepLink)
|
||||
{
|
||||
final FragmentManager manager = getSupportFragmentManager();
|
||||
mMapFragment = (MapFragment) manager.findFragmentByTag(MapFragment.class.getName());
|
||||
if (mMapFragment == null)
|
||||
{
|
||||
Bundle args = new Bundle();
|
||||
args.putBoolean(Map.ARG_LAUNCH_BY_DEEP_LINK, isLaunchByDeepLink);
|
||||
final FragmentFactory factory = manager.getFragmentFactory();
|
||||
mMapFragment = (MapFragment) factory.instantiate(getClassLoader(), MapFragment.class.getName());
|
||||
mMapFragment.setArguments(args);
|
||||
manager.beginTransaction()
|
||||
.replace(R.id.map_fragment_container, mMapFragment, MapFragment.class.getName())
|
||||
.commit();
|
||||
}
|
||||
|
||||
View container = findViewById(R.id.map_fragment_container);
|
||||
if (container != null)
|
||||
{
|
||||
container.setOnTouchListener(this);
|
||||
}
|
||||
}
|
||||
|
||||
private void initNavigationButtons()
|
||||
{
|
||||
prepareNavigationButtons();
|
||||
@@ -1211,7 +1172,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
|
||||
{
|
||||
setIntent(intent);
|
||||
super.onNewIntent(intent);
|
||||
if (isMapRendererActive())
|
||||
if (mMapController.isRenderingActive())
|
||||
processIntent();
|
||||
if (intent.getAction() != null && intent.getAction().equals(TrackRecordingService.STOP_TRACK_RECORDING))
|
||||
{
|
||||
@@ -1221,17 +1182,12 @@ public class MwmActivity extends BaseMwmFragmentActivity
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isMapRendererActive()
|
||||
{
|
||||
return mMapFragment != null && Map.isEngineCreated() && mMapFragment.isContextCreated();
|
||||
}
|
||||
|
||||
@CallSuper
|
||||
@Override
|
||||
protected void onResume()
|
||||
{
|
||||
super.onResume();
|
||||
ThemeSwitcher.INSTANCE.restart(isMapRendererActive());
|
||||
ThemeSwitcher.INSTANCE.restart(mMapController.isRenderingActive());
|
||||
refreshSearchToolbar();
|
||||
setFullscreen(isFullscreen());
|
||||
makeNavigationBarTransparentInLightMode();
|
||||
@@ -1249,15 +1205,6 @@ public class MwmActivity extends BaseMwmFragmentActivity
|
||||
MwmApplication.from(this).getSensorHelper().addListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void recreate()
|
||||
{
|
||||
// Explicitly destroy surface before activity recreation.
|
||||
if (mMapFragment != null)
|
||||
mMapFragment.destroySurface(true);
|
||||
super.recreate();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResumeFragments()
|
||||
{
|
||||
@@ -1459,12 +1406,6 @@ public class MwmActivity extends BaseMwmFragmentActivity
|
||||
return super.onGenericMotionEvent(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouch(View view, MotionEvent event)
|
||||
{
|
||||
return mMapFragment != null && mMapFragment.onTouch(view, event);
|
||||
}
|
||||
|
||||
public void customOnNavigateUp()
|
||||
{
|
||||
if (removeCurrentFragment(true))
|
||||
@@ -1480,10 +1421,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
|
||||
|
||||
void updateCompassOffset(int offsetY, int offsetX)
|
||||
{
|
||||
if (mMapFragment == null || !mMapFragment.isAdded())
|
||||
return;
|
||||
|
||||
mMapFragment.updateCompassOffset(offsetX, offsetY);
|
||||
mMapController.updateCompassOffset(offsetX, offsetY);
|
||||
|
||||
final double north = MwmApplication.from(this).getSensorHelper().getSavedNorth();
|
||||
if (!Double.isNaN(north))
|
||||
@@ -1502,9 +1440,6 @@ public class MwmActivity extends BaseMwmFragmentActivity
|
||||
|
||||
public void updateBottomWidgetsOffset(int offsetX)
|
||||
{
|
||||
if (mMapFragment == null || !mMapFragment.isAdded())
|
||||
return;
|
||||
|
||||
int offsetY = mNavBarHeight;
|
||||
final Float bottomButtonHeight = mMapButtonsViewModel.getBottomButtonsHeight().getValue();
|
||||
if (bottomButtonHeight != null)
|
||||
@@ -1519,8 +1454,8 @@ public class MwmActivity extends BaseMwmFragmentActivity
|
||||
|
||||
if (mDisplayManager.isDeviceDisplayUsed())
|
||||
{
|
||||
mMapFragment.updateBottomWidgetsOffset(offsetX, offsetY);
|
||||
mMapFragment.updateMyPositionRoutingOffset(offsetY);
|
||||
mMapController.updateBottomWidgetsOffset(offsetX, offsetY);
|
||||
mMapController.updateMyPositionRoutingOffset(offsetY);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1738,7 +1673,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
|
||||
public void onNavigationCancelled()
|
||||
{
|
||||
closeFloatingToolbarsAndPanels(true);
|
||||
ThemeSwitcher.INSTANCE.restart(isMapRendererActive());
|
||||
ThemeSwitcher.INSTANCE.restart(mMapController.isRenderingActive());
|
||||
if (mRoutingPlanInplaceController == null)
|
||||
return;
|
||||
|
||||
@@ -1754,7 +1689,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
|
||||
public void onNavigationStarted()
|
||||
{
|
||||
closeFloatingToolbarsAndPanels(true);
|
||||
ThemeSwitcher.INSTANCE.restart(isMapRendererActive());
|
||||
ThemeSwitcher.INSTANCE.restart(mMapController.isRenderingActive());
|
||||
mMapButtonsViewModel.setLayoutMode(MapButtonsController.LayoutMode.navigation);
|
||||
refreshLightStatusBar();
|
||||
|
||||
@@ -1790,7 +1725,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
|
||||
public void onResetToPlanningState()
|
||||
{
|
||||
closeFloatingToolbarsAndPanels(true);
|
||||
ThemeSwitcher.INSTANCE.restart(isMapRendererActive());
|
||||
ThemeSwitcher.INSTANCE.restart(mMapController.isRenderingActive());
|
||||
NavigationService.stopService(this);
|
||||
mMapButtonsViewModel.setSearchOption(null);
|
||||
mMapButtonsViewModel.setLayoutMode(MapButtonsController.LayoutMode.planning);
|
||||
@@ -2619,4 +2554,13 @@ public class MwmActivity extends BaseMwmFragmentActivity
|
||||
window.setNavigationBarContrastEnforced(false);
|
||||
}
|
||||
}
|
||||
|
||||
private void reportUnsupported()
|
||||
{
|
||||
new MaterialAlertDialogBuilder(this, R.style.MwmTheme_AlertDialog)
|
||||
.setMessage(R.string.unsupported_phone)
|
||||
.setCancelable(false)
|
||||
.setPositiveButton(R.string.close, (dlg, which) -> this.moveTaskToBack(true))
|
||||
.show();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,15 +56,6 @@ public class SplashActivity extends AppCompatActivity
|
||||
protected void onCreate(@Nullable Bundle savedInstanceState)
|
||||
{
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
final String theme = Config.UiTheme.getCurrent();
|
||||
if (Config.UiTheme.isDefault(theme))
|
||||
setTheme(R.style.MwmTheme_Splash);
|
||||
else if (Config.UiTheme.isNight(theme))
|
||||
setTheme(R.style.MwmTheme_Night_Splash);
|
||||
else
|
||||
throw new IllegalArgumentException("Attempt to apply unsupported theme: " + theme);
|
||||
|
||||
UiThread.cancelDelayedTasks(mInitCoreDelayedTask);
|
||||
setContentView(R.layout.activity_splash);
|
||||
|
||||
|
||||
@@ -8,14 +8,13 @@ import androidx.annotation.Nullable;
|
||||
import androidx.annotation.StyleRes;
|
||||
import androidx.fragment.app.DialogFragment;
|
||||
import app.organicmaps.R;
|
||||
import app.organicmaps.util.ThemeUtils;
|
||||
|
||||
public class BaseMwmDialogFragment extends DialogFragment
|
||||
{
|
||||
@StyleRes
|
||||
protected final int getFullscreenTheme()
|
||||
{
|
||||
return ThemeUtils.isNightTheme() ? getFullscreenDarkTheme() : getFullscreenLightTheme();
|
||||
return R.style.MwmTheme_DialogFragment_Fullscreen;
|
||||
}
|
||||
|
||||
protected int getStyle()
|
||||
@@ -23,7 +22,8 @@ public class BaseMwmDialogFragment extends DialogFragment
|
||||
return STYLE_NORMAL;
|
||||
}
|
||||
|
||||
protected @StyleRes int getCustomTheme()
|
||||
@StyleRes
|
||||
protected int getCustomTheme()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -40,18 +40,6 @@ public class BaseMwmDialogFragment extends DialogFragment
|
||||
setStyle(style, theme);
|
||||
}
|
||||
|
||||
@StyleRes
|
||||
protected int getFullscreenLightTheme()
|
||||
{
|
||||
return R.style.MwmTheme_DialogFragment_Fullscreen;
|
||||
}
|
||||
|
||||
@StyleRes
|
||||
protected int getFullscreenDarkTheme()
|
||||
{
|
||||
return R.style.MwmTheme_DialogFragment_Fullscreen_Night;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
protected Application getAppContextOrThrow()
|
||||
{
|
||||
|
||||
@@ -11,7 +11,6 @@ import androidx.activity.SystemBarStyle;
|
||||
import androidx.annotation.CallSuper;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.StyleRes;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentFactory;
|
||||
@@ -20,7 +19,6 @@ import app.organicmaps.MwmApplication;
|
||||
import app.organicmaps.R;
|
||||
import app.organicmaps.SplashActivity;
|
||||
import app.organicmaps.sdk.util.Config;
|
||||
import app.organicmaps.sdk.util.concurrency.UiThread;
|
||||
import app.organicmaps.sdk.util.log.Logger;
|
||||
import app.organicmaps.util.RtlUtils;
|
||||
import com.google.android.material.appbar.MaterialToolbar;
|
||||
@@ -32,24 +30,9 @@ public abstract class BaseMwmFragmentActivity extends AppCompatActivity
|
||||
|
||||
private boolean mSafeCreated;
|
||||
|
||||
@NonNull
|
||||
private String mThemeName;
|
||||
|
||||
@StyleRes
|
||||
protected int getThemeResourceId(@NonNull String theme)
|
||||
{
|
||||
if (Config.UiTheme.isDefault(theme))
|
||||
return R.style.MwmTheme;
|
||||
|
||||
if (Config.UiTheme.isNight(theme))
|
||||
return R.style.MwmTheme_Night;
|
||||
|
||||
throw new IllegalArgumentException("Attempt to apply unsupported theme: " + theme);
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows splash screen and initializes the core in case when it was not initialized.
|
||||
*
|
||||
* <p>
|
||||
* Do not override this method!
|
||||
* Use {@link #onSafeCreate(Bundle savedInstanceState)}
|
||||
*/
|
||||
@@ -58,8 +41,6 @@ public abstract class BaseMwmFragmentActivity extends AppCompatActivity
|
||||
protected final void onCreate(@Nullable Bundle savedInstanceState)
|
||||
{
|
||||
super.onCreate(savedInstanceState);
|
||||
mThemeName = Config.UiTheme.getCurrent();
|
||||
setTheme(getThemeResourceId(mThemeName));
|
||||
EdgeToEdge.enable(this, SystemBarStyle.dark(Color.TRANSPARENT));
|
||||
RtlUtils.manageRtl(this);
|
||||
if (!MwmApplication.from(this).getOrganicMaps().arePlatformAndCoreInitialized())
|
||||
@@ -113,18 +94,6 @@ public abstract class BaseMwmFragmentActivity extends AppCompatActivity
|
||||
mSafeCreated = false;
|
||||
}
|
||||
|
||||
@CallSuper
|
||||
@Override
|
||||
public void onPostResume()
|
||||
{
|
||||
super.onPostResume();
|
||||
if (!mThemeName.equals(Config.UiTheme.getCurrent()))
|
||||
{
|
||||
// Workaround described in https://code.google.com/p/android/issues/detail?id=93731
|
||||
UiThread.runLater(this::recreate);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item)
|
||||
{
|
||||
|
||||
@@ -6,13 +6,11 @@ import android.os.Bundle;
|
||||
import androidx.annotation.CallSuper;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.StyleRes;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import app.organicmaps.R;
|
||||
import app.organicmaps.base.BaseToolbarActivity;
|
||||
import app.organicmaps.sdk.bookmarks.data.BookmarkCategory;
|
||||
import app.organicmaps.sdk.bookmarks.data.BookmarkManager;
|
||||
import app.organicmaps.util.ThemeUtils;
|
||||
|
||||
public class BookmarkCategoriesActivity extends BaseToolbarActivity
|
||||
{
|
||||
@@ -38,13 +36,6 @@ public class BookmarkCategoriesActivity extends BaseToolbarActivity
|
||||
super.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
@StyleRes
|
||||
public int getThemeResourceId(@NonNull String theme)
|
||||
{
|
||||
return ThemeUtils.getWindowBgThemeResourceId(theme);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<? extends Fragment> getFragmentClass()
|
||||
{
|
||||
|
||||
@@ -54,7 +54,6 @@ public class BookmarkCategorySettingsFragment extends BaseMwmToolbarFragment
|
||||
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState)
|
||||
{
|
||||
View root = inflater.inflate(R.layout.fragment_bookmark_category_settings, container, false);
|
||||
setHasOptionsMenu(true);
|
||||
initViews(root);
|
||||
return root;
|
||||
}
|
||||
@@ -85,7 +84,7 @@ public class BookmarkCategorySettingsFragment extends BaseMwmToolbarFragment
|
||||
});
|
||||
mEditDescView = root.findViewById(R.id.edit_description);
|
||||
mEditDescView.setText(mCategory.getDescription());
|
||||
mSaveView = root.findViewById(R.id.done);
|
||||
mSaveView = root.findViewById(R.id.save);
|
||||
mSaveView.setOnClickListener(v -> onEditDoneClicked());
|
||||
}
|
||||
|
||||
|
||||
@@ -5,13 +5,11 @@ import android.os.Bundle;
|
||||
import androidx.activity.result.ActivityResultLauncher;
|
||||
import androidx.annotation.CallSuper;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.StyleRes;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import app.organicmaps.R;
|
||||
import app.organicmaps.base.BaseToolbarActivity;
|
||||
import app.organicmaps.sdk.bookmarks.data.BookmarkCategory;
|
||||
import app.organicmaps.sdk.bookmarks.data.BookmarkManager;
|
||||
import app.organicmaps.util.ThemeUtils;
|
||||
|
||||
public class BookmarkListActivity extends BaseToolbarActivity
|
||||
{
|
||||
@@ -37,13 +35,6 @@ public class BookmarkListActivity extends BaseToolbarActivity
|
||||
super.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
@StyleRes
|
||||
public int getThemeResourceId(@NonNull String theme)
|
||||
{
|
||||
return ThemeUtils.getCardBgThemeResourceId(theme);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<? extends Fragment> getFragmentClass()
|
||||
{
|
||||
|
||||
@@ -12,9 +12,12 @@ import androidx.lifecycle.DefaultLifecycleObserver;
|
||||
import androidx.lifecycle.LifecycleOwner;
|
||||
import app.organicmaps.MwmApplication;
|
||||
import app.organicmaps.R;
|
||||
import app.organicmaps.car.renderer.Renderer;
|
||||
import app.organicmaps.car.renderer.RendererFactory;
|
||||
import app.organicmaps.car.screens.ErrorScreen;
|
||||
import app.organicmaps.car.screens.MapPlaceholderScreen;
|
||||
import app.organicmaps.car.screens.MapScreen;
|
||||
import app.organicmaps.car.screens.NavigationScreen;
|
||||
import app.organicmaps.car.screens.PlaceScreen;
|
||||
import app.organicmaps.car.screens.base.BaseMapScreen;
|
||||
import app.organicmaps.car.screens.download.DownloadMapsScreen;
|
||||
@@ -49,8 +52,9 @@ public final class CarAppSession extends Session implements DefaultLifecycleObse
|
||||
|
||||
@Nullable
|
||||
private final SessionInfo mSessionInfo;
|
||||
@SuppressWarnings("NotNullFieldNotInitialized")
|
||||
@NonNull
|
||||
private final SurfaceRenderer mSurfaceRenderer;
|
||||
private Renderer mSurfaceRenderer;
|
||||
@NonNull
|
||||
private final ScreenManager mScreenManager;
|
||||
@SuppressWarnings("NotNullFieldNotInitialized")
|
||||
@@ -67,7 +71,6 @@ public final class CarAppSession extends Session implements DefaultLifecycleObse
|
||||
{
|
||||
getLifecycle().addObserver(this);
|
||||
mSessionInfo = sessionInfo;
|
||||
mSurfaceRenderer = new SurfaceRenderer(getCarContext(), getLifecycle());
|
||||
mScreenManager = getCarContext().getCarService(ScreenManager.class);
|
||||
mCurrentCountryChangedListener = new CurrentCountryChangedListener();
|
||||
}
|
||||
@@ -114,6 +117,8 @@ public final class CarAppSession extends Session implements DefaultLifecycleObse
|
||||
mSensorsManager = new CarSensorsManager(getCarContext());
|
||||
mDisplayManager = MwmApplication.from(getCarContext()).getDisplayManager();
|
||||
mDisplayManager.addListener(DisplayType.Car, this);
|
||||
mSurfaceRenderer = RendererFactory.create(getCarContext(), mDisplayManager,
|
||||
MwmApplication.from(getCarContext()).getLocationHelper(), this);
|
||||
init();
|
||||
}
|
||||
|
||||
@@ -281,7 +286,19 @@ public final class CarAppSession extends Session implements DefaultLifecycleObse
|
||||
private void restoreRoute()
|
||||
{
|
||||
final RoutingController routingController = RoutingController.get();
|
||||
if (routingController.isPlanning() || routingController.isNavigating() || routingController.hasSavedRoute())
|
||||
final boolean isNavigating = routingController.isNavigating();
|
||||
final boolean hasNavigatingScreen = hasNavigationScreenInStack();
|
||||
|
||||
if (!isNavigating && hasNavigatingScreen)
|
||||
mScreenManager.popToRoot();
|
||||
|
||||
if (isNavigating && routingController.getLastRouterType() == PlaceScreen.ROUTER && hasNavigatingScreen)
|
||||
{
|
||||
mScreenManager.popTo(NavigationScreen.MARKER);
|
||||
return;
|
||||
}
|
||||
|
||||
if (routingController.isPlanning() || isNavigating || routingController.hasSavedRoute())
|
||||
{
|
||||
final PlaceScreen placeScreen = new PlaceScreen.Builder(getCarContext(), mSurfaceRenderer)
|
||||
.setMapObject(routingController.getEndPoint())
|
||||
@@ -290,4 +307,14 @@ public final class CarAppSession extends Session implements DefaultLifecycleObse
|
||||
mScreenManager.push(placeScreen);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean hasNavigationScreenInStack()
|
||||
{
|
||||
for (final Screen screen : mScreenManager.getScreenStack())
|
||||
{
|
||||
if (NavigationScreen.MARKER.equals(screen.getMarker()))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,244 +0,0 @@
|
||||
package app.organicmaps.car;
|
||||
|
||||
import static app.organicmaps.sdk.display.DisplayType.Car;
|
||||
|
||||
import android.graphics.Rect;
|
||||
import android.view.Surface;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.car.app.AppManager;
|
||||
import androidx.car.app.CarContext;
|
||||
import androidx.car.app.CarToast;
|
||||
import androidx.car.app.SurfaceCallback;
|
||||
import androidx.car.app.SurfaceContainer;
|
||||
import androidx.lifecycle.DefaultLifecycleObserver;
|
||||
import androidx.lifecycle.Lifecycle;
|
||||
import androidx.lifecycle.LifecycleOwner;
|
||||
import app.organicmaps.MwmApplication;
|
||||
import app.organicmaps.R;
|
||||
import app.organicmaps.sdk.Framework;
|
||||
import app.organicmaps.sdk.Map;
|
||||
import app.organicmaps.sdk.MapRenderingListener;
|
||||
import app.organicmaps.sdk.settings.UnitLocale;
|
||||
import app.organicmaps.sdk.util.concurrency.UiThread;
|
||||
import app.organicmaps.sdk.util.log.Logger;
|
||||
|
||||
public class SurfaceRenderer implements DefaultLifecycleObserver, SurfaceCallback, MapRenderingListener
|
||||
{
|
||||
private static final String TAG = SurfaceRenderer.class.getSimpleName();
|
||||
|
||||
@NonNull
|
||||
private final CarContext mCarContext;
|
||||
|
||||
@NonNull
|
||||
private final Map mMap = new Map(Car);
|
||||
|
||||
@NonNull
|
||||
private Rect mVisibleArea = new Rect();
|
||||
|
||||
@Nullable
|
||||
private Surface mSurface = null;
|
||||
|
||||
private boolean mIsRunning;
|
||||
|
||||
public SurfaceRenderer(@NonNull CarContext carContext, @NonNull Lifecycle lifecycle)
|
||||
{
|
||||
Logger.d(TAG, "SurfaceRenderer()");
|
||||
mCarContext = carContext;
|
||||
mIsRunning = true;
|
||||
lifecycle.addObserver(this);
|
||||
mMap.setMapRenderingListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSurfaceAvailable(@NonNull SurfaceContainer surfaceContainer)
|
||||
{
|
||||
Logger.d(TAG, "Surface available " + surfaceContainer);
|
||||
|
||||
if (mSurface != null)
|
||||
mSurface.release();
|
||||
mSurface = surfaceContainer.getSurface();
|
||||
|
||||
mMap.setLocationHelper(MwmApplication.from(mCarContext).getLocationHelper());
|
||||
mMap.onSurfaceCreated(mCarContext, mSurface,
|
||||
new Rect(0, 0, surfaceContainer.getWidth(), surfaceContainer.getHeight()),
|
||||
surfaceContainer.getDpi());
|
||||
mMap.updateBottomWidgetsOffset(mCarContext, -1, -1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onVisibleAreaChanged(@NonNull Rect visibleArea)
|
||||
{
|
||||
Logger.d(TAG, "Visible area changed. visibleArea: " + visibleArea);
|
||||
mVisibleArea = visibleArea;
|
||||
|
||||
if (!mVisibleArea.isEmpty())
|
||||
Framework.nativeSetVisibleRect(mVisibleArea.left, mVisibleArea.top, mVisibleArea.right, mVisibleArea.bottom);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStableAreaChanged(@NonNull Rect stableArea)
|
||||
{
|
||||
Logger.d(TAG, "Stable area changed. stableArea: " + stableArea);
|
||||
|
||||
if (!stableArea.isEmpty())
|
||||
Framework.nativeSetVisibleRect(stableArea.left, stableArea.top, stableArea.right, stableArea.bottom);
|
||||
else if (!mVisibleArea.isEmpty())
|
||||
Framework.nativeSetVisibleRect(mVisibleArea.left, mVisibleArea.top, mVisibleArea.right, mVisibleArea.bottom);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSurfaceDestroyed(@NonNull SurfaceContainer surfaceContainer)
|
||||
{
|
||||
Logger.d(TAG, "Surface destroyed");
|
||||
if (mSurface != null)
|
||||
{
|
||||
mSurface.release();
|
||||
mSurface = null;
|
||||
}
|
||||
mMap.onSurfaceDestroyed(false, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(@NonNull LifecycleOwner owner)
|
||||
{
|
||||
Logger.d(TAG);
|
||||
mCarContext.getCarService(AppManager.class).setSurfaceCallback(this);
|
||||
mMap.onCreate(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart(@NonNull LifecycleOwner owner)
|
||||
{
|
||||
Logger.d(TAG);
|
||||
mMap.onStart();
|
||||
mMap.setCallbackUnsupported(this::reportUnsupported);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume(@NonNull LifecycleOwner owner)
|
||||
{
|
||||
Logger.d(TAG);
|
||||
mMap.onResume();
|
||||
if (MwmApplication.from(mCarContext).getDisplayManager().isCarDisplayUsed())
|
||||
UiThread.runLater(() -> mMap.updateMyPositionRoutingOffset(0));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause(@NonNull LifecycleOwner owner)
|
||||
{
|
||||
Logger.d(TAG);
|
||||
mMap.onPause(mCarContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStop(@NonNull LifecycleOwner owner)
|
||||
{
|
||||
Logger.d(TAG);
|
||||
mMap.onStop();
|
||||
mMap.setCallbackUnsupported(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onScroll(float distanceX, float distanceY)
|
||||
{
|
||||
Logger.d(TAG, "distanceX: " + distanceX + ", distanceY: " + distanceY);
|
||||
mMap.onScroll(distanceX, distanceY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFling(float velocityX, float velocityY)
|
||||
{
|
||||
Logger.d(TAG, "velocityX: " + velocityX + ", velocityY: " + velocityY);
|
||||
}
|
||||
|
||||
public void onZoomIn()
|
||||
{
|
||||
Map.zoomIn();
|
||||
}
|
||||
|
||||
public void onZoomOut()
|
||||
{
|
||||
Map.zoomOut();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onScale(float focusX, float focusY, float scaleFactor)
|
||||
{
|
||||
Logger.d(TAG, "focusX: " + focusX + ", focusY: " + focusY + ", scaleFactor: " + scaleFactor);
|
||||
float x = focusX;
|
||||
float y = focusY;
|
||||
|
||||
if (!mVisibleArea.isEmpty())
|
||||
{
|
||||
// If a focal point value is negative, use the center point of the visible area.
|
||||
if (x < 0)
|
||||
x = mVisibleArea.centerX();
|
||||
if (y < 0)
|
||||
y = mVisibleArea.centerY();
|
||||
}
|
||||
|
||||
final boolean animated = Float.compare(scaleFactor, 2f) == 0;
|
||||
|
||||
Map.onScale(scaleFactor, x, y, animated);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(float x, float y)
|
||||
{
|
||||
Logger.d(TAG, "x: " + x + ", y: " + y);
|
||||
Map.onClick(x, y);
|
||||
}
|
||||
|
||||
public void disable()
|
||||
{
|
||||
if (!mIsRunning)
|
||||
{
|
||||
Logger.d(TAG, "Already disabled");
|
||||
return;
|
||||
}
|
||||
|
||||
mCarContext.getCarService(AppManager.class).setSurfaceCallback(null);
|
||||
mMap.onSurfaceDestroyed(false, true);
|
||||
mMap.onStop();
|
||||
mMap.setCallbackUnsupported(null);
|
||||
mMap.setMapRenderingListener(null);
|
||||
|
||||
mIsRunning = false;
|
||||
}
|
||||
|
||||
public void enable()
|
||||
{
|
||||
if (mIsRunning)
|
||||
{
|
||||
Logger.d(TAG, "Already enabled");
|
||||
return;
|
||||
}
|
||||
|
||||
mCarContext.getCarService(AppManager.class).setSurfaceCallback(this);
|
||||
mMap.onStart();
|
||||
mMap.setCallbackUnsupported(this::reportUnsupported);
|
||||
mMap.setMapRenderingListener(this);
|
||||
UiThread.runLater(() -> mMap.updateMyPositionRoutingOffset(0));
|
||||
|
||||
mIsRunning = true;
|
||||
}
|
||||
|
||||
public boolean isRenderingActive()
|
||||
{
|
||||
return mIsRunning;
|
||||
}
|
||||
|
||||
private void reportUnsupported()
|
||||
{
|
||||
String message = mCarContext.getString(R.string.unsupported_phone);
|
||||
Logger.e(TAG, message);
|
||||
CarToast.makeText(mCarContext, message, CarToast.LENGTH_LONG).show();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRenderingCreated()
|
||||
{
|
||||
UnitLocale.initializeCurrentUnits();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
package app.organicmaps.car.renderer;
|
||||
|
||||
import androidx.annotation.CallSuper;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.car.app.AppManager;
|
||||
import androidx.car.app.CarContext;
|
||||
import androidx.car.app.SurfaceCallback;
|
||||
import androidx.lifecycle.DefaultLifecycleObserver;
|
||||
import androidx.lifecycle.LifecycleOwner;
|
||||
import app.organicmaps.sdk.Map;
|
||||
import app.organicmaps.sdk.MapRenderingListener;
|
||||
import app.organicmaps.sdk.display.DisplayManager;
|
||||
import app.organicmaps.sdk.location.LocationHelper;
|
||||
import app.organicmaps.sdk.settings.UnitLocale;
|
||||
import app.organicmaps.sdk.util.log.Logger;
|
||||
|
||||
public abstract class Renderer implements DefaultLifecycleObserver
|
||||
{
|
||||
@NonNull
|
||||
private final String TAG;
|
||||
|
||||
private SurfaceCallback mSurfaceCallback;
|
||||
|
||||
private boolean mIsRunning;
|
||||
|
||||
@NonNull
|
||||
protected final CarContext mCarContext;
|
||||
|
||||
@NonNull
|
||||
protected final DisplayManager mDisplayManager;
|
||||
|
||||
@NonNull
|
||||
protected final LocationHelper mLocationHelper;
|
||||
|
||||
@NonNull
|
||||
protected final LifecycleOwner mLifecycleOwner;
|
||||
|
||||
@NonNull
|
||||
private final MapRenderingListener mMapRenderingListener = new MapRenderingListener() {
|
||||
@Override
|
||||
public void onRenderingCreated()
|
||||
{
|
||||
UnitLocale.initializeCurrentUnits();
|
||||
}
|
||||
};
|
||||
|
||||
public Renderer(@NonNull CarContext carContext, @NonNull DisplayManager displayManager,
|
||||
@NonNull LocationHelper locationHelper, @NonNull LifecycleOwner lifecycleOwner)
|
||||
{
|
||||
TAG = getClass().getSimpleName();
|
||||
Logger.d(TAG, "SurfaceRenderer()");
|
||||
mIsRunning = true;
|
||||
mCarContext = carContext;
|
||||
mDisplayManager = displayManager;
|
||||
mLocationHelper = locationHelper;
|
||||
mLifecycleOwner = lifecycleOwner;
|
||||
mLifecycleOwner.getLifecycle().addObserver(this);
|
||||
}
|
||||
|
||||
protected void setSurfaceCallback(@NonNull SurfaceCallback surfaceCallback)
|
||||
{
|
||||
mSurfaceCallback = surfaceCallback;
|
||||
}
|
||||
|
||||
public boolean isRenderingActive()
|
||||
{
|
||||
return mIsRunning;
|
||||
}
|
||||
|
||||
protected MapRenderingListener getMapRenderingListener()
|
||||
{
|
||||
return mMapRenderingListener;
|
||||
}
|
||||
|
||||
@CallSuper
|
||||
@Override
|
||||
public void onCreate(@NonNull LifecycleOwner owner)
|
||||
{
|
||||
Logger.d(TAG);
|
||||
if (mSurfaceCallback == null)
|
||||
throw new IllegalStateException("SurfaceCallback must be set before onCreate()");
|
||||
mCarContext.getCarService(AppManager.class).setSurfaceCallback(mSurfaceCallback);
|
||||
}
|
||||
|
||||
@CallSuper
|
||||
@Override
|
||||
public void onDestroy(@NonNull LifecycleOwner owner)
|
||||
{
|
||||
Logger.d(TAG);
|
||||
mCarContext.getCarService(AppManager.class).setSurfaceCallback(null);
|
||||
}
|
||||
|
||||
@CallSuper
|
||||
public void enable()
|
||||
{
|
||||
if (isRenderingActive())
|
||||
{
|
||||
Logger.d(TAG, "Already enabled");
|
||||
return;
|
||||
}
|
||||
|
||||
if (mSurfaceCallback == null)
|
||||
throw new IllegalStateException("SurfaceCallback must be set before enable()");
|
||||
mCarContext.getCarService(AppManager.class).setSurfaceCallback(mSurfaceCallback);
|
||||
mIsRunning = true;
|
||||
}
|
||||
|
||||
@CallSuper
|
||||
public void disable()
|
||||
{
|
||||
if (!isRenderingActive())
|
||||
{
|
||||
Logger.d(TAG, "Already disabled");
|
||||
return;
|
||||
}
|
||||
|
||||
mCarContext.getCarService(AppManager.class).setSurfaceCallback(null);
|
||||
mIsRunning = false;
|
||||
}
|
||||
|
||||
public void onZoomIn()
|
||||
{
|
||||
Map.zoomIn();
|
||||
}
|
||||
|
||||
public void onZoomOut()
|
||||
{
|
||||
Map.zoomOut();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package app.organicmaps.car.renderer;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.car.app.CarContext;
|
||||
import androidx.lifecycle.LifecycleOwner;
|
||||
import app.organicmaps.sdk.display.DisplayManager;
|
||||
import app.organicmaps.sdk.location.LocationHelper;
|
||||
|
||||
public final class RendererFactory
|
||||
{
|
||||
@NonNull
|
||||
public static Renderer create(@NonNull CarContext carContext, @NonNull DisplayManager displayManager,
|
||||
@NonNull LocationHelper locationHelper, @NonNull LifecycleOwner lifecycleOwner)
|
||||
{
|
||||
if (android.os.Build.VERSION.SDK_INT >= 23)
|
||||
return new SurfaceRenderer(carContext, displayManager, locationHelper, lifecycleOwner);
|
||||
else
|
||||
return new SurfaceRendererLegacy(carContext, displayManager, locationHelper, lifecycleOwner);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
package app.organicmaps.car.renderer;
|
||||
|
||||
import android.app.Presentation;
|
||||
import android.hardware.display.DisplayManager;
|
||||
import android.hardware.display.VirtualDisplay;
|
||||
import android.view.SurfaceHolder;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewParent;
|
||||
import android.widget.FrameLayout;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.RequiresApi;
|
||||
import androidx.car.app.CarContext;
|
||||
import androidx.car.app.SurfaceContainer;
|
||||
import app.organicmaps.sdk.MapController;
|
||||
import app.organicmaps.sdk.util.log.Logger;
|
||||
|
||||
@RequiresApi(23)
|
||||
class SurfaceCallback extends SurfaceCallbackBase
|
||||
{
|
||||
private static final String TAG = SurfaceCallback.class.getSimpleName();
|
||||
|
||||
private static final String VIRTUAL_DISPLAY_NAME = "OM_Android_Auto_Display";
|
||||
|
||||
@NonNull
|
||||
private final MapController mMapController;
|
||||
|
||||
private VirtualDisplay mVirtualDisplay;
|
||||
private Presentation mPresentation;
|
||||
|
||||
public SurfaceCallback(@NonNull CarContext carContext, @NonNull MapController mapController)
|
||||
{
|
||||
super(carContext);
|
||||
mMapController = mapController;
|
||||
mMapController.getView().getHolder().addCallback(new SurfaceHolder.Callback() {
|
||||
@Override
|
||||
public void surfaceChanged(@NonNull SurfaceHolder holder, int format, int width, int height)
|
||||
{
|
||||
mMapController.updateMyPositionRoutingOffset(0);
|
||||
}
|
||||
@Override
|
||||
public void surfaceCreated(@NonNull SurfaceHolder holder)
|
||||
{
|
||||
mMapController.updateMyPositionRoutingOffset(0);
|
||||
}
|
||||
@Override
|
||||
public void surfaceDestroyed(@NonNull SurfaceHolder holder)
|
||||
{}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSurfaceAvailable(@NonNull SurfaceContainer surfaceContainer)
|
||||
{
|
||||
Logger.d(TAG, "Surface available " + surfaceContainer);
|
||||
|
||||
mVirtualDisplay =
|
||||
mCarContext.getSystemService(DisplayManager.class)
|
||||
.createVirtualDisplay(VIRTUAL_DISPLAY_NAME, surfaceContainer.getWidth(), surfaceContainer.getHeight(),
|
||||
surfaceContainer.getDpi(), surfaceContainer.getSurface(), 0);
|
||||
mPresentation = new Presentation(mCarContext, mVirtualDisplay.getDisplay());
|
||||
|
||||
mPresentation.setContentView(prepareViewForPresentation(mMapController.getView()));
|
||||
mPresentation.show();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSurfaceDestroyed(@NonNull SurfaceContainer surfaceContainer)
|
||||
{
|
||||
Logger.d(TAG, "Surface destroyed");
|
||||
mPresentation.dismiss();
|
||||
mVirtualDisplay.release();
|
||||
}
|
||||
|
||||
void stopPresenting()
|
||||
{
|
||||
if (mPresentation != null)
|
||||
mPresentation.dismiss();
|
||||
}
|
||||
|
||||
void startPresenting()
|
||||
{
|
||||
if (mPresentation != null)
|
||||
mPresentation.show();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private View prepareViewForPresentation(@NonNull View view)
|
||||
{
|
||||
final ViewParent parent = view.getParent();
|
||||
if (parent instanceof ViewGroup)
|
||||
((ViewGroup) parent).removeView(view);
|
||||
|
||||
final FrameLayout container = new FrameLayout(mCarContext);
|
||||
container.addView(
|
||||
view, new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
|
||||
|
||||
return container;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
package app.organicmaps.car.renderer;
|
||||
|
||||
import android.graphics.Rect;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.car.app.CarContext;
|
||||
import androidx.car.app.SurfaceCallback;
|
||||
import app.organicmaps.sdk.Framework;
|
||||
import app.organicmaps.sdk.Map;
|
||||
import app.organicmaps.sdk.util.concurrency.UiThread;
|
||||
import app.organicmaps.sdk.util.log.Logger;
|
||||
|
||||
abstract class SurfaceCallbackBase implements SurfaceCallback
|
||||
{
|
||||
@NonNull
|
||||
private final String TAG;
|
||||
|
||||
@NonNull
|
||||
protected final CarContext mCarContext;
|
||||
|
||||
@NonNull
|
||||
protected Rect mVisibleArea = new Rect();
|
||||
|
||||
public SurfaceCallbackBase(@NonNull CarContext carContext)
|
||||
{
|
||||
TAG = getClass().getSimpleName();
|
||||
mCarContext = carContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onVisibleAreaChanged(@NonNull Rect visibleArea)
|
||||
{
|
||||
Logger.d(TAG, "Visible area changed. visibleArea: " + visibleArea);
|
||||
mVisibleArea = visibleArea;
|
||||
|
||||
if (!mVisibleArea.isEmpty())
|
||||
UiThread.runLater(()
|
||||
-> Framework.nativeSetVisibleRect(mVisibleArea.left, mVisibleArea.top, mVisibleArea.right,
|
||||
mVisibleArea.bottom));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStableAreaChanged(@NonNull Rect stableArea)
|
||||
{
|
||||
Logger.d(TAG, "Stable area changed. stableArea: " + stableArea);
|
||||
|
||||
if (!mVisibleArea.isEmpty())
|
||||
UiThread.runLater(()
|
||||
-> Framework.nativeSetVisibleRect(mVisibleArea.left, mVisibleArea.top, mVisibleArea.right,
|
||||
mVisibleArea.bottom));
|
||||
else if (!stableArea.isEmpty())
|
||||
UiThread.runLater(
|
||||
() -> Framework.nativeSetVisibleRect(stableArea.left, stableArea.top, stableArea.right, stableArea.bottom));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onScroll(float distanceX, float distanceY)
|
||||
{
|
||||
Logger.d(TAG, "distanceX: " + distanceX + ", distanceY: " + distanceY);
|
||||
Map.onScroll(distanceX, distanceY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFling(float velocityX, float velocityY)
|
||||
{
|
||||
Logger.d(TAG, "velocityX: " + velocityX + ", velocityY: " + velocityY);
|
||||
// TODO: Implement fling in the native code.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onScale(float focusX, float focusY, float scaleFactor)
|
||||
{
|
||||
Logger.d(TAG, "focusX: " + focusX + ", focusY: " + focusY + ", scaleFactor: " + scaleFactor);
|
||||
float x = focusX;
|
||||
float y = focusY;
|
||||
|
||||
if (!mVisibleArea.isEmpty())
|
||||
{
|
||||
// If a focal point value is negative, use the center point of the visible area.
|
||||
if (x < 0)
|
||||
x = mVisibleArea.centerX();
|
||||
if (y < 0)
|
||||
y = mVisibleArea.centerY();
|
||||
}
|
||||
|
||||
final boolean animated = Float.compare(scaleFactor, 2f) == 0;
|
||||
|
||||
Map.onScale(scaleFactor, x, y, animated);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(float x, float y)
|
||||
{
|
||||
Logger.d(TAG, "x: " + x + ", y: " + y);
|
||||
Map.onClick(x, y);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package app.organicmaps.car.renderer;
|
||||
|
||||
import android.graphics.Rect;
|
||||
import android.view.Surface;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.car.app.CarContext;
|
||||
import androidx.car.app.SurfaceContainer;
|
||||
import app.organicmaps.sdk.Map;
|
||||
import app.organicmaps.sdk.location.LocationHelper;
|
||||
import app.organicmaps.sdk.util.log.Logger;
|
||||
|
||||
class SurfaceCallbackLegacy extends SurfaceCallbackBase
|
||||
{
|
||||
private static final String TAG = SurfaceCallbackLegacy.class.getSimpleName();
|
||||
|
||||
@NonNull
|
||||
private final Map mMap;
|
||||
|
||||
@NonNull
|
||||
private final LocationHelper mLocationHelper;
|
||||
|
||||
@Nullable
|
||||
private Surface mSurface = null;
|
||||
|
||||
public SurfaceCallbackLegacy(@NonNull CarContext carContext, @NonNull Map map, @NonNull LocationHelper locationHelper)
|
||||
{
|
||||
super(carContext);
|
||||
mMap = map;
|
||||
mLocationHelper = locationHelper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSurfaceAvailable(@NonNull SurfaceContainer surfaceContainer)
|
||||
{
|
||||
Logger.d(TAG, "Surface available " + surfaceContainer);
|
||||
|
||||
if (mSurface != null)
|
||||
mSurface.release();
|
||||
mSurface = surfaceContainer.getSurface();
|
||||
|
||||
mMap.setLocationHelper(mLocationHelper);
|
||||
mMap.onSurfaceCreated(mCarContext, mSurface,
|
||||
new Rect(0, 0, surfaceContainer.getWidth(), surfaceContainer.getHeight()),
|
||||
surfaceContainer.getDpi());
|
||||
mMap.updateBottomWidgetsOffset(mCarContext, -1, -1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSurfaceDestroyed(@NonNull SurfaceContainer surfaceContainer)
|
||||
{
|
||||
Logger.d(TAG, "Surface destroyed");
|
||||
if (mSurface != null)
|
||||
{
|
||||
mSurface.release();
|
||||
mSurface = null;
|
||||
}
|
||||
mMap.onSurfaceDestroyed(false);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package app.organicmaps.car.renderer;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.RequiresApi;
|
||||
import androidx.car.app.CarContext;
|
||||
import androidx.lifecycle.LifecycleOwner;
|
||||
import app.organicmaps.sdk.MapController;
|
||||
import app.organicmaps.sdk.MapView;
|
||||
import app.organicmaps.sdk.display.DisplayManager;
|
||||
import app.organicmaps.sdk.display.DisplayType;
|
||||
import app.organicmaps.sdk.location.LocationHelper;
|
||||
|
||||
@RequiresApi(23)
|
||||
class SurfaceRenderer extends Renderer
|
||||
{
|
||||
@NonNull
|
||||
private final MapController mMapController;
|
||||
|
||||
@NonNull
|
||||
private final SurfaceCallback mSurfaceCallback;
|
||||
|
||||
public SurfaceRenderer(@NonNull CarContext carContext, @NonNull DisplayManager displayManager,
|
||||
@NonNull LocationHelper locationHelper, @NonNull LifecycleOwner lifecycleOwner)
|
||||
{
|
||||
super(carContext, displayManager, locationHelper, lifecycleOwner);
|
||||
|
||||
mMapController = new MapController(new MapView(carContext, DisplayType.Car), locationHelper,
|
||||
getMapRenderingListener(), null, false);
|
||||
mLifecycleOwner.getLifecycle().addObserver(mMapController);
|
||||
mSurfaceCallback = new SurfaceCallback(mCarContext, mMapController);
|
||||
setSurfaceCallback(mSurfaceCallback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enable()
|
||||
{
|
||||
super.enable();
|
||||
|
||||
mMapController.onStart(mLifecycleOwner);
|
||||
mMapController.updateMyPositionRoutingOffset(0);
|
||||
mSurfaceCallback.startPresenting();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disable()
|
||||
{
|
||||
super.disable();
|
||||
|
||||
mMapController.onPause(mLifecycleOwner);
|
||||
mSurfaceCallback.stopPresenting();
|
||||
mMapController.onStop(mLifecycleOwner);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
package app.organicmaps.car.renderer;
|
||||
|
||||
import static app.organicmaps.sdk.display.DisplayType.Car;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.car.app.CarContext;
|
||||
import androidx.lifecycle.LifecycleOwner;
|
||||
import app.organicmaps.sdk.Map;
|
||||
import app.organicmaps.sdk.display.DisplayManager;
|
||||
import app.organicmaps.sdk.location.LocationHelper;
|
||||
import app.organicmaps.sdk.util.log.Logger;
|
||||
|
||||
class SurfaceRendererLegacy extends Renderer
|
||||
{
|
||||
private static final String TAG = SurfaceRendererLegacy.class.getSimpleName();
|
||||
|
||||
@NonNull
|
||||
private final Map mMap = new Map(Car);
|
||||
|
||||
public SurfaceRendererLegacy(@NonNull CarContext carContext, @NonNull DisplayManager displayManager,
|
||||
@NonNull LocationHelper locationHelper, @NonNull LifecycleOwner lifecycleOwner)
|
||||
{
|
||||
super(carContext, displayManager, locationHelper, lifecycleOwner);
|
||||
setSurfaceCallback(new SurfaceCallbackLegacy(mCarContext, mMap, mLocationHelper));
|
||||
mMap.setMapRenderingListener(getMapRenderingListener());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(@NonNull LifecycleOwner owner)
|
||||
{
|
||||
super.onCreate(owner);
|
||||
mMap.onCreate(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart(@NonNull LifecycleOwner owner)
|
||||
{
|
||||
Logger.d(TAG);
|
||||
if (mDisplayManager.isCarDisplayUsed())
|
||||
mMap.onStart();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume(@NonNull LifecycleOwner owner)
|
||||
{
|
||||
Logger.d(TAG);
|
||||
if (mDisplayManager.isCarDisplayUsed())
|
||||
{
|
||||
mMap.onResume();
|
||||
mMap.updateMyPositionRoutingOffset(0);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause(@NonNull LifecycleOwner owner)
|
||||
{
|
||||
Logger.d(TAG);
|
||||
if (mDisplayManager.isCarDisplayUsed())
|
||||
mMap.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStop(@NonNull LifecycleOwner owner)
|
||||
{
|
||||
Logger.d(TAG);
|
||||
if (mDisplayManager.isCarDisplayUsed())
|
||||
mMap.onStop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enable()
|
||||
{
|
||||
super.enable();
|
||||
|
||||
mMap.onStart();
|
||||
mMap.setMapRenderingListener(getMapRenderingListener());
|
||||
mMap.updateMyPositionRoutingOffset(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disable()
|
||||
{
|
||||
super.disable();
|
||||
|
||||
mMap.onPause();
|
||||
mMap.onSurfaceDestroyed(false);
|
||||
mMap.onStop();
|
||||
mMap.setMapRenderingListener(null);
|
||||
}
|
||||
}
|
||||
@@ -15,30 +15,29 @@ import androidx.car.app.model.Template;
|
||||
import androidx.car.app.navigation.model.MapWithContentTemplate;
|
||||
import androidx.core.graphics.drawable.IconCompat;
|
||||
import app.organicmaps.R;
|
||||
import app.organicmaps.car.SurfaceRenderer;
|
||||
import app.organicmaps.car.renderer.Renderer;
|
||||
import app.organicmaps.car.screens.base.BaseMapScreen;
|
||||
import app.organicmaps.car.screens.search.SearchOnMapScreen;
|
||||
import app.organicmaps.car.util.ThemeUtils;
|
||||
import app.organicmaps.car.util.UiHelpers;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class CategoriesScreen extends BaseMapScreen
|
||||
{
|
||||
private record CategoryData(@StringRes int nameResId, @DrawableRes int iconResId, @DrawableRes int iconNightResId) {}
|
||||
private record CategoryData(@StringRes int nameResId, @DrawableRes int iconResId) {}
|
||||
|
||||
private static final List<CategoryData> CATEGORIES = Arrays.asList(
|
||||
new CategoryData(R.string.category_fuel, R.drawable.ic_category_fuel, R.drawable.ic_category_fuel_night),
|
||||
new CategoryData(R.string.category_parking, R.drawable.ic_category_parking, R.drawable.ic_category_parking_night),
|
||||
new CategoryData(R.string.category_eat, R.drawable.ic_category_eat, R.drawable.ic_category_eat_night),
|
||||
new CategoryData(R.string.category_food, R.drawable.ic_category_food, R.drawable.ic_category_food_night),
|
||||
new CategoryData(R.string.category_hotel, R.drawable.ic_category_hotel, R.drawable.ic_category_hotel_night),
|
||||
new CategoryData(R.string.category_toilet, R.drawable.ic_category_toilet, R.drawable.ic_category_toilet_night),
|
||||
new CategoryData(R.string.category_rv, R.drawable.ic_category_rv, R.drawable.ic_category_rv_night));
|
||||
private static final List<CategoryData> CATEGORIES =
|
||||
Arrays.asList(new CategoryData(R.string.category_fuel, R.drawable.ic_category_fuel),
|
||||
new CategoryData(R.string.category_parking, R.drawable.ic_category_parking),
|
||||
new CategoryData(R.string.category_eat, R.drawable.ic_category_eat),
|
||||
new CategoryData(R.string.category_food, R.drawable.ic_category_food),
|
||||
new CategoryData(R.string.category_hotel, R.drawable.ic_category_hotel),
|
||||
new CategoryData(R.string.category_toilet, R.drawable.ic_category_toilet),
|
||||
new CategoryData(R.string.category_rv, R.drawable.ic_category_rv));
|
||||
|
||||
private final int MAX_CATEGORIES_SIZE;
|
||||
|
||||
public CategoriesScreen(@NonNull CarContext carContext, @NonNull SurfaceRenderer surfaceRenderer)
|
||||
public CategoriesScreen(@NonNull CarContext carContext, @NonNull Renderer surfaceRenderer)
|
||||
{
|
||||
super(carContext, surfaceRenderer);
|
||||
final ConstraintManager constraintManager = getCarContext().getCarService(ConstraintManager.class);
|
||||
@@ -47,7 +46,7 @@ public class CategoriesScreen extends BaseMapScreen
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Template onGetTemplate()
|
||||
protected Template onGetTemplateImpl()
|
||||
{
|
||||
final MapWithContentTemplate.Builder builder = new MapWithContentTemplate.Builder();
|
||||
builder.setMapController(UiHelpers.createMapController(getCarContext(), getSurfaceRenderer()));
|
||||
@@ -67,7 +66,6 @@ public class CategoriesScreen extends BaseMapScreen
|
||||
@NonNull
|
||||
private GridTemplate createCategoriesListTemplate()
|
||||
{
|
||||
final boolean isNightMode = ThemeUtils.isNightMode(getCarContext());
|
||||
final ItemList.Builder builder = new ItemList.Builder();
|
||||
final int categoriesSize = Math.min(CATEGORIES.size(), MAX_CATEGORIES_SIZE);
|
||||
for (int i = 0; i < categoriesSize; ++i)
|
||||
@@ -75,7 +73,7 @@ public class CategoriesScreen extends BaseMapScreen
|
||||
final GridItem.Builder itemBuilder = new GridItem.Builder();
|
||||
final String title = getCarContext().getString(CATEGORIES.get(i).nameResId);
|
||||
@DrawableRes
|
||||
final int iconResId = isNightMode ? CATEGORIES.get(i).iconNightResId : CATEGORIES.get(i).iconResId;
|
||||
final int iconResId = CATEGORIES.get(i).iconResId;
|
||||
|
||||
itemBuilder.setTitle(title);
|
||||
itemBuilder.setImage(new CarIcon.Builder(IconCompat.createWithResource(getCarContext(), iconResId)).build());
|
||||
|
||||
@@ -43,7 +43,7 @@ public class ErrorScreen extends BaseScreen implements UserActionRequired
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Template onGetTemplate()
|
||||
protected Template onGetTemplateImpl()
|
||||
{
|
||||
final MessageTemplate.Builder builder = new MessageTemplate.Builder(getCarContext().getString(mErrorMessage));
|
||||
|
||||
|
||||
@@ -9,20 +9,20 @@ import androidx.car.app.model.Template;
|
||||
import androidx.car.app.navigation.model.NavigationTemplate;
|
||||
import androidx.core.graphics.drawable.IconCompat;
|
||||
import app.organicmaps.R;
|
||||
import app.organicmaps.car.SurfaceRenderer;
|
||||
import app.organicmaps.car.renderer.Renderer;
|
||||
import app.organicmaps.car.screens.base.BaseMapScreen;
|
||||
import app.organicmaps.car.util.UiHelpers;
|
||||
|
||||
public class FreeDriveScreen extends BaseMapScreen
|
||||
{
|
||||
public FreeDriveScreen(@NonNull CarContext carContext, @NonNull SurfaceRenderer surfaceRenderer)
|
||||
public FreeDriveScreen(@NonNull CarContext carContext, @NonNull Renderer surfaceRenderer)
|
||||
{
|
||||
super(carContext, surfaceRenderer);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Template onGetTemplate()
|
||||
protected Template onGetTemplateImpl()
|
||||
{
|
||||
final NavigationTemplate.Builder builder = new NavigationTemplate.Builder();
|
||||
builder.setMapActionStrip(UiHelpers.createMapActionStrip(getCarContext(), getSurfaceRenderer()));
|
||||
|
||||
@@ -22,7 +22,7 @@ public class MapPlaceholderScreen extends BaseScreen
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Template onGetTemplate()
|
||||
protected Template onGetTemplateImpl()
|
||||
{
|
||||
final MessageTemplate.Builder builder =
|
||||
new MessageTemplate.Builder(getCarContext().getString(R.string.car_used_on_the_phone_screen));
|
||||
|
||||
@@ -14,7 +14,7 @@ import androidx.car.app.model.Template;
|
||||
import androidx.car.app.navigation.model.MapWithContentTemplate;
|
||||
import androidx.core.graphics.drawable.IconCompat;
|
||||
import app.organicmaps.R;
|
||||
import app.organicmaps.car.SurfaceRenderer;
|
||||
import app.organicmaps.car.renderer.Renderer;
|
||||
import app.organicmaps.car.screens.base.BaseMapScreen;
|
||||
import app.organicmaps.car.screens.bookmarks.BookmarkCategoriesScreen;
|
||||
import app.organicmaps.car.screens.search.SearchScreen;
|
||||
@@ -24,14 +24,14 @@ import app.organicmaps.car.util.UiHelpers;
|
||||
|
||||
public class MapScreen extends BaseMapScreen
|
||||
{
|
||||
public MapScreen(@NonNull CarContext carContext, @NonNull SurfaceRenderer surfaceRenderer)
|
||||
public MapScreen(@NonNull CarContext carContext, @NonNull Renderer surfaceRenderer)
|
||||
{
|
||||
super(carContext, surfaceRenderer);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Template onGetTemplate()
|
||||
protected Template onGetTemplateImpl()
|
||||
{
|
||||
SuggestionsHelpers.updateSuggestions(getCarContext());
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ import androidx.lifecycle.LifecycleOwner;
|
||||
import app.organicmaps.MwmApplication;
|
||||
import app.organicmaps.R;
|
||||
import app.organicmaps.car.CarAppService;
|
||||
import app.organicmaps.car.SurfaceRenderer;
|
||||
import app.organicmaps.car.renderer.Renderer;
|
||||
import app.organicmaps.car.screens.base.BaseMapScreen;
|
||||
import app.organicmaps.car.screens.settings.DrivingOptionsScreen;
|
||||
import app.organicmaps.car.util.Colors;
|
||||
@@ -70,7 +70,7 @@ public class NavigationScreen extends BaseMapScreen implements RoutingController
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Template onGetTemplate()
|
||||
protected Template onGetTemplateImpl()
|
||||
{
|
||||
final NavigationTemplate.Builder builder = new NavigationTemplate.Builder();
|
||||
builder.setBackgroundColor(Colors.NAVIGATION_TEMPLATE_BACKGROUND);
|
||||
@@ -104,7 +104,11 @@ public class NavigationScreen extends BaseMapScreen implements RoutingController
|
||||
public void onAutoDriveEnabled()
|
||||
{
|
||||
Logger.i(TAG);
|
||||
final JunctionInfo[] points = Framework.nativeGetRouteJunctionPoints();
|
||||
|
||||
/// @todo Pass maxDistM from RouteSimulationProvider?
|
||||
/// Result speed between points will be in range (25, 50] km/h (for 1 second update interval).
|
||||
final double kMaxDistM = 13.9; // 13.9 m/s == 50 km/h
|
||||
final JunctionInfo[] points = Framework.nativeGetRouteJunctionPoints(kMaxDistM);
|
||||
if (points == null)
|
||||
{
|
||||
Logger.e(TAG, "Navigation has not started yet");
|
||||
@@ -121,6 +125,8 @@ public class NavigationScreen extends BaseMapScreen implements RoutingController
|
||||
if (!mNavigationCancelled)
|
||||
CarToast.makeText(getCarContext(), getCarContext().getString(R.string.trip_finished), CarToast.LENGTH_LONG)
|
||||
.show();
|
||||
NavigationService.stopService(getCarContext());
|
||||
ThemeUtils.update(getCarContext());
|
||||
finish();
|
||||
getScreenManager().popToRoot();
|
||||
}
|
||||
@@ -128,7 +134,7 @@ public class NavigationScreen extends BaseMapScreen implements RoutingController
|
||||
@Override
|
||||
public void onCreate(@NonNull LifecycleOwner owner)
|
||||
{
|
||||
Logger.d(TAG);
|
||||
super.onCreate(owner);
|
||||
mRoutingController.attach(this);
|
||||
ThemeUtils.update(getCarContext());
|
||||
mNavigationManager.setNavigationManagerCallback(this);
|
||||
@@ -144,20 +150,19 @@ public class NavigationScreen extends BaseMapScreen implements RoutingController
|
||||
@Override
|
||||
public void onResume(@NonNull LifecycleOwner owner)
|
||||
{
|
||||
Logger.d(TAG);
|
||||
super.onResume(owner);
|
||||
mRoutingController.attach(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy(@NonNull LifecycleOwner owner)
|
||||
{
|
||||
NavigationService.stopService(getCarContext());
|
||||
super.onDestroy(owner);
|
||||
MwmApplication.from(getCarContext()).getLocationHelper().removeListener(mLocationListener);
|
||||
|
||||
if (mRoutingController.isNavigating())
|
||||
mRoutingController.onSaveState();
|
||||
mRoutingController.detach();
|
||||
ThemeUtils.update(getCarContext());
|
||||
mNavigationManager.navigationEnded();
|
||||
mNavigationManager.clearNavigationManagerCallback();
|
||||
}
|
||||
@@ -257,9 +262,9 @@ public class NavigationScreen extends BaseMapScreen implements RoutingController
|
||||
@NonNull
|
||||
private final CarContext mCarContext;
|
||||
@NonNull
|
||||
private final SurfaceRenderer mSurfaceRenderer;
|
||||
private final Renderer mSurfaceRenderer;
|
||||
|
||||
public Builder(@NonNull final CarContext carContext, @NonNull final SurfaceRenderer surfaceRenderer)
|
||||
public Builder(@NonNull final CarContext carContext, @NonNull final Renderer surfaceRenderer)
|
||||
{
|
||||
mCarContext = carContext;
|
||||
mSurfaceRenderer = surfaceRenderer;
|
||||
|
||||
@@ -26,7 +26,7 @@ import androidx.core.graphics.drawable.IconCompat;
|
||||
import androidx.lifecycle.LifecycleOwner;
|
||||
import app.organicmaps.MwmApplication;
|
||||
import app.organicmaps.R;
|
||||
import app.organicmaps.car.SurfaceRenderer;
|
||||
import app.organicmaps.car.renderer.Renderer;
|
||||
import app.organicmaps.car.screens.base.BaseMapScreen;
|
||||
import app.organicmaps.car.screens.download.DownloadMapsScreenBuilder;
|
||||
import app.organicmaps.car.screens.settings.DrivingOptionsScreen;
|
||||
@@ -46,7 +46,7 @@ import java.util.Objects;
|
||||
|
||||
public class PlaceScreen extends BaseMapScreen implements OnBackPressedCallback.Callback, RoutingController.Container
|
||||
{
|
||||
private static final Router ROUTER = Router.Vehicle;
|
||||
public static final Router ROUTER = Router.Vehicle;
|
||||
|
||||
@Nullable
|
||||
private MapObject mMapObject;
|
||||
@@ -68,7 +68,7 @@ public class PlaceScreen extends BaseMapScreen implements OnBackPressedCallback.
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Template onGetTemplate()
|
||||
protected Template onGetTemplateImpl()
|
||||
{
|
||||
final MapWithContentTemplate.Builder builder = new MapWithContentTemplate.Builder();
|
||||
builder.setMapController(UiHelpers.createMapController(getCarContext(), getSurfaceRenderer()));
|
||||
@@ -80,6 +80,7 @@ public class PlaceScreen extends BaseMapScreen implements OnBackPressedCallback.
|
||||
@Override
|
||||
public void onCreate(@NonNull LifecycleOwner owner)
|
||||
{
|
||||
super.onCreate(owner);
|
||||
mRoutingController.restore();
|
||||
if (mRoutingController.isNavigating() && mRoutingController.getLastRouterType() == ROUTER)
|
||||
{
|
||||
@@ -112,12 +113,14 @@ public class PlaceScreen extends BaseMapScreen implements OnBackPressedCallback.
|
||||
@Override
|
||||
public void onResume(@NonNull LifecycleOwner owner)
|
||||
{
|
||||
super.onResume(owner);
|
||||
mRoutingController.attach(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy(@NonNull LifecycleOwner owner)
|
||||
{
|
||||
super.onDestroy(owner);
|
||||
if (mRoutingController.isPlanning())
|
||||
mRoutingController.onSaveState();
|
||||
if (!mRoutingController.isNavigating())
|
||||
@@ -340,11 +343,11 @@ public class PlaceScreen extends BaseMapScreen implements OnBackPressedCallback.
|
||||
@NonNull
|
||||
private final CarContext mCarContext;
|
||||
@NonNull
|
||||
private final SurfaceRenderer mSurfaceRenderer;
|
||||
private final Renderer mSurfaceRenderer;
|
||||
@Nullable
|
||||
private MapObject mMapObject;
|
||||
|
||||
public Builder(@NonNull final CarContext carContext, @NonNull final SurfaceRenderer surfaceRenderer)
|
||||
public Builder(@NonNull final CarContext carContext, @NonNull final Renderer surfaceRenderer)
|
||||
{
|
||||
mCarContext = carContext;
|
||||
mSurfaceRenderer = surfaceRenderer;
|
||||
|
||||
@@ -2,21 +2,21 @@ package app.organicmaps.car.screens.base;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.car.app.CarContext;
|
||||
import app.organicmaps.car.SurfaceRenderer;
|
||||
import app.organicmaps.car.renderer.Renderer;
|
||||
|
||||
public abstract class BaseMapScreen extends BaseScreen
|
||||
{
|
||||
@NonNull
|
||||
private final SurfaceRenderer mSurfaceRenderer;
|
||||
private final Renderer mSurfaceRenderer;
|
||||
|
||||
public BaseMapScreen(@NonNull CarContext carContext, @NonNull SurfaceRenderer surfaceRenderer)
|
||||
public BaseMapScreen(@NonNull CarContext carContext, @NonNull Renderer surfaceRenderer)
|
||||
{
|
||||
super(carContext);
|
||||
mSurfaceRenderer = surfaceRenderer;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
protected SurfaceRenderer getSurfaceRenderer()
|
||||
protected Renderer getSurfaceRenderer()
|
||||
{
|
||||
return mSurfaceRenderer;
|
||||
}
|
||||
|
||||
@@ -1,15 +1,71 @@
|
||||
package app.organicmaps.car.screens.base;
|
||||
|
||||
import androidx.annotation.CallSuper;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.car.app.CarContext;
|
||||
import androidx.car.app.Screen;
|
||||
import androidx.car.app.model.Template;
|
||||
import androidx.lifecycle.DefaultLifecycleObserver;
|
||||
import androidx.lifecycle.LifecycleOwner;
|
||||
import app.organicmaps.sdk.util.log.Logger;
|
||||
|
||||
public abstract class BaseScreen extends Screen implements DefaultLifecycleObserver
|
||||
{
|
||||
@NonNull
|
||||
private final String TAG;
|
||||
|
||||
public BaseScreen(@NonNull CarContext carContext)
|
||||
{
|
||||
super(carContext);
|
||||
TAG = getClass().getSimpleName();
|
||||
|
||||
getLifecycle().addObserver(this);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
protected abstract Template onGetTemplateImpl();
|
||||
|
||||
@Override
|
||||
@NonNull
|
||||
public final Template onGetTemplate()
|
||||
{
|
||||
Logger.d(TAG);
|
||||
return onGetTemplateImpl();
|
||||
}
|
||||
|
||||
@CallSuper
|
||||
public void onCreate(@NonNull LifecycleOwner owner)
|
||||
{
|
||||
Logger.d(TAG);
|
||||
}
|
||||
|
||||
@CallSuper
|
||||
public void onStart(@NonNull LifecycleOwner owner)
|
||||
{
|
||||
Logger.d(TAG);
|
||||
}
|
||||
|
||||
@CallSuper
|
||||
public void onResume(@NonNull LifecycleOwner owner)
|
||||
{
|
||||
Logger.d(TAG);
|
||||
}
|
||||
|
||||
@CallSuper
|
||||
public void onPause(@NonNull LifecycleOwner owner)
|
||||
{
|
||||
Logger.d(TAG);
|
||||
}
|
||||
|
||||
@CallSuper
|
||||
public void onStop(@NonNull LifecycleOwner owner)
|
||||
{
|
||||
Logger.d(TAG);
|
||||
}
|
||||
|
||||
@CallSuper
|
||||
public void onDestroy(@NonNull LifecycleOwner owner)
|
||||
{
|
||||
Logger.d(TAG);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ import androidx.car.app.model.Row;
|
||||
import androidx.car.app.model.Template;
|
||||
import androidx.car.app.navigation.model.MapWithContentTemplate;
|
||||
import app.organicmaps.R;
|
||||
import app.organicmaps.car.SurfaceRenderer;
|
||||
import app.organicmaps.car.renderer.Renderer;
|
||||
import app.organicmaps.car.screens.base.BaseMapScreen;
|
||||
import app.organicmaps.car.util.UiHelpers;
|
||||
import app.organicmaps.sdk.bookmarks.data.BookmarkCategory;
|
||||
@@ -23,7 +23,7 @@ public class BookmarkCategoriesScreen extends BaseMapScreen
|
||||
{
|
||||
private final int MAX_CATEGORIES_SIZE;
|
||||
|
||||
public BookmarkCategoriesScreen(@NonNull CarContext carContext, @NonNull SurfaceRenderer surfaceRenderer)
|
||||
public BookmarkCategoriesScreen(@NonNull CarContext carContext, @NonNull Renderer surfaceRenderer)
|
||||
{
|
||||
super(carContext, surfaceRenderer);
|
||||
final ConstraintManager constraintManager = getCarContext().getCarService(ConstraintManager.class);
|
||||
@@ -32,7 +32,7 @@ public class BookmarkCategoriesScreen extends BaseMapScreen
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Template onGetTemplate()
|
||||
protected Template onGetTemplateImpl()
|
||||
{
|
||||
final MapWithContentTemplate.Builder builder = new MapWithContentTemplate.Builder();
|
||||
builder.setMapController(UiHelpers.createMapController(getCarContext(), getSurfaceRenderer()));
|
||||
|
||||
@@ -13,7 +13,7 @@ import androidx.car.app.navigation.model.MapWithContentTemplate;
|
||||
import androidx.core.graphics.drawable.IconCompat;
|
||||
import androidx.lifecycle.LifecycleOwner;
|
||||
import app.organicmaps.R;
|
||||
import app.organicmaps.car.SurfaceRenderer;
|
||||
import app.organicmaps.car.renderer.Renderer;
|
||||
import app.organicmaps.car.screens.base.BaseMapScreen;
|
||||
import app.organicmaps.car.util.UiHelpers;
|
||||
import app.organicmaps.sdk.bookmarks.data.BookmarkCategory;
|
||||
@@ -31,7 +31,7 @@ public class BookmarksScreen extends BaseMapScreen
|
||||
|
||||
private boolean mIsOnSortingScreen = false;
|
||||
|
||||
public BookmarksScreen(@NonNull CarContext carContext, @NonNull SurfaceRenderer surfaceRenderer,
|
||||
public BookmarksScreen(@NonNull CarContext carContext, @NonNull Renderer surfaceRenderer,
|
||||
@NonNull BookmarkCategory bookmarkCategory)
|
||||
{
|
||||
super(carContext, surfaceRenderer);
|
||||
@@ -41,7 +41,7 @@ public class BookmarksScreen extends BaseMapScreen
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Template onGetTemplate()
|
||||
protected Template onGetTemplateImpl()
|
||||
{
|
||||
final MapWithContentTemplate.Builder builder = new MapWithContentTemplate.Builder();
|
||||
builder.setMapController(UiHelpers.createMapController(getCarContext(), getSurfaceRenderer()));
|
||||
@@ -52,6 +52,7 @@ public class BookmarksScreen extends BaseMapScreen
|
||||
@Override
|
||||
public void onStop(@NonNull LifecycleOwner owner)
|
||||
{
|
||||
super.onStop(owner);
|
||||
if (!mIsOnSortingScreen)
|
||||
mBookmarksLoader.cancel();
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ import androidx.core.graphics.drawable.IconCompat;
|
||||
import androidx.lifecycle.LifecycleOwner;
|
||||
import app.organicmaps.MwmApplication;
|
||||
import app.organicmaps.R;
|
||||
import app.organicmaps.car.SurfaceRenderer;
|
||||
import app.organicmaps.car.renderer.Renderer;
|
||||
import app.organicmaps.car.screens.base.BaseMapScreen;
|
||||
import app.organicmaps.car.util.UiHelpers;
|
||||
import app.organicmaps.sdk.bookmarks.data.BookmarkCategory;
|
||||
@@ -38,7 +38,7 @@ class SortingScreen extends BaseMapScreen
|
||||
|
||||
private @BookmarkManager.SortingType int mNewSortingType;
|
||||
|
||||
public SortingScreen(@NonNull CarContext carContext, @NonNull SurfaceRenderer surfaceRenderer,
|
||||
public SortingScreen(@NonNull CarContext carContext, @NonNull Renderer surfaceRenderer,
|
||||
@NonNull BookmarkCategory bookmarkCategory)
|
||||
{
|
||||
super(carContext, surfaceRenderer);
|
||||
@@ -53,7 +53,7 @@ class SortingScreen extends BaseMapScreen
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Template onGetTemplate()
|
||||
protected Template onGetTemplateImpl()
|
||||
{
|
||||
final MapWithContentTemplate.Builder builder = new MapWithContentTemplate.Builder();
|
||||
builder.setMapController(UiHelpers.createMapController(getCarContext(), getSurfaceRenderer()));
|
||||
|
||||
@@ -23,6 +23,7 @@ class DownloadMapsForFirstLaunchScreen extends DownloadMapsScreen
|
||||
@Override
|
||||
public void onResume(@NonNull LifecycleOwner owner)
|
||||
{
|
||||
super.onResume(owner);
|
||||
// Attempting to streamline initial download by including the current country in the list of missing maps for
|
||||
// simultaneous retrieval.
|
||||
final Location location = MwmApplication.from(getCarContext()).getLocationHelper().getSavedLocation();
|
||||
|
||||
@@ -34,7 +34,7 @@ public abstract class DownloadMapsScreen extends BaseScreen
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public final Template onGetTemplate()
|
||||
protected final Template onGetTemplateImpl()
|
||||
{
|
||||
final MessageTemplate.Builder builder = new MessageTemplate.Builder(getText(getMapsSize(mMissingMaps)));
|
||||
final Header.Builder headerBuilder = new Header.Builder();
|
||||
|
||||
@@ -102,6 +102,7 @@ class DownloaderScreen extends BaseScreen
|
||||
@Override
|
||||
public void onResume(@NonNull LifecycleOwner owner)
|
||||
{
|
||||
super.onResume(owner);
|
||||
if (mSubscriptionSlot == 0)
|
||||
mSubscriptionSlot = MapManager.nativeSubscribe(mStorageCallback);
|
||||
for (final var item : mMissingMaps.entrySet())
|
||||
@@ -114,6 +115,7 @@ class DownloaderScreen extends BaseScreen
|
||||
@Override
|
||||
public void onPause(@NonNull LifecycleOwner owner)
|
||||
{
|
||||
super.onPause(owner);
|
||||
if (!mIsDownloadFailed)
|
||||
cancelMapsDownloading();
|
||||
if (mSubscriptionSlot != 0)
|
||||
@@ -125,7 +127,7 @@ class DownloaderScreen extends BaseScreen
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Template onGetTemplate()
|
||||
protected Template onGetTemplateImpl()
|
||||
{
|
||||
final MessageTemplate.Builder builder = new MessageTemplate.Builder(getText());
|
||||
builder.setLoading(true);
|
||||
|
||||
@@ -37,7 +37,7 @@ public class RequestPermissionsScreenWithApi extends BaseScreen implements UserA
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Template onGetTemplate()
|
||||
protected Template onGetTemplateImpl()
|
||||
{
|
||||
final MessageTemplate.Builder builder =
|
||||
new MessageTemplate.Builder(getCarContext().getString(R.string.aa_request_permission_activity_text));
|
||||
@@ -63,6 +63,7 @@ public class RequestPermissionsScreenWithApi extends BaseScreen implements UserA
|
||||
@Override
|
||||
public void onResume(@NonNull LifecycleOwner owner)
|
||||
{
|
||||
super.onResume(owner);
|
||||
// Let's review the permissions once more, as we might enter this function following an ErrorScreen situation
|
||||
// where the user manually enabled location permissions.
|
||||
if (LocationUtils.checkFineLocationPermission(getCarContext()))
|
||||
|
||||
@@ -47,7 +47,7 @@ public class RequestPermissionsScreenWithNotification extends BaseScreen impleme
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Template onGetTemplate()
|
||||
protected Template onGetTemplateImpl()
|
||||
{
|
||||
final MessageTemplate.Builder builder =
|
||||
new MessageTemplate.Builder(getCarContext().getString(R.string.aa_location_permissions_request));
|
||||
@@ -66,6 +66,7 @@ public class RequestPermissionsScreenWithNotification extends BaseScreen impleme
|
||||
@RequiresPermission(value = Manifest.permission.POST_NOTIFICATIONS)
|
||||
public void onStart(@NonNull LifecycleOwner owner)
|
||||
{
|
||||
super.onStart(owner);
|
||||
mIsPermissionCheckEnabled = true;
|
||||
mBackgroundExecutor.execute(this::checkPermissions);
|
||||
sendPermissionsRequestNotification();
|
||||
@@ -74,12 +75,14 @@ public class RequestPermissionsScreenWithNotification extends BaseScreen impleme
|
||||
@Override
|
||||
public void onStop(@NonNull LifecycleOwner owner)
|
||||
{
|
||||
super.onStop(owner);
|
||||
mIsPermissionCheckEnabled = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy(@NonNull LifecycleOwner owner)
|
||||
{
|
||||
super.onDestroy(owner);
|
||||
NotificationManagerCompat.from(getCarContext()).cancel(NOTIFICATION_ID);
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ import androidx.core.graphics.drawable.IconCompat;
|
||||
import androidx.lifecycle.LifecycleOwner;
|
||||
import app.organicmaps.MwmApplication;
|
||||
import app.organicmaps.R;
|
||||
import app.organicmaps.car.SurfaceRenderer;
|
||||
import app.organicmaps.car.renderer.Renderer;
|
||||
import app.organicmaps.car.screens.base.BaseMapScreen;
|
||||
import app.organicmaps.car.util.UiHelpers;
|
||||
import app.organicmaps.sdk.bookmarks.data.MapObject;
|
||||
@@ -54,7 +54,7 @@ public class SearchOnMapScreen extends BaseMapScreen implements SearchListener
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Template onGetTemplate()
|
||||
protected Template onGetTemplateImpl()
|
||||
{
|
||||
final MapWithContentTemplate.Builder builder = new MapWithContentTemplate.Builder();
|
||||
builder.setMapController(UiHelpers.createMapController(getCarContext(), getSurfaceRenderer()));
|
||||
@@ -136,12 +136,14 @@ public class SearchOnMapScreen extends BaseMapScreen implements SearchListener
|
||||
@Override
|
||||
public void onStart(@NonNull LifecycleOwner owner)
|
||||
{
|
||||
super.onStart(owner);
|
||||
SearchEngine.INSTANCE.addListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume(@NonNull LifecycleOwner owner)
|
||||
{
|
||||
super.onResume(owner);
|
||||
SearchEngine.INSTANCE.cancel();
|
||||
|
||||
final MapObject location = MwmApplication.from(getCarContext()).getLocationHelper().getMyPosition();
|
||||
@@ -156,6 +158,7 @@ public class SearchOnMapScreen extends BaseMapScreen implements SearchListener
|
||||
@Override
|
||||
public void onStop(@NonNull LifecycleOwner owner)
|
||||
{
|
||||
super.onStop(owner);
|
||||
SearchEngine.INSTANCE.removeListener(this);
|
||||
SearchEngine.INSTANCE.cancel();
|
||||
}
|
||||
@@ -177,7 +180,7 @@ public class SearchOnMapScreen extends BaseMapScreen implements SearchListener
|
||||
@NonNull
|
||||
private final CarContext mCarContext;
|
||||
@NonNull
|
||||
private final SurfaceRenderer mSurfaceRenderer;
|
||||
private final Renderer mSurfaceRenderer;
|
||||
|
||||
@NonNull
|
||||
private String mQuery = "";
|
||||
@@ -185,7 +188,7 @@ public class SearchOnMapScreen extends BaseMapScreen implements SearchListener
|
||||
private String mLocale;
|
||||
private boolean mIsCategory;
|
||||
|
||||
public Builder(@NonNull CarContext carContext, @NonNull SurfaceRenderer surfaceRenderer)
|
||||
public Builder(@NonNull CarContext carContext, @NonNull Renderer surfaceRenderer)
|
||||
{
|
||||
mCarContext = carContext;
|
||||
mSurfaceRenderer = surfaceRenderer;
|
||||
|
||||
@@ -16,7 +16,7 @@ import androidx.core.graphics.drawable.IconCompat;
|
||||
import androidx.lifecycle.LifecycleOwner;
|
||||
import app.organicmaps.MwmApplication;
|
||||
import app.organicmaps.R;
|
||||
import app.organicmaps.car.SurfaceRenderer;
|
||||
import app.organicmaps.car.renderer.Renderer;
|
||||
import app.organicmaps.car.screens.base.BaseMapScreen;
|
||||
import app.organicmaps.sdk.bookmarks.data.MapObject;
|
||||
import app.organicmaps.sdk.search.SearchEngine;
|
||||
@@ -50,7 +50,7 @@ public class SearchScreen extends BaseMapScreen implements SearchTemplate.Search
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Template onGetTemplate()
|
||||
protected Template onGetTemplateImpl()
|
||||
{
|
||||
final SearchTemplate.Builder builder = new SearchTemplate.Builder(this);
|
||||
builder.setHeaderAction(Action.BACK);
|
||||
@@ -106,12 +106,14 @@ public class SearchScreen extends BaseMapScreen implements SearchTemplate.Search
|
||||
@Override
|
||||
public void onStart(@NonNull LifecycleOwner owner)
|
||||
{
|
||||
super.onStart(owner);
|
||||
SearchEngine.INSTANCE.addListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStop(@NonNull LifecycleOwner owner)
|
||||
{
|
||||
super.onStop(owner);
|
||||
SearchEngine.INSTANCE.removeListener(this);
|
||||
SearchEngine.INSTANCE.cancel();
|
||||
}
|
||||
@@ -209,14 +211,14 @@ public class SearchScreen extends BaseMapScreen implements SearchTemplate.Search
|
||||
@NonNull
|
||||
private final CarContext mCarContext;
|
||||
@NonNull
|
||||
private final SurfaceRenderer mSurfaceRenderer;
|
||||
private final Renderer mSurfaceRenderer;
|
||||
|
||||
@NonNull
|
||||
private String mQuery = "";
|
||||
@NonNull
|
||||
private String mLocale;
|
||||
|
||||
public Builder(@NonNull CarContext carContext, @NonNull SurfaceRenderer surfaceRenderer)
|
||||
public Builder(@NonNull CarContext carContext, @NonNull Renderer surfaceRenderer)
|
||||
{
|
||||
mCarContext = carContext;
|
||||
mSurfaceRenderer = surfaceRenderer;
|
||||
|
||||
@@ -13,7 +13,7 @@ import androidx.car.app.model.Template;
|
||||
import androidx.car.app.navigation.model.MapWithContentTemplate;
|
||||
import androidx.lifecycle.LifecycleOwner;
|
||||
import app.organicmaps.R;
|
||||
import app.organicmaps.car.SurfaceRenderer;
|
||||
import app.organicmaps.car.renderer.Renderer;
|
||||
import app.organicmaps.car.screens.base.BaseMapScreen;
|
||||
import app.organicmaps.car.util.Toggle;
|
||||
import app.organicmaps.car.util.UiHelpers;
|
||||
@@ -31,12 +31,13 @@ public class DrivingOptionsScreen extends BaseMapScreen
|
||||
private final DrivingOption[] mDrivingOptions = {new DrivingOption(RoadType.Toll, R.string.avoid_tolls),
|
||||
new DrivingOption(RoadType.Dirty, R.string.avoid_unpaved),
|
||||
new DrivingOption(RoadType.Ferry, R.string.avoid_ferry),
|
||||
new DrivingOption(RoadType.Motorway, R.string.avoid_motorways)};
|
||||
new DrivingOption(RoadType.Motorway, R.string.avoid_motorways),
|
||||
new DrivingOption(RoadType.Steps, R.string.avoid_steps)};
|
||||
|
||||
@NonNull
|
||||
private final Map<RoadType, Boolean> mInitialDrivingOptionsState = new HashMap<>();
|
||||
|
||||
public DrivingOptionsScreen(@NonNull CarContext carContext, @NonNull SurfaceRenderer surfaceRenderer)
|
||||
public DrivingOptionsScreen(@NonNull CarContext carContext, @NonNull Renderer surfaceRenderer)
|
||||
{
|
||||
super(carContext, surfaceRenderer);
|
||||
|
||||
@@ -45,7 +46,7 @@ public class DrivingOptionsScreen extends BaseMapScreen
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Template onGetTemplate()
|
||||
protected Template onGetTemplateImpl()
|
||||
{
|
||||
final MapWithContentTemplate.Builder builder = new MapWithContentTemplate.Builder();
|
||||
builder.setMapController(UiHelpers.createMapController(getCarContext(), getSurfaceRenderer()));
|
||||
@@ -56,6 +57,7 @@ public class DrivingOptionsScreen extends BaseMapScreen
|
||||
@Override
|
||||
public void onStop(@NonNull LifecycleOwner owner)
|
||||
{
|
||||
super.onStop(owner);
|
||||
for (final DrivingOption drivingOption : mDrivingOptions)
|
||||
{
|
||||
if (Boolean.TRUE.equals(mInitialDrivingOptionsState.get(drivingOption.roadType))
|
||||
|
||||
@@ -12,7 +12,7 @@ import androidx.car.app.model.Template;
|
||||
import androidx.car.app.navigation.model.MapWithContentTemplate;
|
||||
import app.organicmaps.BuildConfig;
|
||||
import app.organicmaps.R;
|
||||
import app.organicmaps.car.SurfaceRenderer;
|
||||
import app.organicmaps.car.renderer.Renderer;
|
||||
import app.organicmaps.car.screens.base.BaseMapScreen;
|
||||
import app.organicmaps.car.util.UiHelpers;
|
||||
import app.organicmaps.sdk.Framework;
|
||||
@@ -20,14 +20,14 @@ import app.organicmaps.sdk.util.DateUtils;
|
||||
|
||||
public class HelpScreen extends BaseMapScreen
|
||||
{
|
||||
public HelpScreen(@NonNull CarContext carContext, @NonNull SurfaceRenderer surfaceRenderer)
|
||||
public HelpScreen(@NonNull CarContext carContext, @NonNull Renderer surfaceRenderer)
|
||||
{
|
||||
super(carContext, surfaceRenderer);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Template onGetTemplate()
|
||||
protected Template onGetTemplateImpl()
|
||||
{
|
||||
final MapWithContentTemplate.Builder builder = new MapWithContentTemplate.Builder();
|
||||
builder.setMapController(UiHelpers.createMapController(getCarContext(), getSurfaceRenderer()));
|
||||
|
||||
@@ -13,7 +13,7 @@ import androidx.car.app.model.Row;
|
||||
import androidx.car.app.model.Template;
|
||||
import androidx.car.app.navigation.model.MapWithContentTemplate;
|
||||
import app.organicmaps.R;
|
||||
import app.organicmaps.car.SurfaceRenderer;
|
||||
import app.organicmaps.car.renderer.Renderer;
|
||||
import app.organicmaps.car.screens.base.BaseMapScreen;
|
||||
import app.organicmaps.car.util.ThemeUtils;
|
||||
import app.organicmaps.car.util.Toggle;
|
||||
@@ -33,14 +33,14 @@ public class SettingsScreen extends BaseMapScreen
|
||||
void set(boolean newValue);
|
||||
}
|
||||
|
||||
public SettingsScreen(@NonNull CarContext carContext, @NonNull SurfaceRenderer surfaceRenderer)
|
||||
public SettingsScreen(@NonNull CarContext carContext, @NonNull Renderer surfaceRenderer)
|
||||
{
|
||||
super(carContext, surfaceRenderer);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Template onGetTemplate()
|
||||
protected Template onGetTemplateImpl()
|
||||
{
|
||||
final MapWithContentTemplate.Builder builder = new MapWithContentTemplate.Builder();
|
||||
builder.setMapController(UiHelpers.createMapController(getCarContext(), getSurfaceRenderer()));
|
||||
|
||||
@@ -12,7 +12,7 @@ import androidx.car.app.model.Template;
|
||||
import androidx.car.app.navigation.model.MapWithContentTemplate;
|
||||
import androidx.core.graphics.drawable.IconCompat;
|
||||
import app.organicmaps.R;
|
||||
import app.organicmaps.car.SurfaceRenderer;
|
||||
import app.organicmaps.car.renderer.Renderer;
|
||||
import app.organicmaps.car.screens.base.BaseMapScreen;
|
||||
import app.organicmaps.car.util.ThemeUtils;
|
||||
import app.organicmaps.car.util.UiHelpers;
|
||||
@@ -24,7 +24,7 @@ public class ThemeScreen extends BaseMapScreen
|
||||
@NonNull
|
||||
private final CarIcon mRadioButtonSelectedIcon;
|
||||
|
||||
public ThemeScreen(@NonNull CarContext carContext, @NonNull SurfaceRenderer surfaceRenderer)
|
||||
public ThemeScreen(@NonNull CarContext carContext, @NonNull Renderer surfaceRenderer)
|
||||
{
|
||||
super(carContext, surfaceRenderer);
|
||||
mRadioButtonIcon =
|
||||
@@ -35,7 +35,7 @@ public class ThemeScreen extends BaseMapScreen
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Template onGetTemplate()
|
||||
protected Template onGetTemplateImpl()
|
||||
{
|
||||
final MapWithContentTemplate.Builder builder = new MapWithContentTemplate.Builder();
|
||||
builder.setMapController(UiHelpers.createMapController(getCarContext(), getSurfaceRenderer()));
|
||||
|
||||
@@ -12,7 +12,7 @@ import androidx.car.app.notification.CarPendingIntent;
|
||||
import app.organicmaps.MwmApplication;
|
||||
import app.organicmaps.api.Const;
|
||||
import app.organicmaps.car.CarAppService;
|
||||
import app.organicmaps.car.SurfaceRenderer;
|
||||
import app.organicmaps.car.renderer.Renderer;
|
||||
import app.organicmaps.car.screens.NavigationScreen;
|
||||
import app.organicmaps.car.screens.search.SearchScreen;
|
||||
import app.organicmaps.sdk.Framework;
|
||||
@@ -30,7 +30,7 @@ public final class IntentUtils
|
||||
|
||||
private static final int SEARCH_IN_VIEWPORT_ZOOM = 16;
|
||||
|
||||
public static void processIntent(@NonNull CarContext carContext, @NonNull SurfaceRenderer surfaceRenderer,
|
||||
public static void processIntent(@NonNull CarContext carContext, @NonNull Renderer surfaceRenderer,
|
||||
@NonNull Intent intent)
|
||||
{
|
||||
final String action = intent.getAction();
|
||||
@@ -50,8 +50,8 @@ public final class IntentUtils
|
||||
}
|
||||
|
||||
// https://developer.android.com/reference/androidx/car/app/CarContext#startCarApp(android.content.Intent)
|
||||
private static void processNavigationIntent(@NonNull CarContext carContext, @NonNull SurfaceRenderer surfaceRenderer,
|
||||
@NonNull Intent intent)
|
||||
private static void processNavigationIntent(@NonNull CarContext carContext,
|
||||
@NonNull Renderer surfaceRenderer, @NonNull Intent intent)
|
||||
{
|
||||
// TODO (AndrewShkrob): This logic will need to be revised when we introduce support for adding stops during
|
||||
// navigation or route planning. Skip navigation intents during navigation
|
||||
|
||||
@@ -15,7 +15,7 @@ import androidx.car.app.navigation.model.MapController;
|
||||
import androidx.core.graphics.drawable.IconCompat;
|
||||
import app.organicmaps.MwmApplication;
|
||||
import app.organicmaps.R;
|
||||
import app.organicmaps.car.SurfaceRenderer;
|
||||
import app.organicmaps.car.renderer.Renderer;
|
||||
import app.organicmaps.car.screens.base.BaseMapScreen;
|
||||
import app.organicmaps.car.screens.settings.SettingsScreen;
|
||||
import app.organicmaps.sdk.Map;
|
||||
@@ -33,13 +33,14 @@ public final class UiHelpers
|
||||
{
|
||||
@NonNull
|
||||
public static ActionStrip createSettingsActionStrip(@NonNull BaseMapScreen mapScreen,
|
||||
@NonNull SurfaceRenderer surfaceRenderer)
|
||||
@NonNull Renderer surfaceRenderer)
|
||||
{
|
||||
return new ActionStrip.Builder().addAction(createSettingsAction(mapScreen, surfaceRenderer)).build();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static ActionStrip createMapActionStrip(@NonNull CarContext context, @NonNull SurfaceRenderer surfaceRenderer)
|
||||
public static ActionStrip createMapActionStrip(@NonNull CarContext context,
|
||||
@NonNull Renderer surfaceRenderer)
|
||||
{
|
||||
final CarIcon iconPlus = new CarIcon.Builder(IconCompat.createWithResource(context, R.drawable.ic_plus)).build();
|
||||
final CarIcon iconMinus = new CarIcon.Builder(IconCompat.createWithResource(context, R.drawable.ic_minus)).build();
|
||||
@@ -58,27 +59,30 @@ public final class UiHelpers
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static MapController createMapController(@NonNull CarContext context, @NonNull SurfaceRenderer surfaceRenderer)
|
||||
public static MapController createMapController(@NonNull CarContext context,
|
||||
@NonNull Renderer surfaceRenderer)
|
||||
{
|
||||
return new MapController.Builder().setMapActionStrip(createMapActionStrip(context, surfaceRenderer)).build();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static Action createSettingsAction(@NonNull BaseMapScreen mapScreen, @NonNull SurfaceRenderer surfaceRenderer)
|
||||
public static Action createSettingsAction(@NonNull BaseMapScreen mapScreen,
|
||||
@NonNull Renderer surfaceRenderer)
|
||||
{
|
||||
return createSettingsAction(mapScreen, surfaceRenderer, null);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static Action createSettingsActionForResult(@NonNull BaseMapScreen mapScreen,
|
||||
@NonNull SurfaceRenderer surfaceRenderer,
|
||||
@NonNull Renderer surfaceRenderer,
|
||||
@NonNull OnScreenResultListener onScreenResultListener)
|
||||
{
|
||||
return createSettingsAction(mapScreen, surfaceRenderer, onScreenResultListener);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private static Action createSettingsAction(@NonNull BaseMapScreen mapScreen, @NonNull SurfaceRenderer surfaceRenderer,
|
||||
private static Action createSettingsAction(@NonNull BaseMapScreen mapScreen,
|
||||
@NonNull Renderer surfaceRenderer,
|
||||
@Nullable OnScreenResultListener onScreenResultListener)
|
||||
{
|
||||
final CarContext context = mapScreen.getCarContext();
|
||||
@@ -120,7 +124,7 @@ public final class UiHelpers
|
||||
|
||||
final Row.Builder builder = new Row.Builder();
|
||||
builder.setImage(
|
||||
new CarIcon.Builder(IconCompat.createWithResource(context, R.drawable.ic_operating_hours)).build());
|
||||
new CarIcon.Builder(IconCompat.createWithResource(context, R.drawable.ic_opening_hours)).build());
|
||||
|
||||
if (isEmptyTT)
|
||||
builder.setTitle(ohStr);
|
||||
|
||||
@@ -40,7 +40,6 @@ public class EditTextDialogFragment extends BaseMwmDialogFragment
|
||||
private String mHint;
|
||||
private TextInputEditText mEtInput;
|
||||
private TextInputLayout mEtInputLayout;
|
||||
private Button mPositiveButton;
|
||||
private Validator mInputValidator;
|
||||
private OnTextSaveListener mTextSaveListener;
|
||||
|
||||
@@ -117,21 +116,20 @@ public class EditTextDialogFragment extends BaseMwmDialogFragment
|
||||
AlertDialog editTextDialog = new MaterialAlertDialogBuilder(requireActivity(), R.style.MwmTheme_AlertDialog)
|
||||
.setView(buildView())
|
||||
.setNegativeButton(negativeButtonText, null)
|
||||
.setPositiveButton(positiveButtonText,
|
||||
(dialog, which) -> {
|
||||
final String result = mEtInput.getText().toString();
|
||||
processInput(result);
|
||||
dismiss();
|
||||
})
|
||||
.setPositiveButton(positiveButtonText, null)
|
||||
.create();
|
||||
|
||||
// Wait till alert is shown to get mPositiveButton.
|
||||
// Set up onClick listener for mPositiveButton.
|
||||
editTextDialog.setOnShowListener((dialog) -> {
|
||||
mPositiveButton = editTextDialog.getButton(DialogInterface.BUTTON_POSITIVE);
|
||||
final FragmentActivity activity = getActivity();
|
||||
if (activity == null)
|
||||
return;
|
||||
this.validateInput(activity, mInitialText);
|
||||
Button positiveButton = editTextDialog.getButton(DialogInterface.BUTTON_POSITIVE);
|
||||
|
||||
positiveButton.setOnClickListener(view -> {
|
||||
final String result = mEtInput.getText().toString();
|
||||
if (validateInput(requireActivity(), result)) {
|
||||
processInput(result);
|
||||
editTextDialog.dismiss();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Setup validation on input edit.
|
||||
@@ -149,14 +147,16 @@ public class EditTextDialogFragment extends BaseMwmDialogFragment
|
||||
return editTextDialog;
|
||||
}
|
||||
|
||||
private void validateInput(@NonNull FragmentActivity activity, @Nullable String input)
|
||||
private boolean validateInput(@NonNull FragmentActivity activity, @Nullable String input)
|
||||
{
|
||||
if (mPositiveButton != null && mInputValidator != null)
|
||||
if (mInputValidator != null)
|
||||
{
|
||||
final String maybeError = mInputValidator.validate(activity, input);
|
||||
mPositiveButton.setEnabled(maybeError == null);
|
||||
mEtInputLayout.getEditText().setError(maybeError);
|
||||
mEtInputLayout.requestFocus();
|
||||
return maybeError == null;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void processInput(@Nullable String text)
|
||||
|
||||
@@ -1,13 +1,19 @@
|
||||
package app.organicmaps.editor;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.text.Editable;
|
||||
import android.text.InputType;
|
||||
import android.text.TextUtils;
|
||||
import android.text.TextWatcher;
|
||||
import android.text.method.LinkMovementMethod;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.AutoCompleteTextView;
|
||||
import android.widget.GridLayout;
|
||||
import android.widget.Toast;
|
||||
import androidx.annotation.CallSuper;
|
||||
import androidx.annotation.DrawableRes;
|
||||
import androidx.annotation.IdRes;
|
||||
@@ -22,6 +28,7 @@ import app.organicmaps.base.BaseMwmFragment;
|
||||
import app.organicmaps.dialog.EditTextDialogFragment;
|
||||
import app.organicmaps.editor.data.TimeFormatUtils;
|
||||
import app.organicmaps.sdk.Framework;
|
||||
import app.organicmaps.sdk.bookmarks.data.ChargeSocketDescriptor;
|
||||
import app.organicmaps.sdk.bookmarks.data.Metadata;
|
||||
import app.organicmaps.sdk.editor.Editor;
|
||||
import app.organicmaps.sdk.editor.OpeningHours;
|
||||
@@ -30,26 +37,33 @@ import app.organicmaps.sdk.editor.data.LocalizedStreet;
|
||||
import app.organicmaps.sdk.editor.data.Timetable;
|
||||
import app.organicmaps.sdk.util.StringUtils;
|
||||
import app.organicmaps.sdk.util.Utils;
|
||||
import app.organicmaps.sdk.util.log.Logger;
|
||||
import app.organicmaps.util.Graphics;
|
||||
import app.organicmaps.util.InputUtils;
|
||||
import app.organicmaps.util.UiUtils;
|
||||
|
||||
import com.google.android.material.button.MaterialButton;
|
||||
import com.google.android.material.card.MaterialCardView;
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||
import com.google.android.material.imageview.ShapeableImageView;
|
||||
import com.google.android.material.textfield.TextInputEditText;
|
||||
import com.google.android.material.textfield.TextInputLayout;
|
||||
import com.google.android.material.textview.MaterialTextView;
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class EditorFragment extends BaseMwmFragment implements View.OnClickListener
|
||||
{
|
||||
final static String LAST_INDEX_OF_NAMES_ARRAY = "LastIndexOfNamesArray";
|
||||
private static final String CHARGE_SOCKETS_TAG = "CHARGE_SOCKETS_TAG";
|
||||
|
||||
private MaterialTextView mCategory;
|
||||
private View mCardName;
|
||||
private View mCardAddress;
|
||||
private View mCardChargingStation;
|
||||
private View mCardDetails;
|
||||
private View mCardSocialMedia;
|
||||
private View mCardBuilding;
|
||||
@@ -130,6 +144,8 @@ public class EditorFragment extends BaseMwmFragment implements View.OnClickListe
|
||||
private TextInputLayout mInputHouseNumber;
|
||||
private TextInputLayout mInputBuildingLevels;
|
||||
|
||||
private View mChargeSockets;
|
||||
|
||||
private View mEmptyOpeningHours;
|
||||
private MaterialTextView mOpeningHours;
|
||||
private View mEditOpeningHours;
|
||||
@@ -206,6 +222,7 @@ public class EditorFragment extends BaseMwmFragment implements View.OnClickListe
|
||||
mWifi.setChecked(Editor.nativeHasWifi());
|
||||
// TODO Reimplement this to avoid https://github.com/organicmaps/organicmaps/issues/9049
|
||||
// mOutdoorSeating.setChecked(Editor.nativeGetSwitchInput(Metadata.MetadataType.FMD_OUTDOOR_SEATING.toInt(),"yes"));
|
||||
refreshChargeSockets();
|
||||
refreshOpeningTime();
|
||||
refreshEditableFields();
|
||||
refreshResetButton();
|
||||
@@ -329,6 +346,14 @@ public class EditorFragment extends BaseMwmFragment implements View.OnClickListe
|
||||
|
||||
final int[] editableDetails = Editor.nativeGetEditableProperties();
|
||||
|
||||
// charge sockets have their own card; check whether we should display it.
|
||||
boolean hasChargeSockets = false;
|
||||
for (int type : editableDetails)
|
||||
{
|
||||
hasChargeSockets = hasChargeSockets || (type == Metadata.MetadataType.FMD_CHARGE_SOCKETS.toInt());
|
||||
}
|
||||
UiUtils.showIf(hasChargeSockets, mCardChargingStation);
|
||||
|
||||
setCardVisibility(mCardDetails, mDetailsBlocks, editableDetails);
|
||||
setCardVisibility(mCardSocialMedia, mSocialMediaBlocks, editableDetails);
|
||||
}
|
||||
@@ -351,6 +376,283 @@ public class EditorFragment extends BaseMwmFragment implements View.OnClickListe
|
||||
UiUtils.showIf(anyBlockElement, card);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a dialog for editing or adding a charge socket.
|
||||
*
|
||||
* @param socketIndex The index of the socket to edit, or -1 to add a new socket.
|
||||
* @param type The current type of the socket (e.g., "type2", "type2_combo").
|
||||
* @param count The current number of sockets of this type or 0 for new socket.
|
||||
* @param power The current power output of the socket in kW or 0 for new socket.
|
||||
* @return A MaterialAlertDialogBuilder instance for the configured dialog.
|
||||
*/
|
||||
private MaterialAlertDialogBuilder buildChargeSocketDialog(int socketIndex, String type, int count, double power)
|
||||
{
|
||||
LayoutInflater inflater = LayoutInflater.from(getActivity());
|
||||
View dialogView = inflater.inflate(R.layout.dialog_edit_socket, null);
|
||||
|
||||
GridLayout typeBtns = dialogView.findViewById(R.id.edit_socket_type_grid);
|
||||
typeBtns.removeAllViews();
|
||||
|
||||
List<String> SOCKET_TYPES = Arrays.stream(getResources().getStringArray(R.array.charge_socket_types)).toList();
|
||||
for (String socket : SOCKET_TYPES)
|
||||
{
|
||||
MaterialButton btn = (MaterialButton) inflater.inflate(R.layout.button_socket_type, typeBtns, false);
|
||||
|
||||
btn.setTag(R.id.socket_type, socket);
|
||||
|
||||
// load SVG icon converted into VectorDrawable in res/drawable
|
||||
@SuppressLint("DiscouragedApi")
|
||||
int resIconId =
|
||||
getResources().getIdentifier("ic_charge_socket_" + socket, "drawable", requireContext().getPackageName());
|
||||
if (resIconId != 0)
|
||||
{
|
||||
btn.setIcon(getResources().getDrawable(resIconId));
|
||||
}
|
||||
|
||||
@SuppressLint("DiscouragedApi")
|
||||
int resTypeId =
|
||||
getResources().getIdentifier("charge_socket_" + socket, "string", requireContext().getPackageName());
|
||||
if (resTypeId != 0)
|
||||
{
|
||||
btn.setText(getResources().getString(resTypeId));
|
||||
}
|
||||
|
||||
if (socket.equals(type))
|
||||
{
|
||||
btn.setChecked(true);
|
||||
}
|
||||
|
||||
typeBtns.addView(btn);
|
||||
}
|
||||
|
||||
// manage the grid of socket type buttons as a single 'radio group'
|
||||
// (this can not be done with a MaterialButtonToggleGroup because it does
|
||||
// not support GridLayout)
|
||||
List<MaterialButton> buttonList = new ArrayList<>();
|
||||
|
||||
for (int i = 0; i < typeBtns.getChildCount(); i++)
|
||||
{
|
||||
View child = typeBtns.getChildAt(i);
|
||||
if (child instanceof MaterialButton button)
|
||||
{
|
||||
buttonList.add(button);
|
||||
|
||||
button.setOnClickListener(view -> {
|
||||
// deselect all
|
||||
for (MaterialButton b : buttonList)
|
||||
{
|
||||
b.setChecked(false);
|
||||
}
|
||||
// select clicked
|
||||
button.setChecked(true);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
TextInputLayout countInputLayout = dialogView.findViewById(R.id.edit_socket_count_layout);
|
||||
AutoCompleteTextView countView = dialogView.findViewById(R.id.edit_socket_count);
|
||||
if (count > 0)
|
||||
{
|
||||
countView.setText(String.valueOf(count));
|
||||
}
|
||||
|
||||
// Add a TextWatcher to validate on text change
|
||||
countView.addTextChangedListener(new TextWatcher() {
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
|
||||
|
||||
@Override
|
||||
public void onTextChanged(CharSequence s, int start, int before, int count) {}
|
||||
|
||||
@Override
|
||||
public void afterTextChanged(Editable s) {
|
||||
validatePositiveField(s.toString(), countInputLayout);
|
||||
}
|
||||
});
|
||||
|
||||
TextInputLayout powerInputLayout = dialogView.findViewById(R.id.edit_socket_power_layout);
|
||||
AutoCompleteTextView powerView = dialogView.findViewById(R.id.edit_socket_power);
|
||||
if (power > 0)
|
||||
{
|
||||
powerView.setText(String.valueOf(power));
|
||||
}
|
||||
|
||||
// Add a TextWatcher to validate on text change
|
||||
powerView.addTextChangedListener(new TextWatcher() {
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
|
||||
|
||||
@Override
|
||||
public void onTextChanged(CharSequence s, int start, int before, int count) {}
|
||||
|
||||
@Override
|
||||
public void afterTextChanged(Editable s) {
|
||||
validatePositiveField(s.toString(), powerInputLayout);
|
||||
}
|
||||
});
|
||||
|
||||
return new MaterialAlertDialogBuilder(requireActivity(), R.style.MwmTheme_AlertDialog)
|
||||
.setTitle(R.string.editor_socket)
|
||||
.setView(dialogView)
|
||||
.setPositiveButton(R.string.save,
|
||||
(dialog, which) -> {
|
||||
String socketType = "";
|
||||
for (MaterialButton b : buttonList)
|
||||
{
|
||||
if (b.isChecked())
|
||||
{
|
||||
socketType = b.getTag(R.id.socket_type).toString();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int countValue = 0; // 0 means 'unknown count'
|
||||
try
|
||||
{
|
||||
countValue = Integer.parseInt(countView.getText().toString());
|
||||
}
|
||||
catch (NumberFormatException ignored)
|
||||
{
|
||||
Logger.w(CHARGE_SOCKETS_TAG, "Invalid count value for socket:" + countView.getText().toString());
|
||||
}
|
||||
|
||||
if (countValue < 0)
|
||||
{
|
||||
countValue = 0;
|
||||
Logger.w(CHARGE_SOCKETS_TAG, "Invalid count value for socket:" + countView.getText().toString());
|
||||
}
|
||||
|
||||
double powerValue = 0; // 0 means 'unknown power'
|
||||
try
|
||||
{
|
||||
powerValue = Double.parseDouble(powerView.getText().toString());
|
||||
}
|
||||
catch (NumberFormatException ignored)
|
||||
{
|
||||
Logger.w(CHARGE_SOCKETS_TAG, "Invalid power value for socket:" + powerView.getText().toString());
|
||||
}
|
||||
|
||||
if (powerValue < 0)
|
||||
{
|
||||
powerValue = 0;
|
||||
Logger.w(CHARGE_SOCKETS_TAG, "Invalid power value for socket:" + powerView.getText().toString());
|
||||
}
|
||||
|
||||
ChargeSocketDescriptor socket =
|
||||
new ChargeSocketDescriptor(socketType, countValue, powerValue);
|
||||
|
||||
updateChargeSockets(socketIndex, socket);
|
||||
})
|
||||
.setNegativeButton(R.string.cancel, (dialog, which) -> { dialog.dismiss(); });
|
||||
}
|
||||
|
||||
// Helper method for validation logic
|
||||
private boolean validatePositiveField(String text, TextInputLayout layout) {
|
||||
if (text.isEmpty()) {
|
||||
layout.setError(null); // No error if empty (assuming 0 is the default)
|
||||
return true;
|
||||
}
|
||||
try {
|
||||
double value = Double.parseDouble(text);
|
||||
if (value < 0) {
|
||||
layout.setError(getString(R.string.error_value_must_be_positive));
|
||||
return false;
|
||||
} else {
|
||||
layout.setError(null);
|
||||
return true;
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
layout.setError(getString(R.string.error_invalid_number));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Updates the list of charge sockets.
|
||||
* If socketIndex is >=0, it updates the socket at that index.
|
||||
* Otherwise, it adds the new socket to the list.
|
||||
*
|
||||
* @param socketIndex The index of the socket to update, or -1 to add a new socket.
|
||||
* @param socket The ChargeSocketDescriptor of the socket to add or update.
|
||||
*/
|
||||
private void updateChargeSockets(int socketIndex, ChargeSocketDescriptor socket)
|
||||
{
|
||||
ChargeSocketDescriptor[] sockets = Editor.nativeGetChargeSockets();
|
||||
if (socketIndex >= 0)
|
||||
{
|
||||
sockets[socketIndex] = socket;
|
||||
}
|
||||
else {
|
||||
List<ChargeSocketDescriptor> list = new ArrayList<>(Arrays.asList(sockets));
|
||||
list.add(socket);
|
||||
sockets = list.toArray(new ChargeSocketDescriptor[0]);
|
||||
}
|
||||
Editor.nativeSetChargeSockets(sockets);
|
||||
|
||||
refreshChargeSockets();
|
||||
}
|
||||
private void refreshChargeSockets()
|
||||
{
|
||||
ChargeSocketDescriptor[] sockets = Editor.nativeGetChargeSockets();
|
||||
|
||||
LayoutInflater inflater = LayoutInflater.from(requireContext());
|
||||
|
||||
GridLayout socketsGrid = mChargeSockets.findViewById(R.id.socket_grid_editor);
|
||||
socketsGrid.removeAllViews();
|
||||
|
||||
for (int i = 0; i < sockets.length; i++)
|
||||
{
|
||||
final int currentIndex = i;
|
||||
ChargeSocketDescriptor socket = sockets[i];
|
||||
|
||||
View itemView = inflater.inflate(R.layout.item_charge_socket, socketsGrid, false);
|
||||
|
||||
MaterialTextView type = itemView.findViewById(R.id.socket_type);
|
||||
ShapeableImageView icon = itemView.findViewById(R.id.socket_icon);
|
||||
MaterialTextView power = itemView.findViewById(R.id.socket_power);
|
||||
MaterialTextView count = itemView.findViewById(R.id.socket_count);
|
||||
|
||||
// load SVG icon converted into VectorDrawable in res/drawable
|
||||
@SuppressLint("DiscouragedApi")
|
||||
int resIconId = getResources().getIdentifier("ic_charge_socket_" + socket.type(), "drawable",
|
||||
requireContext().getPackageName());
|
||||
if (resIconId != 0)
|
||||
{
|
||||
icon.setImageResource(resIconId);
|
||||
}
|
||||
|
||||
@SuppressLint("DiscouragedApi")
|
||||
int resTypeId =
|
||||
getResources().getIdentifier("charge_socket_" + socket.type(), "string", requireContext().getPackageName());
|
||||
if (resTypeId != 0)
|
||||
{
|
||||
type.setText(resTypeId);
|
||||
}
|
||||
|
||||
if (socket.power() != 0)
|
||||
{
|
||||
DecimalFormat df = new DecimalFormat("#.##");
|
||||
power.setText(getString(R.string.kw_label, df.format(socket.power())));
|
||||
}
|
||||
|
||||
if (socket.count() != 0)
|
||||
{
|
||||
count.setText(getString(R.string.count_label, socket.count()));
|
||||
}
|
||||
|
||||
itemView.setOnClickListener(v -> {
|
||||
buildChargeSocketDialog(currentIndex, socket.type(), socket.count(), socket.power()).show();
|
||||
});
|
||||
socketsGrid.addView(itemView);
|
||||
}
|
||||
|
||||
// add a 'new item' button at the end, to create new sockets
|
||||
View btnNewItemView = inflater.inflate(R.layout.button_new_item, socketsGrid, false);
|
||||
btnNewItemView.setOnClickListener(v -> {
|
||||
buildChargeSocketDialog(-1, "unknown", -1, -1).show();
|
||||
});
|
||||
socketsGrid.addView(btnNewItemView);
|
||||
}
|
||||
|
||||
private void refreshOpeningTime()
|
||||
{
|
||||
final String openingHours = Editor.nativeGetOpeningHours();
|
||||
@@ -435,6 +737,7 @@ public class EditorFragment extends BaseMwmFragment implements View.OnClickListe
|
||||
mCategory = categoryBlock.findViewById(R.id.name);
|
||||
mCardName = view.findViewById(R.id.cv__name);
|
||||
mCardAddress = view.findViewById(R.id.cv__address);
|
||||
mCardChargingStation = view.findViewById(R.id.cv__charging_station);
|
||||
mCardDetails = view.findViewById(R.id.cv__details);
|
||||
mCardSocialMedia = view.findViewById(R.id.cv__social_media);
|
||||
mCardBuilding = view.findViewById(R.id.cv__building);
|
||||
@@ -507,6 +810,9 @@ public class EditorFragment extends BaseMwmFragment implements View.OnClickListe
|
||||
View blockOutdoorSeating = view.findViewById(R.id.block_outdoor_seating);
|
||||
mOutdoorSeating = view.findViewById(R.id.sw__outdoor_seating);
|
||||
blockOutdoorSeating.setOnClickListener(this);
|
||||
|
||||
mChargeSockets = view.findViewById(R.id.block_charge_sockets);
|
||||
|
||||
View blockOpeningHours = view.findViewById(R.id.block_opening_hours);
|
||||
mEditOpeningHours = blockOpeningHours.findViewById(R.id.edit_opening_hours);
|
||||
mEditOpeningHours.setOnClickListener(this);
|
||||
@@ -701,7 +1007,7 @@ public class EditorFragment extends BaseMwmFragment implements View.OnClickListe
|
||||
private void placeDoesntExist()
|
||||
{
|
||||
EditTextDialogFragment dialogFragment = EditTextDialogFragment.show(
|
||||
getString(R.string.editor_place_doesnt_exist), "", getString(R.string.editor_comment_hint),
|
||||
getString(R.string.editor_place_doesnt_exist), "", getString(R.string.editor_place_doesnt_exist_description),
|
||||
getString(R.string.editor_report_problem_send_button), getString(R.string.cancel), this,
|
||||
getDeleteCommentValidator());
|
||||
dialogFragment.setTextSaveListener(this::commitPlaceDoesntExists);
|
||||
|
||||
@@ -13,7 +13,6 @@ import android.widget.TextView;
|
||||
import android.widget.TimePicker;
|
||||
import androidx.annotation.IntRange;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.StyleRes;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.appcompat.content.res.AppCompatResources;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
@@ -21,7 +20,6 @@ import app.organicmaps.R;
|
||||
import app.organicmaps.base.BaseMwmDialogFragment;
|
||||
import app.organicmaps.sdk.editor.data.HoursMinutes;
|
||||
import app.organicmaps.sdk.util.DateUtils;
|
||||
import app.organicmaps.util.ThemeUtils;
|
||||
import app.organicmaps.util.Utils;
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||
import com.google.android.material.tabs.TabLayout;
|
||||
@@ -79,15 +77,13 @@ public class HoursMinutesPickerFragment extends BaseMwmDialogFragment
|
||||
// noinspection ConstantConditions
|
||||
mTabs.getTabAt(mSelectedTab).select();
|
||||
|
||||
@StyleRes
|
||||
final int theme = ThemeUtils.isNightTheme() ? R.style.MwmMain_DialogFragment_TimePicker_Night
|
||||
: R.style.MwmMain_DialogFragment_TimePicker;
|
||||
final AlertDialog dialog = new MaterialAlertDialogBuilder(requireActivity(), theme)
|
||||
.setView(root)
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
.setPositiveButton(R.string.ok, null)
|
||||
.setCancelable(true)
|
||||
.create();
|
||||
final AlertDialog dialog =
|
||||
new MaterialAlertDialogBuilder(requireActivity(), R.style.MwmMain_DialogFragment_TimePicker)
|
||||
.setView(root)
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
.setPositiveButton(R.string.ok, null)
|
||||
.setCancelable(true)
|
||||
.create();
|
||||
|
||||
dialog.setOnShowListener(dialogInterface -> {
|
||||
mOkButton = dialog.getButton(AlertDialog.BUTTON_POSITIVE);
|
||||
@@ -141,9 +137,8 @@ public class HoursMinutesPickerFragment extends BaseMwmDialogFragment
|
||||
mTabs = root.findViewById(R.id.tabs);
|
||||
MaterialTextView tabView = (MaterialTextView) inflater.inflate(R.layout.tab_timepicker, mTabs, false);
|
||||
tabView.setText(getResources().getString(R.string.editor_time_from));
|
||||
final ColorStateList textColor = AppCompatResources.getColorStateList(
|
||||
requireContext(),
|
||||
ThemeUtils.isNightTheme() ? R.color.accent_color_selector_night : R.color.accent_color_selector);
|
||||
final ColorStateList textColor =
|
||||
AppCompatResources.getColorStateList(requireContext(), R.color.accent_color_selector);
|
||||
tabView.setTextColor(textColor);
|
||||
mTabs.addTab(mTabs.newTab().setCustomView(tabView), true);
|
||||
tabView = (MaterialTextView) inflater.inflate(R.layout.tab_timepicker, mTabs, false);
|
||||
|
||||
@@ -22,7 +22,6 @@ import app.organicmaps.util.UiUtils;
|
||||
import app.organicmaps.util.Utils;
|
||||
import app.organicmaps.util.WindowInsetUtils;
|
||||
import app.organicmaps.widget.StackedButtonDialogFragment;
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||
import com.google.android.material.imageview.ShapeableImageView;
|
||||
import com.google.android.material.textview.MaterialTextView;
|
||||
import java.text.NumberFormat;
|
||||
@@ -135,14 +134,7 @@ public class ProfileFragment extends BaseMwmToolbarFragment
|
||||
|
||||
private void logout()
|
||||
{
|
||||
new MaterialAlertDialogBuilder(requireContext(), R.style.MwmTheme_AlertDialog)
|
||||
.setMessage(R.string.osm_log_out_confirmation)
|
||||
.setPositiveButton(R.string.yes,
|
||||
(dialog, which) -> {
|
||||
OsmOAuth.clearAuthorization();
|
||||
refreshViews();
|
||||
})
|
||||
.setNegativeButton(R.string.no, null)
|
||||
.show();
|
||||
OsmOAuth.clearAuthorization();
|
||||
refreshViews();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package app.organicmaps.maplayer;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.View;
|
||||
import androidx.annotation.AttrRes;
|
||||
import androidx.annotation.DrawableRes;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.StringRes;
|
||||
@@ -13,9 +14,7 @@ import app.organicmaps.util.ThemeUtils;
|
||||
public class LayerBottomSheetItem
|
||||
{
|
||||
@DrawableRes
|
||||
private final int mEnabledStateDrawableResId;
|
||||
@DrawableRes
|
||||
private final int mDisabledStateDrawableResId;
|
||||
private final int mDrawableResId;
|
||||
@StringRes
|
||||
private final int mTitleResId;
|
||||
@NonNull
|
||||
@@ -23,12 +22,10 @@ public class LayerBottomSheetItem
|
||||
@NonNull
|
||||
private final OnItemClickListener<LayerBottomSheetItem> mItemClickListener;
|
||||
|
||||
LayerBottomSheetItem(@DrawableRes int enabledStateDrawableResId, @DrawableRes int disabledStateDrawableResId,
|
||||
@StringRes int titleResId, @NonNull Mode mode,
|
||||
LayerBottomSheetItem(@DrawableRes int drawableResId, @StringRes int titleResId, @NonNull Mode mode,
|
||||
@NonNull OnItemClickListener<LayerBottomSheetItem> itemClickListener)
|
||||
{
|
||||
mEnabledStateDrawableResId = enabledStateDrawableResId;
|
||||
mDisabledStateDrawableResId = disabledStateDrawableResId;
|
||||
mDrawableResId = drawableResId;
|
||||
mTitleResId = titleResId;
|
||||
mMode = mode;
|
||||
mItemClickListener = itemClickListener;
|
||||
@@ -37,35 +34,30 @@ public class LayerBottomSheetItem
|
||||
public static LayerBottomSheetItem create(@NonNull Context mContext, Mode mode,
|
||||
@NonNull OnItemClickListener<LayerBottomSheetItem> layerItemClickListener)
|
||||
{
|
||||
int disabledResource = 0;
|
||||
int enabledResource = 0;
|
||||
@DrawableRes
|
||||
int drawableResId = 0;
|
||||
@StringRes
|
||||
int buttonTextResource = R.string.layers_title;
|
||||
switch (mode)
|
||||
{
|
||||
case OUTDOORS:
|
||||
disabledResource = R.attr.outdoorsMenuDisabled;
|
||||
enabledResource = R.attr.outdoorsMenuEnabled;
|
||||
drawableResId = R.drawable.ic_layers_outdoors;
|
||||
buttonTextResource = R.string.button_layer_outdoor;
|
||||
break;
|
||||
case SUBWAY:
|
||||
disabledResource = R.attr.subwayMenuDisabled;
|
||||
enabledResource = R.attr.subwayMenuEnabled;
|
||||
drawableResId = R.drawable.ic_layers_subway;
|
||||
buttonTextResource = R.string.subway;
|
||||
break;
|
||||
case ISOLINES:
|
||||
disabledResource = R.attr.isoLinesMenuDisabled;
|
||||
enabledResource = R.attr.isoLinesMenuEnabled;
|
||||
drawableResId = R.drawable.ic_layers_isoline;
|
||||
buttonTextResource = R.string.button_layer_isolines;
|
||||
break;
|
||||
case TRAFFIC:
|
||||
disabledResource = R.attr.trafficMenuDisabled;
|
||||
enabledResource = R.attr.trafficMenuEnabled;
|
||||
drawableResId = R.drawable.ic_layers_traffic;
|
||||
buttonTextResource = R.string.button_layer_traffic;
|
||||
break;
|
||||
}
|
||||
int disabled = ThemeUtils.getResource(mContext, disabledResource);
|
||||
int enabled = ThemeUtils.getResource(mContext, enabledResource);
|
||||
return new LayerBottomSheetItem(enabled, disabled, buttonTextResource, mode, layerItemClickListener);
|
||||
return new LayerBottomSheetItem(drawableResId, buttonTextResource, mode, layerItemClickListener);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@@ -75,15 +67,9 @@ public class LayerBottomSheetItem
|
||||
}
|
||||
|
||||
@DrawableRes
|
||||
public int getEnabledStateDrawable()
|
||||
public int getDrawable()
|
||||
{
|
||||
return mEnabledStateDrawableResId;
|
||||
}
|
||||
|
||||
@DrawableRes
|
||||
public int getDisabledStateDrawable()
|
||||
{
|
||||
return mDisabledStateDrawableResId;
|
||||
return mDrawableResId;
|
||||
}
|
||||
|
||||
@StringRes
|
||||
|
||||
@@ -45,7 +45,8 @@ public class LayersAdapter extends RecyclerView.Adapter<LayerHolder>
|
||||
holder.mTitle.setText(item.getTitle());
|
||||
boolean isNewLayer = SharedPropertiesUtils.shouldShowNewMarkerForLayerMode(item.getMode());
|
||||
UiUtils.showIf(isNewLayer, holder.mNewMarker);
|
||||
holder.mButton.setImageResource(isEnabled ? item.getEnabledStateDrawable() : item.getDisabledStateDrawable());
|
||||
holder.mButton.setBackgroundResource(item.getDrawable());
|
||||
holder.mButton.setActivated(isEnabled);
|
||||
holder.mListener = item::onClick;
|
||||
}
|
||||
|
||||
|
||||
@@ -43,20 +43,19 @@ public class TrafficButton
|
||||
void turnOff()
|
||||
{
|
||||
stopWaitingAnimation();
|
||||
mButton.setImageResource(ThemeUtils.isNightTheme() ? R.drawable.ic_traffic_on_night : R.drawable.ic_traffic_on);
|
||||
mButton.setImageResource(R.drawable.ic_traffic_on);
|
||||
}
|
||||
|
||||
void turnOn()
|
||||
{
|
||||
stopWaitingAnimation();
|
||||
mButton.setImageResource(ThemeUtils.isNightTheme() ? R.drawable.ic_traffic_on_night : R.drawable.ic_traffic_on);
|
||||
mButton.setImageResource(R.drawable.ic_traffic_on);
|
||||
}
|
||||
|
||||
void markAsOutdated()
|
||||
{
|
||||
stopWaitingAnimation();
|
||||
mButton.setImageResource(ThemeUtils.isNightTheme() ? R.drawable.ic_traffic_outdated_night
|
||||
: R.drawable.ic_traffic_outdated);
|
||||
mButton.setImageResource(R.drawable.ic_traffic_outdated);
|
||||
}
|
||||
|
||||
void startWaitingAnimation()
|
||||
|
||||
@@ -20,7 +20,6 @@ import com.google.android.material.textview.MaterialTextView;
|
||||
import app.organicmaps.R;
|
||||
import app.organicmaps.sdk.search.DisplayedCategories;
|
||||
import app.organicmaps.sdk.util.Language;
|
||||
import app.organicmaps.util.ThemeUtils;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.util.Locale;
|
||||
@@ -91,11 +90,7 @@ class CategoriesAdapter extends RecyclerView.Adapter<CategoriesAdapter.ViewHolde
|
||||
@DrawableRes
|
||||
private static int getDrawableResIdByKey(@NonNull Context context, @NonNull String packageName, @NonNull String key)
|
||||
{
|
||||
final boolean isNightTheme = ThemeUtils.isNightTheme();
|
||||
String iconId = "ic_" + key;
|
||||
if (isNightTheme)
|
||||
iconId = iconId + "_night";
|
||||
return context.getResources().getIdentifier(iconId, "drawable", packageName);
|
||||
return context.getResources().getIdentifier("ic_" + key, "drawable", packageName);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -33,13 +33,6 @@ public class SearchActivity extends BaseMwmFragmentActivity
|
||||
activity.startActivity(i);
|
||||
}
|
||||
|
||||
@Override
|
||||
@StyleRes
|
||||
public int getThemeResourceId(@NonNull String theme)
|
||||
{
|
||||
return ThemeUtils.getCardBgThemeResourceId(theme);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<? extends Fragment> getFragmentClass()
|
||||
{
|
||||
|
||||
@@ -12,7 +12,6 @@ import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceFragmentCompat;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import app.organicmaps.R;
|
||||
import app.organicmaps.util.ThemeUtils;
|
||||
import app.organicmaps.util.Utils;
|
||||
import app.organicmaps.util.WindowInsetUtils.ScrollableContentInsetsListener;
|
||||
|
||||
@@ -35,24 +34,17 @@ abstract class BaseXmlSettingsFragment extends PreferenceFragmentCompat
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttach(Context context)
|
||||
public void onAttach(@NonNull Context context)
|
||||
{
|
||||
super.onAttach(context);
|
||||
Utils.detachFragmentIfCoreNotInitialized(context, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(View view, @Nullable Bundle savedInstanceState)
|
||||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState)
|
||||
{
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
|
||||
int color;
|
||||
if (ThemeUtils.isDefaultTheme())
|
||||
color = ContextCompat.getColor(requireContext(), R.color.bg_cards);
|
||||
else
|
||||
color = ContextCompat.getColor(requireContext(), R.color.bg_cards_night);
|
||||
view.setBackgroundColor(color);
|
||||
|
||||
view.setBackgroundColor(ContextCompat.getColor(requireContext(), R.color.bg_cards));
|
||||
RecyclerView recyclerView = getListView();
|
||||
ViewCompat.setOnApplyWindowInsetsListener(recyclerView, new ScrollableContentInsetsListener(recyclerView));
|
||||
}
|
||||
|
||||
@@ -107,6 +107,11 @@ public class DrivingOptionsFragment extends BaseMwmToolbarFragment
|
||||
dirtyRoadsBtn.setChecked(RoutingOptions.hasOption(RoadType.Dirty));
|
||||
CompoundButton.OnCheckedChangeListener dirtyBtnListener = new ToggleRoutingOptionListener(RoadType.Dirty);
|
||||
dirtyRoadsBtn.setOnCheckedChangeListener(dirtyBtnListener);
|
||||
|
||||
SwitchCompat stepsBtn = root.findViewById(R.id.avoid_steps_btn);
|
||||
stepsBtn.setChecked(RoutingOptions.hasOption(RoadType.Steps));
|
||||
CompoundButton.OnCheckedChangeListener stepsBtnListener = new ToggleRoutingOptionListener(RoadType.Steps);
|
||||
stepsBtn.setOnCheckedChangeListener(stepsBtnListener);
|
||||
}
|
||||
|
||||
private static class ToggleRoutingOptionListener implements CompoundButton.OnCheckedChangeListener
|
||||
|
||||
@@ -50,7 +50,7 @@ public class SettingsPrefsFragment extends BaseXmlSettingsFragment implements La
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(View view, @Nullable Bundle savedInstanceState)
|
||||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState)
|
||||
{
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
|
||||
|
||||
@@ -137,7 +137,7 @@ public class VoiceInstructionsSettingsFragment extends BaseXmlSettingsFragment
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(View view, @Nullable Bundle savedInstanceState)
|
||||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState)
|
||||
{
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
|
||||
|
||||
@@ -86,7 +86,7 @@ public enum ThemeSwitcher
|
||||
String oldTheme = Config.UiTheme.getCurrent();
|
||||
|
||||
MapStyle style;
|
||||
if (ThemeUtils.isNightTheme())
|
||||
if (Config.UiTheme.isNight(theme))
|
||||
{
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S)
|
||||
uiModeManager.setApplicationNightMode(UiModeManager.MODE_NIGHT_YES);
|
||||
|
||||
@@ -6,8 +6,6 @@ import android.util.TypedValue;
|
||||
import androidx.annotation.AttrRes;
|
||||
import androidx.annotation.ColorInt;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.StyleRes;
|
||||
import app.organicmaps.R;
|
||||
import app.organicmaps.sdk.util.Config;
|
||||
|
||||
public final class ThemeUtils
|
||||
@@ -64,28 +62,4 @@ public final class ThemeUtils
|
||||
{
|
||||
return Config.UiTheme.isNavAuto(Config.UiTheme.getUiThemeSettings());
|
||||
}
|
||||
|
||||
@StyleRes
|
||||
public static int getCardBgThemeResourceId(@NonNull String theme)
|
||||
{
|
||||
if (Config.UiTheme.isDefault(theme))
|
||||
return R.style.MwmTheme_CardBg;
|
||||
|
||||
if (Config.UiTheme.isNight(theme))
|
||||
return R.style.MwmTheme_Night_CardBg;
|
||||
|
||||
throw new IllegalArgumentException("Attempt to apply unsupported theme: " + theme);
|
||||
}
|
||||
|
||||
@StyleRes
|
||||
public static int getWindowBgThemeResourceId(@NonNull String theme)
|
||||
{
|
||||
if (Config.UiTheme.isDefault(theme))
|
||||
return R.style.MwmTheme_WindowBg;
|
||||
|
||||
if (Config.UiTheme.isNight(theme))
|
||||
return R.style.MwmTheme_Night_WindowBg;
|
||||
|
||||
throw new IllegalArgumentException("Attempt to apply unsupported theme: " + theme);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,9 +35,8 @@ public class RoutingToolbarButton extends AppCompatRadioButton
|
||||
|
||||
private void initView()
|
||||
{
|
||||
final boolean isNightTheme = ThemeUtils.isNightTheme();
|
||||
setBackgroundResource(isNightTheme ? R.drawable.routing_toolbar_button_night : R.drawable.routing_toolbar_button);
|
||||
setButtonTintList(isNightTheme ? R.color.routing_toolbar_icon_tint_night : R.color.routing_toolbar_icon_tint);
|
||||
setBackgroundResource(R.drawable.routing_toolbar_button);
|
||||
setButtonTintList(R.color.routing_toolbar_icon_tint);
|
||||
}
|
||||
|
||||
public void progress()
|
||||
|
||||
@@ -72,6 +72,7 @@ import app.organicmaps.util.bottomsheet.MenuBottomSheetFragment;
|
||||
import app.organicmaps.util.bottomsheet.MenuBottomSheetItem;
|
||||
import app.organicmaps.widget.ArrowView;
|
||||
import app.organicmaps.widget.placepage.sections.PlacePageBookmarkFragment;
|
||||
import app.organicmaps.widget.placepage.sections.PlacePageChargeSocketsFragment;
|
||||
import app.organicmaps.widget.placepage.sections.PlacePageLinksFragment;
|
||||
import app.organicmaps.widget.placepage.sections.PlacePageOpeningHoursFragment;
|
||||
import app.organicmaps.widget.placepage.sections.PlacePagePhoneFragment;
|
||||
@@ -98,6 +99,7 @@ public class PlacePageView extends Fragment
|
||||
private static final String BOOKMARK_FRAGMENT_TAG = "BOOKMARK_FRAGMENT_TAG";
|
||||
private static final String TRACK_FRAGMENT_TAG = "TRACK_FRAGMENT_TAG";
|
||||
private static final String WIKIPEDIA_FRAGMENT_TAG = "WIKIPEDIA_FRAGMENT_TAG";
|
||||
private static final String CHARGE_SOCKETS_FRAGMENT_TAG = "CHARGE_SOCKETS_FRAGMENT_TAG";
|
||||
private static final String PHONE_FRAGMENT_TAG = "PHONE_FRAGMENT_TAG";
|
||||
private static final String OPENING_HOURS_FRAGMENT_TAG = "OPENING_HOURS_FRAGMENT_TAG";
|
||||
private static final String LINKS_FRAGMENT_TAG = "LINKS_FRAGMENT_TAG";
|
||||
@@ -146,7 +148,6 @@ public class PlacePageView extends Fragment
|
||||
private MaterialTextView mTvEntrance;
|
||||
private MaterialTextView mTvLastChecked;
|
||||
private View mEditPlace;
|
||||
private View mAddOrganisation;
|
||||
private View mAddPlace;
|
||||
private View mEditTopSpace;
|
||||
private ShapeableImageView mColorIcon;
|
||||
@@ -311,7 +312,6 @@ public class PlacePageView extends Fragment
|
||||
mTvEntrance = mEntrance.findViewById(R.id.tv__place_entrance);
|
||||
mTvLastChecked = mFrame.findViewById(R.id.place_page_last_checked);
|
||||
mEditPlace = mFrame.findViewById(R.id.ll__place_editor);
|
||||
mAddOrganisation = mFrame.findViewById(R.id.ll__add_organisation);
|
||||
mAddPlace = mFrame.findViewById(R.id.ll__place_add);
|
||||
mEditTopSpace = mFrame.findViewById(R.id.edit_top_space);
|
||||
latlon.setOnLongClickListener(this);
|
||||
@@ -407,6 +407,12 @@ public class PlacePageView extends Fragment
|
||||
R.id.place_page_opening_hours_fragment, !TextUtils.isEmpty(ohStr));
|
||||
}
|
||||
|
||||
private void updateChargeSocketsView()
|
||||
{
|
||||
updateViewFragment(PlacePageChargeSocketsFragment.class, CHARGE_SOCKETS_FRAGMENT_TAG,
|
||||
R.id.place_page_charge_sockets_fragment, mMapObject.hasChargeSockets());
|
||||
}
|
||||
|
||||
private void updatePhoneView()
|
||||
{
|
||||
updateViewFragment(PlacePagePhoneFragment.class, PHONE_FRAGMENT_TAG, R.id.place_page_phone_fragment,
|
||||
@@ -665,28 +671,25 @@ public class PlacePageView extends Fragment
|
||||
if (!lastChecked.isEmpty())
|
||||
{
|
||||
String periodSinceCheck = DateUtils.getRelativePeriodString(getResources(), lastChecked);
|
||||
UiUtils.setTextAndShow(mTvLastChecked, requireContext().getString(R.string.existence_confirmed_time_ago, periodSinceCheck));
|
||||
UiUtils.setTextAndShow(mTvLastChecked,
|
||||
requireContext().getString(R.string.existence_confirmed_time_ago, periodSinceCheck));
|
||||
}
|
||||
else
|
||||
UiUtils.hide(mTvLastChecked);
|
||||
|
||||
if (RoutingController.get().isNavigating() || RoutingController.get().isPlanning())
|
||||
{
|
||||
UiUtils.hide(mEditPlace, mAddOrganisation, mAddPlace, mEditTopSpace);
|
||||
UiUtils.hide(mEditPlace, mAddPlace, mEditTopSpace);
|
||||
}
|
||||
else
|
||||
{
|
||||
UiUtils.showIf(Editor.nativeShouldShowEditPlace(), mEditPlace);
|
||||
UiUtils.showIf(Editor.nativeShouldShowAddBusiness(), mAddOrganisation);
|
||||
UiUtils.showIf(Editor.nativeShouldShowAddPlace(), mAddPlace);
|
||||
MaterialButton mTvEditPlace = mEditPlace.findViewById(R.id.mb__place_editor);
|
||||
MaterialButton mTvAddBusiness = mAddOrganisation.findViewById(R.id.mb__add_organisation);
|
||||
MaterialButton mTvAddPlace = mAddPlace.findViewById(R.id.mb__place_add);
|
||||
mTvEditPlace.setOnClickListener(this);
|
||||
mTvAddBusiness.setOnClickListener(this);
|
||||
mTvAddPlace.setOnClickListener(this);
|
||||
mTvEditPlace.setEnabled(Editor.nativeShouldEnableEditPlace());
|
||||
mTvAddBusiness.setEnabled(Editor.nativeShouldEnableAddPlace());
|
||||
mTvAddPlace.setEnabled(Editor.nativeShouldEnableAddPlace());
|
||||
final int editPlaceButtonColor =
|
||||
Editor.nativeShouldEnableEditPlace()
|
||||
@@ -695,19 +698,18 @@ public class PlacePageView extends Fragment
|
||||
UiUtils.getStyledResourceId(getContext(), com.google.android.material.R.attr.colorSecondary))
|
||||
: ContextCompat.getColor(getContext(), R.color.button_accent_text_disabled);
|
||||
mTvEditPlace.setTextColor(editPlaceButtonColor);
|
||||
mTvAddBusiness.setTextColor(editPlaceButtonColor);
|
||||
mTvAddPlace.setTextColor(editPlaceButtonColor);
|
||||
mTvEditPlace.setStrokeColor(ColorStateList.valueOf(editPlaceButtonColor));
|
||||
mTvAddBusiness.setStrokeColor(ColorStateList.valueOf(editPlaceButtonColor));
|
||||
mTvAddPlace.setStrokeColor(ColorStateList.valueOf(editPlaceButtonColor));
|
||||
UiUtils.showIf(
|
||||
UiUtils.isVisible(mEditPlace) || UiUtils.isVisible(mAddOrganisation) || UiUtils.isVisible(mAddPlace),
|
||||
UiUtils.isVisible(mEditPlace) || UiUtils.isVisible(mAddPlace),
|
||||
mEditTopSpace);
|
||||
}
|
||||
updateLinksView();
|
||||
updateOpeningHoursView();
|
||||
updateWikipediaView();
|
||||
updateBookmarkView();
|
||||
updateChargeSocketsView();
|
||||
updatePhoneView();
|
||||
updateTrackView();
|
||||
}
|
||||
@@ -837,11 +839,6 @@ public class PlacePageView extends Fragment
|
||||
UiUtils.hide(mTvOpenState);
|
||||
}
|
||||
|
||||
private void addOrganisation()
|
||||
{
|
||||
((MwmActivity) requireActivity()).showPositionChooserForEditor(true, true);
|
||||
}
|
||||
|
||||
private void addPlace()
|
||||
{
|
||||
((MwmActivity) requireActivity()).showPositionChooserForEditor(false, true);
|
||||
@@ -859,8 +856,6 @@ public class PlacePageView extends Fragment
|
||||
}
|
||||
else if (id == R.id.mb__place_editor)
|
||||
((MwmActivity) requireActivity()).showEditor();
|
||||
else if (id == R.id.mb__add_organisation)
|
||||
addOrganisation();
|
||||
else if (id == R.id.mb__place_add)
|
||||
addPlace();
|
||||
else if (id == R.id.ll__place_latlon)
|
||||
|
||||
@@ -0,0 +1,121 @@
|
||||
package app.organicmaps.widget.placepage.sections;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.GridLayout;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.lifecycle.Observer;
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
|
||||
import com.google.android.material.imageview.ShapeableImageView;
|
||||
import com.google.android.material.textview.MaterialTextView;
|
||||
|
||||
import app.organicmaps.R;
|
||||
import app.organicmaps.sdk.Framework;
|
||||
import app.organicmaps.sdk.bookmarks.data.ChargeSocketDescriptor;
|
||||
import app.organicmaps.sdk.bookmarks.data.MapObject;
|
||||
import app.organicmaps.sdk.bookmarks.data.Metadata;
|
||||
import app.organicmaps.widget.placepage.PlacePageViewModel;
|
||||
import java.text.DecimalFormat;
|
||||
|
||||
public class PlacePageChargeSocketsFragment extends Fragment implements Observer<MapObject>
|
||||
{
|
||||
private GridLayout mGrid;
|
||||
private PlacePageViewModel mViewModel;
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
|
||||
@Nullable Bundle savedInstanceState)
|
||||
{
|
||||
mViewModel = new ViewModelProvider(requireActivity()).get(PlacePageViewModel.class);
|
||||
return inflater.inflate(R.layout.place_page_charge_sockets_fragment, container, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState)
|
||||
{
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
|
||||
mGrid = view.findViewById(R.id.socket_grid);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart()
|
||||
{
|
||||
super.onStart();
|
||||
mViewModel.getMapObject().observe(requireActivity(), this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStop()
|
||||
{
|
||||
super.onStop();
|
||||
mViewModel.getMapObject().removeObserver(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChanged(@Nullable MapObject mapObject)
|
||||
{
|
||||
if (mapObject == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
mGrid.removeAllViews();
|
||||
|
||||
ChargeSocketDescriptor[] sockets = Framework.nativeGetActiveObjectChargeSockets();
|
||||
|
||||
LayoutInflater inflater = LayoutInflater.from(requireContext());
|
||||
|
||||
for (ChargeSocketDescriptor socket : sockets)
|
||||
{
|
||||
View itemView = inflater.inflate(R.layout.item_charge_socket, mGrid, false);
|
||||
|
||||
itemView.setClickable(false);
|
||||
itemView.setFocusable(false);
|
||||
|
||||
MaterialTextView type = itemView.findViewById(R.id.socket_type);
|
||||
ShapeableImageView icon = itemView.findViewById(R.id.socket_icon);
|
||||
MaterialTextView power = itemView.findViewById(R.id.socket_power);
|
||||
MaterialTextView count = itemView.findViewById(R.id.socket_count);
|
||||
|
||||
// load SVG icon converted into VectorDrawable in res/drawable
|
||||
@SuppressLint("DiscouragedApi")
|
||||
int resIconId = getResources().getIdentifier("ic_charge_socket_" + socket.type(), "drawable",
|
||||
requireContext().getPackageName());
|
||||
if (resIconId != 0)
|
||||
{
|
||||
icon.setImageResource(resIconId);
|
||||
}
|
||||
|
||||
@SuppressLint("DiscouragedApi")
|
||||
int resTypeId =
|
||||
getResources().getIdentifier("charge_socket_" + socket.type(), "string", requireContext().getPackageName());
|
||||
if (resTypeId != 0)
|
||||
{
|
||||
type.setText(resTypeId);
|
||||
}
|
||||
|
||||
if (socket.power() != 0)
|
||||
{
|
||||
DecimalFormat df = new DecimalFormat("#.##");
|
||||
power.setText(getString(R.string.kw_label, df.format(socket.power())));
|
||||
}
|
||||
|
||||
if (socket.count() != 0)
|
||||
{
|
||||
count.setText(getString(R.string.count_label, socket.count()));
|
||||
}
|
||||
|
||||
mGrid.addView(itemView);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<item android:color="@color/base_accent_night"
|
||||
android:state_selected="true"/>
|
||||
|
||||
<item android:color="@color/base_accent_night"
|
||||
android:state_checked="true"/>
|
||||
|
||||
<item android:color="@color/base_accent_night"
|
||||
app:layers_enabled="true"/>
|
||||
|
||||
<item android:color="@color/white_secondary"/>
|
||||
</selector>
|
||||
@@ -1,7 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:color="@color/button_accent_normal_night"
|
||||
android:state_enabled="true"/>
|
||||
|
||||
<item android:color="@color/button_accent_disabled_night"/>
|
||||
</selector>
|
||||
@@ -1,7 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:color="@color/button_normal_night"
|
||||
android:state_enabled="true"/>
|
||||
|
||||
<item android:color="@color/button_disabled_night"/>
|
||||
</selector>
|
||||
@@ -1,11 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item
|
||||
android:state_activated="true"
|
||||
android:color="@color/routing_button_activated_tint_night"/>
|
||||
<item
|
||||
android:state_pressed="true"
|
||||
android:color="@color/routing_button_pressed_tint"/>
|
||||
<item
|
||||
android:color="@color/routing_button_tint"/>
|
||||
</selector>
|
||||
|
Before Width: | Height: | Size: 702 B After Width: | Height: | Size: 702 B |
|
Before Width: | Height: | Size: 702 B After Width: | Height: | Size: 702 B |
|
Before Width: | Height: | Size: 718 B After Width: | Height: | Size: 718 B |
|
Before Width: | Height: | Size: 716 B After Width: | Height: | Size: 716 B |
|
Before Width: | Height: | Size: 722 B After Width: | Height: | Size: 722 B |
|
Before Width: | Height: | Size: 712 B After Width: | Height: | Size: 712 B |
|
Before Width: | Height: | Size: 712 B After Width: | Height: | Size: 712 B |
|
Before Width: | Height: | Size: 714 B After Width: | Height: | Size: 714 B |
|
Before Width: | Height: | Size: 718 B After Width: | Height: | Size: 718 B |
|
Before Width: | Height: | Size: 706 B After Width: | Height: | Size: 706 B |
|
Before Width: | Height: | Size: 714 B After Width: | Height: | Size: 714 B |
|
Before Width: | Height: | Size: 714 B After Width: | Height: | Size: 714 B |
|
Before Width: | Height: | Size: 722 B After Width: | Height: | Size: 722 B |
|
Before Width: | Height: | Size: 714 B After Width: | Height: | Size: 714 B |
|
Before Width: | Height: | Size: 712 B After Width: | Height: | Size: 712 B |
|
Before Width: | Height: | Size: 718 B After Width: | Height: | Size: 718 B |