Merge commit '2601ec854a' into traffic

# Conflicts:
#	iphone/Maps/Model/Settings.swift
#	iphone/Maps/UI/Settings/SettingsNavigationView.swift
This commit is contained in:
mvglasow
2025-11-05 23:06:07 +02:00
561 changed files with 7632 additions and 4277 deletions

View File

@@ -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!

View File

@@ -1,10 +1,9 @@
Karten-Daten vom 6. September Verbesserte Sichtbarkeit & Benutzeroberfläche für Navigationsanweisungen
Zeitstrafen für Radrouting Option um Treppen zu vermeiden
Farbige POI-Beschriftungen in Autonavigation Verbesserte Suche in mehreren Sprachen
POI-Suche nach Filialnamen Spezifisches Symbol für Busbahnöfe hinzugefügt
Abspannportale, Sicherheitskabinen & Büros hinzugefügt Probleme mit Android Auto behoben (via OM)
Aktualisierte Symbole für Türme, Nachtclubs, Apotheken und Fahnenmasten Verbesserter Editor mit kleinere Bugfixes
Lesezeichen-Farbe in GPX-Exporten Kartenstile verbessert (via OM)
Farbfüllung von Fußgängerbereiche auf Plätzen Verbesserte Übersetzungen
• Android Auto: Anzeige Ausfahrtsnummern in Kreisverkehren Für weitere Änderungen siehe Codeberg-Versionshinweise
Weitere Änderungen in Codeberg-Versionshinweisen!

View File

@@ -1,10 +1,9 @@
OpenStreetMap data as of September 6 Improved visibility and UI of instructions in navigation
Turn penalties for bicycle routing Added option to avoid steps
Colored POI labels for car navigation map style Improved search in multiple languages
Search POIs by branch name Added specific icon for bus stations
Added power portals, security booths and offices Fixed Android Auto issues (via OM project)
Update icons for towers, nightclubs, chemists, flagpoles Improved editor and fix minor issues
Save bookmark color to GPX exports Improved map styles (via OM project)
Color fill pedestrian parts of squares Improved app translations
• Android Auto: display roundabout exit numbers
Check our Codeberg release notes for more changes! Check our Codeberg release notes for more changes!

View File

@@ -1,10 +1,8 @@
Datos a 6 de septiembre Mejora de la visibilidad y la interfaz de usuario de las instrucciones de navegación
Penalizaciones de giros en rutas de bici Se ha añadido la opción de evitar escaleras
Etiquetas de puntos de interés en color en navegación Mejora de la búsqueda en varios idiomas como ES
Buscar por nombre de sucursal Se ha añadido un icono específico para las estaciones de autobús
Añadir portales de energía, cabinas de seguridad y oficinas Se han solucionado los problemas de Android Auto (a través del proyecto OM)
Nuevos iconos: torres, discotecas, parafarmacias y mástiles Se ha mejorado el editor y se han solucionado pequeños problemas
Guardar color en exportaciones GPX Se han mejorado los estilos de los mapas (a través del proyecto OM)
• Colorear áreas peatonales de plazas
• Android Auto: mostrar números de salida de rotondas
Más detalles en Codeberg Más detalles en Codeberg

View File

@@ -1,9 +1,9 @@
Données OSM du 06 septembre Interface utilisateur et visibilité des instructions en navigation améliorée
Pénalités dans les calculs d'itinéraires vélos Option pour éviter les escaliers ajoutée
Ajout de labels colorés en mode navigation Recherche améliorée dans différents languages
Support du tag branch dans la recherche Icône pour les gares routières ajoutée
Ajout des portiques électriques, postes de sécurité Corrections de bugs liées à Android Auto (via OM)
Mise à jour des icônes de tours, boîtes de nuits, chimiste et mat Editeur amélioré et corrections de bugs
Enregistrement de la couleur des signets dans les exports GPX Style de la carte amélioré (via OM)
Android Auto: Affichage du numéro de sortie des ronds-points Traductions améliorées
Plus d'informations sur notre Codeberg Plus d'informations sur notre Codeberg

View 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!

View File

@@ -0,0 +1 @@
Navigasi peta mudah Temukan lebih banyak Didukung oleh komunitas

View File

@@ -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

View File

@@ -1 +1 @@
Lett kart navigasjon - Opplev mere på din reise - Drevet av felleskapet Enkel kartnavigering - Opplev mere på din reise - Drevet av felleskapet

View File

@@ -1 +1 @@
CoMaps - Gå tur, sykkel, kjør - med personvern CoMaps - Gå, sykle, kjøre offline med personvern

View File

@@ -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ść

View File

@@ -1,10 +1,9 @@
Dados OSM de 6/09 Visibilidade e interface do usuário aprimoradas para instruções na navegação
Penalidades de conversão para bicicleta Opção adicionada para evitar degraus
Etiquetas de POI coloridas para o estilo do mapa de navegação de carros Busca aprimorada em vários idiomas
Busca de POIs por nome de filial Adição de ícone específico para rodoviárias
Adição de portais de energia, guaritas e escritórios Problemas corrigidos no Android Auto (via projeto OM)
Atualização de ícones para torres, discotecas, farmácias e mastros Editor aprimorado e correção de problemas menores
Salva a cor dos favoritos nas exportações GPX Estilos de mapa aprimorados (via projeto OM)
Preenchimento de praças pavimentadas Traduções aprimoradas
• Android Auto: exibe números de saída de rotatória Confira nossas notas de lançamento do Codeberg para mais mudanças!
Confira nossas notas de lançamento do Codeberg para mais mudanças

View File

@@ -1,10 +1,9 @@
Данные на 6 сентября Лучшая видимость и интерфейс при навигации
Предупреждения на веломаршруте Добавлена возможность пропускать шаги
Цветные метки POI при автонавигации Улучшен поиск на нескольких языках
Поиск POI по названию ветки Новый значок автостанций
Добавлены высоковольтные опоры, помещения охраны и офисы Исправлены проблемы с Android Auto (через OM)
Обновлены значки башен,вышек,мачт,ночных клубов,аптек Улучшен редактор и исправлены мелкие недочёты
Сохранение цвета закладок при экспорте в GPX (через OM) Улучшены стили карт (через OM)
Отображение цветом пешеходных зон Улучшены переводы приложения
• Android Auto: отображение номеров съездов на кольцевых развязках Ознакомьтесь с примечаниями к выпуску Codeberg, чтобы узнать изменениях!
Посмотрите примечания к выпуску Codeberg, чтобы узнать о других изменениях!

View File

@@ -0,0 +1 @@
Navigasi peta mudah Temukan lebih banyak Didukung oleh komunitas

View File

@@ -0,0 +1 @@
CoMaps - Jelajah dengan Privat

View File

@@ -0,0 +1 @@
Enkel kartnavigering - Opplev mere på din reise - Drevet av felleskapet

View File

@@ -0,0 +1 @@
CoMaps -Naviger med personvern

View File

@@ -0,0 +1 @@
Łatwa nawigacja po mapie - Odkryj więcej z podróży - Wspierane przez społeczność

View File

@@ -104,6 +104,7 @@
<!-- Allows for config and orientation change without killing/restarting main activity --> <!-- Allows for config and orientation change without killing/restarting main activity -->
<activity <activity
android:name="app.organicmaps.SplashActivity" android:name="app.organicmaps.SplashActivity"
android:theme="@style/MwmTheme.Splash"
android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation" android:configChanges="orientation|screenSize|smallestScreenSize|density|screenLayout|uiMode|keyboard|keyboardHidden|navigation"
android:screenOrientation="fullUser" android:screenOrientation="fullUser"
android:exported="true"> android:exported="true">
@@ -364,6 +365,7 @@
<activity <activity
android:name="app.organicmaps.DownloadResourcesLegacyActivity" android:name="app.organicmaps.DownloadResourcesLegacyActivity"
android:theme="@style/MwmTheme.DownloadResourcesLegacy"
android:configChanges="orientation|screenLayout|screenSize" android:configChanges="orientation|screenLayout|screenSize"
android:screenOrientation="fullUser"/> android:screenOrientation="fullUser"/>
@@ -380,6 +382,7 @@
<activity <activity
android:name="app.organicmaps.MwmActivity" android:name="app.organicmaps.MwmActivity"
android:theme="@style/MwmTheme.MainActivity"
android:launchMode="singleTask" android:launchMode="singleTask"
android:configChanges="uiMode" android:configChanges="uiMode"
android:screenOrientation="fullUser" android:screenOrientation="fullUser"
@@ -401,6 +404,7 @@
<activity <activity
android:name="app.organicmaps.search.SearchActivity" android:name="app.organicmaps.search.SearchActivity"
android:theme="@style/MwmTheme.CardBg"
android:configChanges="orientation|screenLayout|screenSize" android:configChanges="orientation|screenLayout|screenSize"
android:screenOrientation="fullUser" android:screenOrientation="fullUser"
android:label="@string/search_map" android:label="@string/search_map"
@@ -427,6 +431,7 @@
<activity <activity
android:name="app.organicmaps.bookmarks.BookmarkCategoriesActivity" android:name="app.organicmaps.bookmarks.BookmarkCategoriesActivity"
android:theme="@style/MwmTheme.WindowBg"
android:configChanges="orientation|screenLayout|screenSize" android:configChanges="orientation|screenLayout|screenSize"
android:screenOrientation="fullUser" android:screenOrientation="fullUser"
android:label="@string/bookmarks_and_tracks" android:label="@string/bookmarks_and_tracks"
@@ -435,6 +440,7 @@
<activity <activity
android:name="app.organicmaps.bookmarks.BookmarkListActivity" android:name="app.organicmaps.bookmarks.BookmarkListActivity"
android:theme="@style/MwmTheme.CardBg"
android:configChanges="orientation|screenLayout|screenSize" android:configChanges="orientation|screenLayout|screenSize"
android:screenOrientation="fullUser" android:screenOrientation="fullUser"
android:label="@string/bookmarks" android:label="@string/bookmarks"

View File

@@ -24,7 +24,6 @@ import androidx.annotation.CallSuper;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.annotation.StringRes; import androidx.annotation.StringRes;
import androidx.annotation.StyleRes;
import androidx.core.view.ViewCompat; import androidx.core.view.ViewCompat;
import app.organicmaps.base.BaseMwmFragmentActivity; import app.organicmaps.base.BaseMwmFragmentActivity;
import app.organicmaps.downloader.MapManagerHelper; import app.organicmaps.downloader.MapManagerHelper;
@@ -438,11 +437,4 @@ public class DownloadResourcesLegacyActivity extends BaseMwmFragmentActivity
.setOnDismissListener(dialog -> mAlertDialog = null) .setOnDismissListener(dialog -> mAlertDialog = null)
.show(); .show();
} }
@Override
@StyleRes
public int getThemeResourceId(@NonNull String theme)
{
return R.style.MwmTheme_DownloadResourcesLegacy;
}
} }

View File

@@ -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;
}
}

View File

@@ -42,7 +42,6 @@ import androidx.annotation.CallSuper;
import androidx.annotation.Keep; import androidx.annotation.Keep;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.annotation.StyleRes;
import androidx.annotation.UiThread; import androidx.annotation.UiThread;
import androidx.core.app.ActivityCompat; import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat; import androidx.core.content.ContextCompat;
@@ -85,6 +84,7 @@ import app.organicmaps.routing.RoutingPlanInplaceController;
import app.organicmaps.sdk.ChoosePositionMode; import app.organicmaps.sdk.ChoosePositionMode;
import app.organicmaps.sdk.Framework; import app.organicmaps.sdk.Framework;
import app.organicmaps.sdk.Map; import app.organicmaps.sdk.Map;
import app.organicmaps.sdk.MapController;
import app.organicmaps.sdk.MapRenderingListener; import app.organicmaps.sdk.MapRenderingListener;
import app.organicmaps.sdk.PlacePageActivationListener; import app.organicmaps.sdk.PlacePageActivationListener;
import app.organicmaps.sdk.Router; import app.organicmaps.sdk.Router;
@@ -138,10 +138,10 @@ import java.util.ArrayList;
import java.util.Objects; import java.util.Objects;
public class MwmActivity extends BaseMwmFragmentActivity public class MwmActivity extends BaseMwmFragmentActivity
implements PlacePageActivationListener, View.OnTouchListener, MapRenderingListener, RoutingController.Container, implements PlacePageActivationListener, MapRenderingListener, RoutingController.Container, LocationListener,
LocationListener, SensorListener, LocationState.ModeChangeListener, SensorListener, LocationState.ModeChangeListener, RoutingPlanInplaceController.RoutingPlanListener,
RoutingPlanInplaceController.RoutingPlanListener, RoutingBottomMenuListener, RoutingBottomMenuListener, BookmarkManager.BookmarksLoadingListener,
BookmarkManager.BookmarksLoadingListener, FloatingSearchToolbarController.SearchToolbarListener, FloatingSearchToolbarController.SearchToolbarListener,
MenuBottomSheetFragment.MenuBottomSheetInterfaceWithHeader, MenuBottomSheetFragment.MenuBottomSheetInterfaceWithHeader,
PlacePageController.PlacePageRouteSettingsListener, MapButtonsController.MapButtonClickListener, PlacePageController.PlacePageRouteSettingsListener, MapButtonsController.MapButtonClickListener,
DisplayChangedListener DisplayChangedListener
@@ -171,8 +171,9 @@ public class MwmActivity extends BaseMwmFragmentActivity
private static final String POWER_SAVE_DISCLAIMER_SHOWN = "POWER_SAVE_DISCLAIMER_SHOWN"; private static final String POWER_SAVE_DISCLAIMER_SHOWN = "POWER_SAVE_DISCLAIMER_SHOWN";
@Nullable @SuppressWarnings("NotNullFieldNotInitialized")
private MapFragment mMapFragment; @NonNull
private MapController mMapController;
private View mPointChooser; private View mPointChooser;
private MaterialToolbar mPointChooserToolbar; private MaterialToolbar mPointChooserToolbar;
@@ -245,7 +246,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
ManageRouteBottomSheet mManageRouteBottomSheet; ManageRouteBottomSheet mManageRouteBottomSheet;
private boolean mRemoveDisplayListener = true; private boolean mRemoveDisplayListener = true;
private int mLastUiMode = Configuration.UI_MODE_TYPE_UNDEFINED; private static int mLastUiMode = Configuration.UI_MODE_TYPE_UNDEFINED;
public interface LeftAnimationTrackListener 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 @Override
public void onDisplayChangedToCar(@NonNull Runnable onTaskFinishedCallback) public void onDisplayChangedToCar(@NonNull Runnable onTaskFinishedCallback)
{ {
mRemoveDisplayListener = false; mRemoveDisplayListener = false;
startActivity(new Intent(this, MapPlaceholderActivity.class)); startActivity(new Intent(this, MapPlaceholderActivity.class));
Objects.requireNonNull(mMapFragment).notifyOnSurfaceDestroyed(onTaskFinishedCallback); mMapController.setOnDestroyListener(onTaskFinishedCallback);
finish(); finish();
} }
@@ -482,13 +470,15 @@ public class MwmActivity extends BaseMwmFragmentActivity
{ {
super.onConfigurationChanged(newConfig); super.onConfigurationChanged(newConfig);
final int newUiMode = newConfig.uiMode & Configuration.UI_MODE_TYPE_MASK; final int newType = newConfig.uiMode & Configuration.UI_MODE_TYPE_MASK;
final boolean newUiModeIsCarConnected = newUiMode == Configuration.UI_MODE_TYPE_CAR; final int oldType = mLastUiMode & Configuration.UI_MODE_TYPE_MASK;
final boolean newUiModeIsCarDisconnected =
mLastUiMode == Configuration.UI_MODE_TYPE_CAR && newUiMode == Configuration.UI_MODE_TYPE_NORMAL;
mLastUiMode = newUiMode;
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; return;
makeNavigationBarTransparentInLightMode(); makeNavigationBarTransparentInLightMode();
@@ -550,7 +540,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
updateViewsInsets(); updateViewsInsets();
if (getIntent().getBooleanExtra(EXTRA_UPDATE_THEME, false)) 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 * 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) 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(); initNavigationButtons();
if (!mIsTabletLayout) if (!mIsTabletLayout)
@@ -732,16 +725,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
private void showPositionChooser(ChoosePositionMode mode, boolean isBusiness, boolean applyPosition) private void showPositionChooser(ChoosePositionMode mode, boolean isBusiness, boolean applyPosition)
{ {
closeFloatingToolbarsAndPanels(false); 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); UiUtils.show(mPointChooser);
mMapButtonsViewModel.setButtonsHidden(true); mMapButtonsViewModel.setButtonsHidden(true);
ChoosePositionMode.set(mode, isBusiness, applyPosition); ChoosePositionMode.set(mode, isBusiness, applyPosition);
@@ -760,29 +744,6 @@ public class MwmActivity extends BaseMwmFragmentActivity
finish(); 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() private void initNavigationButtons()
{ {
prepareNavigationButtons(); prepareNavigationButtons();
@@ -1211,7 +1172,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
{ {
setIntent(intent); setIntent(intent);
super.onNewIntent(intent); super.onNewIntent(intent);
if (isMapRendererActive()) if (mMapController.isRenderingActive())
processIntent(); processIntent();
if (intent.getAction() != null && intent.getAction().equals(TrackRecordingService.STOP_TRACK_RECORDING)) 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 @CallSuper
@Override @Override
protected void onResume() protected void onResume()
{ {
super.onResume(); super.onResume();
ThemeSwitcher.INSTANCE.restart(isMapRendererActive()); ThemeSwitcher.INSTANCE.restart(mMapController.isRenderingActive());
refreshSearchToolbar(); refreshSearchToolbar();
setFullscreen(isFullscreen()); setFullscreen(isFullscreen());
makeNavigationBarTransparentInLightMode(); makeNavigationBarTransparentInLightMode();
@@ -1249,15 +1205,6 @@ public class MwmActivity extends BaseMwmFragmentActivity
MwmApplication.from(this).getSensorHelper().addListener(this); 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 @Override
protected void onResumeFragments() protected void onResumeFragments()
{ {
@@ -1459,12 +1406,6 @@ public class MwmActivity extends BaseMwmFragmentActivity
return super.onGenericMotionEvent(event); return super.onGenericMotionEvent(event);
} }
@Override
public boolean onTouch(View view, MotionEvent event)
{
return mMapFragment != null && mMapFragment.onTouch(view, event);
}
public void customOnNavigateUp() public void customOnNavigateUp()
{ {
if (removeCurrentFragment(true)) if (removeCurrentFragment(true))
@@ -1480,10 +1421,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
void updateCompassOffset(int offsetY, int offsetX) void updateCompassOffset(int offsetY, int offsetX)
{ {
if (mMapFragment == null || !mMapFragment.isAdded()) mMapController.updateCompassOffset(offsetX, offsetY);
return;
mMapFragment.updateCompassOffset(offsetX, offsetY);
final double north = MwmApplication.from(this).getSensorHelper().getSavedNorth(); final double north = MwmApplication.from(this).getSensorHelper().getSavedNorth();
if (!Double.isNaN(north)) if (!Double.isNaN(north))
@@ -1502,9 +1440,6 @@ public class MwmActivity extends BaseMwmFragmentActivity
public void updateBottomWidgetsOffset(int offsetX) public void updateBottomWidgetsOffset(int offsetX)
{ {
if (mMapFragment == null || !mMapFragment.isAdded())
return;
int offsetY = mNavBarHeight; int offsetY = mNavBarHeight;
final Float bottomButtonHeight = mMapButtonsViewModel.getBottomButtonsHeight().getValue(); final Float bottomButtonHeight = mMapButtonsViewModel.getBottomButtonsHeight().getValue();
if (bottomButtonHeight != null) if (bottomButtonHeight != null)
@@ -1519,8 +1454,8 @@ public class MwmActivity extends BaseMwmFragmentActivity
if (mDisplayManager.isDeviceDisplayUsed()) if (mDisplayManager.isDeviceDisplayUsed())
{ {
mMapFragment.updateBottomWidgetsOffset(offsetX, offsetY); mMapController.updateBottomWidgetsOffset(offsetX, offsetY);
mMapFragment.updateMyPositionRoutingOffset(offsetY); mMapController.updateMyPositionRoutingOffset(offsetY);
} }
} }
@@ -1738,7 +1673,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
public void onNavigationCancelled() public void onNavigationCancelled()
{ {
closeFloatingToolbarsAndPanels(true); closeFloatingToolbarsAndPanels(true);
ThemeSwitcher.INSTANCE.restart(isMapRendererActive()); ThemeSwitcher.INSTANCE.restart(mMapController.isRenderingActive());
if (mRoutingPlanInplaceController == null) if (mRoutingPlanInplaceController == null)
return; return;
@@ -1754,7 +1689,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
public void onNavigationStarted() public void onNavigationStarted()
{ {
closeFloatingToolbarsAndPanels(true); closeFloatingToolbarsAndPanels(true);
ThemeSwitcher.INSTANCE.restart(isMapRendererActive()); ThemeSwitcher.INSTANCE.restart(mMapController.isRenderingActive());
mMapButtonsViewModel.setLayoutMode(MapButtonsController.LayoutMode.navigation); mMapButtonsViewModel.setLayoutMode(MapButtonsController.LayoutMode.navigation);
refreshLightStatusBar(); refreshLightStatusBar();
@@ -1790,7 +1725,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
public void onResetToPlanningState() public void onResetToPlanningState()
{ {
closeFloatingToolbarsAndPanels(true); closeFloatingToolbarsAndPanels(true);
ThemeSwitcher.INSTANCE.restart(isMapRendererActive()); ThemeSwitcher.INSTANCE.restart(mMapController.isRenderingActive());
NavigationService.stopService(this); NavigationService.stopService(this);
mMapButtonsViewModel.setSearchOption(null); mMapButtonsViewModel.setSearchOption(null);
mMapButtonsViewModel.setLayoutMode(MapButtonsController.LayoutMode.planning); mMapButtonsViewModel.setLayoutMode(MapButtonsController.LayoutMode.planning);
@@ -2619,4 +2554,13 @@ public class MwmActivity extends BaseMwmFragmentActivity
window.setNavigationBarContrastEnforced(false); 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();
}
} }

View File

@@ -56,15 +56,6 @@ public class SplashActivity extends AppCompatActivity
protected void onCreate(@Nullable Bundle savedInstanceState) protected void onCreate(@Nullable Bundle savedInstanceState)
{ {
super.onCreate(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); UiThread.cancelDelayedTasks(mInitCoreDelayedTask);
setContentView(R.layout.activity_splash); setContentView(R.layout.activity_splash);

View File

@@ -8,14 +8,13 @@ import androidx.annotation.Nullable;
import androidx.annotation.StyleRes; import androidx.annotation.StyleRes;
import androidx.fragment.app.DialogFragment; import androidx.fragment.app.DialogFragment;
import app.organicmaps.R; import app.organicmaps.R;
import app.organicmaps.util.ThemeUtils;
public class BaseMwmDialogFragment extends DialogFragment public class BaseMwmDialogFragment extends DialogFragment
{ {
@StyleRes @StyleRes
protected final int getFullscreenTheme() protected final int getFullscreenTheme()
{ {
return ThemeUtils.isNightTheme() ? getFullscreenDarkTheme() : getFullscreenLightTheme(); return R.style.MwmTheme_DialogFragment_Fullscreen;
} }
protected int getStyle() protected int getStyle()
@@ -23,7 +22,8 @@ public class BaseMwmDialogFragment extends DialogFragment
return STYLE_NORMAL; return STYLE_NORMAL;
} }
protected @StyleRes int getCustomTheme() @StyleRes
protected int getCustomTheme()
{ {
return 0; return 0;
} }
@@ -40,18 +40,6 @@ public class BaseMwmDialogFragment extends DialogFragment
setStyle(style, theme); 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 @NonNull
protected Application getAppContextOrThrow() protected Application getAppContextOrThrow()
{ {

View File

@@ -11,7 +11,6 @@ import androidx.activity.SystemBarStyle;
import androidx.annotation.CallSuper; import androidx.annotation.CallSuper;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.annotation.StyleRes;
import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentFactory; import androidx.fragment.app.FragmentFactory;
@@ -20,7 +19,6 @@ import app.organicmaps.MwmApplication;
import app.organicmaps.R; import app.organicmaps.R;
import app.organicmaps.SplashActivity; import app.organicmaps.SplashActivity;
import app.organicmaps.sdk.util.Config; import app.organicmaps.sdk.util.Config;
import app.organicmaps.sdk.util.concurrency.UiThread;
import app.organicmaps.sdk.util.log.Logger; import app.organicmaps.sdk.util.log.Logger;
import app.organicmaps.util.RtlUtils; import app.organicmaps.util.RtlUtils;
import com.google.android.material.appbar.MaterialToolbar; import com.google.android.material.appbar.MaterialToolbar;
@@ -32,24 +30,9 @@ public abstract class BaseMwmFragmentActivity extends AppCompatActivity
private boolean mSafeCreated; 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. * Shows splash screen and initializes the core in case when it was not initialized.
* * <p>
* Do not override this method! * Do not override this method!
* Use {@link #onSafeCreate(Bundle savedInstanceState)} * Use {@link #onSafeCreate(Bundle savedInstanceState)}
*/ */
@@ -58,8 +41,6 @@ public abstract class BaseMwmFragmentActivity extends AppCompatActivity
protected final void onCreate(@Nullable Bundle savedInstanceState) protected final void onCreate(@Nullable Bundle savedInstanceState)
{ {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
mThemeName = Config.UiTheme.getCurrent();
setTheme(getThemeResourceId(mThemeName));
EdgeToEdge.enable(this, SystemBarStyle.dark(Color.TRANSPARENT)); EdgeToEdge.enable(this, SystemBarStyle.dark(Color.TRANSPARENT));
RtlUtils.manageRtl(this); RtlUtils.manageRtl(this);
if (!MwmApplication.from(this).getOrganicMaps().arePlatformAndCoreInitialized()) if (!MwmApplication.from(this).getOrganicMaps().arePlatformAndCoreInitialized())
@@ -113,18 +94,6 @@ public abstract class BaseMwmFragmentActivity extends AppCompatActivity
mSafeCreated = false; 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 @Override
public boolean onOptionsItemSelected(MenuItem item) public boolean onOptionsItemSelected(MenuItem item)
{ {

View File

@@ -6,13 +6,11 @@ import android.os.Bundle;
import androidx.annotation.CallSuper; import androidx.annotation.CallSuper;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.annotation.StyleRes;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import app.organicmaps.R; import app.organicmaps.R;
import app.organicmaps.base.BaseToolbarActivity; import app.organicmaps.base.BaseToolbarActivity;
import app.organicmaps.sdk.bookmarks.data.BookmarkCategory; import app.organicmaps.sdk.bookmarks.data.BookmarkCategory;
import app.organicmaps.sdk.bookmarks.data.BookmarkManager; import app.organicmaps.sdk.bookmarks.data.BookmarkManager;
import app.organicmaps.util.ThemeUtils;
public class BookmarkCategoriesActivity extends BaseToolbarActivity public class BookmarkCategoriesActivity extends BaseToolbarActivity
{ {
@@ -38,13 +36,6 @@ public class BookmarkCategoriesActivity extends BaseToolbarActivity
super.onPause(); super.onPause();
} }
@Override
@StyleRes
public int getThemeResourceId(@NonNull String theme)
{
return ThemeUtils.getWindowBgThemeResourceId(theme);
}
@Override @Override
protected Class<? extends Fragment> getFragmentClass() protected Class<? extends Fragment> getFragmentClass()
{ {

View File

@@ -54,7 +54,6 @@ public class BookmarkCategorySettingsFragment extends BaseMwmToolbarFragment
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState)
{ {
View root = inflater.inflate(R.layout.fragment_bookmark_category_settings, container, false); View root = inflater.inflate(R.layout.fragment_bookmark_category_settings, container, false);
setHasOptionsMenu(true);
initViews(root); initViews(root);
return root; return root;
} }
@@ -85,7 +84,7 @@ public class BookmarkCategorySettingsFragment extends BaseMwmToolbarFragment
}); });
mEditDescView = root.findViewById(R.id.edit_description); mEditDescView = root.findViewById(R.id.edit_description);
mEditDescView.setText(mCategory.getDescription()); mEditDescView.setText(mCategory.getDescription());
mSaveView = root.findViewById(R.id.done); mSaveView = root.findViewById(R.id.save);
mSaveView.setOnClickListener(v -> onEditDoneClicked()); mSaveView.setOnClickListener(v -> onEditDoneClicked());
} }

View File

@@ -5,13 +5,11 @@ import android.os.Bundle;
import androidx.activity.result.ActivityResultLauncher; import androidx.activity.result.ActivityResultLauncher;
import androidx.annotation.CallSuper; import androidx.annotation.CallSuper;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.StyleRes;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import app.organicmaps.R; import app.organicmaps.R;
import app.organicmaps.base.BaseToolbarActivity; import app.organicmaps.base.BaseToolbarActivity;
import app.organicmaps.sdk.bookmarks.data.BookmarkCategory; import app.organicmaps.sdk.bookmarks.data.BookmarkCategory;
import app.organicmaps.sdk.bookmarks.data.BookmarkManager; import app.organicmaps.sdk.bookmarks.data.BookmarkManager;
import app.organicmaps.util.ThemeUtils;
public class BookmarkListActivity extends BaseToolbarActivity public class BookmarkListActivity extends BaseToolbarActivity
{ {
@@ -37,13 +35,6 @@ public class BookmarkListActivity extends BaseToolbarActivity
super.onPause(); super.onPause();
} }
@Override
@StyleRes
public int getThemeResourceId(@NonNull String theme)
{
return ThemeUtils.getCardBgThemeResourceId(theme);
}
@Override @Override
protected Class<? extends Fragment> getFragmentClass() protected Class<? extends Fragment> getFragmentClass()
{ {

View File

@@ -12,9 +12,12 @@ import androidx.lifecycle.DefaultLifecycleObserver;
import androidx.lifecycle.LifecycleOwner; import androidx.lifecycle.LifecycleOwner;
import app.organicmaps.MwmApplication; import app.organicmaps.MwmApplication;
import app.organicmaps.R; 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.ErrorScreen;
import app.organicmaps.car.screens.MapPlaceholderScreen; import app.organicmaps.car.screens.MapPlaceholderScreen;
import app.organicmaps.car.screens.MapScreen; import app.organicmaps.car.screens.MapScreen;
import app.organicmaps.car.screens.NavigationScreen;
import app.organicmaps.car.screens.PlaceScreen; import app.organicmaps.car.screens.PlaceScreen;
import app.organicmaps.car.screens.base.BaseMapScreen; import app.organicmaps.car.screens.base.BaseMapScreen;
import app.organicmaps.car.screens.download.DownloadMapsScreen; import app.organicmaps.car.screens.download.DownloadMapsScreen;
@@ -49,8 +52,9 @@ public final class CarAppSession extends Session implements DefaultLifecycleObse
@Nullable @Nullable
private final SessionInfo mSessionInfo; private final SessionInfo mSessionInfo;
@SuppressWarnings("NotNullFieldNotInitialized")
@NonNull @NonNull
private final SurfaceRenderer mSurfaceRenderer; private Renderer mSurfaceRenderer;
@NonNull @NonNull
private final ScreenManager mScreenManager; private final ScreenManager mScreenManager;
@SuppressWarnings("NotNullFieldNotInitialized") @SuppressWarnings("NotNullFieldNotInitialized")
@@ -67,7 +71,6 @@ public final class CarAppSession extends Session implements DefaultLifecycleObse
{ {
getLifecycle().addObserver(this); getLifecycle().addObserver(this);
mSessionInfo = sessionInfo; mSessionInfo = sessionInfo;
mSurfaceRenderer = new SurfaceRenderer(getCarContext(), getLifecycle());
mScreenManager = getCarContext().getCarService(ScreenManager.class); mScreenManager = getCarContext().getCarService(ScreenManager.class);
mCurrentCountryChangedListener = new CurrentCountryChangedListener(); mCurrentCountryChangedListener = new CurrentCountryChangedListener();
} }
@@ -114,6 +117,8 @@ public final class CarAppSession extends Session implements DefaultLifecycleObse
mSensorsManager = new CarSensorsManager(getCarContext()); mSensorsManager = new CarSensorsManager(getCarContext());
mDisplayManager = MwmApplication.from(getCarContext()).getDisplayManager(); mDisplayManager = MwmApplication.from(getCarContext()).getDisplayManager();
mDisplayManager.addListener(DisplayType.Car, this); mDisplayManager.addListener(DisplayType.Car, this);
mSurfaceRenderer = RendererFactory.create(getCarContext(), mDisplayManager,
MwmApplication.from(getCarContext()).getLocationHelper(), this);
init(); init();
} }
@@ -281,7 +286,19 @@ public final class CarAppSession extends Session implements DefaultLifecycleObse
private void restoreRoute() private void restoreRoute()
{ {
final RoutingController routingController = RoutingController.get(); 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) final PlaceScreen placeScreen = new PlaceScreen.Builder(getCarContext(), mSurfaceRenderer)
.setMapObject(routingController.getEndPoint()) .setMapObject(routingController.getEndPoint())
@@ -290,4 +307,14 @@ public final class CarAppSession extends Session implements DefaultLifecycleObse
mScreenManager.push(placeScreen); mScreenManager.push(placeScreen);
} }
} }
private boolean hasNavigationScreenInStack()
{
for (final Screen screen : mScreenManager.getScreenStack())
{
if (NavigationScreen.MARKER.equals(screen.getMarker()))
return true;
}
return false;
}
} }

View File

@@ -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();
}
}

View File

@@ -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();
}
}

View File

@@ -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);
}
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -15,30 +15,29 @@ import androidx.car.app.model.Template;
import androidx.car.app.navigation.model.MapWithContentTemplate; import androidx.car.app.navigation.model.MapWithContentTemplate;
import androidx.core.graphics.drawable.IconCompat; import androidx.core.graphics.drawable.IconCompat;
import app.organicmaps.R; 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.base.BaseMapScreen;
import app.organicmaps.car.screens.search.SearchOnMapScreen; import app.organicmaps.car.screens.search.SearchOnMapScreen;
import app.organicmaps.car.util.ThemeUtils;
import app.organicmaps.car.util.UiHelpers; import app.organicmaps.car.util.UiHelpers;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
public class CategoriesScreen extends BaseMapScreen 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( private static final List<CategoryData> CATEGORIES =
new CategoryData(R.string.category_fuel, R.drawable.ic_category_fuel, R.drawable.ic_category_fuel_night), Arrays.asList(new CategoryData(R.string.category_fuel, R.drawable.ic_category_fuel),
new CategoryData(R.string.category_parking, R.drawable.ic_category_parking, R.drawable.ic_category_parking_night), new CategoryData(R.string.category_parking, R.drawable.ic_category_parking),
new CategoryData(R.string.category_eat, R.drawable.ic_category_eat, R.drawable.ic_category_eat_night), new CategoryData(R.string.category_eat, R.drawable.ic_category_eat),
new CategoryData(R.string.category_food, R.drawable.ic_category_food, R.drawable.ic_category_food_night), new CategoryData(R.string.category_food, R.drawable.ic_category_food),
new CategoryData(R.string.category_hotel, R.drawable.ic_category_hotel, R.drawable.ic_category_hotel_night), new CategoryData(R.string.category_hotel, R.drawable.ic_category_hotel),
new CategoryData(R.string.category_toilet, R.drawable.ic_category_toilet, R.drawable.ic_category_toilet_night), new CategoryData(R.string.category_toilet, R.drawable.ic_category_toilet),
new CategoryData(R.string.category_rv, R.drawable.ic_category_rv, R.drawable.ic_category_rv_night)); new CategoryData(R.string.category_rv, R.drawable.ic_category_rv));
private final int MAX_CATEGORIES_SIZE; 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); super(carContext, surfaceRenderer);
final ConstraintManager constraintManager = getCarContext().getCarService(ConstraintManager.class); final ConstraintManager constraintManager = getCarContext().getCarService(ConstraintManager.class);
@@ -47,7 +46,7 @@ public class CategoriesScreen extends BaseMapScreen
@NonNull @NonNull
@Override @Override
public Template onGetTemplate() protected Template onGetTemplateImpl()
{ {
final MapWithContentTemplate.Builder builder = new MapWithContentTemplate.Builder(); final MapWithContentTemplate.Builder builder = new MapWithContentTemplate.Builder();
builder.setMapController(UiHelpers.createMapController(getCarContext(), getSurfaceRenderer())); builder.setMapController(UiHelpers.createMapController(getCarContext(), getSurfaceRenderer()));
@@ -67,7 +66,6 @@ public class CategoriesScreen extends BaseMapScreen
@NonNull @NonNull
private GridTemplate createCategoriesListTemplate() private GridTemplate createCategoriesListTemplate()
{ {
final boolean isNightMode = ThemeUtils.isNightMode(getCarContext());
final ItemList.Builder builder = new ItemList.Builder(); final ItemList.Builder builder = new ItemList.Builder();
final int categoriesSize = Math.min(CATEGORIES.size(), MAX_CATEGORIES_SIZE); final int categoriesSize = Math.min(CATEGORIES.size(), MAX_CATEGORIES_SIZE);
for (int i = 0; i < categoriesSize; ++i) for (int i = 0; i < categoriesSize; ++i)
@@ -75,7 +73,7 @@ public class CategoriesScreen extends BaseMapScreen
final GridItem.Builder itemBuilder = new GridItem.Builder(); final GridItem.Builder itemBuilder = new GridItem.Builder();
final String title = getCarContext().getString(CATEGORIES.get(i).nameResId); final String title = getCarContext().getString(CATEGORIES.get(i).nameResId);
@DrawableRes @DrawableRes
final int iconResId = isNightMode ? CATEGORIES.get(i).iconNightResId : CATEGORIES.get(i).iconResId; final int iconResId = CATEGORIES.get(i).iconResId;
itemBuilder.setTitle(title); itemBuilder.setTitle(title);
itemBuilder.setImage(new CarIcon.Builder(IconCompat.createWithResource(getCarContext(), iconResId)).build()); itemBuilder.setImage(new CarIcon.Builder(IconCompat.createWithResource(getCarContext(), iconResId)).build());

View File

@@ -43,7 +43,7 @@ public class ErrorScreen extends BaseScreen implements UserActionRequired
@NonNull @NonNull
@Override @Override
public Template onGetTemplate() protected Template onGetTemplateImpl()
{ {
final MessageTemplate.Builder builder = new MessageTemplate.Builder(getCarContext().getString(mErrorMessage)); final MessageTemplate.Builder builder = new MessageTemplate.Builder(getCarContext().getString(mErrorMessage));

View File

@@ -9,20 +9,20 @@ import androidx.car.app.model.Template;
import androidx.car.app.navigation.model.NavigationTemplate; import androidx.car.app.navigation.model.NavigationTemplate;
import androidx.core.graphics.drawable.IconCompat; import androidx.core.graphics.drawable.IconCompat;
import app.organicmaps.R; 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.base.BaseMapScreen;
import app.organicmaps.car.util.UiHelpers; import app.organicmaps.car.util.UiHelpers;
public class FreeDriveScreen extends BaseMapScreen public class FreeDriveScreen extends BaseMapScreen
{ {
public FreeDriveScreen(@NonNull CarContext carContext, @NonNull SurfaceRenderer surfaceRenderer) public FreeDriveScreen(@NonNull CarContext carContext, @NonNull Renderer surfaceRenderer)
{ {
super(carContext, surfaceRenderer); super(carContext, surfaceRenderer);
} }
@NonNull @NonNull
@Override @Override
public Template onGetTemplate() protected Template onGetTemplateImpl()
{ {
final NavigationTemplate.Builder builder = new NavigationTemplate.Builder(); final NavigationTemplate.Builder builder = new NavigationTemplate.Builder();
builder.setMapActionStrip(UiHelpers.createMapActionStrip(getCarContext(), getSurfaceRenderer())); builder.setMapActionStrip(UiHelpers.createMapActionStrip(getCarContext(), getSurfaceRenderer()));

View File

@@ -22,7 +22,7 @@ public class MapPlaceholderScreen extends BaseScreen
@NonNull @NonNull
@Override @Override
public Template onGetTemplate() protected Template onGetTemplateImpl()
{ {
final MessageTemplate.Builder builder = final MessageTemplate.Builder builder =
new MessageTemplate.Builder(getCarContext().getString(R.string.car_used_on_the_phone_screen)); new MessageTemplate.Builder(getCarContext().getString(R.string.car_used_on_the_phone_screen));

View File

@@ -14,7 +14,7 @@ import androidx.car.app.model.Template;
import androidx.car.app.navigation.model.MapWithContentTemplate; import androidx.car.app.navigation.model.MapWithContentTemplate;
import androidx.core.graphics.drawable.IconCompat; import androidx.core.graphics.drawable.IconCompat;
import app.organicmaps.R; 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.base.BaseMapScreen;
import app.organicmaps.car.screens.bookmarks.BookmarkCategoriesScreen; import app.organicmaps.car.screens.bookmarks.BookmarkCategoriesScreen;
import app.organicmaps.car.screens.search.SearchScreen; import app.organicmaps.car.screens.search.SearchScreen;
@@ -24,14 +24,14 @@ import app.organicmaps.car.util.UiHelpers;
public class MapScreen extends BaseMapScreen public class MapScreen extends BaseMapScreen
{ {
public MapScreen(@NonNull CarContext carContext, @NonNull SurfaceRenderer surfaceRenderer) public MapScreen(@NonNull CarContext carContext, @NonNull Renderer surfaceRenderer)
{ {
super(carContext, surfaceRenderer); super(carContext, surfaceRenderer);
} }
@NonNull @NonNull
@Override @Override
public Template onGetTemplate() protected Template onGetTemplateImpl()
{ {
SuggestionsHelpers.updateSuggestions(getCarContext()); SuggestionsHelpers.updateSuggestions(getCarContext());

View File

@@ -20,7 +20,7 @@ import androidx.lifecycle.LifecycleOwner;
import app.organicmaps.MwmApplication; import app.organicmaps.MwmApplication;
import app.organicmaps.R; import app.organicmaps.R;
import app.organicmaps.car.CarAppService; 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.base.BaseMapScreen;
import app.organicmaps.car.screens.settings.DrivingOptionsScreen; import app.organicmaps.car.screens.settings.DrivingOptionsScreen;
import app.organicmaps.car.util.Colors; import app.organicmaps.car.util.Colors;
@@ -70,7 +70,7 @@ public class NavigationScreen extends BaseMapScreen implements RoutingController
@NonNull @NonNull
@Override @Override
public Template onGetTemplate() protected Template onGetTemplateImpl()
{ {
final NavigationTemplate.Builder builder = new NavigationTemplate.Builder(); final NavigationTemplate.Builder builder = new NavigationTemplate.Builder();
builder.setBackgroundColor(Colors.NAVIGATION_TEMPLATE_BACKGROUND); builder.setBackgroundColor(Colors.NAVIGATION_TEMPLATE_BACKGROUND);
@@ -104,7 +104,11 @@ public class NavigationScreen extends BaseMapScreen implements RoutingController
public void onAutoDriveEnabled() public void onAutoDriveEnabled()
{ {
Logger.i(TAG); 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) if (points == null)
{ {
Logger.e(TAG, "Navigation has not started yet"); Logger.e(TAG, "Navigation has not started yet");
@@ -121,6 +125,8 @@ public class NavigationScreen extends BaseMapScreen implements RoutingController
if (!mNavigationCancelled) if (!mNavigationCancelled)
CarToast.makeText(getCarContext(), getCarContext().getString(R.string.trip_finished), CarToast.LENGTH_LONG) CarToast.makeText(getCarContext(), getCarContext().getString(R.string.trip_finished), CarToast.LENGTH_LONG)
.show(); .show();
NavigationService.stopService(getCarContext());
ThemeUtils.update(getCarContext());
finish(); finish();
getScreenManager().popToRoot(); getScreenManager().popToRoot();
} }
@@ -128,7 +134,7 @@ public class NavigationScreen extends BaseMapScreen implements RoutingController
@Override @Override
public void onCreate(@NonNull LifecycleOwner owner) public void onCreate(@NonNull LifecycleOwner owner)
{ {
Logger.d(TAG); super.onCreate(owner);
mRoutingController.attach(this); mRoutingController.attach(this);
ThemeUtils.update(getCarContext()); ThemeUtils.update(getCarContext());
mNavigationManager.setNavigationManagerCallback(this); mNavigationManager.setNavigationManagerCallback(this);
@@ -144,20 +150,19 @@ public class NavigationScreen extends BaseMapScreen implements RoutingController
@Override @Override
public void onResume(@NonNull LifecycleOwner owner) public void onResume(@NonNull LifecycleOwner owner)
{ {
Logger.d(TAG); super.onResume(owner);
mRoutingController.attach(this); mRoutingController.attach(this);
} }
@Override @Override
public void onDestroy(@NonNull LifecycleOwner owner) public void onDestroy(@NonNull LifecycleOwner owner)
{ {
NavigationService.stopService(getCarContext()); super.onDestroy(owner);
MwmApplication.from(getCarContext()).getLocationHelper().removeListener(mLocationListener); MwmApplication.from(getCarContext()).getLocationHelper().removeListener(mLocationListener);
if (mRoutingController.isNavigating()) if (mRoutingController.isNavigating())
mRoutingController.onSaveState(); mRoutingController.onSaveState();
mRoutingController.detach(); mRoutingController.detach();
ThemeUtils.update(getCarContext());
mNavigationManager.navigationEnded(); mNavigationManager.navigationEnded();
mNavigationManager.clearNavigationManagerCallback(); mNavigationManager.clearNavigationManagerCallback();
} }
@@ -257,9 +262,9 @@ public class NavigationScreen extends BaseMapScreen implements RoutingController
@NonNull @NonNull
private final CarContext mCarContext; private final CarContext mCarContext;
@NonNull @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; mCarContext = carContext;
mSurfaceRenderer = surfaceRenderer; mSurfaceRenderer = surfaceRenderer;

View File

@@ -26,7 +26,7 @@ import androidx.core.graphics.drawable.IconCompat;
import androidx.lifecycle.LifecycleOwner; import androidx.lifecycle.LifecycleOwner;
import app.organicmaps.MwmApplication; import app.organicmaps.MwmApplication;
import app.organicmaps.R; 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.base.BaseMapScreen;
import app.organicmaps.car.screens.download.DownloadMapsScreenBuilder; import app.organicmaps.car.screens.download.DownloadMapsScreenBuilder;
import app.organicmaps.car.screens.settings.DrivingOptionsScreen; 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 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 @Nullable
private MapObject mMapObject; private MapObject mMapObject;
@@ -68,7 +68,7 @@ public class PlaceScreen extends BaseMapScreen implements OnBackPressedCallback.
@NonNull @NonNull
@Override @Override
public Template onGetTemplate() protected Template onGetTemplateImpl()
{ {
final MapWithContentTemplate.Builder builder = new MapWithContentTemplate.Builder(); final MapWithContentTemplate.Builder builder = new MapWithContentTemplate.Builder();
builder.setMapController(UiHelpers.createMapController(getCarContext(), getSurfaceRenderer())); builder.setMapController(UiHelpers.createMapController(getCarContext(), getSurfaceRenderer()));
@@ -80,6 +80,7 @@ public class PlaceScreen extends BaseMapScreen implements OnBackPressedCallback.
@Override @Override
public void onCreate(@NonNull LifecycleOwner owner) public void onCreate(@NonNull LifecycleOwner owner)
{ {
super.onCreate(owner);
mRoutingController.restore(); mRoutingController.restore();
if (mRoutingController.isNavigating() && mRoutingController.getLastRouterType() == ROUTER) if (mRoutingController.isNavigating() && mRoutingController.getLastRouterType() == ROUTER)
{ {
@@ -112,12 +113,14 @@ public class PlaceScreen extends BaseMapScreen implements OnBackPressedCallback.
@Override @Override
public void onResume(@NonNull LifecycleOwner owner) public void onResume(@NonNull LifecycleOwner owner)
{ {
super.onResume(owner);
mRoutingController.attach(this); mRoutingController.attach(this);
} }
@Override @Override
public void onDestroy(@NonNull LifecycleOwner owner) public void onDestroy(@NonNull LifecycleOwner owner)
{ {
super.onDestroy(owner);
if (mRoutingController.isPlanning()) if (mRoutingController.isPlanning())
mRoutingController.onSaveState(); mRoutingController.onSaveState();
if (!mRoutingController.isNavigating()) if (!mRoutingController.isNavigating())
@@ -340,11 +343,11 @@ public class PlaceScreen extends BaseMapScreen implements OnBackPressedCallback.
@NonNull @NonNull
private final CarContext mCarContext; private final CarContext mCarContext;
@NonNull @NonNull
private final SurfaceRenderer mSurfaceRenderer; private final Renderer mSurfaceRenderer;
@Nullable @Nullable
private MapObject mMapObject; 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; mCarContext = carContext;
mSurfaceRenderer = surfaceRenderer; mSurfaceRenderer = surfaceRenderer;

View File

@@ -2,21 +2,21 @@ package app.organicmaps.car.screens.base;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.car.app.CarContext; import androidx.car.app.CarContext;
import app.organicmaps.car.SurfaceRenderer; import app.organicmaps.car.renderer.Renderer;
public abstract class BaseMapScreen extends BaseScreen public abstract class BaseMapScreen extends BaseScreen
{ {
@NonNull @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); super(carContext);
mSurfaceRenderer = surfaceRenderer; mSurfaceRenderer = surfaceRenderer;
} }
@NonNull @NonNull
protected SurfaceRenderer getSurfaceRenderer() protected Renderer getSurfaceRenderer()
{ {
return mSurfaceRenderer; return mSurfaceRenderer;
} }

View File

@@ -1,15 +1,71 @@
package app.organicmaps.car.screens.base; package app.organicmaps.car.screens.base;
import androidx.annotation.CallSuper;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.car.app.CarContext; import androidx.car.app.CarContext;
import androidx.car.app.Screen; import androidx.car.app.Screen;
import androidx.car.app.model.Template;
import androidx.lifecycle.DefaultLifecycleObserver; import androidx.lifecycle.DefaultLifecycleObserver;
import androidx.lifecycle.LifecycleOwner;
import app.organicmaps.sdk.util.log.Logger;
public abstract class BaseScreen extends Screen implements DefaultLifecycleObserver public abstract class BaseScreen extends Screen implements DefaultLifecycleObserver
{ {
@NonNull
private final String TAG;
public BaseScreen(@NonNull CarContext carContext) public BaseScreen(@NonNull CarContext carContext)
{ {
super(carContext); super(carContext);
TAG = getClass().getSimpleName();
getLifecycle().addObserver(this); 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);
}
} }

View File

@@ -11,7 +11,7 @@ import androidx.car.app.model.Row;
import androidx.car.app.model.Template; import androidx.car.app.model.Template;
import androidx.car.app.navigation.model.MapWithContentTemplate; import androidx.car.app.navigation.model.MapWithContentTemplate;
import app.organicmaps.R; 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.base.BaseMapScreen;
import app.organicmaps.car.util.UiHelpers; import app.organicmaps.car.util.UiHelpers;
import app.organicmaps.sdk.bookmarks.data.BookmarkCategory; import app.organicmaps.sdk.bookmarks.data.BookmarkCategory;
@@ -23,7 +23,7 @@ public class BookmarkCategoriesScreen extends BaseMapScreen
{ {
private final int MAX_CATEGORIES_SIZE; 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); super(carContext, surfaceRenderer);
final ConstraintManager constraintManager = getCarContext().getCarService(ConstraintManager.class); final ConstraintManager constraintManager = getCarContext().getCarService(ConstraintManager.class);
@@ -32,7 +32,7 @@ public class BookmarkCategoriesScreen extends BaseMapScreen
@NonNull @NonNull
@Override @Override
public Template onGetTemplate() protected Template onGetTemplateImpl()
{ {
final MapWithContentTemplate.Builder builder = new MapWithContentTemplate.Builder(); final MapWithContentTemplate.Builder builder = new MapWithContentTemplate.Builder();
builder.setMapController(UiHelpers.createMapController(getCarContext(), getSurfaceRenderer())); builder.setMapController(UiHelpers.createMapController(getCarContext(), getSurfaceRenderer()));

View File

@@ -13,7 +13,7 @@ import androidx.car.app.navigation.model.MapWithContentTemplate;
import androidx.core.graphics.drawable.IconCompat; import androidx.core.graphics.drawable.IconCompat;
import androidx.lifecycle.LifecycleOwner; import androidx.lifecycle.LifecycleOwner;
import app.organicmaps.R; 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.base.BaseMapScreen;
import app.organicmaps.car.util.UiHelpers; import app.organicmaps.car.util.UiHelpers;
import app.organicmaps.sdk.bookmarks.data.BookmarkCategory; import app.organicmaps.sdk.bookmarks.data.BookmarkCategory;
@@ -31,7 +31,7 @@ public class BookmarksScreen extends BaseMapScreen
private boolean mIsOnSortingScreen = false; private boolean mIsOnSortingScreen = false;
public BookmarksScreen(@NonNull CarContext carContext, @NonNull SurfaceRenderer surfaceRenderer, public BookmarksScreen(@NonNull CarContext carContext, @NonNull Renderer surfaceRenderer,
@NonNull BookmarkCategory bookmarkCategory) @NonNull BookmarkCategory bookmarkCategory)
{ {
super(carContext, surfaceRenderer); super(carContext, surfaceRenderer);
@@ -41,7 +41,7 @@ public class BookmarksScreen extends BaseMapScreen
@NonNull @NonNull
@Override @Override
public Template onGetTemplate() protected Template onGetTemplateImpl()
{ {
final MapWithContentTemplate.Builder builder = new MapWithContentTemplate.Builder(); final MapWithContentTemplate.Builder builder = new MapWithContentTemplate.Builder();
builder.setMapController(UiHelpers.createMapController(getCarContext(), getSurfaceRenderer())); builder.setMapController(UiHelpers.createMapController(getCarContext(), getSurfaceRenderer()));
@@ -52,6 +52,7 @@ public class BookmarksScreen extends BaseMapScreen
@Override @Override
public void onStop(@NonNull LifecycleOwner owner) public void onStop(@NonNull LifecycleOwner owner)
{ {
super.onStop(owner);
if (!mIsOnSortingScreen) if (!mIsOnSortingScreen)
mBookmarksLoader.cancel(); mBookmarksLoader.cancel();
} }

View File

@@ -16,7 +16,7 @@ import androidx.core.graphics.drawable.IconCompat;
import androidx.lifecycle.LifecycleOwner; import androidx.lifecycle.LifecycleOwner;
import app.organicmaps.MwmApplication; import app.organicmaps.MwmApplication;
import app.organicmaps.R; 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.base.BaseMapScreen;
import app.organicmaps.car.util.UiHelpers; import app.organicmaps.car.util.UiHelpers;
import app.organicmaps.sdk.bookmarks.data.BookmarkCategory; import app.organicmaps.sdk.bookmarks.data.BookmarkCategory;
@@ -38,7 +38,7 @@ class SortingScreen extends BaseMapScreen
private @BookmarkManager.SortingType int mNewSortingType; private @BookmarkManager.SortingType int mNewSortingType;
public SortingScreen(@NonNull CarContext carContext, @NonNull SurfaceRenderer surfaceRenderer, public SortingScreen(@NonNull CarContext carContext, @NonNull Renderer surfaceRenderer,
@NonNull BookmarkCategory bookmarkCategory) @NonNull BookmarkCategory bookmarkCategory)
{ {
super(carContext, surfaceRenderer); super(carContext, surfaceRenderer);
@@ -53,7 +53,7 @@ class SortingScreen extends BaseMapScreen
@NonNull @NonNull
@Override @Override
public Template onGetTemplate() protected Template onGetTemplateImpl()
{ {
final MapWithContentTemplate.Builder builder = new MapWithContentTemplate.Builder(); final MapWithContentTemplate.Builder builder = new MapWithContentTemplate.Builder();
builder.setMapController(UiHelpers.createMapController(getCarContext(), getSurfaceRenderer())); builder.setMapController(UiHelpers.createMapController(getCarContext(), getSurfaceRenderer()));

View File

@@ -23,6 +23,7 @@ class DownloadMapsForFirstLaunchScreen extends DownloadMapsScreen
@Override @Override
public void onResume(@NonNull LifecycleOwner owner) 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 // Attempting to streamline initial download by including the current country in the list of missing maps for
// simultaneous retrieval. // simultaneous retrieval.
final Location location = MwmApplication.from(getCarContext()).getLocationHelper().getSavedLocation(); final Location location = MwmApplication.from(getCarContext()).getLocationHelper().getSavedLocation();

View File

@@ -34,7 +34,7 @@ public abstract class DownloadMapsScreen extends BaseScreen
@NonNull @NonNull
@Override @Override
public final Template onGetTemplate() protected final Template onGetTemplateImpl()
{ {
final MessageTemplate.Builder builder = new MessageTemplate.Builder(getText(getMapsSize(mMissingMaps))); final MessageTemplate.Builder builder = new MessageTemplate.Builder(getText(getMapsSize(mMissingMaps)));
final Header.Builder headerBuilder = new Header.Builder(); final Header.Builder headerBuilder = new Header.Builder();

View File

@@ -102,6 +102,7 @@ class DownloaderScreen extends BaseScreen
@Override @Override
public void onResume(@NonNull LifecycleOwner owner) public void onResume(@NonNull LifecycleOwner owner)
{ {
super.onResume(owner);
if (mSubscriptionSlot == 0) if (mSubscriptionSlot == 0)
mSubscriptionSlot = MapManager.nativeSubscribe(mStorageCallback); mSubscriptionSlot = MapManager.nativeSubscribe(mStorageCallback);
for (final var item : mMissingMaps.entrySet()) for (final var item : mMissingMaps.entrySet())
@@ -114,6 +115,7 @@ class DownloaderScreen extends BaseScreen
@Override @Override
public void onPause(@NonNull LifecycleOwner owner) public void onPause(@NonNull LifecycleOwner owner)
{ {
super.onPause(owner);
if (!mIsDownloadFailed) if (!mIsDownloadFailed)
cancelMapsDownloading(); cancelMapsDownloading();
if (mSubscriptionSlot != 0) if (mSubscriptionSlot != 0)
@@ -125,7 +127,7 @@ class DownloaderScreen extends BaseScreen
@NonNull @NonNull
@Override @Override
public Template onGetTemplate() protected Template onGetTemplateImpl()
{ {
final MessageTemplate.Builder builder = new MessageTemplate.Builder(getText()); final MessageTemplate.Builder builder = new MessageTemplate.Builder(getText());
builder.setLoading(true); builder.setLoading(true);

View File

@@ -37,7 +37,7 @@ public class RequestPermissionsScreenWithApi extends BaseScreen implements UserA
@NonNull @NonNull
@Override @Override
public Template onGetTemplate() protected Template onGetTemplateImpl()
{ {
final MessageTemplate.Builder builder = final MessageTemplate.Builder builder =
new MessageTemplate.Builder(getCarContext().getString(R.string.aa_request_permission_activity_text)); new MessageTemplate.Builder(getCarContext().getString(R.string.aa_request_permission_activity_text));
@@ -63,6 +63,7 @@ public class RequestPermissionsScreenWithApi extends BaseScreen implements UserA
@Override @Override
public void onResume(@NonNull LifecycleOwner owner) 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 // Let's review the permissions once more, as we might enter this function following an ErrorScreen situation
// where the user manually enabled location permissions. // where the user manually enabled location permissions.
if (LocationUtils.checkFineLocationPermission(getCarContext())) if (LocationUtils.checkFineLocationPermission(getCarContext()))

View File

@@ -47,7 +47,7 @@ public class RequestPermissionsScreenWithNotification extends BaseScreen impleme
@NonNull @NonNull
@Override @Override
public Template onGetTemplate() protected Template onGetTemplateImpl()
{ {
final MessageTemplate.Builder builder = final MessageTemplate.Builder builder =
new MessageTemplate.Builder(getCarContext().getString(R.string.aa_location_permissions_request)); 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) @RequiresPermission(value = Manifest.permission.POST_NOTIFICATIONS)
public void onStart(@NonNull LifecycleOwner owner) public void onStart(@NonNull LifecycleOwner owner)
{ {
super.onStart(owner);
mIsPermissionCheckEnabled = true; mIsPermissionCheckEnabled = true;
mBackgroundExecutor.execute(this::checkPermissions); mBackgroundExecutor.execute(this::checkPermissions);
sendPermissionsRequestNotification(); sendPermissionsRequestNotification();
@@ -74,12 +75,14 @@ public class RequestPermissionsScreenWithNotification extends BaseScreen impleme
@Override @Override
public void onStop(@NonNull LifecycleOwner owner) public void onStop(@NonNull LifecycleOwner owner)
{ {
super.onStop(owner);
mIsPermissionCheckEnabled = false; mIsPermissionCheckEnabled = false;
} }
@Override @Override
public void onDestroy(@NonNull LifecycleOwner owner) public void onDestroy(@NonNull LifecycleOwner owner)
{ {
super.onDestroy(owner);
NotificationManagerCompat.from(getCarContext()).cancel(NOTIFICATION_ID); NotificationManagerCompat.from(getCarContext()).cancel(NOTIFICATION_ID);
} }

View File

@@ -17,7 +17,7 @@ import androidx.core.graphics.drawable.IconCompat;
import androidx.lifecycle.LifecycleOwner; import androidx.lifecycle.LifecycleOwner;
import app.organicmaps.MwmApplication; import app.organicmaps.MwmApplication;
import app.organicmaps.R; 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.base.BaseMapScreen;
import app.organicmaps.car.util.UiHelpers; import app.organicmaps.car.util.UiHelpers;
import app.organicmaps.sdk.bookmarks.data.MapObject; import app.organicmaps.sdk.bookmarks.data.MapObject;
@@ -54,7 +54,7 @@ public class SearchOnMapScreen extends BaseMapScreen implements SearchListener
@NonNull @NonNull
@Override @Override
public Template onGetTemplate() protected Template onGetTemplateImpl()
{ {
final MapWithContentTemplate.Builder builder = new MapWithContentTemplate.Builder(); final MapWithContentTemplate.Builder builder = new MapWithContentTemplate.Builder();
builder.setMapController(UiHelpers.createMapController(getCarContext(), getSurfaceRenderer())); builder.setMapController(UiHelpers.createMapController(getCarContext(), getSurfaceRenderer()));
@@ -136,12 +136,14 @@ public class SearchOnMapScreen extends BaseMapScreen implements SearchListener
@Override @Override
public void onStart(@NonNull LifecycleOwner owner) public void onStart(@NonNull LifecycleOwner owner)
{ {
super.onStart(owner);
SearchEngine.INSTANCE.addListener(this); SearchEngine.INSTANCE.addListener(this);
} }
@Override @Override
public void onResume(@NonNull LifecycleOwner owner) public void onResume(@NonNull LifecycleOwner owner)
{ {
super.onResume(owner);
SearchEngine.INSTANCE.cancel(); SearchEngine.INSTANCE.cancel();
final MapObject location = MwmApplication.from(getCarContext()).getLocationHelper().getMyPosition(); final MapObject location = MwmApplication.from(getCarContext()).getLocationHelper().getMyPosition();
@@ -156,6 +158,7 @@ public class SearchOnMapScreen extends BaseMapScreen implements SearchListener
@Override @Override
public void onStop(@NonNull LifecycleOwner owner) public void onStop(@NonNull LifecycleOwner owner)
{ {
super.onStop(owner);
SearchEngine.INSTANCE.removeListener(this); SearchEngine.INSTANCE.removeListener(this);
SearchEngine.INSTANCE.cancel(); SearchEngine.INSTANCE.cancel();
} }
@@ -177,7 +180,7 @@ public class SearchOnMapScreen extends BaseMapScreen implements SearchListener
@NonNull @NonNull
private final CarContext mCarContext; private final CarContext mCarContext;
@NonNull @NonNull
private final SurfaceRenderer mSurfaceRenderer; private final Renderer mSurfaceRenderer;
@NonNull @NonNull
private String mQuery = ""; private String mQuery = "";
@@ -185,7 +188,7 @@ public class SearchOnMapScreen extends BaseMapScreen implements SearchListener
private String mLocale; private String mLocale;
private boolean mIsCategory; private boolean mIsCategory;
public Builder(@NonNull CarContext carContext, @NonNull SurfaceRenderer surfaceRenderer) public Builder(@NonNull CarContext carContext, @NonNull Renderer surfaceRenderer)
{ {
mCarContext = carContext; mCarContext = carContext;
mSurfaceRenderer = surfaceRenderer; mSurfaceRenderer = surfaceRenderer;

View File

@@ -16,7 +16,7 @@ import androidx.core.graphics.drawable.IconCompat;
import androidx.lifecycle.LifecycleOwner; import androidx.lifecycle.LifecycleOwner;
import app.organicmaps.MwmApplication; import app.organicmaps.MwmApplication;
import app.organicmaps.R; 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.base.BaseMapScreen;
import app.organicmaps.sdk.bookmarks.data.MapObject; import app.organicmaps.sdk.bookmarks.data.MapObject;
import app.organicmaps.sdk.search.SearchEngine; import app.organicmaps.sdk.search.SearchEngine;
@@ -50,7 +50,7 @@ public class SearchScreen extends BaseMapScreen implements SearchTemplate.Search
@NonNull @NonNull
@Override @Override
public Template onGetTemplate() protected Template onGetTemplateImpl()
{ {
final SearchTemplate.Builder builder = new SearchTemplate.Builder(this); final SearchTemplate.Builder builder = new SearchTemplate.Builder(this);
builder.setHeaderAction(Action.BACK); builder.setHeaderAction(Action.BACK);
@@ -106,12 +106,14 @@ public class SearchScreen extends BaseMapScreen implements SearchTemplate.Search
@Override @Override
public void onStart(@NonNull LifecycleOwner owner) public void onStart(@NonNull LifecycleOwner owner)
{ {
super.onStart(owner);
SearchEngine.INSTANCE.addListener(this); SearchEngine.INSTANCE.addListener(this);
} }
@Override @Override
public void onStop(@NonNull LifecycleOwner owner) public void onStop(@NonNull LifecycleOwner owner)
{ {
super.onStop(owner);
SearchEngine.INSTANCE.removeListener(this); SearchEngine.INSTANCE.removeListener(this);
SearchEngine.INSTANCE.cancel(); SearchEngine.INSTANCE.cancel();
} }
@@ -209,14 +211,14 @@ public class SearchScreen extends BaseMapScreen implements SearchTemplate.Search
@NonNull @NonNull
private final CarContext mCarContext; private final CarContext mCarContext;
@NonNull @NonNull
private final SurfaceRenderer mSurfaceRenderer; private final Renderer mSurfaceRenderer;
@NonNull @NonNull
private String mQuery = ""; private String mQuery = "";
@NonNull @NonNull
private String mLocale; private String mLocale;
public Builder(@NonNull CarContext carContext, @NonNull SurfaceRenderer surfaceRenderer) public Builder(@NonNull CarContext carContext, @NonNull Renderer surfaceRenderer)
{ {
mCarContext = carContext; mCarContext = carContext;
mSurfaceRenderer = surfaceRenderer; mSurfaceRenderer = surfaceRenderer;

View File

@@ -13,7 +13,7 @@ import androidx.car.app.model.Template;
import androidx.car.app.navigation.model.MapWithContentTemplate; import androidx.car.app.navigation.model.MapWithContentTemplate;
import androidx.lifecycle.LifecycleOwner; import androidx.lifecycle.LifecycleOwner;
import app.organicmaps.R; 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.base.BaseMapScreen;
import app.organicmaps.car.util.Toggle; import app.organicmaps.car.util.Toggle;
import app.organicmaps.car.util.UiHelpers; 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), private final DrivingOption[] mDrivingOptions = {new DrivingOption(RoadType.Toll, R.string.avoid_tolls),
new DrivingOption(RoadType.Dirty, R.string.avoid_unpaved), new DrivingOption(RoadType.Dirty, R.string.avoid_unpaved),
new DrivingOption(RoadType.Ferry, R.string.avoid_ferry), 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 @NonNull
private final Map<RoadType, Boolean> mInitialDrivingOptionsState = new HashMap<>(); 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); super(carContext, surfaceRenderer);
@@ -45,7 +46,7 @@ public class DrivingOptionsScreen extends BaseMapScreen
@NonNull @NonNull
@Override @Override
public Template onGetTemplate() protected Template onGetTemplateImpl()
{ {
final MapWithContentTemplate.Builder builder = new MapWithContentTemplate.Builder(); final MapWithContentTemplate.Builder builder = new MapWithContentTemplate.Builder();
builder.setMapController(UiHelpers.createMapController(getCarContext(), getSurfaceRenderer())); builder.setMapController(UiHelpers.createMapController(getCarContext(), getSurfaceRenderer()));
@@ -56,6 +57,7 @@ public class DrivingOptionsScreen extends BaseMapScreen
@Override @Override
public void onStop(@NonNull LifecycleOwner owner) public void onStop(@NonNull LifecycleOwner owner)
{ {
super.onStop(owner);
for (final DrivingOption drivingOption : mDrivingOptions) for (final DrivingOption drivingOption : mDrivingOptions)
{ {
if (Boolean.TRUE.equals(mInitialDrivingOptionsState.get(drivingOption.roadType)) if (Boolean.TRUE.equals(mInitialDrivingOptionsState.get(drivingOption.roadType))

View File

@@ -12,7 +12,7 @@ import androidx.car.app.model.Template;
import androidx.car.app.navigation.model.MapWithContentTemplate; import androidx.car.app.navigation.model.MapWithContentTemplate;
import app.organicmaps.BuildConfig; import app.organicmaps.BuildConfig;
import app.organicmaps.R; 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.base.BaseMapScreen;
import app.organicmaps.car.util.UiHelpers; import app.organicmaps.car.util.UiHelpers;
import app.organicmaps.sdk.Framework; import app.organicmaps.sdk.Framework;
@@ -20,14 +20,14 @@ import app.organicmaps.sdk.util.DateUtils;
public class HelpScreen extends BaseMapScreen public class HelpScreen extends BaseMapScreen
{ {
public HelpScreen(@NonNull CarContext carContext, @NonNull SurfaceRenderer surfaceRenderer) public HelpScreen(@NonNull CarContext carContext, @NonNull Renderer surfaceRenderer)
{ {
super(carContext, surfaceRenderer); super(carContext, surfaceRenderer);
} }
@NonNull @NonNull
@Override @Override
public Template onGetTemplate() protected Template onGetTemplateImpl()
{ {
final MapWithContentTemplate.Builder builder = new MapWithContentTemplate.Builder(); final MapWithContentTemplate.Builder builder = new MapWithContentTemplate.Builder();
builder.setMapController(UiHelpers.createMapController(getCarContext(), getSurfaceRenderer())); builder.setMapController(UiHelpers.createMapController(getCarContext(), getSurfaceRenderer()));

View File

@@ -13,7 +13,7 @@ import androidx.car.app.model.Row;
import androidx.car.app.model.Template; import androidx.car.app.model.Template;
import androidx.car.app.navigation.model.MapWithContentTemplate; import androidx.car.app.navigation.model.MapWithContentTemplate;
import app.organicmaps.R; 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.base.BaseMapScreen;
import app.organicmaps.car.util.ThemeUtils; import app.organicmaps.car.util.ThemeUtils;
import app.organicmaps.car.util.Toggle; import app.organicmaps.car.util.Toggle;
@@ -33,14 +33,14 @@ public class SettingsScreen extends BaseMapScreen
void set(boolean newValue); void set(boolean newValue);
} }
public SettingsScreen(@NonNull CarContext carContext, @NonNull SurfaceRenderer surfaceRenderer) public SettingsScreen(@NonNull CarContext carContext, @NonNull Renderer surfaceRenderer)
{ {
super(carContext, surfaceRenderer); super(carContext, surfaceRenderer);
} }
@NonNull @NonNull
@Override @Override
public Template onGetTemplate() protected Template onGetTemplateImpl()
{ {
final MapWithContentTemplate.Builder builder = new MapWithContentTemplate.Builder(); final MapWithContentTemplate.Builder builder = new MapWithContentTemplate.Builder();
builder.setMapController(UiHelpers.createMapController(getCarContext(), getSurfaceRenderer())); builder.setMapController(UiHelpers.createMapController(getCarContext(), getSurfaceRenderer()));

View File

@@ -12,7 +12,7 @@ import androidx.car.app.model.Template;
import androidx.car.app.navigation.model.MapWithContentTemplate; import androidx.car.app.navigation.model.MapWithContentTemplate;
import androidx.core.graphics.drawable.IconCompat; import androidx.core.graphics.drawable.IconCompat;
import app.organicmaps.R; 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.base.BaseMapScreen;
import app.organicmaps.car.util.ThemeUtils; import app.organicmaps.car.util.ThemeUtils;
import app.organicmaps.car.util.UiHelpers; import app.organicmaps.car.util.UiHelpers;
@@ -24,7 +24,7 @@ public class ThemeScreen extends BaseMapScreen
@NonNull @NonNull
private final CarIcon mRadioButtonSelectedIcon; private final CarIcon mRadioButtonSelectedIcon;
public ThemeScreen(@NonNull CarContext carContext, @NonNull SurfaceRenderer surfaceRenderer) public ThemeScreen(@NonNull CarContext carContext, @NonNull Renderer surfaceRenderer)
{ {
super(carContext, surfaceRenderer); super(carContext, surfaceRenderer);
mRadioButtonIcon = mRadioButtonIcon =
@@ -35,7 +35,7 @@ public class ThemeScreen extends BaseMapScreen
@NonNull @NonNull
@Override @Override
public Template onGetTemplate() protected Template onGetTemplateImpl()
{ {
final MapWithContentTemplate.Builder builder = new MapWithContentTemplate.Builder(); final MapWithContentTemplate.Builder builder = new MapWithContentTemplate.Builder();
builder.setMapController(UiHelpers.createMapController(getCarContext(), getSurfaceRenderer())); builder.setMapController(UiHelpers.createMapController(getCarContext(), getSurfaceRenderer()));

View File

@@ -12,7 +12,7 @@ import androidx.car.app.notification.CarPendingIntent;
import app.organicmaps.MwmApplication; import app.organicmaps.MwmApplication;
import app.organicmaps.api.Const; import app.organicmaps.api.Const;
import app.organicmaps.car.CarAppService; 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.NavigationScreen;
import app.organicmaps.car.screens.search.SearchScreen; import app.organicmaps.car.screens.search.SearchScreen;
import app.organicmaps.sdk.Framework; import app.organicmaps.sdk.Framework;
@@ -30,7 +30,7 @@ public final class IntentUtils
private static final int SEARCH_IN_VIEWPORT_ZOOM = 16; 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) @NonNull Intent intent)
{ {
final String action = intent.getAction(); 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) // https://developer.android.com/reference/androidx/car/app/CarContext#startCarApp(android.content.Intent)
private static void processNavigationIntent(@NonNull CarContext carContext, @NonNull SurfaceRenderer surfaceRenderer, private static void processNavigationIntent(@NonNull CarContext carContext,
@NonNull Intent intent) @NonNull Renderer surfaceRenderer, @NonNull Intent intent)
{ {
// TODO (AndrewShkrob): This logic will need to be revised when we introduce support for adding stops during // 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 // navigation or route planning. Skip navigation intents during navigation

View File

@@ -15,7 +15,7 @@ import androidx.car.app.navigation.model.MapController;
import androidx.core.graphics.drawable.IconCompat; import androidx.core.graphics.drawable.IconCompat;
import app.organicmaps.MwmApplication; import app.organicmaps.MwmApplication;
import app.organicmaps.R; 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.base.BaseMapScreen;
import app.organicmaps.car.screens.settings.SettingsScreen; import app.organicmaps.car.screens.settings.SettingsScreen;
import app.organicmaps.sdk.Map; import app.organicmaps.sdk.Map;
@@ -33,13 +33,14 @@ public final class UiHelpers
{ {
@NonNull @NonNull
public static ActionStrip createSettingsActionStrip(@NonNull BaseMapScreen mapScreen, public static ActionStrip createSettingsActionStrip(@NonNull BaseMapScreen mapScreen,
@NonNull SurfaceRenderer surfaceRenderer) @NonNull Renderer surfaceRenderer)
{ {
return new ActionStrip.Builder().addAction(createSettingsAction(mapScreen, surfaceRenderer)).build(); return new ActionStrip.Builder().addAction(createSettingsAction(mapScreen, surfaceRenderer)).build();
} }
@NonNull @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 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(); final CarIcon iconMinus = new CarIcon.Builder(IconCompat.createWithResource(context, R.drawable.ic_minus)).build();
@@ -58,27 +59,30 @@ public final class UiHelpers
} }
@NonNull @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(); return new MapController.Builder().setMapActionStrip(createMapActionStrip(context, surfaceRenderer)).build();
} }
@NonNull @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); return createSettingsAction(mapScreen, surfaceRenderer, null);
} }
@NonNull @NonNull
public static Action createSettingsActionForResult(@NonNull BaseMapScreen mapScreen, public static Action createSettingsActionForResult(@NonNull BaseMapScreen mapScreen,
@NonNull SurfaceRenderer surfaceRenderer, @NonNull Renderer surfaceRenderer,
@NonNull OnScreenResultListener onScreenResultListener) @NonNull OnScreenResultListener onScreenResultListener)
{ {
return createSettingsAction(mapScreen, surfaceRenderer, onScreenResultListener); return createSettingsAction(mapScreen, surfaceRenderer, onScreenResultListener);
} }
@NonNull @NonNull
private static Action createSettingsAction(@NonNull BaseMapScreen mapScreen, @NonNull SurfaceRenderer surfaceRenderer, private static Action createSettingsAction(@NonNull BaseMapScreen mapScreen,
@NonNull Renderer surfaceRenderer,
@Nullable OnScreenResultListener onScreenResultListener) @Nullable OnScreenResultListener onScreenResultListener)
{ {
final CarContext context = mapScreen.getCarContext(); final CarContext context = mapScreen.getCarContext();
@@ -120,7 +124,7 @@ public final class UiHelpers
final Row.Builder builder = new Row.Builder(); final Row.Builder builder = new Row.Builder();
builder.setImage( 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) if (isEmptyTT)
builder.setTitle(ohStr); builder.setTitle(ohStr);

View File

@@ -40,7 +40,6 @@ public class EditTextDialogFragment extends BaseMwmDialogFragment
private String mHint; private String mHint;
private TextInputEditText mEtInput; private TextInputEditText mEtInput;
private TextInputLayout mEtInputLayout; private TextInputLayout mEtInputLayout;
private Button mPositiveButton;
private Validator mInputValidator; private Validator mInputValidator;
private OnTextSaveListener mTextSaveListener; private OnTextSaveListener mTextSaveListener;
@@ -117,21 +116,20 @@ public class EditTextDialogFragment extends BaseMwmDialogFragment
AlertDialog editTextDialog = new MaterialAlertDialogBuilder(requireActivity(), R.style.MwmTheme_AlertDialog) AlertDialog editTextDialog = new MaterialAlertDialogBuilder(requireActivity(), R.style.MwmTheme_AlertDialog)
.setView(buildView()) .setView(buildView())
.setNegativeButton(negativeButtonText, null) .setNegativeButton(negativeButtonText, null)
.setPositiveButton(positiveButtonText, .setPositiveButton(positiveButtonText, null)
(dialog, which) -> {
final String result = mEtInput.getText().toString();
processInput(result);
dismiss();
})
.create(); .create();
// Wait till alert is shown to get mPositiveButton. // Set up onClick listener for mPositiveButton.
editTextDialog.setOnShowListener((dialog) -> { editTextDialog.setOnShowListener((dialog) -> {
mPositiveButton = editTextDialog.getButton(DialogInterface.BUTTON_POSITIVE); Button positiveButton = editTextDialog.getButton(DialogInterface.BUTTON_POSITIVE);
final FragmentActivity activity = getActivity();
if (activity == null) positiveButton.setOnClickListener(view -> {
return; final String result = mEtInput.getText().toString();
this.validateInput(activity, mInitialText); if (validateInput(requireActivity(), result)) {
processInput(result);
editTextDialog.dismiss();
}
});
}); });
// Setup validation on input edit. // Setup validation on input edit.
@@ -149,14 +147,16 @@ public class EditTextDialogFragment extends BaseMwmDialogFragment
return editTextDialog; 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); final String maybeError = mInputValidator.validate(activity, input);
mPositiveButton.setEnabled(maybeError == null);
mEtInputLayout.getEditText().setError(maybeError); mEtInputLayout.getEditText().setError(maybeError);
mEtInputLayout.requestFocus();
return maybeError == null;
} }
return false;
} }
private void processInput(@Nullable String text) private void processInput(@Nullable String text)

View File

@@ -1,13 +1,19 @@
package app.organicmaps.editor; package app.organicmaps.editor;
import android.annotation.SuppressLint;
import android.content.Context; import android.content.Context;
import android.os.Bundle; import android.os.Bundle;
import android.text.Editable;
import android.text.InputType; import android.text.InputType;
import android.text.TextUtils; import android.text.TextUtils;
import android.text.TextWatcher;
import android.text.method.LinkMovementMethod; import android.text.method.LinkMovementMethod;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.AutoCompleteTextView;
import android.widget.GridLayout;
import android.widget.Toast;
import androidx.annotation.CallSuper; import androidx.annotation.CallSuper;
import androidx.annotation.DrawableRes; import androidx.annotation.DrawableRes;
import androidx.annotation.IdRes; import androidx.annotation.IdRes;
@@ -22,6 +28,7 @@ import app.organicmaps.base.BaseMwmFragment;
import app.organicmaps.dialog.EditTextDialogFragment; import app.organicmaps.dialog.EditTextDialogFragment;
import app.organicmaps.editor.data.TimeFormatUtils; import app.organicmaps.editor.data.TimeFormatUtils;
import app.organicmaps.sdk.Framework; import app.organicmaps.sdk.Framework;
import app.organicmaps.sdk.bookmarks.data.ChargeSocketDescriptor;
import app.organicmaps.sdk.bookmarks.data.Metadata; import app.organicmaps.sdk.bookmarks.data.Metadata;
import app.organicmaps.sdk.editor.Editor; import app.organicmaps.sdk.editor.Editor;
import app.organicmaps.sdk.editor.OpeningHours; 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.editor.data.Timetable;
import app.organicmaps.sdk.util.StringUtils; import app.organicmaps.sdk.util.StringUtils;
import app.organicmaps.sdk.util.Utils; import app.organicmaps.sdk.util.Utils;
import app.organicmaps.sdk.util.log.Logger;
import app.organicmaps.util.Graphics; import app.organicmaps.util.Graphics;
import app.organicmaps.util.InputUtils; import app.organicmaps.util.InputUtils;
import app.organicmaps.util.UiUtils; import app.organicmaps.util.UiUtils;
import com.google.android.material.button.MaterialButton; 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.dialog.MaterialAlertDialogBuilder;
import com.google.android.material.imageview.ShapeableImageView; import com.google.android.material.imageview.ShapeableImageView;
import com.google.android.material.textfield.TextInputEditText; import com.google.android.material.textfield.TextInputEditText;
import com.google.android.material.textfield.TextInputLayout; import com.google.android.material.textfield.TextInputLayout;
import com.google.android.material.textview.MaterialTextView; 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.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
public class EditorFragment extends BaseMwmFragment implements View.OnClickListener public class EditorFragment extends BaseMwmFragment implements View.OnClickListener
{ {
final static String LAST_INDEX_OF_NAMES_ARRAY = "LastIndexOfNamesArray"; final static String LAST_INDEX_OF_NAMES_ARRAY = "LastIndexOfNamesArray";
private static final String CHARGE_SOCKETS_TAG = "CHARGE_SOCKETS_TAG";
private MaterialTextView mCategory; private MaterialTextView mCategory;
private View mCardName; private View mCardName;
private View mCardAddress; private View mCardAddress;
private View mCardChargingStation;
private View mCardDetails; private View mCardDetails;
private View mCardSocialMedia; private View mCardSocialMedia;
private View mCardBuilding; private View mCardBuilding;
@@ -130,6 +144,8 @@ public class EditorFragment extends BaseMwmFragment implements View.OnClickListe
private TextInputLayout mInputHouseNumber; private TextInputLayout mInputHouseNumber;
private TextInputLayout mInputBuildingLevels; private TextInputLayout mInputBuildingLevels;
private View mChargeSockets;
private View mEmptyOpeningHours; private View mEmptyOpeningHours;
private MaterialTextView mOpeningHours; private MaterialTextView mOpeningHours;
private View mEditOpeningHours; private View mEditOpeningHours;
@@ -206,6 +222,7 @@ public class EditorFragment extends BaseMwmFragment implements View.OnClickListe
mWifi.setChecked(Editor.nativeHasWifi()); mWifi.setChecked(Editor.nativeHasWifi());
// TODO Reimplement this to avoid https://github.com/organicmaps/organicmaps/issues/9049 // TODO Reimplement this to avoid https://github.com/organicmaps/organicmaps/issues/9049
// mOutdoorSeating.setChecked(Editor.nativeGetSwitchInput(Metadata.MetadataType.FMD_OUTDOOR_SEATING.toInt(),"yes")); // mOutdoorSeating.setChecked(Editor.nativeGetSwitchInput(Metadata.MetadataType.FMD_OUTDOOR_SEATING.toInt(),"yes"));
refreshChargeSockets();
refreshOpeningTime(); refreshOpeningTime();
refreshEditableFields(); refreshEditableFields();
refreshResetButton(); refreshResetButton();
@@ -329,6 +346,14 @@ public class EditorFragment extends BaseMwmFragment implements View.OnClickListe
final int[] editableDetails = Editor.nativeGetEditableProperties(); 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(mCardDetails, mDetailsBlocks, editableDetails);
setCardVisibility(mCardSocialMedia, mSocialMediaBlocks, editableDetails); setCardVisibility(mCardSocialMedia, mSocialMediaBlocks, editableDetails);
} }
@@ -351,6 +376,283 @@ public class EditorFragment extends BaseMwmFragment implements View.OnClickListe
UiUtils.showIf(anyBlockElement, card); 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() private void refreshOpeningTime()
{ {
final String openingHours = Editor.nativeGetOpeningHours(); final String openingHours = Editor.nativeGetOpeningHours();
@@ -435,6 +737,7 @@ public class EditorFragment extends BaseMwmFragment implements View.OnClickListe
mCategory = categoryBlock.findViewById(R.id.name); mCategory = categoryBlock.findViewById(R.id.name);
mCardName = view.findViewById(R.id.cv__name); mCardName = view.findViewById(R.id.cv__name);
mCardAddress = view.findViewById(R.id.cv__address); mCardAddress = view.findViewById(R.id.cv__address);
mCardChargingStation = view.findViewById(R.id.cv__charging_station);
mCardDetails = view.findViewById(R.id.cv__details); mCardDetails = view.findViewById(R.id.cv__details);
mCardSocialMedia = view.findViewById(R.id.cv__social_media); mCardSocialMedia = view.findViewById(R.id.cv__social_media);
mCardBuilding = view.findViewById(R.id.cv__building); 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); View blockOutdoorSeating = view.findViewById(R.id.block_outdoor_seating);
mOutdoorSeating = view.findViewById(R.id.sw__outdoor_seating); mOutdoorSeating = view.findViewById(R.id.sw__outdoor_seating);
blockOutdoorSeating.setOnClickListener(this); blockOutdoorSeating.setOnClickListener(this);
mChargeSockets = view.findViewById(R.id.block_charge_sockets);
View blockOpeningHours = view.findViewById(R.id.block_opening_hours); View blockOpeningHours = view.findViewById(R.id.block_opening_hours);
mEditOpeningHours = blockOpeningHours.findViewById(R.id.edit_opening_hours); mEditOpeningHours = blockOpeningHours.findViewById(R.id.edit_opening_hours);
mEditOpeningHours.setOnClickListener(this); mEditOpeningHours.setOnClickListener(this);
@@ -701,7 +1007,7 @@ public class EditorFragment extends BaseMwmFragment implements View.OnClickListe
private void placeDoesntExist() private void placeDoesntExist()
{ {
EditTextDialogFragment dialogFragment = EditTextDialogFragment.show( 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, getString(R.string.editor_report_problem_send_button), getString(R.string.cancel), this,
getDeleteCommentValidator()); getDeleteCommentValidator());
dialogFragment.setTextSaveListener(this::commitPlaceDoesntExists); dialogFragment.setTextSaveListener(this::commitPlaceDoesntExists);

View File

@@ -13,7 +13,6 @@ import android.widget.TextView;
import android.widget.TimePicker; import android.widget.TimePicker;
import androidx.annotation.IntRange; import androidx.annotation.IntRange;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.StyleRes;
import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.content.res.AppCompatResources; import androidx.appcompat.content.res.AppCompatResources;
import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentManager;
@@ -21,7 +20,6 @@ import app.organicmaps.R;
import app.organicmaps.base.BaseMwmDialogFragment; import app.organicmaps.base.BaseMwmDialogFragment;
import app.organicmaps.sdk.editor.data.HoursMinutes; import app.organicmaps.sdk.editor.data.HoursMinutes;
import app.organicmaps.sdk.util.DateUtils; import app.organicmaps.sdk.util.DateUtils;
import app.organicmaps.util.ThemeUtils;
import app.organicmaps.util.Utils; import app.organicmaps.util.Utils;
import com.google.android.material.dialog.MaterialAlertDialogBuilder; import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.google.android.material.tabs.TabLayout; import com.google.android.material.tabs.TabLayout;
@@ -79,15 +77,13 @@ public class HoursMinutesPickerFragment extends BaseMwmDialogFragment
// noinspection ConstantConditions // noinspection ConstantConditions
mTabs.getTabAt(mSelectedTab).select(); mTabs.getTabAt(mSelectedTab).select();
@StyleRes final AlertDialog dialog =
final int theme = ThemeUtils.isNightTheme() ? R.style.MwmMain_DialogFragment_TimePicker_Night new MaterialAlertDialogBuilder(requireActivity(), R.style.MwmMain_DialogFragment_TimePicker)
: R.style.MwmMain_DialogFragment_TimePicker; .setView(root)
final AlertDialog dialog = new MaterialAlertDialogBuilder(requireActivity(), theme) .setNegativeButton(R.string.cancel, null)
.setView(root) .setPositiveButton(R.string.ok, null)
.setNegativeButton(R.string.cancel, null) .setCancelable(true)
.setPositiveButton(R.string.ok, null) .create();
.setCancelable(true)
.create();
dialog.setOnShowListener(dialogInterface -> { dialog.setOnShowListener(dialogInterface -> {
mOkButton = dialog.getButton(AlertDialog.BUTTON_POSITIVE); mOkButton = dialog.getButton(AlertDialog.BUTTON_POSITIVE);
@@ -141,9 +137,8 @@ public class HoursMinutesPickerFragment extends BaseMwmDialogFragment
mTabs = root.findViewById(R.id.tabs); mTabs = root.findViewById(R.id.tabs);
MaterialTextView tabView = (MaterialTextView) inflater.inflate(R.layout.tab_timepicker, mTabs, false); MaterialTextView tabView = (MaterialTextView) inflater.inflate(R.layout.tab_timepicker, mTabs, false);
tabView.setText(getResources().getString(R.string.editor_time_from)); tabView.setText(getResources().getString(R.string.editor_time_from));
final ColorStateList textColor = AppCompatResources.getColorStateList( final ColorStateList textColor =
requireContext(), AppCompatResources.getColorStateList(requireContext(), R.color.accent_color_selector);
ThemeUtils.isNightTheme() ? R.color.accent_color_selector_night : R.color.accent_color_selector);
tabView.setTextColor(textColor); tabView.setTextColor(textColor);
mTabs.addTab(mTabs.newTab().setCustomView(tabView), true); mTabs.addTab(mTabs.newTab().setCustomView(tabView), true);
tabView = (MaterialTextView) inflater.inflate(R.layout.tab_timepicker, mTabs, false); tabView = (MaterialTextView) inflater.inflate(R.layout.tab_timepicker, mTabs, false);

View File

@@ -22,7 +22,6 @@ import app.organicmaps.util.UiUtils;
import app.organicmaps.util.Utils; import app.organicmaps.util.Utils;
import app.organicmaps.util.WindowInsetUtils; import app.organicmaps.util.WindowInsetUtils;
import app.organicmaps.widget.StackedButtonDialogFragment; import app.organicmaps.widget.StackedButtonDialogFragment;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.google.android.material.imageview.ShapeableImageView; import com.google.android.material.imageview.ShapeableImageView;
import com.google.android.material.textview.MaterialTextView; import com.google.android.material.textview.MaterialTextView;
import java.text.NumberFormat; import java.text.NumberFormat;
@@ -135,14 +134,7 @@ public class ProfileFragment extends BaseMwmToolbarFragment
private void logout() private void logout()
{ {
new MaterialAlertDialogBuilder(requireContext(), R.style.MwmTheme_AlertDialog) OsmOAuth.clearAuthorization();
.setMessage(R.string.osm_log_out_confirmation) refreshViews();
.setPositiveButton(R.string.yes,
(dialog, which) -> {
OsmOAuth.clearAuthorization();
refreshViews();
})
.setNegativeButton(R.string.no, null)
.show();
} }
} }

View File

@@ -2,6 +2,7 @@ package app.organicmaps.maplayer;
import android.content.Context; import android.content.Context;
import android.view.View; import android.view.View;
import androidx.annotation.AttrRes;
import androidx.annotation.DrawableRes; import androidx.annotation.DrawableRes;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.StringRes; import androidx.annotation.StringRes;
@@ -13,9 +14,7 @@ import app.organicmaps.util.ThemeUtils;
public class LayerBottomSheetItem public class LayerBottomSheetItem
{ {
@DrawableRes @DrawableRes
private final int mEnabledStateDrawableResId; private final int mDrawableResId;
@DrawableRes
private final int mDisabledStateDrawableResId;
@StringRes @StringRes
private final int mTitleResId; private final int mTitleResId;
@NonNull @NonNull
@@ -23,12 +22,10 @@ public class LayerBottomSheetItem
@NonNull @NonNull
private final OnItemClickListener<LayerBottomSheetItem> mItemClickListener; private final OnItemClickListener<LayerBottomSheetItem> mItemClickListener;
LayerBottomSheetItem(@DrawableRes int enabledStateDrawableResId, @DrawableRes int disabledStateDrawableResId, LayerBottomSheetItem(@DrawableRes int drawableResId, @StringRes int titleResId, @NonNull Mode mode,
@StringRes int titleResId, @NonNull Mode mode,
@NonNull OnItemClickListener<LayerBottomSheetItem> itemClickListener) @NonNull OnItemClickListener<LayerBottomSheetItem> itemClickListener)
{ {
mEnabledStateDrawableResId = enabledStateDrawableResId; mDrawableResId = drawableResId;
mDisabledStateDrawableResId = disabledStateDrawableResId;
mTitleResId = titleResId; mTitleResId = titleResId;
mMode = mode; mMode = mode;
mItemClickListener = itemClickListener; mItemClickListener = itemClickListener;
@@ -37,35 +34,30 @@ public class LayerBottomSheetItem
public static LayerBottomSheetItem create(@NonNull Context mContext, Mode mode, public static LayerBottomSheetItem create(@NonNull Context mContext, Mode mode,
@NonNull OnItemClickListener<LayerBottomSheetItem> layerItemClickListener) @NonNull OnItemClickListener<LayerBottomSheetItem> layerItemClickListener)
{ {
int disabledResource = 0; @DrawableRes
int enabledResource = 0; int drawableResId = 0;
@StringRes
int buttonTextResource = R.string.layers_title; int buttonTextResource = R.string.layers_title;
switch (mode) switch (mode)
{ {
case OUTDOORS: case OUTDOORS:
disabledResource = R.attr.outdoorsMenuDisabled; drawableResId = R.drawable.ic_layers_outdoors;
enabledResource = R.attr.outdoorsMenuEnabled;
buttonTextResource = R.string.button_layer_outdoor; buttonTextResource = R.string.button_layer_outdoor;
break; break;
case SUBWAY: case SUBWAY:
disabledResource = R.attr.subwayMenuDisabled; drawableResId = R.drawable.ic_layers_subway;
enabledResource = R.attr.subwayMenuEnabled;
buttonTextResource = R.string.subway; buttonTextResource = R.string.subway;
break; break;
case ISOLINES: case ISOLINES:
disabledResource = R.attr.isoLinesMenuDisabled; drawableResId = R.drawable.ic_layers_isoline;
enabledResource = R.attr.isoLinesMenuEnabled;
buttonTextResource = R.string.button_layer_isolines; buttonTextResource = R.string.button_layer_isolines;
break; break;
case TRAFFIC: case TRAFFIC:
disabledResource = R.attr.trafficMenuDisabled; drawableResId = R.drawable.ic_layers_traffic;
enabledResource = R.attr.trafficMenuEnabled;
buttonTextResource = R.string.button_layer_traffic; buttonTextResource = R.string.button_layer_traffic;
break; break;
} }
int disabled = ThemeUtils.getResource(mContext, disabledResource); return new LayerBottomSheetItem(drawableResId, buttonTextResource, mode, layerItemClickListener);
int enabled = ThemeUtils.getResource(mContext, enabledResource);
return new LayerBottomSheetItem(enabled, disabled, buttonTextResource, mode, layerItemClickListener);
} }
@NonNull @NonNull
@@ -75,15 +67,9 @@ public class LayerBottomSheetItem
} }
@DrawableRes @DrawableRes
public int getEnabledStateDrawable() public int getDrawable()
{ {
return mEnabledStateDrawableResId; return mDrawableResId;
}
@DrawableRes
public int getDisabledStateDrawable()
{
return mDisabledStateDrawableResId;
} }
@StringRes @StringRes

View File

@@ -45,7 +45,8 @@ public class LayersAdapter extends RecyclerView.Adapter<LayerHolder>
holder.mTitle.setText(item.getTitle()); holder.mTitle.setText(item.getTitle());
boolean isNewLayer = SharedPropertiesUtils.shouldShowNewMarkerForLayerMode(item.getMode()); boolean isNewLayer = SharedPropertiesUtils.shouldShowNewMarkerForLayerMode(item.getMode());
UiUtils.showIf(isNewLayer, holder.mNewMarker); 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; holder.mListener = item::onClick;
} }

View File

@@ -43,20 +43,19 @@ public class TrafficButton
void turnOff() void turnOff()
{ {
stopWaitingAnimation(); 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() void turnOn()
{ {
stopWaitingAnimation(); 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() void markAsOutdated()
{ {
stopWaitingAnimation(); stopWaitingAnimation();
mButton.setImageResource(ThemeUtils.isNightTheme() ? R.drawable.ic_traffic_outdated_night mButton.setImageResource(R.drawable.ic_traffic_outdated);
: R.drawable.ic_traffic_outdated);
} }
void startWaitingAnimation() void startWaitingAnimation()

View File

@@ -20,7 +20,6 @@ import com.google.android.material.textview.MaterialTextView;
import app.organicmaps.R; import app.organicmaps.R;
import app.organicmaps.sdk.search.DisplayedCategories; import app.organicmaps.sdk.search.DisplayedCategories;
import app.organicmaps.sdk.util.Language; import app.organicmaps.sdk.util.Language;
import app.organicmaps.util.ThemeUtils;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.util.Locale; import java.util.Locale;
@@ -91,11 +90,7 @@ class CategoriesAdapter extends RecyclerView.Adapter<CategoriesAdapter.ViewHolde
@DrawableRes @DrawableRes
private static int getDrawableResIdByKey(@NonNull Context context, @NonNull String packageName, @NonNull String key) private static int getDrawableResIdByKey(@NonNull Context context, @NonNull String packageName, @NonNull String key)
{ {
final boolean isNightTheme = ThemeUtils.isNightTheme(); return context.getResources().getIdentifier("ic_" + key, "drawable", packageName);
String iconId = "ic_" + key;
if (isNightTheme)
iconId = iconId + "_night";
return context.getResources().getIdentifier(iconId, "drawable", packageName);
} }
@Override @Override

View File

@@ -33,13 +33,6 @@ public class SearchActivity extends BaseMwmFragmentActivity
activity.startActivity(i); activity.startActivity(i);
} }
@Override
@StyleRes
public int getThemeResourceId(@NonNull String theme)
{
return ThemeUtils.getCardBgThemeResourceId(theme);
}
@Override @Override
protected Class<? extends Fragment> getFragmentClass() protected Class<? extends Fragment> getFragmentClass()
{ {

View File

@@ -12,7 +12,6 @@ import androidx.preference.Preference;
import androidx.preference.PreferenceFragmentCompat; import androidx.preference.PreferenceFragmentCompat;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import app.organicmaps.R; import app.organicmaps.R;
import app.organicmaps.util.ThemeUtils;
import app.organicmaps.util.Utils; import app.organicmaps.util.Utils;
import app.organicmaps.util.WindowInsetUtils.ScrollableContentInsetsListener; import app.organicmaps.util.WindowInsetUtils.ScrollableContentInsetsListener;
@@ -35,24 +34,17 @@ abstract class BaseXmlSettingsFragment extends PreferenceFragmentCompat
} }
@Override @Override
public void onAttach(Context context) public void onAttach(@NonNull Context context)
{ {
super.onAttach(context); super.onAttach(context);
Utils.detachFragmentIfCoreNotInitialized(context, this); Utils.detachFragmentIfCoreNotInitialized(context, this);
} }
@Override @Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState)
{ {
super.onViewCreated(view, savedInstanceState); super.onViewCreated(view, savedInstanceState);
view.setBackgroundColor(ContextCompat.getColor(requireContext(), R.color.bg_cards));
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);
RecyclerView recyclerView = getListView(); RecyclerView recyclerView = getListView();
ViewCompat.setOnApplyWindowInsetsListener(recyclerView, new ScrollableContentInsetsListener(recyclerView)); ViewCompat.setOnApplyWindowInsetsListener(recyclerView, new ScrollableContentInsetsListener(recyclerView));
} }

View File

@@ -107,6 +107,11 @@ public class DrivingOptionsFragment extends BaseMwmToolbarFragment
dirtyRoadsBtn.setChecked(RoutingOptions.hasOption(RoadType.Dirty)); dirtyRoadsBtn.setChecked(RoutingOptions.hasOption(RoadType.Dirty));
CompoundButton.OnCheckedChangeListener dirtyBtnListener = new ToggleRoutingOptionListener(RoadType.Dirty); CompoundButton.OnCheckedChangeListener dirtyBtnListener = new ToggleRoutingOptionListener(RoadType.Dirty);
dirtyRoadsBtn.setOnCheckedChangeListener(dirtyBtnListener); 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 private static class ToggleRoutingOptionListener implements CompoundButton.OnCheckedChangeListener

View File

@@ -60,7 +60,7 @@ public class SettingsPrefsFragment extends BaseXmlSettingsFragment implements La
} }
@Override @Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState)
{ {
super.onViewCreated(view, savedInstanceState); super.onViewCreated(view, savedInstanceState);

View File

@@ -137,7 +137,7 @@ public class VoiceInstructionsSettingsFragment extends BaseXmlSettingsFragment
} }
@Override @Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState)
{ {
super.onViewCreated(view, savedInstanceState); super.onViewCreated(view, savedInstanceState);

View File

@@ -86,7 +86,7 @@ public enum ThemeSwitcher
String oldTheme = Config.UiTheme.getCurrent(); String oldTheme = Config.UiTheme.getCurrent();
MapStyle style; MapStyle style;
if (ThemeUtils.isNightTheme()) if (Config.UiTheme.isNight(theme))
{ {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S)
uiModeManager.setApplicationNightMode(UiModeManager.MODE_NIGHT_YES); uiModeManager.setApplicationNightMode(UiModeManager.MODE_NIGHT_YES);

View File

@@ -6,8 +6,6 @@ import android.util.TypedValue;
import androidx.annotation.AttrRes; import androidx.annotation.AttrRes;
import androidx.annotation.ColorInt; import androidx.annotation.ColorInt;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.StyleRes;
import app.organicmaps.R;
import app.organicmaps.sdk.util.Config; import app.organicmaps.sdk.util.Config;
public final class ThemeUtils public final class ThemeUtils
@@ -64,28 +62,4 @@ public final class ThemeUtils
{ {
return Config.UiTheme.isNavAuto(Config.UiTheme.getUiThemeSettings()); 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);
}
} }

View File

@@ -35,9 +35,8 @@ public class RoutingToolbarButton extends AppCompatRadioButton
private void initView() private void initView()
{ {
final boolean isNightTheme = ThemeUtils.isNightTheme(); setBackgroundResource(R.drawable.routing_toolbar_button);
setBackgroundResource(isNightTheme ? R.drawable.routing_toolbar_button_night : R.drawable.routing_toolbar_button); setButtonTintList(R.color.routing_toolbar_icon_tint);
setButtonTintList(isNightTheme ? R.color.routing_toolbar_icon_tint_night : R.color.routing_toolbar_icon_tint);
} }
public void progress() public void progress()

View File

@@ -72,6 +72,7 @@ import app.organicmaps.util.bottomsheet.MenuBottomSheetFragment;
import app.organicmaps.util.bottomsheet.MenuBottomSheetItem; import app.organicmaps.util.bottomsheet.MenuBottomSheetItem;
import app.organicmaps.widget.ArrowView; import app.organicmaps.widget.ArrowView;
import app.organicmaps.widget.placepage.sections.PlacePageBookmarkFragment; 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.PlacePageLinksFragment;
import app.organicmaps.widget.placepage.sections.PlacePageOpeningHoursFragment; import app.organicmaps.widget.placepage.sections.PlacePageOpeningHoursFragment;
import app.organicmaps.widget.placepage.sections.PlacePagePhoneFragment; 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 BOOKMARK_FRAGMENT_TAG = "BOOKMARK_FRAGMENT_TAG";
private static final String TRACK_FRAGMENT_TAG = "TRACK_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 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 PHONE_FRAGMENT_TAG = "PHONE_FRAGMENT_TAG";
private static final String OPENING_HOURS_FRAGMENT_TAG = "OPENING_HOURS_FRAGMENT_TAG"; private static final String OPENING_HOURS_FRAGMENT_TAG = "OPENING_HOURS_FRAGMENT_TAG";
private static final String LINKS_FRAGMENT_TAG = "LINKS_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 mTvEntrance;
private MaterialTextView mTvLastChecked; private MaterialTextView mTvLastChecked;
private View mEditPlace; private View mEditPlace;
private View mAddOrganisation;
private View mAddPlace; private View mAddPlace;
private View mEditTopSpace; private View mEditTopSpace;
private ShapeableImageView mColorIcon; private ShapeableImageView mColorIcon;
@@ -311,7 +312,6 @@ public class PlacePageView extends Fragment
mTvEntrance = mEntrance.findViewById(R.id.tv__place_entrance); mTvEntrance = mEntrance.findViewById(R.id.tv__place_entrance);
mTvLastChecked = mFrame.findViewById(R.id.place_page_last_checked); mTvLastChecked = mFrame.findViewById(R.id.place_page_last_checked);
mEditPlace = mFrame.findViewById(R.id.ll__place_editor); mEditPlace = mFrame.findViewById(R.id.ll__place_editor);
mAddOrganisation = mFrame.findViewById(R.id.ll__add_organisation);
mAddPlace = mFrame.findViewById(R.id.ll__place_add); mAddPlace = mFrame.findViewById(R.id.ll__place_add);
mEditTopSpace = mFrame.findViewById(R.id.edit_top_space); mEditTopSpace = mFrame.findViewById(R.id.edit_top_space);
latlon.setOnLongClickListener(this); latlon.setOnLongClickListener(this);
@@ -407,6 +407,12 @@ public class PlacePageView extends Fragment
R.id.place_page_opening_hours_fragment, !TextUtils.isEmpty(ohStr)); 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() private void updatePhoneView()
{ {
updateViewFragment(PlacePagePhoneFragment.class, PHONE_FRAGMENT_TAG, R.id.place_page_phone_fragment, updateViewFragment(PlacePagePhoneFragment.class, PHONE_FRAGMENT_TAG, R.id.place_page_phone_fragment,
@@ -665,28 +671,25 @@ public class PlacePageView extends Fragment
if (!lastChecked.isEmpty()) if (!lastChecked.isEmpty())
{ {
String periodSinceCheck = DateUtils.getRelativePeriodString(getResources(), lastChecked); 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 else
UiUtils.hide(mTvLastChecked); UiUtils.hide(mTvLastChecked);
if (RoutingController.get().isNavigating() || RoutingController.get().isPlanning()) if (RoutingController.get().isNavigating() || RoutingController.get().isPlanning())
{ {
UiUtils.hide(mEditPlace, mAddOrganisation, mAddPlace, mEditTopSpace); UiUtils.hide(mEditPlace, mAddPlace, mEditTopSpace);
} }
else else
{ {
UiUtils.showIf(Editor.nativeShouldShowEditPlace(), mEditPlace); UiUtils.showIf(Editor.nativeShouldShowEditPlace(), mEditPlace);
UiUtils.showIf(Editor.nativeShouldShowAddBusiness(), mAddOrganisation);
UiUtils.showIf(Editor.nativeShouldShowAddPlace(), mAddPlace); UiUtils.showIf(Editor.nativeShouldShowAddPlace(), mAddPlace);
MaterialButton mTvEditPlace = mEditPlace.findViewById(R.id.mb__place_editor); 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); MaterialButton mTvAddPlace = mAddPlace.findViewById(R.id.mb__place_add);
mTvEditPlace.setOnClickListener(this); mTvEditPlace.setOnClickListener(this);
mTvAddBusiness.setOnClickListener(this);
mTvAddPlace.setOnClickListener(this); mTvAddPlace.setOnClickListener(this);
mTvEditPlace.setEnabled(Editor.nativeShouldEnableEditPlace()); mTvEditPlace.setEnabled(Editor.nativeShouldEnableEditPlace());
mTvAddBusiness.setEnabled(Editor.nativeShouldEnableAddPlace());
mTvAddPlace.setEnabled(Editor.nativeShouldEnableAddPlace()); mTvAddPlace.setEnabled(Editor.nativeShouldEnableAddPlace());
final int editPlaceButtonColor = final int editPlaceButtonColor =
Editor.nativeShouldEnableEditPlace() Editor.nativeShouldEnableEditPlace()
@@ -695,19 +698,18 @@ public class PlacePageView extends Fragment
UiUtils.getStyledResourceId(getContext(), com.google.android.material.R.attr.colorSecondary)) UiUtils.getStyledResourceId(getContext(), com.google.android.material.R.attr.colorSecondary))
: ContextCompat.getColor(getContext(), R.color.button_accent_text_disabled); : ContextCompat.getColor(getContext(), R.color.button_accent_text_disabled);
mTvEditPlace.setTextColor(editPlaceButtonColor); mTvEditPlace.setTextColor(editPlaceButtonColor);
mTvAddBusiness.setTextColor(editPlaceButtonColor);
mTvAddPlace.setTextColor(editPlaceButtonColor); mTvAddPlace.setTextColor(editPlaceButtonColor);
mTvEditPlace.setStrokeColor(ColorStateList.valueOf(editPlaceButtonColor)); mTvEditPlace.setStrokeColor(ColorStateList.valueOf(editPlaceButtonColor));
mTvAddBusiness.setStrokeColor(ColorStateList.valueOf(editPlaceButtonColor));
mTvAddPlace.setStrokeColor(ColorStateList.valueOf(editPlaceButtonColor)); mTvAddPlace.setStrokeColor(ColorStateList.valueOf(editPlaceButtonColor));
UiUtils.showIf( UiUtils.showIf(
UiUtils.isVisible(mEditPlace) || UiUtils.isVisible(mAddOrganisation) || UiUtils.isVisible(mAddPlace), UiUtils.isVisible(mEditPlace) || UiUtils.isVisible(mAddPlace),
mEditTopSpace); mEditTopSpace);
} }
updateLinksView(); updateLinksView();
updateOpeningHoursView(); updateOpeningHoursView();
updateWikipediaView(); updateWikipediaView();
updateBookmarkView(); updateBookmarkView();
updateChargeSocketsView();
updatePhoneView(); updatePhoneView();
updateTrackView(); updateTrackView();
} }
@@ -837,11 +839,6 @@ public class PlacePageView extends Fragment
UiUtils.hide(mTvOpenState); UiUtils.hide(mTvOpenState);
} }
private void addOrganisation()
{
((MwmActivity) requireActivity()).showPositionChooserForEditor(true, true);
}
private void addPlace() private void addPlace()
{ {
((MwmActivity) requireActivity()).showPositionChooserForEditor(false, true); ((MwmActivity) requireActivity()).showPositionChooserForEditor(false, true);
@@ -859,8 +856,6 @@ public class PlacePageView extends Fragment
} }
else if (id == R.id.mb__place_editor) else if (id == R.id.mb__place_editor)
((MwmActivity) requireActivity()).showEditor(); ((MwmActivity) requireActivity()).showEditor();
else if (id == R.id.mb__add_organisation)
addOrganisation();
else if (id == R.id.mb__place_add) else if (id == R.id.mb__place_add)
addPlace(); addPlace();
else if (id == R.id.ll__place_latlon) else if (id == R.id.ll__place_latlon)

View File

@@ -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);
}
}
}

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

Before

Width:  |  Height:  |  Size: 702 B

After

Width:  |  Height:  |  Size: 702 B

View File

Before

Width:  |  Height:  |  Size: 714 B

After

Width:  |  Height:  |  Size: 714 B

View File

Before

Width:  |  Height:  |  Size: 714 B

After

Width:  |  Height:  |  Size: 714 B

View File

Before

Width:  |  Height:  |  Size: 722 B

After

Width:  |  Height:  |  Size: 722 B

View File

Before

Width:  |  Height:  |  Size: 714 B

After

Width:  |  Height:  |  Size: 714 B

View File

Before

Width:  |  Height:  |  Size: 712 B

After

Width:  |  Height:  |  Size: 712 B

View File

Before

Width:  |  Height:  |  Size: 718 B

After

Width:  |  Height:  |  Size: 718 B

Some files were not shown because too many files have changed in this diff Show More