[android] Re-format java code by clang-format

Signed-off-by: Konstantin Pastbin <konstantin.pastbin@gmail.com>
This commit is contained in:
Konstantin Pastbin
2025-07-29 22:31:32 +07:00
parent 65b5234396
commit 5333ad3597
348 changed files with 4770 additions and 5563 deletions

View File

@@ -8,10 +8,10 @@ import android.app.PendingIntent;
import android.content.Context; import android.content.Context;
import android.location.Location; import android.location.Location;
import android.os.Looper; import android.os.Looper;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.RequiresPermission; import androidx.annotation.RequiresPermission;
import app.organicmaps.sdk.util.LocationUtils;
import app.organicmaps.sdk.util.log.Logger;
import com.google.android.gms.common.api.ApiException; import com.google.android.gms.common.api.ApiException;
import com.google.android.gms.common.api.ResolvableApiException; import com.google.android.gms.common.api.ResolvableApiException;
import com.google.android.gms.location.FusedLocationProviderClient; import com.google.android.gms.location.FusedLocationProviderClient;
@@ -26,9 +26,6 @@ import com.google.android.gms.location.LocationSettingsStatusCodes;
import com.google.android.gms.location.Priority; import com.google.android.gms.location.Priority;
import com.google.android.gms.location.SettingsClient; import com.google.android.gms.location.SettingsClient;
import app.organicmaps.sdk.util.LocationUtils;
import app.organicmaps.sdk.util.log.Logger;
class GoogleFusedLocationProvider extends BaseLocationProvider class GoogleFusedLocationProvider extends BaseLocationProvider
{ {
private static final String TAG = GoogleFusedLocationProvider.class.getSimpleName(); private static final String TAG = GoogleFusedLocationProvider.class.getSimpleName();
@@ -72,71 +69,75 @@ class GoogleFusedLocationProvider extends BaseLocationProvider
{ {
Logger.d(TAG); Logger.d(TAG);
final LocationRequest locationRequest = new LocationRequest.Builder(Priority.PRIORITY_HIGH_ACCURACY, interval) final LocationRequest locationRequest =
// Wait a few seconds for accurate locations initially, when accurate locations could not be computed on the device immediately. new LocationRequest
// https://github.com/organicmaps/organicmaps/issues/2149 .Builder(Priority.PRIORITY_HIGH_ACCURACY, interval)
.setWaitForAccurateLocation(true) // Wait a few seconds for accurate locations initially, when accurate locations could not be computed on the
// The desired location granularity should correspond to the client permission level. The client will be // device immediately. https://github.com/organicmaps/organicmaps/issues/2149
// delivered fine locations while it has the Manifest.permission.ACCESS_FINE_LOCATION permission, coarse .setWaitForAccurateLocation(true)
// locations while it has only the Manifest.permission.ACCESS_COARSE_LOCATION permission, and no location // The desired location granularity should correspond to the client permission level. The client will be
// if it lacks either. // delivered fine locations while it has the Manifest.permission.ACCESS_FINE_LOCATION permission, coarse
.setGranularity(Granularity.GRANULARITY_PERMISSION_LEVEL) // locations while it has only the Manifest.permission.ACCESS_COARSE_LOCATION permission, and no location
// Sets the maximum age of an initial historical location delivered for this request. // if it lacks either.
.setMaxUpdateAgeMillis(60 * 60 * 1000L) // 1 hour .setGranularity(Granularity.GRANULARITY_PERMISSION_LEVEL)
.build(); // Sets the maximum age of an initial historical location delivered for this request.
.setMaxUpdateAgeMillis(60 * 60 * 1000L) // 1 hour
.build();
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder(); LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder();
builder.addLocationRequest(locationRequest); builder.addLocationRequest(locationRequest);
builder.setAlwaysShow(true); // improves the wording/appearance of the dialog builder.setAlwaysShow(true); // improves the wording/appearance of the dialog
final LocationSettingsRequest locationSettingsRequest = builder.build(); final LocationSettingsRequest locationSettingsRequest = builder.build();
mSettingsClient.checkLocationSettings(locationSettingsRequest).addOnSuccessListener(locationSettingsResponse -> { mSettingsClient.checkLocationSettings(locationSettingsRequest)
Logger.d(TAG, "Service is available"); .addOnSuccessListener(locationSettingsResponse -> {
mFusedLocationClient.requestLocationUpdates(locationRequest, mCallback, Looper.myLooper()); Logger.d(TAG, "Service is available");
}).addOnFailureListener(e -> { mFusedLocationClient.requestLocationUpdates(locationRequest, mCallback, Looper.myLooper());
try })
{ .addOnFailureListener(e -> {
int statusCode = ((ApiException) e).getStatusCode(); try
if (statusCode == LocationSettingsStatusCodes.RESOLUTION_REQUIRED)
{
// This case happens if at least one of the following system settings is off:
// 1. Location Services a.k.a GPS;
// 2. Google Location Accuracy a.k.a High Accuracy;
// 3. Both Wi-Fi && Mobile Data together (needed for 2).
//
// PendingIntent below will show a special Google "For better experience... enable (1) and/or (2) and/or (3)"
// dialog. This system dialog can change system settings if "Yes" is pressed. We can't do it from our app.
// However, we don't want to annoy a user who disabled (2) or (3) intentionally. GPS (1) is mandatory to
// continue, while (2) and (3) are not dealbreakers here.
//
// See https://github.com/organicmaps/organicmaps/issues/3846
//
if (LocationUtils.areLocationServicesTurnedOn(mContext))
{ {
Logger.d(TAG, "Don't show 'location resolution' dialog because location services are already on"); int statusCode = ((ApiException) e).getStatusCode();
mFusedLocationClient.requestLocationUpdates(locationRequest, mCallback, Looper.myLooper()); if (statusCode == LocationSettingsStatusCodes.RESOLUTION_REQUIRED)
return; {
// This case happens if at least one of the following system settings is off:
// 1. Location Services a.k.a GPS;
// 2. Google Location Accuracy a.k.a High Accuracy;
// 3. Both Wi-Fi && Mobile Data together (needed for 2).
//
// PendingIntent below will show a special Google "For better experience... enable (1) and/or (2) and/or
// (3)" dialog. This system dialog can change system settings if "Yes" is pressed. We can't do it from our
// app. However, we don't want to annoy a user who disabled (2) or (3) intentionally. GPS (1) is mandatory
// to continue, while (2) and (3) are not dealbreakers here.
//
// See https://github.com/organicmaps/organicmaps/issues/3846
//
if (LocationUtils.areLocationServicesTurnedOn(mContext))
{
Logger.d(TAG, "Don't show 'location resolution' dialog because location services are already on");
mFusedLocationClient.requestLocationUpdates(locationRequest, mCallback, Looper.myLooper());
return;
}
Logger.d(TAG, "Requesting 'location resolution' dialog");
final ResolvableApiException resolvable = (ResolvableApiException) e;
final PendingIntent pendingIntent = resolvable.getResolution();
// Call this callback in the next event loop to allow LocationHelper::start() to finish.
runLater(() -> mListener.onLocationResolutionRequired(pendingIntent));
return;
}
} }
Logger.d(TAG, "Requesting 'location resolution' dialog"); catch (ClassCastException ex)
final ResolvableApiException resolvable = (ResolvableApiException) e; {
final PendingIntent pendingIntent = resolvable.getResolution(); // Ignore, should be an impossible error.
// https://developers.google.com/android/reference/com/google/android/gms/location/SettingsClient
Logger.e(TAG, "An error that should be impossible: " + ex);
}
// Location settings are not satisfied. However, we have no way to fix the
// settings so we won't show the dialog.
Logger.e(TAG, "Service is not available: " + e);
// Call this callback in the next event loop to allow LocationHelper::start() to finish. // Call this callback in the next event loop to allow LocationHelper::start() to finish.
runLater(() -> mListener.onLocationResolutionRequired(pendingIntent)); runLater(mListener::onFusedLocationUnsupported);
return; });
}
}
catch (ClassCastException ex)
{
// Ignore, should be an impossible error.
// https://developers.google.com/android/reference/com/google/android/gms/location/SettingsClient
Logger.e(TAG, "An error that should be impossible: " + ex);
}
// Location settings are not satisfied. However, we have no way to fix the
// settings so we won't show the dialog.
Logger.e(TAG, "Service is not available: " + e);
// Call this callback in the next event loop to allow LocationHelper::start() to finish.
runLater(mListener::onFusedLocationUnsupported);
});
} }
@Override @Override

View File

@@ -1,13 +1,11 @@
package app.organicmaps.sdk.location; package app.organicmaps.sdk.location;
import android.content.Context; import android.content.Context;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GoogleApiAvailability;
import app.organicmaps.sdk.util.Config; import app.organicmaps.sdk.util.Config;
import app.organicmaps.sdk.util.log.Logger; import app.organicmaps.sdk.util.log.Logger;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GoogleApiAvailability;
public class LocationProviderFactory public class LocationProviderFactory
{ {
@@ -18,7 +16,8 @@ public class LocationProviderFactory
return GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(context) == ConnectionResult.SUCCESS; return GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(context) == ConnectionResult.SUCCESS;
} }
public static BaseLocationProvider getProvider(@NonNull Context context, @NonNull BaseLocationProvider.Listener listener) public static BaseLocationProvider getProvider(@NonNull Context context,
@NonNull BaseLocationProvider.Listener listener)
{ {
if (isGoogleLocationAvailable(context) && Config.useGoogleServices()) if (isGoogleLocationAvailable(context) && Config.useGoogleServices())
{ {

View File

@@ -5,10 +5,16 @@ import android.content.res.Resources;
import android.graphics.Color; import android.graphics.Color;
import android.view.View; import android.view.View;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.core.content.ContextCompat; import androidx.core.content.ContextCompat;
import app.organicmaps.sdk.Framework;
import app.organicmaps.sdk.bookmarks.data.BookmarkManager;
import app.organicmaps.sdk.bookmarks.data.ElevationInfo;
import app.organicmaps.util.ThemeUtils;
import app.organicmaps.util.Utils;
import app.organicmaps.widget.placepage.AxisValueFormatter;
import app.organicmaps.widget.placepage.CurrentLocationMarkerView;
import app.organicmaps.widget.placepage.FloatingMarkerView;
import com.github.mikephil.charting.charts.LineChart; import com.github.mikephil.charting.charts.LineChart;
import com.github.mikephil.charting.components.Legend; import com.github.mikephil.charting.components.Legend;
import com.github.mikephil.charting.components.MarkerView; import com.github.mikephil.charting.components.MarkerView;
@@ -20,16 +26,6 @@ import com.github.mikephil.charting.data.LineDataSet;
import com.github.mikephil.charting.formatter.ValueFormatter; import com.github.mikephil.charting.formatter.ValueFormatter;
import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.highlight.Highlight;
import com.github.mikephil.charting.listener.OnChartValueSelectedListener; import com.github.mikephil.charting.listener.OnChartValueSelectedListener;
import app.organicmaps.sdk.Framework;
import app.organicmaps.sdk.bookmarks.data.BookmarkManager;
import app.organicmaps.sdk.bookmarks.data.ElevationInfo;
import app.organicmaps.widget.placepage.AxisValueFormatter;
import app.organicmaps.widget.placepage.CurrentLocationMarkerView;
import app.organicmaps.widget.placepage.FloatingMarkerView;
import app.organicmaps.util.ThemeUtils;
import app.organicmaps.util.Utils;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
@@ -151,7 +147,7 @@ public class ChartController implements OnChartValueSelectedListener,
mTrackId = info.getId(); mTrackId = info.getId();
List<Entry> values = new ArrayList<>(); List<Entry> values = new ArrayList<>();
for (ElevationInfo.Point point: info.getPoints()) for (ElevationInfo.Point point : info.getPoints())
values.add(new Entry((float) point.getDistance(), point.getAltitude())); values.add(new Entry((float) point.getDistance(), point.getAltitude()));
LineDataSet set = new LineDataSet(values, "Elevation_profile_points"); LineDataSet set = new LineDataSet(values, "Elevation_profile_points");
@@ -184,15 +180,15 @@ public class ChartController implements OnChartValueSelectedListener,
} }
@Override @Override
public void onValueSelected(Entry e, Highlight h) { public void onValueSelected(Entry e, Highlight h)
{
mFloatingMarkerView.updateOffsets(e, h); mFloatingMarkerView.updateOffsets(e, h);
Highlight curPos = getCurrentPosHighlight(); Highlight curPos = getCurrentPosHighlight();
if (mCurrentPositionOutOfTrack) if (mCurrentPositionOutOfTrack)
mChart.highlightValues(Collections.singletonList(h), Collections.singletonList(mFloatingMarkerView)); mChart.highlightValues(Collections.singletonList(h), Collections.singletonList(mFloatingMarkerView));
else else
mChart.highlightValues(Arrays.asList(curPos, h), Arrays.asList(mCurrentLocationMarkerView, mChart.highlightValues(Arrays.asList(curPos, h), Arrays.asList(mCurrentLocationMarkerView, mFloatingMarkerView));
mFloatingMarkerView));
if (mTrackId == Utils.INVALID_ID) if (mTrackId == Utils.INVALID_ID)
return; return;

View File

@@ -18,7 +18,6 @@ import android.location.Location;
import android.os.Bundle; import android.os.Bundle;
import android.text.TextUtils; import android.text.TextUtils;
import android.view.View; import android.view.View;
import androidx.activity.result.ActivityResultLauncher; import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts; import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.CallSuper; import androidx.annotation.CallSuper;
@@ -28,10 +27,10 @@ import androidx.annotation.StringRes;
import androidx.annotation.StyleRes; 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.intent.Factory;
import app.organicmaps.sdk.Framework; import app.organicmaps.sdk.Framework;
import app.organicmaps.sdk.downloader.CountryItem; import app.organicmaps.sdk.downloader.CountryItem;
import app.organicmaps.sdk.downloader.MapManager; import app.organicmaps.sdk.downloader.MapManager;
import app.organicmaps.intent.Factory;
import app.organicmaps.sdk.location.LocationListener; import app.organicmaps.sdk.location.LocationListener;
import app.organicmaps.sdk.util.Config; import app.organicmaps.sdk.util.Config;
import app.organicmaps.sdk.util.ConnectionState; import app.organicmaps.sdk.util.ConnectionState;
@@ -39,13 +38,11 @@ import app.organicmaps.sdk.util.StringUtils;
import app.organicmaps.sdk.util.UiUtils; import app.organicmaps.sdk.util.UiUtils;
import app.organicmaps.util.Utils; import app.organicmaps.util.Utils;
import app.organicmaps.util.WindowInsetUtils.PaddingInsetsListener; import app.organicmaps.util.WindowInsetUtils.PaddingInsetsListener;
import com.google.android.material.button.MaterialButton; import com.google.android.material.button.MaterialButton;
import com.google.android.material.checkbox.MaterialCheckBox; import com.google.android.material.checkbox.MaterialCheckBox;
import com.google.android.material.dialog.MaterialAlertDialogBuilder; import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.google.android.material.progressindicator.LinearProgressIndicator; import com.google.android.material.progressindicator.LinearProgressIndicator;
import com.google.android.material.textview.MaterialTextView; import com.google.android.material.textview.MaterialTextView;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
@@ -81,8 +78,7 @@ public class DownloadResourcesLegacyActivity extends BaseMwmFragmentActivity
private int mCountryDownloadListenerSlot; private int mCountryDownloadListenerSlot;
private final LocationListener mLocationListener = new LocationListener() private final LocationListener mLocationListener = new LocationListener() {
{
@Override @Override
public void onLocationUpdated(Location location) public void onLocationUpdated(Location location)
{ {
@@ -117,34 +113,33 @@ public class DownloadResourcesLegacyActivity extends BaseMwmFragmentActivity
} }
}; };
private final app.organicmaps.sdk.DownloadResourcesLegacyActivity.Listener mResourcesDownloadListener = new app.organicmaps.sdk.DownloadResourcesLegacyActivity.Listener() private final app.organicmaps.sdk.DownloadResourcesLegacyActivity.Listener mResourcesDownloadListener =
{ new app.organicmaps.sdk.DownloadResourcesLegacyActivity.Listener() {
@Override @Override
public void onProgress(final int percent) public void onProgress(final int percent)
{ {
if (!isFinishing()) if (!isFinishing())
mProgress.setProgressCompat(percent, true); mProgress.setProgressCompat(percent, true);
} }
@Override @Override
public void onFinish(final int errorCode) public void onFinish(final int errorCode)
{ {
if (isFinishing()) if (isFinishing())
return; return;
if (errorCode == ERR_DOWNLOAD_SUCCESS) if (errorCode == ERR_DOWNLOAD_SUCCESS)
{ {
final int res = nativeStartNextFileDownload(mResourcesDownloadListener); final int res = nativeStartNextFileDownload(mResourcesDownloadListener);
if (res == ERR_NO_MORE_FILES) if (res == ERR_NO_MORE_FILES)
finishFilesDownload(res); finishFilesDownload(res);
} }
else else
finishFilesDownload(errorCode); finishFilesDownload(errorCode);
} }
}; };
private final MapManager.StorageCallback mCountryDownloadListener = new MapManager.StorageCallback() private final MapManager.StorageCallback mCountryDownloadListener = new MapManager.StorageCallback() {
{
@Override @Override
public void onStatusChanged(List<MapManager.StorageCallbackData> data) public void onStatusChanged(List<MapManager.StorageCallbackData> data)
{ {
@@ -155,14 +150,14 @@ public class DownloadResourcesLegacyActivity extends BaseMwmFragmentActivity
switch (item.newStatus) switch (item.newStatus)
{ {
case CountryItem.STATUS_DONE: case CountryItem.STATUS_DONE:
mAreResourcesDownloaded = true; mAreResourcesDownloaded = true;
showMap(); showMap();
return; return;
case CountryItem.STATUS_FAILED: case CountryItem.STATUS_FAILED:
MapManager.showError(DownloadResourcesLegacyActivity.this, item, null); MapManager.showError(DownloadResourcesLegacyActivity.this, item, null);
return; return;
} }
} }
} }
@@ -237,8 +232,7 @@ public class DownloadResourcesLegacyActivity extends BaseMwmFragmentActivity
private void setDownloadMessage(int bytesToDownload) private void setDownloadMessage(int bytesToDownload)
{ {
mTvMessage.setText(getString(R.string.download_resources, mTvMessage.setText(getString(R.string.download_resources, StringUtils.getFileSizeString(this, bytesToDownload)));
StringUtils.getFileSizeString(this, bytesToDownload)));
} }
private boolean prepareFilesDownload(boolean showMap) private boolean prepareFilesDownload(boolean showMap)
@@ -375,7 +369,7 @@ public class DownloadResourcesLegacyActivity extends BaseMwmFragmentActivity
CountryItem item = CountryItem.fill(mCurrentCountry); CountryItem item = CountryItem.fill(mCurrentCountry);
String fileSizeString = StringUtils.getFileSizeString(this, item.totalSize); String fileSizeString = StringUtils.getFileSizeString(this, item.totalSize);
mTvMessage.setText(getString(R.string.downloading_country_can_proceed, item.name, fileSizeString)); mTvMessage.setText(getString(R.string.downloading_country_can_proceed, item.name, fileSizeString));
mProgress.setMax((int)item.totalSize); mProgress.setMax((int) item.totalSize);
mProgress.setProgressCompat(0, true); mProgress.setProgressCompat(0, true);
mCountryDownloadListenerSlot = MapManager.nativeSubscribe(mCountryDownloadListener); mCountryDownloadListenerSlot = MapManager.nativeSubscribe(mCountryDownloadListener);
@@ -399,8 +393,10 @@ public class DownloadResourcesLegacyActivity extends BaseMwmFragmentActivity
if (mAlertDialog != null && mAlertDialog.isShowing()) if (mAlertDialog != null && mAlertDialog.isShowing())
return; return;
@StringRes final int titleId; @StringRes
@StringRes final int messageId = switch (result) final int titleId;
@StringRes
final int messageId = switch (result)
{ {
case ERR_NOT_ENOUGH_FREE_SPACE -> case ERR_NOT_ENOUGH_FREE_SPACE ->
{ {
@@ -415,8 +411,8 @@ public class DownloadResourcesLegacyActivity extends BaseMwmFragmentActivity
case ERR_DOWNLOAD_ERROR -> case ERR_DOWNLOAD_ERROR ->
{ {
titleId = R.string.connection_failure; titleId = R.string.connection_failure;
yield (ConnectionState.INSTANCE.isConnected() ? R.string.download_has_failed yield(ConnectionState.INSTANCE.isConnected() ? R.string.download_has_failed
: R.string.common_check_internet_connection_dialog); : R.string.common_check_internet_connection_dialog);
} }
case ERR_DISK_ERROR -> case ERR_DISK_ERROR ->
{ {
@@ -426,17 +422,18 @@ public class DownloadResourcesLegacyActivity extends BaseMwmFragmentActivity
default -> throw new AssertionError("Unexpected result code = " + result); default -> throw new AssertionError("Unexpected result code = " + result);
}; };
mAlertDialog = new MaterialAlertDialogBuilder(this, R.style.MwmTheme_AlertDialog) mAlertDialog = new MaterialAlertDialogBuilder(this, R.style.MwmTheme_AlertDialog)
.setTitle(titleId) .setTitle(titleId)
.setMessage(messageId) .setMessage(messageId)
.setCancelable(true) .setCancelable(true)
.setOnCancelListener((dialog) -> setAction(PAUSE)) .setOnCancelListener((dialog) -> setAction(PAUSE))
.setPositiveButton(R.string.try_again, (dialog, which) -> { .setPositiveButton(R.string.try_again,
setAction(TRY_AGAIN); (dialog, which) -> {
onTryAgainClicked(); setAction(TRY_AGAIN);
}) onTryAgainClicked();
.setOnDismissListener(dialog -> mAlertDialog = null) })
.show(); .setOnDismissListener(dialog -> mAlertDialog = null)
.show();
} }
@Override @Override

View File

@@ -10,17 +10,14 @@ import android.view.SurfaceHolder;
import android.view.SurfaceView; import android.view.SurfaceView;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.core.content.res.ConfigurationHelper; import androidx.core.content.res.ConfigurationHelper;
import app.organicmaps.base.BaseMwmFragment; import app.organicmaps.base.BaseMwmFragment;
import app.organicmaps.sdk.display.DisplayType;
import app.organicmaps.sdk.Map; import app.organicmaps.sdk.Map;
import app.organicmaps.sdk.MapRenderingListener; import app.organicmaps.sdk.MapRenderingListener;
import app.organicmaps.sdk.display.DisplayType;
import app.organicmaps.sdk.util.log.Logger; import app.organicmaps.sdk.util.log.Logger;
import com.google.android.material.dialog.MaterialAlertDialogBuilder; import com.google.android.material.dialog.MaterialAlertDialogBuilder;
public class MapFragment extends BaseMwmFragment implements View.OnTouchListener, SurfaceHolder.Callback public class MapFragment extends BaseMwmFragment implements View.OnTouchListener, SurfaceHolder.Callback
@@ -71,7 +68,8 @@ public class MapFragment extends BaseMwmFragment implements View.OnTouchListener
public void surfaceChanged(SurfaceHolder surfaceHolder, int format, int width, int height) public void surfaceChanged(SurfaceHolder surfaceHolder, int format, int width, int height)
{ {
Logger.d(TAG); Logger.d(TAG);
mMap.onSurfaceChanged(requireContext(), surfaceHolder.getSurface(), surfaceHolder.getSurfaceFrame(), surfaceHolder.isCreating()); mMap.onSurfaceChanged(requireContext(), surfaceHolder.getSurface(), surfaceHolder.getSurfaceFrame(),
surfaceHolder.isCreating());
} }
@Override @Override

View File

@@ -2,10 +2,8 @@ package app.organicmaps;
import android.content.Intent; import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import app.organicmaps.base.BaseMwmFragmentActivity; import app.organicmaps.base.BaseMwmFragmentActivity;
import app.organicmaps.sdk.display.DisplayChangedListener; import app.organicmaps.sdk.display.DisplayChangedListener;
import app.organicmaps.sdk.display.DisplayManager; import app.organicmaps.sdk.display.DisplayManager;
@@ -34,8 +32,7 @@ public class MapPlaceholderActivity extends BaseMwmFragmentActivity implements D
public void onDisplayChangedToDevice(@NonNull Runnable onTaskFinishedCallback) public void onDisplayChangedToDevice(@NonNull Runnable onTaskFinishedCallback)
{ {
mRemoveDisplayListener = false; mRemoveDisplayListener = false;
startActivity(new Intent(this, MwmActivity.class) startActivity(new Intent(this, MwmActivity.class).putExtra(MwmActivity.EXTRA_UPDATE_THEME, true));
.putExtra(MwmActivity.EXTRA_UPDATE_THEME, true));
finish(); finish();
onTaskFinishedCallback.run(); onTaskFinishedCallback.run();
} }

File diff suppressed because it is too large Load Diff

View File

@@ -7,7 +7,6 @@ import android.app.Application;
import android.content.Context; import android.content.Context;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.os.Bundle; import android.os.Bundle;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.annotation.UiThread; import androidx.annotation.UiThread;
@@ -15,30 +14,28 @@ import androidx.lifecycle.DefaultLifecycleObserver;
import androidx.lifecycle.LifecycleObserver; import androidx.lifecycle.LifecycleObserver;
import androidx.lifecycle.LifecycleOwner; import androidx.lifecycle.LifecycleOwner;
import androidx.lifecycle.ProcessLifecycleOwner; import androidx.lifecycle.ProcessLifecycleOwner;
import java.io.IOException;
import java.lang.ref.WeakReference;
import app.organicmaps.background.OsmUploadWork; import app.organicmaps.background.OsmUploadWork;
import app.organicmaps.downloader.Android7RootCertificateWorkaround; import app.organicmaps.downloader.Android7RootCertificateWorkaround;
import app.organicmaps.downloader.DownloaderNotifier; import app.organicmaps.downloader.DownloaderNotifier;
import app.organicmaps.sdk.display.DisplayManager; import app.organicmaps.location.TrackRecordingService;
import app.organicmaps.routing.NavigationService;
import app.organicmaps.routing.RoutingController;
import app.organicmaps.sdk.Map; import app.organicmaps.sdk.Map;
import app.organicmaps.sdk.OrganicMaps;
import app.organicmaps.sdk.display.DisplayManager;
import app.organicmaps.sdk.location.LocationHelper; import app.organicmaps.sdk.location.LocationHelper;
import app.organicmaps.sdk.location.LocationState; import app.organicmaps.sdk.location.LocationState;
import app.organicmaps.sdk.location.SensorHelper; import app.organicmaps.sdk.location.SensorHelper;
import app.organicmaps.sdk.location.TrackRecorder; import app.organicmaps.sdk.location.TrackRecorder;
import app.organicmaps.location.TrackRecordingService;
import app.organicmaps.sdk.maplayer.isolines.IsolinesManager; import app.organicmaps.sdk.maplayer.isolines.IsolinesManager;
import app.organicmaps.sdk.maplayer.subway.SubwayManager; import app.organicmaps.sdk.maplayer.subway.SubwayManager;
import app.organicmaps.routing.NavigationService;
import app.organicmaps.routing.RoutingController;
import app.organicmaps.sdk.OrganicMaps;
import app.organicmaps.sdk.util.Config; import app.organicmaps.sdk.util.Config;
import app.organicmaps.sdk.util.ConnectionState; import app.organicmaps.sdk.util.ConnectionState;
import app.organicmaps.util.Utils;
import app.organicmaps.sdk.util.log.Logger; import app.organicmaps.sdk.util.log.Logger;
import app.organicmaps.sdk.util.log.LogsManager; import app.organicmaps.sdk.util.log.LogsManager;
import app.organicmaps.util.Utils;
import java.io.IOException;
import java.lang.ref.WeakReference;
public class MwmApplication extends Application implements Application.ActivityLifecycleCallbacks public class MwmApplication extends Application implements Application.ActivityLifecycleCallbacks
{ {
@@ -146,8 +143,7 @@ public class MwmApplication extends Application implements Application.ActivityL
}); });
} }
private final LifecycleObserver mProcessLifecycleObserver = new DefaultLifecycleObserver() private final LifecycleObserver mProcessLifecycleObserver = new DefaultLifecycleObserver() {
{
@Override @Override
public void onStart(@NonNull LifecycleOwner owner) public void onStart(@NonNull LifecycleOwner owner)
{ {

View File

@@ -5,21 +5,19 @@ import android.animation.ValueAnimator;
import android.os.Bundle; import android.os.Bundle;
import android.view.View; import android.view.View;
import android.view.animation.AccelerateInterpolator; import android.view.animation.AccelerateInterpolator;
import androidx.annotation.IntegerRes; import androidx.annotation.IntegerRes;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import org.chromium.base.ObserverList;
import app.organicmaps.sdk.util.UiUtils; import app.organicmaps.sdk.util.UiUtils;
import org.chromium.base.ObserverList;
class PanelAnimator class PanelAnimator
{ {
private final MwmActivity mActivity; private final MwmActivity mActivity;
private final ObserverList<MwmActivity.LeftAnimationTrackListener> mAnimationTrackListeners = new ObserverList<>(); private final ObserverList<MwmActivity.LeftAnimationTrackListener> mAnimationTrackListeners = new ObserverList<>();
private final ObserverList.RewindableIterator<MwmActivity.LeftAnimationTrackListener> mAnimationTrackIterator = mAnimationTrackListeners.rewindableIterator(); private final ObserverList.RewindableIterator<MwmActivity.LeftAnimationTrackListener> mAnimationTrackIterator =
mAnimationTrackListeners.rewindableIterator();
private final View mPanel; private final View mPanel;
private final int mWidth; private final int mWidth;
@IntegerRes @IntegerRes
@@ -50,7 +48,8 @@ class PanelAnimator
} }
/** @param completionListener will be called before the fragment becomes actually visible */ /** @param completionListener will be called before the fragment becomes actually visible */
public void show(final Class<? extends Fragment> clazz, final Bundle args, @Nullable final Runnable completionListener) public void show(final Class<? extends Fragment> clazz, final Bundle args,
@Nullable final Runnable completionListener)
{ {
if (isVisible()) if (isVisible())
{ {
@@ -78,8 +77,7 @@ class PanelAnimator
ValueAnimator animator = ValueAnimator.ofFloat(-mWidth, 0.0f); ValueAnimator animator = ValueAnimator.ofFloat(-mWidth, 0.0f);
animator.addUpdateListener(this::track); animator.addUpdateListener(this::track);
animator.addListener(new UiUtils.SimpleAnimatorListener() animator.addListener(new UiUtils.SimpleAnimatorListener() {
{
@Override @Override
public void onAnimationEnd(Animator animation) public void onAnimationEnd(Animator animation)
{ {
@@ -109,8 +107,7 @@ class PanelAnimator
ValueAnimator animator = ValueAnimator.ofFloat(0.0f, -mWidth); ValueAnimator animator = ValueAnimator.ofFloat(0.0f, -mWidth);
animator.addUpdateListener(this::track); animator.addUpdateListener(this::track);
animator.addListener(new UiUtils.SimpleAnimatorListener() animator.addListener(new UiUtils.SimpleAnimatorListener() {
{
@Override @Override
public void onAnimationEnd(Animator animation) public void onAnimationEnd(Animator animation)
{ {

View File

@@ -9,7 +9,6 @@ import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.util.Log; import android.util.Log;
import android.view.View; import android.view.View;
import androidx.activity.result.ActivityResultLauncher; import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts; import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.Keep; import androidx.annotation.Keep;
@@ -21,20 +20,18 @@ import androidx.core.graphics.Insets;
import androidx.core.view.OnApplyWindowInsetsListener; import androidx.core.view.OnApplyWindowInsetsListener;
import androidx.core.view.ViewCompat; import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat; import androidx.core.view.WindowInsetsCompat;
import app.organicmaps.sdk.display.DisplayManager;
import app.organicmaps.downloader.DownloaderActivity; import app.organicmaps.downloader.DownloaderActivity;
import app.organicmaps.intent.Factory; import app.organicmaps.intent.Factory;
import app.organicmaps.sdk.display.DisplayManager;
import app.organicmaps.sdk.location.LocationHelper; import app.organicmaps.sdk.location.LocationHelper;
import app.organicmaps.sdk.util.Config; import app.organicmaps.sdk.util.Config;
import app.organicmaps.sdk.util.LocationUtils; import app.organicmaps.sdk.util.LocationUtils;
import app.organicmaps.sdk.util.concurrency.UiThread;
import app.organicmaps.sdk.util.log.Logger;
import app.organicmaps.util.SharingUtils; import app.organicmaps.util.SharingUtils;
import app.organicmaps.util.ThemeUtils; import app.organicmaps.util.ThemeUtils;
import app.organicmaps.util.Utils; import app.organicmaps.util.Utils;
import app.organicmaps.sdk.util.concurrency.UiThread;
import app.organicmaps.sdk.util.log.Logger;
import com.google.android.material.dialog.MaterialAlertDialogBuilder; import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import java.io.IOException; import java.io.IOException;
import java.util.Objects; import java.util.Objects;
@@ -86,7 +83,7 @@ public class SplashActivity extends AppCompatActivity
} }
}); });
mPermissionRequest = registerForActivityResult(new ActivityResultContracts.RequestMultiplePermissions(), mPermissionRequest = registerForActivityResult(new ActivityResultContracts.RequestMultiplePermissions(),
result -> Config.setLocationRequested()); result -> Config.setLocationRequested());
mApiRequest = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> { mApiRequest = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> {
setResult(result.getResultCode(), result.getData()); setResult(result.getResultCode(), result.getData());
finish(); finish();
@@ -109,10 +106,7 @@ public class SplashActivity extends AppCompatActivity
if (!Config.isLocationRequested() && !LocationUtils.checkLocationPermission(this)) if (!Config.isLocationRequested() && !LocationUtils.checkLocationPermission(this))
{ {
Logger.d(TAG, "Requesting location permissions"); Logger.d(TAG, "Requesting location permissions");
mPermissionRequest.launch(new String[]{ mPermissionRequest.launch(new String[] {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION});
ACCESS_COARSE_LOCATION,
ACCESS_FINE_LOCATION
});
return; return;
} }
@@ -140,19 +134,13 @@ public class SplashActivity extends AppCompatActivity
{ {
mCanceled = true; mCanceled = true;
new MaterialAlertDialogBuilder(this, R.style.MwmTheme_AlertDialog) new MaterialAlertDialogBuilder(this, R.style.MwmTheme_AlertDialog)
.setTitle(titleId) .setTitle(titleId)
.setMessage(messageId) .setMessage(messageId)
.setPositiveButton( .setPositiveButton(
R.string.report_a_bug, R.string.report_a_bug,
(dialog, which) -> Utils.sendBugReport( (dialog, which) -> Utils.sendBugReport(mShareLauncher, this, "Fatal Error", Log.getStackTraceString(error)))
mShareLauncher, .setCancelable(false)
this, .show();
"Fatal Error",
Log.getStackTraceString(error)
)
)
.setCancelable(false)
.show();
} }
private void init() private void init()
@@ -162,7 +150,8 @@ public class SplashActivity extends AppCompatActivity
try try
{ {
asyncContinue = app.initOrganicMaps(this::processNavigation); asyncContinue = app.initOrganicMaps(this::processNavigation);
} catch (IOException error) }
catch (IOException error)
{ {
showFatalErrorDialog(R.string.dialog_error_storage_title, R.string.dialog_error_storage_message, error); showFatalErrorDialog(R.string.dialog_error_storage_title, R.string.dialog_error_storage_message, error);
return; return;
@@ -195,9 +184,12 @@ public class SplashActivity extends AppCompatActivity
// https://github.com/organicmaps/organicmaps/issues/6944 // https://github.com/organicmaps/organicmaps/issues/6944
final Intent intent = Objects.requireNonNull(getIntent()); final Intent intent = Objects.requireNonNull(getIntent());
if (isManageSpaceActivity(intent)) { if (isManageSpaceActivity(intent))
{
intent.setComponent(new ComponentName(this, DownloaderActivity.class)); intent.setComponent(new ComponentName(this, DownloaderActivity.class));
} else { }
else
{
intent.setComponent(new ComponentName(this, DownloadResourcesLegacyActivity.class)); intent.setComponent(new ComponentName(this, DownloadResourcesLegacyActivity.class));
} }
@@ -219,11 +211,14 @@ public class SplashActivity extends AppCompatActivity
finish(); finish();
} }
private boolean isManageSpaceActivity(Intent intent) { private boolean isManageSpaceActivity(Intent intent)
{
var component = intent.getComponent(); var component = intent.getComponent();
if (!Intent.ACTION_VIEW.equals(intent.getAction())) return false; if (!Intent.ACTION_VIEW.equals(intent.getAction()))
if (component == null) return false; return false;
if (component == null)
return false;
var manageSpaceActivityName = BuildConfig.APPLICATION_ID + ".ManageSpaceActivity"; var manageSpaceActivityName = BuildConfig.APPLICATION_ID + ".ManageSpaceActivity";

View File

@@ -7,9 +7,7 @@ import android.net.Uri;
import android.view.View; import android.view.View;
import android.webkit.WebView; import android.webkit.WebView;
import android.webkit.WebViewClient; import android.webkit.WebViewClient;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import app.organicmaps.base.OnBackPressListener; import app.organicmaps.base.OnBackPressListener;
import app.organicmaps.sdk.util.UiUtils; import app.organicmaps.sdk.util.UiUtils;
@@ -21,8 +19,7 @@ public abstract class WebContainerDelegate implements OnBackPressListener
@SuppressLint("SetJavaScriptEnabled") @SuppressLint("SetJavaScriptEnabled")
private void initWebView(String url) private void initWebView(String url)
{ {
mWebView.setWebViewClient(new WebViewClient() mWebView.setWebViewClient(new WebViewClient() {
{
@Override @Override
public void onPageFinished(WebView view, String url) public void onPageFinished(WebView view, String url)
{ {
@@ -37,7 +34,7 @@ public abstract class WebContainerDelegate implements OnBackPressListener
{ {
MailTo parser = MailTo.parse(url); MailTo parser = MailTo.parse(url);
doStartActivity(new Intent(Intent.ACTION_SEND) doStartActivity(new Intent(Intent.ACTION_SEND)
.putExtra(Intent.EXTRA_EMAIL, new String[] { parser.getTo() }) .putExtra(Intent.EXTRA_EMAIL, new String[] {parser.getTo()})
.putExtra(Intent.EXTRA_TEXT, parser.getBody()) .putExtra(Intent.EXTRA_TEXT, parser.getBody())
.putExtra(Intent.EXTRA_SUBJECT, parser.getSubject()) .putExtra(Intent.EXTRA_SUBJECT, parser.getSubject())
.putExtra(Intent.EXTRA_CC, parser.getCc()) .putExtra(Intent.EXTRA_CC, parser.getCc())
@@ -46,8 +43,7 @@ public abstract class WebContainerDelegate implements OnBackPressListener
return true; return true;
} }
doStartActivity(new Intent(Intent.ACTION_VIEW) doStartActivity(new Intent(Intent.ACTION_VIEW).setData(Uri.parse(url)));
.setData(Uri.parse(url)));
return true; return true;
} }
}); });

View File

@@ -4,18 +4,23 @@ import android.content.Context;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.SimpleExpandableListAdapter; import android.widget.SimpleExpandableListAdapter;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
/** /**
* Disables child selections, also fixes bug with SimpleExpandableListAdapter not switching expandedGroupLayout and collapsedGroupLayout correctly. * Disables child selections, also fixes bug with SimpleExpandableListAdapter not switching expandedGroupLayout and
* collapsedGroupLayout correctly.
*/ */
public class DisabledChildSimpleExpandableListAdapter extends SimpleExpandableListAdapter public class DisabledChildSimpleExpandableListAdapter extends SimpleExpandableListAdapter
{ {
public DisabledChildSimpleExpandableListAdapter(Context context, List<? extends Map<String, ?>> groupData, int expandedGroupLayout, int collapsedGroupLayout, String[] groupFrom, int[] groupTo, List<? extends List<? extends Map<String, ?>>> childData, int childLayout, String[] childFrom, int[] childTo) public DisabledChildSimpleExpandableListAdapter(Context context, List<? extends Map<String, ?>> groupData,
int expandedGroupLayout, int collapsedGroupLayout, String[] groupFrom,
int[] groupTo,
List<? extends List<? extends Map<String, ?>>> childData,
int childLayout, String[] childFrom, int[] childTo)
{ {
super(context, groupData, expandedGroupLayout, collapsedGroupLayout, groupFrom, groupTo, childData, childLayout, childFrom, childTo); super(context, groupData, expandedGroupLayout, collapsedGroupLayout, groupFrom, groupTo, childData, childLayout,
childFrom, childTo);
} }
@Override @Override
@@ -29,8 +34,7 @@ public class DisabledChildSimpleExpandableListAdapter extends SimpleExpandableLi
* See http://stackoverflow.com/questions/19520037/simpleexpandablelistadapter-and-expandedgrouplayout for details * See http://stackoverflow.com/questions/19520037/simpleexpandablelistadapter-and-expandedgrouplayout for details
*/ */
@Override @Override
public View getGroupView(int groupPosition, boolean isExpanded, View convertView, public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent)
ViewGroup parent)
{ {
return super.getGroupView(groupPosition, isExpanded, null, parent); return super.getGroupView(groupPosition, isExpanded, null, parent);
} }

View File

@@ -1,7 +1,6 @@
package app.organicmaps.adapter; package app.organicmaps.adapter;
import android.view.View; import android.view.View;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
public interface OnItemClickListener<T> public interface OnItemClickListener<T>

View File

@@ -1,7 +1,6 @@
package app.organicmaps.background; package app.organicmaps.background;
import android.content.Context; import android.content.Context;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.work.Constraints; import androidx.work.Constraints;
import androidx.work.NetworkType; import androidx.work.NetworkType;
@@ -17,7 +16,6 @@ import app.organicmaps.sdk.util.log.Logger;
public class OsmUploadWork extends Worker public class OsmUploadWork extends Worker
{ {
private static final String TAG = OsmUploadWork.class.getSimpleName(); private static final String TAG = OsmUploadWork.class.getSimpleName();
private final Context mContext; private final Context mContext;
private final WorkerParameters mWorkerParameters; private final WorkerParameters mWorkerParameters;

View File

@@ -1,8 +1,8 @@
package app.organicmaps.backup; package app.organicmaps.backup;
import static app.organicmaps.sdk.util.StorageUtils.isFolderWritable;
import static app.organicmaps.settings.BackupSettingsFragment.MAX_BACKUPS_DEFAULT_COUNT; import static app.organicmaps.settings.BackupSettingsFragment.MAX_BACKUPS_DEFAULT_COUNT;
import static app.organicmaps.settings.BackupSettingsFragment.MAX_BACKUPS_KEY; import static app.organicmaps.settings.BackupSettingsFragment.MAX_BACKUPS_KEY;
import static app.organicmaps.sdk.util.StorageUtils.isFolderWritable;
import android.content.Context; import android.content.Context;
import android.content.SharedPreferences; import android.content.SharedPreferences;
@@ -12,25 +12,23 @@ import android.text.SpannableStringBuilder;
import android.text.Spanned; import android.text.Spanned;
import android.text.TextUtils; import android.text.TextUtils;
import android.text.style.AbsoluteSizeSpan; import android.text.style.AbsoluteSizeSpan;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.documentfile.provider.DocumentFile; import androidx.documentfile.provider.DocumentFile;
import app.organicmaps.R;
import app.organicmaps.sdk.util.UiUtils;
import app.organicmaps.sdk.util.log.Logger;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import app.organicmaps.R;
import app.organicmaps.sdk.util.UiUtils;
import app.organicmaps.sdk.util.log.Logger;
public class BackupUtils public class BackupUtils
{ {
private static final String BACKUP_PREFIX = "backup_"; private static final String BACKUP_PREFIX = "backup_";
private static final String BACKUP_EXTENSION = ".kmz"; private static final String BACKUP_EXTENSION = ".kmz";
private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd_HH-mm-ss").withLocale(Locale.US); private static final DateTimeFormatter DATE_FORMATTER =
DateTimeFormatter.ofPattern("yyyy-MM-dd_HH-mm-ss").withLocale(Locale.US);
private static final String TAG = BackupUtils.class.getSimpleName(); private static final String TAG = BackupUtils.class.getSimpleName();
public static CharSequence formatReadableFolderPath(Context context, @NonNull Uri uri) public static CharSequence formatReadableFolderPath(Context context, @NonNull Uri uri)
@@ -57,8 +55,10 @@ public class BackupUtils
volumeName = context.getString(R.string.maps_storage_removable); volumeName = context.getString(R.string.maps_storage_removable);
SpannableStringBuilder sb = new SpannableStringBuilder(); SpannableStringBuilder sb = new SpannableStringBuilder();
sb.append(volumeName + ": \n", new AbsoluteSizeSpan(UiUtils.dimen(context, R.dimen.text_size_body_3)), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); sb.append(volumeName + ": \n", new AbsoluteSizeSpan(UiUtils.dimen(context, R.dimen.text_size_body_3)),
sb.append("/" + subPath, new AbsoluteSizeSpan(UiUtils.dimen(context, R.dimen.text_size_body_4)), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
sb.append("/" + subPath, new AbsoluteSizeSpan(UiUtils.dimen(context, R.dimen.text_size_body_4)),
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
return sb; return sb;
} }
@@ -68,12 +68,14 @@ public class BackupUtils
try try
{ {
return Integer.parseInt(rawValue); return Integer.parseInt(rawValue);
} catch (NumberFormatException e) }
catch (NumberFormatException e)
{ {
Logger.e(TAG, "Failed to parse max backups count, raw value: " + rawValue + " set to default: " + MAX_BACKUPS_DEFAULT_COUNT, e); Logger.e(
prefs.edit() TAG,
.putString(MAX_BACKUPS_KEY, String.valueOf(MAX_BACKUPS_DEFAULT_COUNT)) "Failed to parse max backups count, raw value: " + rawValue + " set to default: " + MAX_BACKUPS_DEFAULT_COUNT,
.apply(); e);
prefs.edit().putString(MAX_BACKUPS_KEY, String.valueOf(MAX_BACKUPS_DEFAULT_COUNT)).apply();
return MAX_BACKUPS_DEFAULT_COUNT; return MAX_BACKUPS_DEFAULT_COUNT;
} }
} }

View File

@@ -1,22 +1,14 @@
package app.organicmaps.backup; package app.organicmaps.backup;
import static app.organicmaps.backup.BackupUtils.getBackupName;
import static app.organicmaps.backup.BackupUtils.getBackupFolders; import static app.organicmaps.backup.BackupUtils.getBackupFolders;
import static app.organicmaps.backup.BackupUtils.getBackupName;
import static app.organicmaps.sdk.util.StorageUtils.copyFileToDocumentFile; import static app.organicmaps.sdk.util.StorageUtils.copyFileToDocumentFile;
import static app.organicmaps.sdk.util.StorageUtils.deleteDirectoryRecursive; import static app.organicmaps.sdk.util.StorageUtils.deleteDirectoryRecursive;
import android.app.Activity; import android.app.Activity;
import android.net.Uri; import android.net.Uri;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.documentfile.provider.DocumentFile; import androidx.documentfile.provider.DocumentFile;
import java.io.File;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
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.sdk.bookmarks.data.BookmarkSharingResult; import app.organicmaps.sdk.bookmarks.data.BookmarkSharingResult;
@@ -24,6 +16,11 @@ import app.organicmaps.sdk.bookmarks.data.KmlFileType;
import app.organicmaps.sdk.util.concurrency.ThreadPool; import app.organicmaps.sdk.util.concurrency.ThreadPool;
import app.organicmaps.sdk.util.concurrency.UiThread; import app.organicmaps.sdk.util.concurrency.UiThread;
import app.organicmaps.sdk.util.log.Logger; import app.organicmaps.sdk.util.log.Logger;
import java.io.File;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
public class LocalBackupManager implements BookmarkManager.BookmarksSharingListener public class LocalBackupManager implements BookmarkManager.BookmarksSharingListener
{ {
@@ -65,39 +62,39 @@ public class LocalBackupManager implements BookmarkManager.BookmarksSharingListe
ErrorCode errorCode = null; ErrorCode errorCode = null;
switch (result.getCode()) switch (result.getCode())
{ {
case BookmarkSharingResult.SUCCESS -> case BookmarkSharingResult.SUCCESS ->
{ {
if (!saveBackup(result)) if (!saveBackup(result))
{
Logger.e(TAG, "Failed to save backup. See system log above");
errorCode = ErrorCode.FILE_ERROR;
}
else
{
Logger.i(TAG, "Backup was created and saved successfully");
}
}
case BookmarkSharingResult.EMPTY_CATEGORY ->
{
errorCode = ErrorCode.EMPTY_CATEGORY;
Logger.e(TAG, "Failed to create backup. Category is empty");
}
case BookmarkSharingResult.ARCHIVE_ERROR ->
{
errorCode = ErrorCode.ARCHIVE_ERROR;
Logger.e(TAG, "Failed to create archive of bookmarks");
}
case BookmarkSharingResult.FILE_ERROR ->
{ {
Logger.e(TAG, "Failed to save backup. See system log above");
errorCode = ErrorCode.FILE_ERROR; errorCode = ErrorCode.FILE_ERROR;
Logger.e(TAG, "Failed create file for archive");
} }
else default ->
{ {
Logger.i(TAG, "Backup was created and saved successfully"); errorCode = ErrorCode.UNSUPPORTED;
Logger.e(TAG, "Failed to create backup. Unknown error");
} }
} }
case BookmarkSharingResult.EMPTY_CATEGORY ->
{
errorCode = ErrorCode.EMPTY_CATEGORY;
Logger.e(TAG, "Failed to create backup. Category is empty");
}
case BookmarkSharingResult.ARCHIVE_ERROR ->
{
errorCode = ErrorCode.ARCHIVE_ERROR;
Logger.e(TAG, "Failed to create archive of bookmarks");
}
case BookmarkSharingResult.FILE_ERROR ->
{
errorCode = ErrorCode.FILE_ERROR;
Logger.e(TAG, "Failed create file for archive");
}
default ->
{
errorCode = ErrorCode.UNSUPPORTED;
Logger.e(TAG, "Failed to create backup. Unknown error");
}
}
ErrorCode finalErrorCode = errorCode; ErrorCode finalErrorCode = errorCode;
UiThread.run(() -> { UiThread.run(() -> {
@@ -139,8 +136,8 @@ public class LocalBackupManager implements BookmarkManager.BookmarksSharingListe
} }
} }
cleanOldBackups(parentFolder); cleanOldBackups(parentFolder);
}
} catch (Exception e) catch (Exception e)
{ {
Logger.e(TAG, "Failed to save backup", e); Logger.e(TAG, "Failed to save backup", e);
} }

View File

@@ -8,9 +8,7 @@ import static app.organicmaps.settings.BackupSettingsFragment.LAST_BACKUP_TIME_K
import android.app.Activity; import android.app.Activity;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import androidx.preference.PreferenceManager; import androidx.preference.PreferenceManager;
import app.organicmaps.sdk.util.log.Logger; import app.organicmaps.sdk.util.log.Logger;
public class PeriodicBackupRunner public class PeriodicBackupRunner
@@ -67,7 +65,8 @@ public class PeriodicBackupRunner
try try
{ {
return Long.parseLong(prefs.getString(BACKUP_INTERVAL_KEY, defaultValue)); return Long.parseLong(prefs.getString(BACKUP_INTERVAL_KEY, defaultValue));
} catch (NumberFormatException e) }
catch (NumberFormatException e)
{ {
return 0; return 0;
} }
@@ -76,8 +75,7 @@ public class PeriodicBackupRunner
private void performBackup(String backupFolderPath, int maxBackups) private void performBackup(String backupFolderPath, int maxBackups)
{ {
LocalBackupManager backupManager = new LocalBackupManager(activity, backupFolderPath, maxBackups); LocalBackupManager backupManager = new LocalBackupManager(activity, backupFolderPath, maxBackups);
backupManager.setListener(new LocalBackupManager.Listener() backupManager.setListener(new LocalBackupManager.Listener() {
{
@Override @Override
public void onBackupStarted() public void onBackupStarted()
{ {

View File

@@ -3,12 +3,10 @@ package app.organicmaps.base;
import android.app.Application; import android.app.Application;
import android.content.Context; import android.content.Context;
import android.os.Bundle; import android.os.Bundle;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; 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; import app.organicmaps.util.ThemeUtils;
@@ -38,7 +36,7 @@ public class BaseMwmDialogFragment extends DialogFragment
int style = getStyle(); int style = getStyle();
int theme = getCustomTheme(); int theme = getCustomTheme();
if (style != STYLE_NORMAL || theme != 0) if (style != STYLE_NORMAL || theme != 0)
//noinspection WrongConstant // noinspection WrongConstant
setStyle(style, theme); setStyle(style, theme);
} }
@@ -62,5 +60,4 @@ public class BaseMwmDialogFragment extends DialogFragment
throw new IllegalStateException("Before call this method make sure that the context exists"); throw new IllegalStateException("Before call this method make sure that the context exists");
return (Application) context.getApplicationContext(); return (Application) context.getApplicationContext();
} }
} }

View File

@@ -1,9 +1,7 @@
package app.organicmaps.base; package app.organicmaps.base;
import android.content.Context; import android.content.Context;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import app.organicmaps.util.Utils; import app.organicmaps.util.Utils;
public class BaseMwmFragment extends Fragment implements OnBackPressListener public class BaseMwmFragment extends Fragment implements OnBackPressListener
@@ -20,5 +18,4 @@ public class BaseMwmFragment extends Fragment implements OnBackPressListener
{ {
return false; return false;
} }
} }

View File

@@ -7,7 +7,6 @@ import android.graphics.Color;
import android.media.AudioManager; import android.media.AudioManager;
import android.os.Bundle; import android.os.Bundle;
import android.view.MenuItem; import android.view.MenuItem;
import androidx.activity.EdgeToEdge; import androidx.activity.EdgeToEdge;
import androidx.activity.SystemBarStyle; import androidx.activity.SystemBarStyle;
import androidx.annotation.CallSuper; import androidx.annotation.CallSuper;
@@ -18,18 +17,15 @@ 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;
import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentManager;
import com.google.android.material.appbar.MaterialToolbar;
import app.organicmaps.MwmApplication; 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.util.RtlUtils;
import app.organicmaps.util.ThemeUtils;
import app.organicmaps.sdk.util.concurrency.UiThread; 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.ThemeUtils;
import com.google.android.material.appbar.MaterialToolbar;
import java.util.Objects; import java.util.Objects;
public abstract class BaseMwmFragmentActivity extends AppCompatActivity public abstract class BaseMwmFragmentActivity extends AppCompatActivity
@@ -47,7 +43,7 @@ public abstract class BaseMwmFragmentActivity extends AppCompatActivity
Context context = getApplicationContext(); Context context = getApplicationContext();
if (ThemeUtils.isDefaultTheme(context, theme)) if (ThemeUtils.isDefaultTheme(context, theme))
return R.style.MwmTheme; return R.style.MwmTheme;
if (ThemeUtils.isNightTheme(context, theme)) if (ThemeUtils.isNightTheme(context, theme))
return R.style.MwmTheme_Night; return R.style.MwmTheme_Night;
@@ -216,11 +212,13 @@ public abstract class BaseMwmFragmentActivity extends AppCompatActivity
/** /**
* Replace attached fragment with the new one. * Replace attached fragment with the new one.
*/ */
public void replaceFragment(@NonNull Class<? extends Fragment> fragmentClass, @Nullable Bundle args, @Nullable Runnable completionListener) public void replaceFragment(@NonNull Class<? extends Fragment> fragmentClass, @Nullable Bundle args,
@Nullable Runnable completionListener)
{ {
final int resId = getFragmentContentResId(); final int resId = getFragmentContentResId();
if (resId <= 0 || findViewById(resId) == null) if (resId <= 0 || findViewById(resId) == null)
throw new IllegalStateException("Fragment can't be added, since getFragmentContentResId() isn't implemented or returns wrong resourceId."); throw new IllegalStateException(
"Fragment can't be added, since getFragmentContentResId() isn't implemented or returns wrong resourceId.");
String name = fragmentClass.getName(); String name = fragmentClass.getName();
Fragment potentialInstance = getSupportFragmentManager().findFragmentByTag(name); Fragment potentialInstance = getSupportFragmentManager().findFragmentByTag(name);
@@ -230,9 +228,7 @@ public abstract class BaseMwmFragmentActivity extends AppCompatActivity
final FragmentFactory factory = manager.getFragmentFactory(); final FragmentFactory factory = manager.getFragmentFactory();
final Fragment fragment = factory.instantiate(getClassLoader(), name); final Fragment fragment = factory.instantiate(getClassLoader(), name);
fragment.setArguments(args); fragment.setArguments(args);
manager.beginTransaction() manager.beginTransaction().replace(resId, fragment, name).commitAllowingStateLoss();
.replace(resId, fragment, name)
.commitAllowingStateLoss();
manager.executePendingTransactions(); manager.executePendingTransactions();
if (completionListener != null) if (completionListener != null)
completionListener.run(); completionListener.run();
@@ -240,8 +236,8 @@ public abstract class BaseMwmFragmentActivity extends AppCompatActivity
} }
/** /**
* Override to automatically attach fragment in onCreate. Tag applied to fragment in back stack is set to fragment name, too. * Override to automatically attach fragment in onCreate. Tag applied to fragment in back stack is set to fragment
* WARNING : if custom layout for activity is set, getFragmentContentResId() must be implemented, too. * name, too. WARNING : if custom layout for activity is set, getFragmentContentResId() must be implemented, too.
* @return class of the fragment, eg FragmentClass.getClass() * @return class of the fragment, eg FragmentClass.getClass()
*/ */
protected Class<? extends Fragment> getFragmentClass() protected Class<? extends Fragment> getFragmentClass()

View File

@@ -5,7 +5,6 @@ import android.os.Bundle;
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 androidx.annotation.CallSuper; import androidx.annotation.CallSuper;
import androidx.annotation.LayoutRes; import androidx.annotation.LayoutRes;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
@@ -14,14 +13,12 @@ import androidx.core.view.ViewCompat;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import com.google.android.material.appbar.MaterialToolbar;
import app.organicmaps.R; import app.organicmaps.R;
import app.organicmaps.sdk.util.UiUtils; import app.organicmaps.sdk.util.UiUtils;
import app.organicmaps.util.Utils; import app.organicmaps.util.Utils;
import app.organicmaps.util.WindowInsetUtils.ScrollableContentInsetsListener; import app.organicmaps.util.WindowInsetUtils.ScrollableContentInsetsListener;
import app.organicmaps.widget.PlaceholderView; import app.organicmaps.widget.PlaceholderView;
import com.google.android.material.appbar.MaterialToolbar;
public abstract class BaseMwmRecyclerFragment<T extends RecyclerView.Adapter> extends Fragment public abstract class BaseMwmRecyclerFragment<T extends RecyclerView.Adapter> extends Fragment
{ {
@@ -39,8 +36,7 @@ public abstract class BaseMwmRecyclerFragment<T extends RecyclerView.Adapter> ex
private T mAdapter; private T mAdapter;
@NonNull @NonNull
private final View.OnClickListener mNavigationClickListener private final View.OnClickListener mNavigationClickListener = view -> Utils.navigateToParent(requireActivity());
= view -> Utils.navigateToParent(requireActivity());
@NonNull @NonNull
protected abstract T createAdapter(); protected abstract T createAdapter();

View File

@@ -2,10 +2,8 @@ package app.organicmaps.base;
import android.os.Bundle; import android.os.Bundle;
import android.view.View; import android.view.View;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import app.organicmaps.widget.ToolbarController; import app.organicmaps.widget.ToolbarController;
public class BaseMwmToolbarFragment extends BaseMwmFragment public class BaseMwmToolbarFragment extends BaseMwmFragment

View File

@@ -1,7 +1,6 @@
package app.organicmaps.base; package app.organicmaps.base;
import android.os.Bundle; 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;
@@ -10,12 +9,10 @@ import androidx.core.view.ViewCompat;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentFactory; import androidx.fragment.app.FragmentFactory;
import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentManager;
import com.google.android.material.appbar.MaterialToolbar;
import app.organicmaps.R; import app.organicmaps.R;
import app.organicmaps.sdk.util.UiUtils; import app.organicmaps.sdk.util.UiUtils;
import app.organicmaps.util.WindowInsetUtils.PaddingInsetsListener; import app.organicmaps.util.WindowInsetUtils.PaddingInsetsListener;
import com.google.android.material.appbar.MaterialToolbar;
public abstract class BaseToolbarActivity extends BaseMwmFragmentActivity public abstract class BaseToolbarActivity extends BaseMwmFragmentActivity
{ {
@@ -73,23 +70,20 @@ public abstract class BaseToolbarActivity extends BaseMwmFragmentActivity
return R.id.fragment_container; return R.id.fragment_container;
} }
public Fragment stackFragment(@NonNull Class<? extends Fragment> fragmentClass, public Fragment stackFragment(@NonNull Class<? extends Fragment> fragmentClass, @Nullable String title,
@Nullable String title, @Nullable Bundle args) @Nullable Bundle args)
{ {
final int resId = getFragmentContentResId(); final int resId = getFragmentContentResId();
if (resId <= 0 || findViewById(resId) == null) if (resId <= 0 || findViewById(resId) == null)
throw new IllegalStateException("Fragment can't be added, since getFragmentContentResId() " + throw new IllegalStateException("Fragment can't be added, since getFragmentContentResId() "
"isn't implemented or returns wrong resourceId."); + "isn't implemented or returns wrong resourceId.");
String name = fragmentClass.getName(); String name = fragmentClass.getName();
final FragmentManager manager = getSupportFragmentManager(); final FragmentManager manager = getSupportFragmentManager();
final FragmentFactory factory = manager.getFragmentFactory(); final FragmentFactory factory = manager.getFragmentFactory();
final Fragment fragment = factory.instantiate(getClassLoader(), name); final Fragment fragment = factory.instantiate(getClassLoader(), name);
fragment.setArguments(args); fragment.setArguments(args);
manager.beginTransaction() manager.beginTransaction().replace(resId, fragment, name).addToBackStack(null).commitAllowingStateLoss();
.replace(resId, fragment, name)
.addToBackStack(null)
.commitAllowingStateLoss();
manager.executePendingTransactions(); manager.executePendingTransactions();
if (title != null) if (title != null)

View File

@@ -1,16 +1,12 @@
package app.organicmaps.bookmarks; package app.organicmaps.bookmarks;
import android.content.Context; import android.content.Context;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import app.organicmaps.sdk.bookmarks.data.BookmarkCategory; import app.organicmaps.sdk.bookmarks.data.BookmarkCategory;
import java.util.List; import java.util.List;
public abstract class BaseBookmarkCategoryAdapter<V extends RecyclerView.ViewHolder> public abstract class BaseBookmarkCategoryAdapter<V extends RecyclerView.ViewHolder> extends RecyclerView.Adapter<V>
extends RecyclerView.Adapter<V>
{ {
@NonNull @NonNull
private final Context mContext; private final Context mContext;
@@ -54,6 +50,5 @@ public abstract class BaseBookmarkCategoryAdapter<V extends RecyclerView.ViewHol
if (position < 0 || position > categories.size() - 1) if (position < 0 || position > categories.size() - 1)
throw new ArrayIndexOutOfBoundsException(position); throw new ArrayIndexOutOfBoundsException(position);
return categories.get(position); return categories.get(position);
} }
} }

View File

@@ -3,13 +3,11 @@ package app.organicmaps.bookmarks;
import android.app.Activity; import android.app.Activity;
import android.content.Intent; import android.content.Intent;
import android.os.Bundle; 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.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;

View File

@@ -7,16 +7,13 @@ import android.content.Context;
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 androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import app.organicmaps.R; import app.organicmaps.R;
import app.organicmaps.adapter.OnItemClickListener; import app.organicmaps.adapter.OnItemClickListener;
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 java.util.List; import java.util.List;
public class BookmarkCategoriesAdapter extends BaseBookmarkCategoryAdapter<RecyclerView.ViewHolder> public class BookmarkCategoriesAdapter extends BaseBookmarkCategoryAdapter<RecyclerView.ViewHolder>
@@ -122,8 +119,7 @@ public class BookmarkCategoriesAdapter extends BaseBookmarkCategoryAdapter<Recyc
case TYPE_ACTION_HEADER -> case TYPE_ACTION_HEADER ->
{ {
HeaderViewHolder headerViewHolder = (HeaderViewHolder) holder; HeaderViewHolder headerViewHolder = (HeaderViewHolder) holder;
headerViewHolder.setAction(mMassOperationAction, headerViewHolder.setAction(mMassOperationAction, BookmarkManager.INSTANCE.areAllCategoriesInvisible());
BookmarkManager.INSTANCE.areAllCategoriesInvisible());
headerViewHolder.getText().setText(R.string.bookmark_lists); headerViewHolder.getText().setText(R.string.bookmark_lists);
} }
case TYPE_CATEGORY_ITEM -> case TYPE_CATEGORY_ITEM ->
@@ -191,7 +187,6 @@ public class BookmarkCategoriesAdapter extends BaseBookmarkCategoryAdapter<Recyc
private int toCategoryPosition(int adapterPosition) private int toCategoryPosition(int adapterPosition)
{ {
int type = getItemViewType(adapterPosition); int type = getItemViewType(adapterPosition);
if (type != TYPE_CATEGORY_ITEM) if (type != TYPE_CATEGORY_ITEM)
throw new AssertionError("An element at specified position is not category!"); throw new AssertionError("An element at specified position is not category!");

View File

@@ -12,7 +12,6 @@ import android.os.Bundle;
import android.provider.DocumentsContract; import android.provider.DocumentsContract;
import android.view.View; import android.view.View;
import android.widget.Toast; import android.widget.Toast;
import androidx.activity.result.ActivityResultLauncher; import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts; import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.CallSuper; import androidx.annotation.CallSuper;
@@ -20,42 +19,35 @@ import androidx.annotation.LayoutRes;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import app.organicmaps.MwmApplication; import app.organicmaps.MwmApplication;
import app.organicmaps.R; import app.organicmaps.R;
import app.organicmaps.adapter.OnItemClickListener; import app.organicmaps.adapter.OnItemClickListener;
import app.organicmaps.base.BaseMwmRecyclerFragment; import app.organicmaps.base.BaseMwmRecyclerFragment;
import app.organicmaps.dialog.EditTextDialogFragment;
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.sdk.bookmarks.data.BookmarkSharingResult; import app.organicmaps.sdk.bookmarks.data.BookmarkSharingResult;
import app.organicmaps.sdk.bookmarks.data.KmlFileType; import app.organicmaps.sdk.bookmarks.data.KmlFileType;
import app.organicmaps.dialog.EditTextDialogFragment;
import app.organicmaps.util.SharingUtils;
import app.organicmaps.util.Utils;
import app.organicmaps.widget.PlaceholderView;
import app.organicmaps.widget.recycler.DividerItemDecorationWithPadding;
import app.organicmaps.sdk.util.StorageUtils; import app.organicmaps.sdk.util.StorageUtils;
import app.organicmaps.util.bottomsheet.MenuBottomSheetFragment;
import app.organicmaps.util.bottomsheet.MenuBottomSheetItem;
import app.organicmaps.sdk.util.concurrency.ThreadPool; import app.organicmaps.sdk.util.concurrency.ThreadPool;
import app.organicmaps.sdk.util.concurrency.UiThread; 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.SharingUtils;
import app.organicmaps.util.Utils;
import app.organicmaps.util.bottomsheet.MenuBottomSheetFragment;
import app.organicmaps.util.bottomsheet.MenuBottomSheetItem;
import app.organicmaps.widget.PlaceholderView;
import app.organicmaps.widget.recycler.DividerItemDecorationWithPadding;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import java.io.File; import java.io.File;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
public class BookmarkCategoriesFragment extends BaseMwmRecyclerFragment<BookmarkCategoriesAdapter> public class BookmarkCategoriesFragment extends BaseMwmRecyclerFragment<BookmarkCategoriesAdapter>
implements BookmarkManager.BookmarksLoadingListener, implements BookmarkManager.BookmarksLoadingListener, CategoryListCallback, OnItemClickListener<BookmarkCategory>,
CategoryListCallback, OnItemMoreClickListener<BookmarkCategory>, OnItemLongClickListener<BookmarkCategory>,
OnItemClickListener<BookmarkCategory>, BookmarkManager.BookmarksSharingListener, MenuBottomSheetFragment.MenuBottomSheetInterface
OnItemMoreClickListener<BookmarkCategory>,
OnItemLongClickListener<BookmarkCategory>,
BookmarkManager.BookmarksSharingListener,
MenuBottomSheetFragment.MenuBottomSheetInterface
{ {
private static final String TAG = BookmarkCategoriesFragment.class.getSimpleName(); private static final String TAG = BookmarkCategoriesFragment.class.getSimpleName();
@@ -75,21 +67,24 @@ public class BookmarkCategoriesFragment extends BaseMwmRecyclerFragment<Bookmark
@NonNull @NonNull
private DataChangedListener mCategoriesAdapterObserver; private DataChangedListener mCategoriesAdapterObserver;
private final ActivityResultLauncher<Intent> startBookmarkListForResult = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), activityResult -> { private final ActivityResultLauncher<Intent> startBookmarkListForResult =
if( activityResult.getResultCode() == Activity.RESULT_OK) registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), activityResult -> {
onDeleteActionSelected(getSelectedCategory()); if (activityResult.getResultCode() == Activity.RESULT_OK)
}); onDeleteActionSelected(getSelectedCategory());
});
private final ActivityResultLauncher<Intent> startImportDirectoryForResult = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), activityResult -> private final ActivityResultLauncher<Intent> startImportDirectoryForResult =
{ registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), activityResult -> {
if( activityResult.getResultCode() == Activity.RESULT_OK) if (activityResult.getResultCode() == Activity.RESULT_OK)
onImportDirectoryResult(activityResult.getData()); onImportDirectoryResult(activityResult.getData());
}); });
private final ActivityResultLauncher<Intent> startBookmarkSettingsForResult = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), activityResult -> {
// not handled at the moment
});
private final ActivityResultLauncher<Intent> startBookmarkSettingsForResult =
registerForActivityResult(new ActivityResultContracts.StartActivityForResult(),
activityResult
-> {
// not handled at the moment
});
@Override @Override
@LayoutRes @LayoutRes
@@ -119,7 +114,8 @@ public class BookmarkCategoriesFragment extends BaseMwmRecyclerFragment<Bookmark
getAdapter().setCategoryListCallback(this); getAdapter().setCategoryListCallback(this);
RecyclerView rw = getRecyclerView(); RecyclerView rw = getRecyclerView();
if (rw == null) return; if (rw == null)
return;
rw.setNestedScrollingEnabled(false); rw.setNestedScrollingEnabled(false);
RecyclerView.ItemDecoration decor = new DividerItemDecorationWithPadding(requireContext()); RecyclerView.ItemDecoration decor = new DividerItemDecorationWithPadding(requireContext());
@@ -148,7 +144,7 @@ public class BookmarkCategoriesFragment extends BaseMwmRecyclerFragment<Bookmark
BookmarkManager.INSTANCE.addLoadingListener(this); BookmarkManager.INSTANCE.addLoadingListener(this);
BookmarkManager.INSTANCE.addSharingListener(this); BookmarkManager.INSTANCE.addSharingListener(this);
} }
@Override @Override
public void onStop() public void onStop()
{ {
@@ -181,7 +177,7 @@ public class BookmarkCategoriesFragment extends BaseMwmRecyclerFragment<Bookmark
{ {
mSelectedCategory = item; mSelectedCategory = item;
MenuBottomSheetFragment.newInstance(BOOKMARKS_CATEGORIES_MENU_ID, item.getName()) MenuBottomSheetFragment.newInstance(BOOKMARKS_CATEGORIES_MENU_ID, item.getName())
.show(getChildFragmentManager(), BOOKMARKS_CATEGORIES_MENU_ID); .show(getChildFragmentManager(), BOOKMARKS_CATEGORIES_MENU_ID);
} }
@Override @Override
@@ -191,28 +187,19 @@ public class BookmarkCategoriesFragment extends BaseMwmRecyclerFragment<Bookmark
ArrayList<MenuBottomSheetItem> items = new ArrayList<>(); ArrayList<MenuBottomSheetItem> items = new ArrayList<>();
if (mSelectedCategory != null) if (mSelectedCategory != null)
{ {
items.add(new MenuBottomSheetItem( items.add(new MenuBottomSheetItem(R.string.edit, R.drawable.ic_settings,
R.string.edit, () -> onSettingsActionSelected(mSelectedCategory)));
R.drawable.ic_settings, items.add(new MenuBottomSheetItem(mSelectedCategory.isVisible() ? R.string.hide : R.string.show,
() -> onSettingsActionSelected(mSelectedCategory))); mSelectedCategory.isVisible() ? R.drawable.ic_hide : R.drawable.ic_show,
items.add(new MenuBottomSheetItem( () -> onShowActionSelected(mSelectedCategory)));
mSelectedCategory.isVisible() ? R.string.hide : R.string.show, items.add(new MenuBottomSheetItem(R.string.export_file, R.drawable.ic_file_kmz,
mSelectedCategory.isVisible() ? R.drawable.ic_hide : R.drawable.ic_show, () -> onShareActionSelected(mSelectedCategory, KmlFileType.Text)));
() -> onShowActionSelected(mSelectedCategory))); items.add(new MenuBottomSheetItem(R.string.export_file_gpx, R.drawable.ic_file_gpx,
items.add(new MenuBottomSheetItem( () -> onShareActionSelected(mSelectedCategory, KmlFileType.Gpx)));
R.string.export_file,
R.drawable.ic_file_kmz,
() -> onShareActionSelected(mSelectedCategory, KmlFileType.Text)));
items.add(new MenuBottomSheetItem(
R.string.export_file_gpx,
R.drawable.ic_file_gpx,
() -> onShareActionSelected(mSelectedCategory, KmlFileType.Gpx)));
// Disallow deleting the last category // Disallow deleting the last category
if (getAdapter().getBookmarkCategories().size() > 1) if (getAdapter().getBookmarkCategories().size() > 1)
items.add(new MenuBottomSheetItem( items.add(new MenuBottomSheetItem(R.string.delete, R.drawable.ic_delete,
R.string.delete, () -> onDeleteActionSelected(mSelectedCategory)));
R.drawable.ic_delete,
() -> onDeleteActionSelected(mSelectedCategory)));
} }
return items; return items;
} }
@@ -245,15 +232,10 @@ public class BookmarkCategoriesFragment extends BaseMwmRecyclerFragment<Bookmark
{ {
mCategoryEditor = BookmarkManager.INSTANCE::createCategory; mCategoryEditor = BookmarkManager.INSTANCE::createCategory;
EditTextDialogFragment dialogFragment = EditTextDialogFragment dialogFragment = EditTextDialogFragment.show(
EditTextDialogFragment.show(getString(R.string.bookmarks_create_new_group), getString(R.string.bookmarks_create_new_group), getString(R.string.bookmarks_new_list_hint),
getString(R.string.bookmarks_new_list_hint), getString(R.string.bookmark_set_name), getString(R.string.create), getString(R.string.cancel),
getString(R.string.bookmark_set_name), MAX_CATEGORY_NAME_LENGTH, this, new CategoryValidator());
getString(R.string.create),
getString(R.string.cancel),
MAX_CATEGORY_NAME_LENGTH,
this,
new CategoryValidator());
dialogFragment.setTextSaveListener(this::onSaveText); dialogFragment.setTextSaveListener(this::onSaveText);
} }
@@ -280,7 +262,8 @@ public class BookmarkCategoriesFragment extends BaseMwmRecyclerFragment<Bookmark
showNoFileManagerError(); showNoFileManagerError();
} }
private void showNoFileManagerError() { private void showNoFileManagerError()
{
new MaterialAlertDialogBuilder(requireActivity()) new MaterialAlertDialogBuilder(requireActivity())
.setMessage(R.string.error_no_file_manager_app) .setMessage(R.string.error_no_file_manager_app)
.setPositiveButton(android.R.string.ok, (dialog, which) -> dialog.dismiss()) .setPositiveButton(android.R.string.ok, (dialog, which) -> dialog.dismiss())
@@ -341,17 +324,16 @@ public class BookmarkCategoriesFragment extends BaseMwmRecyclerFragment<Bookmark
final ContentResolver resolver = context.getContentResolver(); final ContentResolver resolver = context.getContentResolver();
ThreadPool.getStorage().execute(() -> { ThreadPool.getStorage().execute(() -> {
AtomicInteger found = new AtomicInteger(0); AtomicInteger found = new AtomicInteger(0);
StorageUtils.listContentProviderFilesRecursively( StorageUtils.listContentProviderFilesRecursively(resolver, rootUri, uri -> {
resolver, rootUri, uri -> { if (BookmarkManager.INSTANCE.importBookmarksFile(resolver, uri, tempDir))
if (BookmarkManager.INSTANCE.importBookmarksFile(resolver, uri, tempDir)) found.incrementAndGet();
found.incrementAndGet(); });
});
UiThread.run(() -> { UiThread.run(() -> {
if (dialog.isShowing()) if (dialog.isShowing())
dialog.dismiss(); dialog.dismiss();
int found_val = found.get(); int found_val = found.get();
String message = context.getResources().getQuantityString( String message =
R.plurals.bookmarks_detect_message, found_val, found_val); context.getResources().getQuantityString(R.plurals.bookmarks_detect_message, found_val, found_val);
Toast.makeText(requireContext(), message, Toast.LENGTH_LONG).show(); Toast.makeText(requireContext(), message, Toast.LENGTH_LONG).show();
}); });
}); });

View File

@@ -1,11 +1,9 @@
package app.organicmaps.bookmarks; package app.organicmaps.bookmarks;
import android.content.Intent; import android.content.Intent;
import androidx.activity.result.ActivityResultLauncher; import androidx.activity.result.ActivityResultLauncher;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import app.organicmaps.R; import app.organicmaps.R;
import app.organicmaps.base.BaseMwmFragmentActivity; import app.organicmaps.base.BaseMwmFragmentActivity;
import app.organicmaps.sdk.bookmarks.data.BookmarkCategory; import app.organicmaps.sdk.bookmarks.data.BookmarkCategory;
@@ -32,11 +30,12 @@ public class BookmarkCategorySettingsActivity extends BaseMwmFragmentActivity
return BookmarkCategorySettingsFragment.class; return BookmarkCategorySettingsFragment.class;
} }
public static void startForResult(@NonNull Fragment fragment, ActivityResultLauncher<Intent> startBookmarkSettingsForResult, public static void startForResult(@NonNull Fragment fragment,
@NonNull BookmarkCategory category) ActivityResultLauncher<Intent> startBookmarkSettingsForResult,
@NonNull BookmarkCategory category)
{ {
android.content.Intent intent = new Intent(fragment.requireActivity(), BookmarkCategorySettingsActivity.class) android.content.Intent intent = new Intent(fragment.requireActivity(), BookmarkCategorySettingsActivity.class)
.putExtra(EXTRA_BOOKMARK_CATEGORY, category); .putExtra(EXTRA_BOOKMARK_CATEGORY, category);
startBookmarkSettingsForResult.launch(intent); startBookmarkSettingsForResult.launch(intent);
} }
} }

View File

@@ -11,21 +11,17 @@ import android.view.MenuInflater;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import app.organicmaps.R; import app.organicmaps.R;
import app.organicmaps.base.BaseMwmToolbarFragment; import app.organicmaps.base.BaseMwmToolbarFragment;
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.Utils;
import app.organicmaps.util.InputUtils; import app.organicmaps.util.InputUtils;
import app.organicmaps.util.Utils;
import com.google.android.material.dialog.MaterialAlertDialogBuilder; import com.google.android.material.dialog.MaterialAlertDialogBuilder;
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 java.util.Objects; import java.util.Objects;
public class BookmarkCategorySettingsFragment extends BaseMwmToolbarFragment public class BookmarkCategorySettingsFragment extends BaseMwmToolbarFragment
@@ -49,14 +45,13 @@ public class BookmarkCategorySettingsFragment extends BaseMwmToolbarFragment
{ {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
final Bundle args = requireArguments(); final Bundle args = requireArguments();
mCategory = Objects.requireNonNull(Utils.getParcelable(args, mCategory = Objects.requireNonNull(
BookmarkCategorySettingsActivity.EXTRA_BOOKMARK_CATEGORY, BookmarkCategory.class)); Utils.getParcelable(args, BookmarkCategorySettingsActivity.EXTRA_BOOKMARK_CATEGORY, BookmarkCategory.class));
} }
@Nullable @Nullable
@Override @Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState)
@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); setHasOptionsMenu(true);
@@ -70,13 +65,13 @@ public class BookmarkCategorySettingsFragment extends BaseMwmToolbarFragment
TextInputLayout clearNameBtn = root.findViewById(R.id.edit_list_name_input); TextInputLayout clearNameBtn = root.findViewById(R.id.edit_list_name_input);
clearNameBtn.setEndIconOnClickListener(v -> clearAndFocus(mEditCategoryNameView)); clearNameBtn.setEndIconOnClickListener(v -> clearAndFocus(mEditCategoryNameView));
mEditCategoryNameView.setText(mCategory.getName()); mEditCategoryNameView.setText(mCategory.getName());
InputFilter[] f = { new InputFilter.LengthFilter(TEXT_LENGTH_LIMIT) }; InputFilter[] f = {new InputFilter.LengthFilter(TEXT_LENGTH_LIMIT)};
mEditCategoryNameView.setFilters(f); mEditCategoryNameView.setFilters(f);
mEditCategoryNameView.requestFocus(); mEditCategoryNameView.requestFocus();
mEditCategoryNameView.addTextChangedListener(new TextWatcher() mEditCategoryNameView.addTextChangedListener(new TextWatcher() {
{
@Override @Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {} public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2)
{}
@Override @Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) public void onTextChanged(CharSequence charSequence, int i, int i1, int i2)
@@ -85,7 +80,8 @@ public class BookmarkCategorySettingsFragment extends BaseMwmToolbarFragment
} }
@Override @Override
public void afterTextChanged(Editable editable) {} public void afterTextChanged(Editable editable)
{}
}); });
mEditDescView = root.findViewById(R.id.edit_description); mEditDescView = root.findViewById(R.id.edit_description);
mEditDescView.setText(mCategory.getDescription()); mEditDescView.setText(mCategory.getDescription());

View File

@@ -3,18 +3,15 @@ package app.organicmaps.bookmarks;
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 androidx.annotation.IntDef; import androidx.annotation.IntDef;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import app.organicmaps.R; import app.organicmaps.R;
import app.organicmaps.adapter.OnItemClickListener; import app.organicmaps.adapter.OnItemClickListener;
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.sdk.util.UiUtils; import app.organicmaps.sdk.util.UiUtils;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.util.List; import java.util.List;
@@ -22,8 +19,9 @@ import java.util.List;
public class BookmarkCollectionAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> public class BookmarkCollectionAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
{ {
@Retention(RetentionPolicy.SOURCE) @Retention(RetentionPolicy.SOURCE)
@IntDef({ TYPE_HEADER_ITEM, TYPE_CATEGORY_ITEM }) @IntDef({TYPE_HEADER_ITEM, TYPE_CATEGORY_ITEM})
public @interface SectionType { } public @interface SectionType
{}
private final static int TYPE_CATEGORY_ITEM = BookmarkManager.CATEGORY; private final static int TYPE_CATEGORY_ITEM = BookmarkManager.CATEGORY;
private final static int TYPE_HEADER_ITEM = 3; private final static int TYPE_HEADER_ITEM = 3;
@@ -63,11 +61,10 @@ public class BookmarkCollectionAdapter extends RecyclerView.Adapter<RecyclerView
} }
} }
BookmarkCollectionAdapter(@NonNull BookmarkCategory bookmarkCategory, BookmarkCollectionAdapter(@NonNull BookmarkCategory bookmarkCategory, @NonNull List<BookmarkCategory> itemsCategories)
@NonNull List<BookmarkCategory> itemsCategories)
{ {
mBookmarkCategory = bookmarkCategory; mBookmarkCategory = bookmarkCategory;
//noinspection AssignmentOrReturnOfFieldWithMutableType // noinspection AssignmentOrReturnOfFieldWithMutableType
mItemsCategory = itemsCategories; mItemsCategory = itemsCategories;
mSectionCount = 0; mSectionCount = 0;
@@ -93,7 +90,7 @@ public class BookmarkCollectionAdapter extends RecyclerView.Adapter<RecyclerView
@NonNull @NonNull
private List<BookmarkCategory> getItemsListByType(@SectionType int type) private List<BookmarkCategory> getItemsListByType(@SectionType int type)
{ {
return mItemsCategory; return mItemsCategory;
} }
@NonNull @NonNull
@@ -129,18 +126,15 @@ public class BookmarkCollectionAdapter extends RecyclerView.Adapter<RecyclerView
@NonNull @NonNull
@Override @Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, @SectionType int viewType)
@SectionType int viewType)
{ {
LayoutInflater inflater = LayoutInflater.from(parent.getContext()); LayoutInflater inflater = LayoutInflater.from(parent.getContext());
RecyclerView.ViewHolder holder = null; RecyclerView.ViewHolder holder = null;
if (viewType == TYPE_HEADER_ITEM) if (viewType == TYPE_HEADER_ITEM)
holder = new Holders.HeaderViewHolder(inflater.inflate(R.layout.item_bookmark_group_list_header, holder = new Holders.HeaderViewHolder(inflater.inflate(R.layout.item_bookmark_group_list_header, parent, false));
parent, false));
if (viewType == TYPE_CATEGORY_ITEM) if (viewType == TYPE_CATEGORY_ITEM)
holder = new Holders.CollectionViewHolder(inflater.inflate(R.layout.item_bookmark_collection, holder = new Holders.CollectionViewHolder(inflater.inflate(R.layout.item_bookmark_collection, parent, false));
parent, false));
if (holder == null) if (holder == null)
throw new AssertionError("Unsupported view type: " + viewType); throw new AssertionError("Unsupported view type: " + viewType);
@@ -170,8 +164,7 @@ public class BookmarkCollectionAdapter extends RecyclerView.Adapter<RecyclerView
throw new AssertionError("Position not found: " + position); throw new AssertionError("Position not found: " + position);
} }
private void bindCollectionHolder(RecyclerView.ViewHolder holder, SectionPosition position, private void bindCollectionHolder(RecyclerView.ViewHolder holder, SectionPosition position, @SectionType int type)
@SectionType int type)
{ {
final BookmarkCategory category = getGroupByPosition(position, type); final BookmarkCategory category = getGroupByPosition(position, type);
Holders.CollectionViewHolder collectionViewHolder = (Holders.CollectionViewHolder) holder; Holders.CollectionViewHolder collectionViewHolder = (Holders.CollectionViewHolder) holder;
@@ -188,8 +181,7 @@ public class BookmarkCollectionAdapter extends RecyclerView.Adapter<RecyclerView
private void bindHeaderHolder(@NonNull RecyclerView.ViewHolder holder, int nextSectionPosition) private void bindHeaderHolder(@NonNull RecyclerView.ViewHolder holder, int nextSectionPosition)
{ {
Holders.HeaderViewHolder headerViewHolder = (Holders.HeaderViewHolder) holder; Holders.HeaderViewHolder headerViewHolder = (Holders.HeaderViewHolder) holder;
headerViewHolder.getText() headerViewHolder.getText().setText(holder.itemView.getResources().getString(R.string.bookmarks));
.setText(holder.itemView.getResources().getString(R.string.bookmarks));
final boolean visibility = !BookmarkManager.INSTANCE.areAllCategoriesVisible(); final boolean visibility = !BookmarkManager.INSTANCE.areAllCategoriesVisible();
headerViewHolder.setAction(mMassOperationAction, visibility); headerViewHolder.setAction(mMassOperationAction, visibility);
updateVisibility(headerViewHolder.itemView); updateVisibility(headerViewHolder.itemView);
@@ -251,4 +243,3 @@ public class BookmarkCollectionAdapter extends RecyclerView.Adapter<RecyclerView
} }
} }
} }

View File

@@ -2,13 +2,11 @@ package app.organicmaps.bookmarks;
import android.content.Intent; import android.content.Intent;
import android.os.Bundle; 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.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;
@@ -58,7 +56,8 @@ public class BookmarkListActivity extends BaseToolbarActivity
return R.layout.bookmarks_activity; return R.layout.bookmarks_activity;
} }
static void startForResult(@NonNull Fragment fragment, ActivityResultLauncher<Intent> startBookmarkListForResult, @NonNull BookmarkCategory category) static void startForResult(@NonNull Fragment fragment, ActivityResultLauncher<Intent> startBookmarkListForResult,
@NonNull BookmarkCategory category)
{ {
Bundle args = new Bundle(); Bundle args = new Bundle();
Intent intent = new Intent(fragment.requireActivity(), BookmarkListActivity.class); Intent intent = new Intent(fragment.requireActivity(), BookmarkListActivity.class);

View File

@@ -4,13 +4,9 @@ import android.content.res.Resources;
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 androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import com.google.android.material.textview.MaterialTextView;
import app.organicmaps.R; import app.organicmaps.R;
import app.organicmaps.sdk.bookmarks.data.BookmarkCategory; import app.organicmaps.sdk.bookmarks.data.BookmarkCategory;
import app.organicmaps.sdk.bookmarks.data.BookmarkInfo; import app.organicmaps.sdk.bookmarks.data.BookmarkInfo;
@@ -20,7 +16,7 @@ import app.organicmaps.sdk.bookmarks.data.SortedBlock;
import app.organicmaps.sdk.content.DataSource; import app.organicmaps.sdk.content.DataSource;
import app.organicmaps.widget.recycler.RecyclerClickListener; import app.organicmaps.widget.recycler.RecyclerClickListener;
import app.organicmaps.widget.recycler.RecyclerLongClickListener; import app.organicmaps.widget.recycler.RecyclerLongClickListener;
import com.google.android.material.textview.MaterialTextView;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
@@ -62,12 +58,14 @@ public class BookmarkListAdapter extends RecyclerView.Adapter<Holders.BaseBookma
mDataSource = dataSource; mDataSource = dataSource;
} }
public BookmarkCategory getCategory() { return mDataSource.getData(); } public BookmarkCategory getCategory()
{
return mDataSource.getData();
}
boolean hasDescription() boolean hasDescription()
{ {
return (!mDataSource.getData().getAnnotation().isEmpty() || return (!mDataSource.getData().getAnnotation().isEmpty() || !mDataSource.getData().getDescription().isEmpty());
!mDataSource.getData().getDescription().isEmpty());
} }
void invalidate() void invalidate()
@@ -115,7 +113,10 @@ public class BookmarkListAdapter extends RecyclerView.Adapter<Holders.BaseBookma
} }
@Override @Override
public int getSectionsCount() { return mSectionsCount; } public int getSectionsCount()
{
return mSectionsCount;
}
@Override @Override
public boolean isEditable(int sectionIndex) public boolean isEditable(int sectionIndex)
@@ -124,7 +125,10 @@ public class BookmarkListAdapter extends RecyclerView.Adapter<Holders.BaseBookma
} }
@Override @Override
public boolean hasTitle(int sectionIndex) { return true; } public boolean hasTitle(int sectionIndex)
{
return true;
}
@Nullable @Nullable
public String getTitle(int sectionIndex, @NonNull Resources rs) public String getTitle(int sectionIndex, @NonNull Resources rs)
@@ -172,15 +176,13 @@ public class BookmarkListAdapter extends RecyclerView.Adapter<Holders.BaseBookma
@Override @Override
public long getBookmarkId(@NonNull SectionPosition pos) public long getBookmarkId(@NonNull SectionPosition pos)
{ {
return BookmarkManager.INSTANCE.getBookmarkIdByPosition(getCategory().getId(), return BookmarkManager.INSTANCE.getBookmarkIdByPosition(getCategory().getId(), pos.getItemIndex());
pos.getItemIndex());
} }
@Override @Override
public long getTrackId(@NonNull SectionPosition pos) public long getTrackId(@NonNull SectionPosition pos)
{ {
return BookmarkManager.INSTANCE.getTrackIdByPosition(getCategory().getId(), return BookmarkManager.INSTANCE.getTrackIdByPosition(getCategory().getId(), pos.getItemIndex());
pos.getItemIndex());
} }
} }
@@ -189,30 +191,47 @@ public class BookmarkListAdapter extends RecyclerView.Adapter<Holders.BaseBookma
@NonNull @NonNull
private final List<Long> mSearchResults; private final List<Long> mSearchResults;
SearchResultsSectionsDataSource(@NonNull DataSource<BookmarkCategory> dataSource, SearchResultsSectionsDataSource(@NonNull DataSource<BookmarkCategory> dataSource, @NonNull List<Long> searchResults)
@NonNull List<Long> searchResults)
{ {
super(dataSource); super(dataSource);
mSearchResults = searchResults; mSearchResults = searchResults;
} }
@Override @Override
public int getSectionsCount() { return 1; } public int getSectionsCount()
{
return 1;
}
@Override @Override
public boolean isEditable(int sectionIndex) { return true; } public boolean isEditable(int sectionIndex)
{
return true;
}
@Override @Override
public boolean hasTitle(int sectionIndex) { return false; } public boolean hasTitle(int sectionIndex)
{
return false;
}
@Nullable @Nullable
public String getTitle(int sectionIndex, @NonNull Resources rs) { return null; } public String getTitle(int sectionIndex, @NonNull Resources rs)
{
return null;
}
@Override @Override
public int getItemsCount(int sectionIndex) { return mSearchResults.size(); } public int getItemsCount(int sectionIndex)
{
return mSearchResults.size();
}
@Override @Override
public int getItemsType(int sectionIndex) { return TYPE_BOOKMARK; } public int getItemsType(int sectionIndex)
{
return TYPE_BOOKMARK;
}
@Override @Override
public void onDelete(@NonNull SectionPosition pos) public void onDelete(@NonNull SectionPosition pos)
@@ -238,8 +257,7 @@ public class BookmarkListAdapter extends RecyclerView.Adapter<Holders.BaseBookma
@NonNull @NonNull
private final List<SortedBlock> mSortedBlocks; private final List<SortedBlock> mSortedBlocks;
SortedSectionsDataSource(@NonNull DataSource<BookmarkCategory> dataSource, SortedSectionsDataSource(@NonNull DataSource<BookmarkCategory> dataSource, @NonNull List<SortedBlock> sortedBlocks)
@NonNull List<SortedBlock> sortedBlocks)
{ {
super(dataSource); super(dataSource);
mSortedBlocks = sortedBlocks; mSortedBlocks = sortedBlocks;
@@ -272,7 +290,10 @@ public class BookmarkListAdapter extends RecyclerView.Adapter<Holders.BaseBookma
} }
@Override @Override
public boolean hasTitle(int sectionIndex) { return true; } public boolean hasTitle(int sectionIndex)
{
return true;
}
@Nullable @Nullable
public String getTitle(int sectionIndex, @NonNull Resources rs) public String getTitle(int sectionIndex, @NonNull Resources rs)
@@ -423,8 +444,7 @@ public class BookmarkListAdapter extends RecyclerView.Adapter<Holders.BaseBookma
{ {
case TYPE_TRACK: case TYPE_TRACK:
Holders.TrackViewHolder trackHolder = Holders.TrackViewHolder trackHolder =
new Holders.TrackViewHolder(inflater.inflate(R.layout.item_track, parent, new Holders.TrackViewHolder(inflater.inflate(R.layout.item_track, parent, false));
false));
trackHolder.setOnClickListener(mClickListener); trackHolder.setOnClickListener(mClickListener);
trackHolder.setOnLongClickListener(mLongClickListener); trackHolder.setOnLongClickListener(mLongClickListener);
trackHolder.setTrackIconClickListener(mIconClickListener); trackHolder.setTrackIconClickListener(mIconClickListener);
@@ -433,8 +453,7 @@ public class BookmarkListAdapter extends RecyclerView.Adapter<Holders.BaseBookma
break; break;
case TYPE_BOOKMARK: case TYPE_BOOKMARK:
Holders.BookmarkViewHolder bookmarkHolder = Holders.BookmarkViewHolder bookmarkHolder =
new Holders.BookmarkViewHolder(inflater.inflate(R.layout.item_bookmark, parent, new Holders.BookmarkViewHolder(inflater.inflate(R.layout.item_bookmark, parent, false));
false));
bookmarkHolder.setOnClickListener(mClickListener); bookmarkHolder.setOnClickListener(mClickListener);
bookmarkHolder.setOnLongClickListener(mLongClickListener); bookmarkHolder.setOnLongClickListener(mLongClickListener);
holder = bookmarkHolder; holder = bookmarkHolder;

View File

@@ -11,7 +11,6 @@ import android.view.MenuInflater;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import androidx.activity.result.ActivityResultLauncher; import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts; import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.CallSuper; import androidx.annotation.CallSuper;
@@ -40,9 +39,9 @@ import app.organicmaps.sdk.bookmarks.data.SortedBlock;
import app.organicmaps.sdk.bookmarks.data.Track; import app.organicmaps.sdk.bookmarks.data.Track;
import app.organicmaps.sdk.search.BookmarkSearchListener; import app.organicmaps.sdk.search.BookmarkSearchListener;
import app.organicmaps.sdk.search.SearchEngine; import app.organicmaps.sdk.search.SearchEngine;
import app.organicmaps.sdk.util.UiUtils;
import app.organicmaps.util.Graphics; import app.organicmaps.util.Graphics;
import app.organicmaps.util.SharingUtils; import app.organicmaps.util.SharingUtils;
import app.organicmaps.sdk.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.util.bottomsheet.MenuBottomSheetFragment; import app.organicmaps.util.bottomsheet.MenuBottomSheetFragment;
@@ -53,16 +52,13 @@ import app.organicmaps.widget.placepage.EditBookmarkFragment;
import app.organicmaps.widget.recycler.DividerItemDecorationWithPadding; import app.organicmaps.widget.recycler.DividerItemDecorationWithPadding;
import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton; import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton;
import com.google.android.material.imageview.ShapeableImageView; import com.google.android.material.imageview.ShapeableImageView;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
public class BookmarksListFragment extends BaseMwmRecyclerFragment<ConcatAdapter> public class BookmarksListFragment extends BaseMwmRecyclerFragment<ConcatAdapter>
implements BookmarkManager.BookmarksSharingListener, implements BookmarkManager.BookmarksSharingListener, BookmarkManager.BookmarksSortingListener,
BookmarkManager.BookmarksSortingListener, BookmarkManager.BookmarksLoadingListener, BookmarkSearchListener,
BookmarkManager.BookmarksLoadingListener,
BookmarkSearchListener,
ChooseBookmarksSortingTypeFragment.ChooseSortingTypeListener, ChooseBookmarksSortingTypeFragment.ChooseSortingTypeListener,
MenuBottomSheetFragment.MenuBottomSheetInterface MenuBottomSheetFragment.MenuBottomSheetInterface
{ {
@@ -75,15 +71,17 @@ public class BookmarksListFragment extends BaseMwmRecyclerFragment<ConcatAdapter
private static final String OPTIONS_MENU_ID = "OPTIONS_MENU_BOTTOM_SHEET"; private static final String OPTIONS_MENU_ID = "OPTIONS_MENU_BOTTOM_SHEET";
private ActivityResultLauncher<SharingUtils.SharingIntent> shareLauncher; private ActivityResultLauncher<SharingUtils.SharingIntent> shareLauncher;
private final ActivityResultLauncher<Intent> startBookmarkListForResult = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), activityResult -> { private final ActivityResultLauncher<Intent> startBookmarkListForResult =
System.out.println("resultCode: " + activityResult.getResultCode()); registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), activityResult -> {
handleActivityResult(); System.out.println("resultCode: " + activityResult.getResultCode());
}); handleActivityResult();
});
private final ActivityResultLauncher<Intent> startBookmarkSettingsForResult = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), activityResult -> { private final ActivityResultLauncher<Intent> startBookmarkSettingsForResult =
System.out.println("resultCode: " + activityResult.getResultCode()); registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), activityResult -> {
handleActivityResult(); System.out.println("resultCode: " + activityResult.getResultCode());
}); handleActivityResult();
});
@SuppressWarnings("NotNullFieldNotInitialized") @SuppressWarnings("NotNullFieldNotInitialized")
@NonNull @NonNull
@@ -104,8 +102,7 @@ public class BookmarksListFragment extends BaseMwmRecyclerFragment<ConcatAdapter
private ExtendedFloatingActionButton mFabViewOnMap; private ExtendedFloatingActionButton mFabViewOnMap;
@SuppressWarnings("NotNullFieldNotInitialized") @SuppressWarnings("NotNullFieldNotInitialized")
@NonNull @NonNull
private final RecyclerView.OnScrollListener mRecyclerListener = new RecyclerView.OnScrollListener() private final RecyclerView.OnScrollListener mRecyclerListener = new RecyclerView.OnScrollListener() {
{
@Override @Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) public void onScrollStateChanged(RecyclerView recyclerView, int newState)
{ {
@@ -140,7 +137,7 @@ public class BookmarksListFragment extends BaseMwmRecyclerFragment<ConcatAdapter
{ {
BookmarkCategory category = mCategoryDataSource.getData(); BookmarkCategory category = mCategoryDataSource.getData();
return new ConcatAdapter(initAndGetCollectionAdapter(category.getId()), return new ConcatAdapter(initAndGetCollectionAdapter(category.getId()),
new BookmarkListAdapter(mCategoryDataSource)); new BookmarkListAdapter(mCategoryDataSource));
} }
@NonNull @NonNull
@@ -148,16 +145,15 @@ public class BookmarksListFragment extends BaseMwmRecyclerFragment<ConcatAdapter
{ {
List<BookmarkCategory> mCategoryItems = BookmarkManager.INSTANCE.getChildrenCategories(categoryId); List<BookmarkCategory> mCategoryItems = BookmarkManager.INSTANCE.getChildrenCategories(categoryId);
BookmarkCollectionAdapter adapter = new BookmarkCollectionAdapter(getCategoryOrThrow(), BookmarkCollectionAdapter adapter = new BookmarkCollectionAdapter(getCategoryOrThrow(), mCategoryItems);
mCategoryItems); adapter.setOnClickListener(
adapter.setOnClickListener((v, item) -> BookmarkListActivity.startForResult(this, startBookmarkListForResult, item)); (v, item) -> BookmarkListActivity.startForResult(this, startBookmarkListForResult, item));
return adapter; return adapter;
} }
@Override @Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState)
@Nullable Bundle savedInstanceState)
{ {
return inflater.inflate(R.layout.fragment_bookmark_list, container, false); return inflater.inflate(R.layout.fragment_bookmark_list, container, false);
} }
@@ -202,8 +198,7 @@ public class BookmarksListFragment extends BaseMwmRecyclerFragment<ConcatAdapter
// recycler view already has an InsetListener in BaseMwmRecyclerFragment // recycler view already has an InsetListener in BaseMwmRecyclerFragment
// here we must reset it, because the logic is different from a common use case // here we must reset it, because the logic is different from a common use case
ViewCompat.setOnApplyWindowInsetsListener( ViewCompat.setOnApplyWindowInsetsListener(
getRecyclerView(), getRecyclerView(), new WindowInsetUtils.ScrollableContentInsetsListener(getRecyclerView(), mFabViewOnMap));
new WindowInsetUtils.ScrollableContentInsetsListener(getRecyclerView(), mFabViewOnMap));
updateLoadingPlaceholder(view, false); updateLoadingPlaceholder(view, false);
} }
@@ -261,8 +256,7 @@ public class BookmarksListFragment extends BaseMwmRecyclerFragment<ConcatAdapter
private void configureFab(@NonNull View view) private void configureFab(@NonNull View view)
{ {
mFabViewOnMap = view.findViewById(R.id.show_on_map_fab); mFabViewOnMap = view.findViewById(R.id.show_on_map_fab);
mFabViewOnMap.setOnClickListener(v -> mFabViewOnMap.setOnClickListener(v -> {
{
final Intent i = makeMwmActivityIntent(); final Intent i = makeMwmActivityIntent();
i.putExtra(MwmActivity.EXTRA_CATEGORY_ID, mCategoryDataSource.getData().getId()); i.putExtra(MwmActivity.EXTRA_CATEGORY_ID, mCategoryDataSource.getData().getId());
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
@@ -288,13 +282,11 @@ public class BookmarksListFragment extends BaseMwmRecyclerFragment<ConcatAdapter
{ {
if (isEmptySearchResults()) if (isEmptySearchResults())
{ {
requirePlaceholder().setContent(R.string.search_not_found, requirePlaceholder().setContent(R.string.search_not_found, R.string.search_not_found_query);
R.string.search_not_found_query);
} }
else if (isEmpty()) else if (isEmpty())
{ {
requirePlaceholder().setContent(R.string.bookmarks_empty_list_title, requirePlaceholder().setContent(R.string.bookmarks_empty_list_title, R.string.bookmarks_empty_list_message);
R.string.bookmarks_empty_list_message);
} }
boolean isEmptyRecycler = isEmpty() || isEmptySearchResults(); boolean isEmptyRecycler = isEmpty() || isEmptySearchResults();
@@ -330,9 +322,7 @@ public class BookmarksListFragment extends BaseMwmRecyclerFragment<ConcatAdapter
SearchEngine.INSTANCE.cancel(); SearchEngine.INSTANCE.cancel();
mLastQueryTimestamp = System.nanoTime(); mLastQueryTimestamp = System.nanoTime();
if (SearchEngine.INSTANCE.searchInBookmarks(query, if (SearchEngine.INSTANCE.searchInBookmarks(query, mCategoryDataSource.getData().getId(), mLastQueryTimestamp))
mCategoryDataSource.getData().getId(),
mLastQueryTimestamp))
{ {
mToolbarController.showProgress(true); mToolbarController.showProgress(true);
} }
@@ -431,8 +421,7 @@ public class BookmarksListFragment extends BaseMwmRecyclerFragment<ConcatAdapter
final double lon = hasMyPosition ? loc.getLongitude() : 0; final double lon = hasMyPosition ? loc.getLongitude() : 0;
BookmarkManager.INSTANCE.setLastSortingType(catId, sortingType); BookmarkManager.INSTANCE.setLastSortingType(catId, sortingType);
BookmarkManager.INSTANCE.getSortedCategory(catId, sortingType, hasMyPosition, lat, lon, BookmarkManager.INSTANCE.getSortedCategory(catId, sortingType, hasMyPosition, lat, lon, mLastSortTimestamp);
mLastSortTimestamp);
updateSortingProgressBar(); updateSortingProgressBar();
} }
@@ -446,8 +435,7 @@ public class BookmarksListFragment extends BaseMwmRecyclerFragment<ConcatAdapter
@NonNull @NonNull
private BookmarkCollectionAdapter getBookmarkCollectionAdapter() private BookmarkCollectionAdapter getBookmarkCollectionAdapter()
{ {
return (BookmarkCollectionAdapter) getAdapter().getAdapters() return (BookmarkCollectionAdapter) getAdapter().getAdapters().get(INDEX_BOOKMARKS_COLLECTION_ADAPTER);
.get(INDEX_BOOKMARKS_COLLECTION_ADAPTER);
} }
@Override @Override
@@ -525,7 +513,8 @@ public class BookmarksListFragment extends BaseMwmRecyclerFragment<ConcatAdapter
private int getLastAvailableSortingType() private int getLastAvailableSortingType()
{ {
int currentType = getLastSortingType(); int currentType = getLastSortingType();
@BookmarkManager.SortingType int[] types = getAvailableSortingTypes(); @BookmarkManager.SortingType
int[] types = getAvailableSortingTypes();
for (@BookmarkManager.SortingType int type : types) for (@BookmarkManager.SortingType int type : types)
{ {
if (type == currentType) if (type == currentType)
@@ -536,14 +525,12 @@ public class BookmarksListFragment extends BaseMwmRecyclerFragment<ConcatAdapter
private boolean isEmpty() private boolean isEmpty()
{ {
return !getBookmarkListAdapter().isSearchResults() return !getBookmarkListAdapter().isSearchResults() && getBookmarkListAdapter().getItemCount() == 0;
&& getBookmarkListAdapter().getItemCount() == 0;
} }
private boolean isEmptySearchResults() private boolean isEmptySearchResults()
{ {
return getBookmarkListAdapter().isSearchResults() return getBookmarkListAdapter().isSearchResults() && getBookmarkListAdapter().getItemCount() == 0;
&& getBookmarkListAdapter().getItemCount() == 0;
} }
private boolean isLastOwnedCategory() private boolean isLastOwnedCategory()
@@ -589,8 +576,7 @@ public class BookmarksListFragment extends BaseMwmRecyclerFragment<ConcatAdapter
i.putExtra(MwmActivity.EXTRA_TRACK_ID, track.getTrackId()); i.putExtra(MwmActivity.EXTRA_TRACK_ID, track.getTrackId());
} }
private void onBookmarkClicked(int position, @NonNull Intent i, private void onBookmarkClicked(int position, @NonNull Intent i, @NonNull BookmarkListAdapter adapter)
@NonNull BookmarkListAdapter adapter)
{ {
final BookmarkInfo bookmark = (BookmarkInfo) adapter.getItem(position); final BookmarkInfo bookmark = (BookmarkInfo) adapter.getItem(position);
i.putExtra(MwmActivity.EXTRA_CATEGORY_ID, bookmark.getCategoryId()); i.putExtra(MwmActivity.EXTRA_CATEGORY_ID, bookmark.getCategoryId());
@@ -603,7 +589,8 @@ public class BookmarksListFragment extends BaseMwmRecyclerFragment<ConcatAdapter
mSelectedPosition = position; mSelectedPosition = position;
final Track mTrack = (Track) adapter.getItem(mSelectedPosition); final Track mTrack = (Track) adapter.getItem(mSelectedPosition);
if (mTrack == null) return; if (mTrack == null)
return;
final Bundle args = new Bundle(); final Bundle args = new Bundle();
args.putInt(BookmarkColorDialogFragment.ICON_TYPE, Icon.getColorPosition(mTrack.getColor())); args.putInt(BookmarkColorDialogFragment.ICON_TYPE, Icon.getColorPosition(mTrack.getColor()));
final FragmentManager manager = getChildFragmentManager(); final FragmentManager manager = getChildFragmentManager();
@@ -618,9 +605,7 @@ public class BookmarksListFragment extends BaseMwmRecyclerFragment<ConcatAdapter
if (from == to) if (from == to)
return; return;
BookmarkManager.INSTANCE.changeTrackColor(mTrack.getTrackId(), to); BookmarkManager.INSTANCE.changeTrackColor(mTrack.getTrackId(), to);
Drawable circle = Graphics.drawCircle(to, Drawable circle = Graphics.drawCircle(to, R.dimen.track_circle_size, requireContext().getResources());
R.dimen.track_circle_size,
requireContext().getResources());
v.setImageDrawable(circle); v.setImageDrawable(circle);
}); });
@@ -644,7 +629,7 @@ public class BookmarksListFragment extends BaseMwmRecyclerFragment<ConcatAdapter
case BookmarkListAdapter.TYPE_BOOKMARK: case BookmarkListAdapter.TYPE_BOOKMARK:
final BookmarkInfo bookmark = (BookmarkInfo) adapter.getItem(mSelectedPosition); final BookmarkInfo bookmark = (BookmarkInfo) adapter.getItem(mSelectedPosition);
MenuBottomSheetFragment.newInstance(BOOKMARKS_MENU_ID, bookmark.getName()) MenuBottomSheetFragment.newInstance(BOOKMARKS_MENU_ID, bookmark.getName())
.show(getChildFragmentManager(), BOOKMARKS_MENU_ID); .show(getChildFragmentManager(), BOOKMARKS_MENU_ID);
break; break;
case BookmarkListAdapter.TYPE_TRACK: case BookmarkListAdapter.TYPE_TRACK:
@@ -697,7 +682,7 @@ public class BookmarksListFragment extends BaseMwmRecyclerFragment<ConcatAdapter
if (item.getItemId() == R.id.bookmarks_more) if (item.getItemId() == R.id.bookmarks_more)
{ {
MenuBottomSheetFragment.newInstance(OPTIONS_MENU_ID, mCategoryDataSource.getData().getName()) MenuBottomSheetFragment.newInstance(OPTIONS_MENU_ID, mCategoryDataSource.getData().getName())
.show(getChildFragmentManager(), OPTIONS_MENU_ID); .show(getChildFragmentManager(), OPTIONS_MENU_ID);
return true; return true;
} }
@@ -714,29 +699,25 @@ public class BookmarksListFragment extends BaseMwmRecyclerFragment<ConcatAdapter
{ {
BookmarkListAdapter adapter = getBookmarkListAdapter(); BookmarkListAdapter adapter = getBookmarkListAdapter();
BookmarkInfo info = (BookmarkInfo) adapter.getItem(mSelectedPosition); BookmarkInfo info = (BookmarkInfo) adapter.getItem(mSelectedPosition);
EditBookmarkFragment.editBookmark( EditBookmarkFragment.editBookmark(info.getCategoryId(), info.getBookmarkId(), requireActivity(),
info.getCategoryId(), info.getBookmarkId(), requireActivity(), getChildFragmentManager(), getChildFragmentManager(), (bookmarkId, movedFromCategory) -> {
(bookmarkId, movedFromCategory) -> if (movedFromCategory)
{ resetSearchAndSort();
if (movedFromCategory) else
resetSearchAndSort(); adapter.notifyDataSetChanged();
else });
adapter.notifyDataSetChanged();
});
} }
private void onTrackEditActionSelected() private void onTrackEditActionSelected()
{ {
Track track = (Track) getBookmarkListAdapter().getItem(mSelectedPosition); Track track = (Track) getBookmarkListAdapter().getItem(mSelectedPosition);
EditBookmarkFragment.editTrack( EditBookmarkFragment.editTrack(track.getCategoryId(), track.getTrackId(), requireActivity(),
track.getCategoryId(), track.getTrackId(), requireActivity(), getChildFragmentManager(), getChildFragmentManager(), (trackId, movedFromCategory) -> {
(trackId, movedFromCategory) -> if (movedFromCategory)
{ resetSearchAndSort();
if (movedFromCategory) else
resetSearchAndSort(); getBookmarkListAdapter().notifyDataSetChanged();
else });
getBookmarkListAdapter().notifyDataSetChanged();
});
} }
private void onDeleteActionSelected() private void onDeleteActionSelected()
@@ -754,8 +735,8 @@ public class BookmarksListFragment extends BaseMwmRecyclerFragment<ConcatAdapter
private void onSortOptionSelected() private void onSortOptionSelected()
{ {
ChooseBookmarksSortingTypeFragment.chooseSortingType(getAvailableSortingTypes(), ChooseBookmarksSortingTypeFragment.chooseSortingType(getAvailableSortingTypes(), getLastSortingType(),
getLastSortingType(), requireActivity(), getChildFragmentManager()); requireActivity(), getChildFragmentManager());
} }
private void onShareOptionSelected(KmlFileType kmlFileType) private void onShareOptionSelected(KmlFileType kmlFileType)
@@ -766,7 +747,8 @@ public class BookmarksListFragment extends BaseMwmRecyclerFragment<ConcatAdapter
private void onSettingsOptionSelected() private void onSettingsOptionSelected()
{ {
BookmarkCategorySettingsActivity.startForResult(this, startBookmarkSettingsForResult, mCategoryDataSource.getData()); BookmarkCategorySettingsActivity.startForResult(this, startBookmarkSettingsForResult,
mCategoryDataSource.getData());
} }
private void onDeleteOptionSelected() private void onDeleteOptionSelected()
@@ -777,14 +759,17 @@ public class BookmarksListFragment extends BaseMwmRecyclerFragment<ConcatAdapter
private ArrayList<MenuBottomSheetItem> getOptionsMenuItems() private ArrayList<MenuBottomSheetItem> getOptionsMenuItems()
{ {
@BookmarkManager.SortingType int[] types = getAvailableSortingTypes(); @BookmarkManager.SortingType
int[] types = getAvailableSortingTypes();
ArrayList<MenuBottomSheetItem> items = new ArrayList<>(); ArrayList<MenuBottomSheetItem> items = new ArrayList<>();
if (!isEmpty()) if (!isEmpty())
{ {
if (types.length > 0) if (types.length > 0)
items.add(new MenuBottomSheetItem(R.string.sort, R.drawable.ic_sort, this::onSortOptionSelected)); items.add(new MenuBottomSheetItem(R.string.sort, R.drawable.ic_sort, this::onSortOptionSelected));
items.add(new MenuBottomSheetItem(R.string.export_file, R.drawable.ic_file_kmz, () -> onShareOptionSelected(KmlFileType.Text))); items.add(new MenuBottomSheetItem(R.string.export_file, R.drawable.ic_file_kmz,
items.add(new MenuBottomSheetItem(R.string.export_file_gpx, R.drawable.ic_file_gpx, () -> onShareOptionSelected(KmlFileType.Gpx))); () -> onShareOptionSelected(KmlFileType.Text)));
items.add(new MenuBottomSheetItem(R.string.export_file_gpx, R.drawable.ic_file_gpx,
() -> onShareOptionSelected(KmlFileType.Gpx)));
} }
items.add(new MenuBottomSheetItem(R.string.edit, R.drawable.ic_settings, this::onSettingsOptionSelected)); items.add(new MenuBottomSheetItem(R.string.edit, R.drawable.ic_settings, this::onSettingsOptionSelected));
if (!isLastOwnedCategory()) if (!isLastOwnedCategory())
@@ -805,9 +790,12 @@ public class BookmarksListFragment extends BaseMwmRecyclerFragment<ConcatAdapter
{ {
ArrayList<MenuBottomSheetItem> items = new ArrayList<>(); ArrayList<MenuBottomSheetItem> items = new ArrayList<>();
items.add(new MenuBottomSheetItem(R.string.edit, R.drawable.ic_edit, this::onTrackEditActionSelected)); items.add(new MenuBottomSheetItem(R.string.edit, R.drawable.ic_edit, this::onTrackEditActionSelected));
items.add(new MenuBottomSheetItem(R.string.export_file, R.drawable.ic_file_kmz, () -> onShareTrackSelected(track.getTrackId(), KmlFileType.Text))); items.add(new MenuBottomSheetItem(R.string.export_file, R.drawable.ic_file_kmz,
items.add(new MenuBottomSheetItem(R.string.export_file_gpx, R.drawable.ic_file_gpx, () -> onShareTrackSelected(track.getTrackId(), KmlFileType.Gpx))); () -> onShareTrackSelected(track.getTrackId(), KmlFileType.Text)));
items.add(new MenuBottomSheetItem(R.string.delete, R.drawable.ic_delete, () -> onDeleteTrackSelected(track.getTrackId()))); items.add(new MenuBottomSheetItem(R.string.export_file_gpx, R.drawable.ic_file_gpx,
() -> onShareTrackSelected(track.getTrackId(), KmlFileType.Gpx)));
items.add(new MenuBottomSheetItem(R.string.delete, R.drawable.ic_delete,
() -> onDeleteTrackSelected(track.getTrackId())));
return items; return items;
} }
@@ -853,18 +841,22 @@ public class BookmarksListFragment extends BaseMwmRecyclerFragment<ConcatAdapter
@Nullable @Nullable
public ArrayList<MenuBottomSheetItem> getMenuBottomSheetItems(String id) public ArrayList<MenuBottomSheetItem> getMenuBottomSheetItems(String id)
{ {
switch (id) { switch (id)
case BOOKMARKS_MENU_ID -> { {
return getBookmarkMenuItems(); case BOOKMARKS_MENU_ID ->
} {
case TRACK_MENU_ID -> { return getBookmarkMenuItems();
final Track track = (Track) getBookmarkListAdapter().getItem(mSelectedPosition);
return getTrackMenuItems(track);
}
case OPTIONS_MENU_ID -> {
return getOptionsMenuItems();
}
} }
return null; case TRACK_MENU_ID ->
{
final Track track = (Track) getBookmarkListAdapter().getItem(mSelectedPosition);
return getTrackMenuItems(track);
}
case OPTIONS_MENU_ID ->
{
return getOptionsMenuItems();
}
}
return null;
} }
} }

View File

@@ -2,25 +2,21 @@ package app.organicmaps.bookmarks;
import android.app.Activity; import android.app.Activity;
import android.app.ProgressDialog; import android.app.ProgressDialog;
import androidx.activity.result.ActivityResultLauncher; import androidx.activity.result.ActivityResultLauncher;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.fragment.app.FragmentActivity; import androidx.fragment.app.FragmentActivity;
import app.organicmaps.R; import app.organicmaps.R;
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.sdk.bookmarks.data.BookmarkSharingResult; import app.organicmaps.sdk.bookmarks.data.BookmarkSharingResult;
import app.organicmaps.sdk.bookmarks.data.KmlFileType; import app.organicmaps.sdk.bookmarks.data.KmlFileType;
import app.organicmaps.util.SharingUtils;
import app.organicmaps.sdk.util.log.Logger; import app.organicmaps.sdk.util.log.Logger;
import app.organicmaps.util.SharingUtils;
import com.google.android.material.dialog.MaterialAlertDialogBuilder; import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
public enum BookmarksSharingHelper public enum BookmarksSharingHelper
{ {
INSTANCE; INSTANCE;
@@ -33,7 +29,7 @@ public enum BookmarksSharingHelper
public void prepareBookmarkCategoryForSharing(@NonNull Activity context, long catId, KmlFileType kmlFileType) public void prepareBookmarkCategoryForSharing(@NonNull Activity context, long catId, KmlFileType kmlFileType)
{ {
showProgressDialog(context); showProgressDialog(context);
BookmarkManager.INSTANCE.prepareCategoriesForSharing(new long[]{catId}, kmlFileType); BookmarkManager.INSTANCE.prepareCategoriesForSharing(new long[] {catId}, kmlFileType);
} }
public void prepareTrackForSharing(@NonNull Activity context, long trackId, KmlFileType kmlFileType) public void prepareTrackForSharing(@NonNull Activity context, long trackId, KmlFileType kmlFileType)
@@ -62,13 +58,13 @@ public enum BookmarksSharingHelper
switch (result.getCode()) switch (result.getCode())
{ {
case BookmarkSharingResult.SUCCESS -> case BookmarkSharingResult.SUCCESS ->
SharingUtils.shareBookmarkFile(context, launcher, result.getSharingPath(), result.getMimeType()); SharingUtils.shareBookmarkFile(context, launcher, result.getSharingPath(), result.getMimeType());
case BookmarkSharingResult.EMPTY_CATEGORY -> case BookmarkSharingResult.EMPTY_CATEGORY ->
new MaterialAlertDialogBuilder(context, R.style.MwmTheme_AlertDialog) new MaterialAlertDialogBuilder(context, R.style.MwmTheme_AlertDialog)
.setTitle(R.string.bookmarks_error_title_share_empty) .setTitle(R.string.bookmarks_error_title_share_empty)
.setMessage(R.string.bookmarks_error_message_share_empty) .setMessage(R.string.bookmarks_error_message_share_empty)
.setPositiveButton(R.string.ok, null) .setPositiveButton(R.string.ok, null)
.show(); .show();
case BookmarkSharingResult.ARCHIVE_ERROR, BookmarkSharingResult.FILE_ERROR -> case BookmarkSharingResult.ARCHIVE_ERROR, BookmarkSharingResult.FILE_ERROR ->
{ {
new MaterialAlertDialogBuilder(context, R.style.MwmTheme_AlertDialog) new MaterialAlertDialogBuilder(context, R.style.MwmTheme_AlertDialog)

View File

@@ -2,9 +2,7 @@ package app.organicmaps.bookmarks;
import android.app.Activity; import android.app.Activity;
import android.view.View; import android.view.View;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import app.organicmaps.widget.SearchToolbarController; import app.organicmaps.widget.SearchToolbarController;
public class BookmarksToolbarController extends SearchToolbarController public class BookmarksToolbarController extends SearchToolbarController
@@ -12,8 +10,7 @@ public class BookmarksToolbarController extends SearchToolbarController
@NonNull @NonNull
private final BookmarksListFragment mFragment; private final BookmarksListFragment mFragment;
BookmarksToolbarController(@NonNull View root, @NonNull Activity activity, BookmarksToolbarController(@NonNull View root, @NonNull Activity activity, @NonNull BookmarksListFragment fragment)
@NonNull BookmarksListFragment fragment)
{ {
super(root, activity); super(root, activity);
mFragment = fragment; mFragment = fragment;

View File

@@ -2,13 +2,11 @@ package app.organicmaps.bookmarks;
import android.app.Activity; import android.app.Activity;
import android.text.TextUtils; import android.text.TextUtils;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import app.organicmaps.R; import app.organicmaps.R;
import app.organicmaps.sdk.bookmarks.data.BookmarkManager;
import app.organicmaps.dialog.EditTextDialogFragment; import app.organicmaps.dialog.EditTextDialogFragment;
import app.organicmaps.sdk.bookmarks.data.BookmarkManager;
class CategoryValidator implements EditTextDialogFragment.Validator class CategoryValidator implements EditTextDialogFragment.Validator
{ {

View File

@@ -4,19 +4,16 @@ import android.content.Context;
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 androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import com.google.android.material.radiobutton.MaterialRadioButton;
import com.google.android.material.textview.MaterialTextView;
import app.organicmaps.R; import app.organicmaps.R;
import app.organicmaps.sdk.bookmarks.data.BookmarkCategory; import app.organicmaps.sdk.bookmarks.data.BookmarkCategory;
import com.google.android.material.radiobutton.MaterialRadioButton;
import com.google.android.material.textview.MaterialTextView;
import java.util.List; import java.util.List;
public class ChooseBookmarkCategoryAdapter extends BaseBookmarkCategoryAdapter<ChooseBookmarkCategoryAdapter.SingleChoiceHolder> public class ChooseBookmarkCategoryAdapter
extends BaseBookmarkCategoryAdapter<ChooseBookmarkCategoryAdapter.SingleChoiceHolder>
{ {
public static final int VIEW_TYPE_CATEGORY = 0; public static final int VIEW_TYPE_CATEGORY = 0;
public static final int VIEW_TYPE_ADD_NEW = 1; public static final int VIEW_TYPE_ADD_NEW = 1;
@@ -32,8 +29,7 @@ public class ChooseBookmarkCategoryAdapter extends BaseBookmarkCategoryAdapter<C
private CategoryListener mListener; private CategoryListener mListener;
public ChooseBookmarkCategoryAdapter(Context context, int pos, public ChooseBookmarkCategoryAdapter(Context context, int pos, @NonNull List<BookmarkCategory> categories)
@NonNull List<BookmarkCategory> categories)
{ {
super(context, categories); super(context, categories);
mCheckedPosition = pos; mCheckedPosition = pos;

View File

@@ -5,23 +5,20 @@ import android.os.Bundle;
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 androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import app.organicmaps.R; import app.organicmaps.R;
import app.organicmaps.base.BaseMwmDialogFragment; import app.organicmaps.base.BaseMwmDialogFragment;
import app.organicmaps.dialog.EditTextDialogFragment;
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.dialog.EditTextDialogFragment;
import java.util.List; import java.util.List;
public class ChooseBookmarkCategoryFragment extends BaseMwmDialogFragment public class ChooseBookmarkCategoryFragment
implements ChooseBookmarkCategoryAdapter.CategoryListener extends BaseMwmDialogFragment implements ChooseBookmarkCategoryAdapter.CategoryListener
{ {
public static final String CATEGORY_POSITION = "ExtraCategoryPosition"; public static final String CATEGORY_POSITION = "ExtraCategoryPosition";
@@ -126,13 +123,8 @@ public class ChooseBookmarkCategoryFragment extends BaseMwmDialogFragment
@Override @Override
public void onCategoryCreate() public void onCategoryCreate()
{ {
EditTextDialogFragment dialogFragment = EditTextDialogFragment dialogFragment = EditTextDialogFragment.show(
EditTextDialogFragment.show(getString(R.string.bookmark_set_name), getString(R.string.bookmark_set_name), null, getString(R.string.ok), null, this, new CategoryValidator());
null,
getString(R.string.ok),
null,
this,
new CategoryValidator());
dialogFragment.setTextSaveListener(this::createCategory); dialogFragment.setTextSaveListener(this::createCategory);
} }
} }

View File

@@ -6,19 +6,17 @@ import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.RadioGroup; import android.widget.RadioGroup;
import androidx.annotation.IdRes; import androidx.annotation.IdRes;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentManager;
import app.organicmaps.R; import app.organicmaps.R;
import app.organicmaps.base.BaseMwmDialogFragment; import app.organicmaps.base.BaseMwmDialogFragment;
import app.organicmaps.sdk.bookmarks.data.BookmarkManager; import app.organicmaps.sdk.bookmarks.data.BookmarkManager;
import app.organicmaps.sdk.util.UiUtils; import app.organicmaps.sdk.util.UiUtils;
public class ChooseBookmarksSortingTypeFragment extends BaseMwmDialogFragment public class ChooseBookmarksSortingTypeFragment
implements RadioGroup.OnCheckedChangeListener extends BaseMwmDialogFragment implements RadioGroup.OnCheckedChangeListener
{ {
private static final String EXTRA_SORTING_TYPES = "sorting_types"; private static final String EXTRA_SORTING_TYPES = "sorting_types";
private static final String EXTRA_CURRENT_SORT_TYPE = "current_sort_type"; private static final String EXTRA_CURRENT_SORT_TYPE = "current_sort_type";
@@ -32,17 +30,15 @@ public class ChooseBookmarksSortingTypeFragment extends BaseMwmDialogFragment
void onSort(@BookmarkManager.SortingType int sortingType); void onSort(@BookmarkManager.SortingType int sortingType);
} }
public static void chooseSortingType(@NonNull @BookmarkManager.SortingType int[] availableTypes, public static void chooseSortingType(@NonNull @BookmarkManager.SortingType int[] availableTypes, int currentType,
int currentType, @NonNull Context context, @NonNull Context context, @NonNull FragmentManager manager)
@NonNull FragmentManager manager)
{ {
Bundle args = new Bundle(); Bundle args = new Bundle();
args.putIntArray(EXTRA_SORTING_TYPES, availableTypes); args.putIntArray(EXTRA_SORTING_TYPES, availableTypes);
args.putInt(EXTRA_CURRENT_SORT_TYPE, currentType); args.putInt(EXTRA_CURRENT_SORT_TYPE, currentType);
String name = ChooseBookmarksSortingTypeFragment.class.getName(); String name = ChooseBookmarksSortingTypeFragment.class.getName();
final ChooseBookmarksSortingTypeFragment fragment = (ChooseBookmarksSortingTypeFragment) manager final ChooseBookmarksSortingTypeFragment fragment =
.getFragmentFactory() (ChooseBookmarksSortingTypeFragment) manager.getFragmentFactory().instantiate(context.getClassLoader(), name);
.instantiate(context.getClassLoader(), name);
fragment.setArguments(args); fragment.setArguments(args);
fragment.show(manager, name); fragment.show(manager, name);
} }
@@ -68,14 +64,10 @@ public class ChooseBookmarksSortingTypeFragment extends BaseMwmDialogFragment
{ {
switch (sortingType) switch (sortingType)
{ {
case BookmarkManager.SORT_BY_TYPE: case BookmarkManager.SORT_BY_TYPE: return R.id.sort_by_type;
return R.id.sort_by_type; case BookmarkManager.SORT_BY_DISTANCE: return R.id.sort_by_distance;
case BookmarkManager.SORT_BY_DISTANCE: case BookmarkManager.SORT_BY_TIME: return R.id.sort_by_time;
return R.id.sort_by_distance; case BookmarkManager.SORT_BY_NAME: return R.id.sort_by_name;
case BookmarkManager.SORT_BY_TIME:
return R.id.sort_by_time;
case BookmarkManager.SORT_BY_NAME:
return R.id.sort_by_name;
} }
} }
return R.id.sort_by_default; return R.id.sort_by_default;
@@ -117,8 +109,7 @@ public class ChooseBookmarksSortingTypeFragment extends BaseMwmDialogFragment
private void onAttachInternal() private void onAttachInternal()
{ {
mListener = (ChooseSortingTypeListener) (getParentFragment() == null ? getTargetFragment() mListener = (ChooseSortingTypeListener) (getParentFragment() == null ? getTargetFragment() : getParentFragment());
: getParentFragment());
} }
@Override @Override

View File

@@ -6,16 +6,10 @@ import android.location.Location;
import android.text.Spanned; import android.text.Spanned;
import android.text.TextUtils; import android.text.TextUtils;
import android.view.View; import android.view.View;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.annotation.PluralsRes; import androidx.annotation.PluralsRes;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import com.google.android.material.imageview.ShapeableImageView;
import com.google.android.material.textview.MaterialTextView;
import com.google.android.material.checkbox.MaterialCheckBox;
import app.organicmaps.MwmApplication; import app.organicmaps.MwmApplication;
import app.organicmaps.R; import app.organicmaps.R;
import app.organicmaps.adapter.OnItemClickListener; import app.organicmaps.adapter.OnItemClickListener;
@@ -24,11 +18,14 @@ import app.organicmaps.sdk.bookmarks.data.BookmarkInfo;
import app.organicmaps.sdk.bookmarks.data.BookmarkManager; import app.organicmaps.sdk.bookmarks.data.BookmarkManager;
import app.organicmaps.sdk.bookmarks.data.IconClickListener; import app.organicmaps.sdk.bookmarks.data.IconClickListener;
import app.organicmaps.sdk.bookmarks.data.Track; import app.organicmaps.sdk.bookmarks.data.Track;
import app.organicmaps.sdk.util.UiUtils;
import app.organicmaps.util.Graphics;
import app.organicmaps.util.Utils; import app.organicmaps.util.Utils;
import app.organicmaps.widget.recycler.RecyclerClickListener; import app.organicmaps.widget.recycler.RecyclerClickListener;
import app.organicmaps.widget.recycler.RecyclerLongClickListener; import app.organicmaps.widget.recycler.RecyclerLongClickListener;
import app.organicmaps.util.Graphics; import com.google.android.material.checkbox.MaterialCheckBox;
import app.organicmaps.sdk.util.UiUtils; import com.google.android.material.imageview.ShapeableImageView;
import com.google.android.material.textview.MaterialTextView;
public class Holders public class Holders
{ {
@@ -66,7 +63,6 @@ public class Holders
@NonNull @NonNull
private final MaterialTextView mText; private final MaterialTextView mText;
HeaderViewHolder(@NonNull View itemView) HeaderViewHolder(@NonNull View itemView)
{ {
super(itemView); super(itemView);
@@ -86,23 +82,16 @@ public class Holders
return mButton; return mButton;
} }
void setAction(@NonNull HeaderAction action, void setAction(@NonNull HeaderAction action, final boolean showAll)
final boolean showAll)
{ {
mButton.setText(showAll mButton.setText(showAll ? R.string.bookmark_lists_show_all : R.string.bookmark_lists_hide_all);
? R.string.bookmark_lists_show_all
: R.string.bookmark_lists_hide_all);
mButton.setOnClickListener(new ToggleShowAllClickListener(action, showAll)); mButton.setOnClickListener(new ToggleShowAllClickListener(action, showAll));
} }
void setAction(@NonNull HeaderActionChildCategories action, void setAction(@NonNull HeaderActionChildCategories action, final boolean showAll)
final boolean showAll)
{ {
mButton.setText(showAll mButton.setText(showAll ? R.string.bookmark_lists_show_all : R.string.bookmark_lists_hide_all);
? R.string.bookmark_lists_show_all mButton.setOnClickListener(new ToggleShowAllChildCategoryClickListener(action, showAll));
: R.string.bookmark_lists_hide_all);
mButton.setOnClickListener(new ToggleShowAllChildCategoryClickListener(
action, showAll));
} }
public interface HeaderAction public interface HeaderAction
@@ -124,8 +113,7 @@ public class Holders
private final HeaderActionChildCategories mAction; private final HeaderActionChildCategories mAction;
private final boolean mShowAll; private final boolean mShowAll;
ToggleShowAllChildCategoryClickListener(@NonNull HeaderActionChildCategories action, ToggleShowAllChildCategoryClickListener(@NonNull HeaderActionChildCategories action, boolean showAll)
boolean showAll)
{ {
mAction = action; mAction = action;
mShowAll = showAll; mShowAll = showAll;
@@ -223,7 +211,6 @@ public class Holders
{ {
return resources.getQuantityString(plural, size, size); return resources.getQuantityString(plural, size, size);
} }
} }
static class CollectionViewHolder extends CategoryViewHolderBase static class CollectionViewHolder extends CategoryViewHolderBase
{ {
@@ -354,17 +341,17 @@ public class Holders
} }
@Override @Override
void bind(@NonNull SectionPosition position, void bind(@NonNull SectionPosition position, @NonNull BookmarkListAdapter.SectionsDataSource sectionsDataSource)
@NonNull BookmarkListAdapter.SectionsDataSource sectionsDataSource)
{ {
final long bookmarkId = sectionsDataSource.getBookmarkId(position); final long bookmarkId = sectionsDataSource.getBookmarkId(position);
BookmarkInfo bookmark = new BookmarkInfo(sectionsDataSource.getCategory().getId(), BookmarkInfo bookmark = new BookmarkInfo(sectionsDataSource.getCategory().getId(), bookmarkId);
bookmarkId);
mName.setText(bookmark.getName()); mName.setText(bookmark.getName());
final Location loc = MwmApplication.from(mIcon.getContext()).getLocationHelper().getSavedLocation(); final Location loc = MwmApplication.from(mIcon.getContext()).getLocationHelper().getSavedLocation();
String distanceValue = loc == null ? "" : bookmark.getDistance(loc.getLatitude(), String distanceValue =
loc.getLongitude(), 0.0).toString(mDistance.getContext()); loc == null
? ""
: bookmark.getDistance(loc.getLatitude(), loc.getLongitude(), 0.0).toString(mDistance.getContext());
String separator = ""; String separator = "";
if (!distanceValue.isEmpty() && !bookmark.getFeatureType().isEmpty()) if (!distanceValue.isEmpty() && !bookmark.getFeatureType().isEmpty())
separator = ""; separator = "";
@@ -373,11 +360,9 @@ public class Holders
UiUtils.hideIf(TextUtils.isEmpty(subtitleValue), mDistance); UiUtils.hideIf(TextUtils.isEmpty(subtitleValue), mDistance);
mIcon.setImageResource(bookmark.getIcon().getResId()); mIcon.setImageResource(bookmark.getIcon().getResId());
Drawable circle = Graphics.drawCircleAndImage(bookmark.getIcon().argb(), Drawable circle =
R.dimen.track_circle_size, Graphics.drawCircleAndImage(bookmark.getIcon().argb(), R.dimen.track_circle_size,
bookmark.getIcon().getResId(), bookmark.getIcon().getResId(), R.dimen.bookmark_icon_size, mIcon.getContext());
R.dimen.bookmark_icon_size,
mIcon.getContext());
mIcon.setImageDrawable(circle); mIcon.setImageDrawable(circle);
} }
} }
@@ -402,19 +387,18 @@ public class Holders
} }
@Override @Override
void bind(@NonNull SectionPosition position, void bind(@NonNull SectionPosition position, @NonNull BookmarkListAdapter.SectionsDataSource sectionsDataSource)
@NonNull BookmarkListAdapter.SectionsDataSource sectionsDataSource)
{ {
final long trackId = sectionsDataSource.getTrackId(position); final long trackId = sectionsDataSource.getTrackId(position);
Track track = BookmarkManager.INSTANCE.getTrack(trackId); Track track = BookmarkManager.INSTANCE.getTrack(trackId);
mName.setText(track.getName()); mName.setText(track.getName());
mDistance.setText(new StringBuilder().append(mDistance.getContext() mDistance.setText(new StringBuilder()
.getString(R.string.length)) .append(mDistance.getContext().getString(R.string.length))
.append(" ") .append(" ")
.append(track.getLength().toString(mDistance.getContext())) .append(track.getLength().toString(mDistance.getContext()))
.toString()); .toString());
Drawable circle = Graphics.drawCircle(track.getColor(), R.dimen.track_circle_size, Drawable circle =
mIcon.getContext().getResources()); Graphics.drawCircle(track.getColor(), R.dimen.track_circle_size, mIcon.getContext().getResources());
mIcon.setImageDrawable(circle); mIcon.setImageDrawable(circle);
} }
@@ -441,8 +425,7 @@ public class Holders
} }
@Override @Override
void bind(@NonNull SectionPosition position, void bind(@NonNull SectionPosition position, @NonNull BookmarkListAdapter.SectionsDataSource sectionsDataSource)
@NonNull BookmarkListAdapter.SectionsDataSource sectionsDataSource)
{ {
mView.setText(sectionsDataSource.getTitle(position.getSectionIndex(), mView.getResources())); mView.setText(sectionsDataSource.getTitle(position.getSectionIndex(), mView.getResources()));
} }
@@ -465,8 +448,7 @@ public class Holders
} }
@Override @Override
void bind(@NonNull SectionPosition position, void bind(@NonNull SectionPosition position, @NonNull BookmarkListAdapter.SectionsDataSource sectionsDataSource)
@NonNull BookmarkListAdapter.SectionsDataSource sectionsDataSource)
{ {
mTitle.setText(sectionsDataSource.getCategory().getName()); mTitle.setText(sectionsDataSource.getCategory().getName());
bindDescription(sectionsDataSource.getCategory()); bindDescription(sectionsDataSource.getCategory());
@@ -474,9 +456,7 @@ public class Holders
private void bindDescription(@NonNull BookmarkCategory category) private void bindDescription(@NonNull BookmarkCategory category)
{ {
String desc = TextUtils.isEmpty(category.getAnnotation()) String desc = TextUtils.isEmpty(category.getAnnotation()) ? category.getDescription() : category.getAnnotation();
? category.getDescription()
: category.getAnnotation();
String formattedDesc = desc.replace("\n", "<br>"); String formattedDesc = desc.replace("\n", "<br>");
Spanned spannedDesc = Utils.fromHtml(formattedDesc); Spanned spannedDesc = Utils.fromHtml(formattedDesc);

View File

@@ -6,13 +6,10 @@ import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.ArrayAdapter; import android.widget.ArrayAdapter;
import com.google.android.material.imageview.ShapeableImageView;
import app.organicmaps.R; import app.organicmaps.R;
import app.organicmaps.sdk.bookmarks.data.Icon; import app.organicmaps.sdk.bookmarks.data.Icon;
import app.organicmaps.util.Graphics; import app.organicmaps.util.Graphics;
import com.google.android.material.imageview.ShapeableImageView;
import java.util.List; import java.util.List;
public class IconsAdapter extends ArrayAdapter<Icon> public class IconsAdapter extends ArrayAdapter<Icon>
@@ -43,18 +40,13 @@ public class IconsAdapter extends ArrayAdapter<Icon>
Drawable circle; Drawable circle;
if (icon.getColor() == mCheckedIconColor) if (icon.getColor() == mCheckedIconColor)
{ {
circle = Graphics.drawCircleAndImage(getItem(position).argb(), circle = Graphics.drawCircleAndImage(getItem(position).argb(), R.dimen.track_circle_size,
R.dimen.track_circle_size, R.drawable.ic_bookmark_none, R.dimen.bookmark_icon_size, getContext());
R.drawable.ic_bookmark_none,
R.dimen.bookmark_icon_size,
getContext());
} }
else else
{ {
circle = Graphics.drawCircle(getItem(position).argb(), circle =
R.dimen.select_color_circle_size, Graphics.drawCircle(getItem(position).argb(), R.dimen.select_color_circle_size, getContext().getResources());
getContext().getResources());
} }
holder.icon.setImageDrawable(circle); holder.icon.setImageDrawable(circle);
return convertView; return convertView;

View File

@@ -1,7 +1,6 @@
package app.organicmaps.bookmarks; package app.organicmaps.bookmarks;
import android.view.View; import android.view.View;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
public interface OnItemLongClickListener<T> public interface OnItemLongClickListener<T>

View File

@@ -1,7 +1,6 @@
package app.organicmaps.bookmarks; package app.organicmaps.bookmarks;
import android.view.View; import android.view.View;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
public interface OnItemMoreClickListener<T> public interface OnItemMoreClickListener<T>

View File

@@ -2,10 +2,8 @@ package app.organicmaps.bookmarks;
import android.os.Parcel; import android.os.Parcel;
import android.os.Parcelable; import android.os.Parcelable;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.core.os.ParcelCompat; import androidx.core.os.ParcelCompat;
import app.organicmaps.sdk.bookmarks.data.Error; import app.organicmaps.sdk.bookmarks.data.Error;
import app.organicmaps.sdk.bookmarks.data.Result; import app.organicmaps.sdk.bookmarks.data.Result;
@@ -28,8 +26,7 @@ public class OperationStatus implements Parcelable
mError = ParcelCompat.readParcelable(in, Error.class.getClassLoader(), Error.class); mError = ParcelCompat.readParcelable(in, Error.class.getClassLoader(), Error.class);
} }
public static final Creator<OperationStatus> CREATOR = new Creator<>() public static final Creator<OperationStatus> CREATOR = new Creator<>() {
{
@Override @Override
public OperationStatus createFromParcel(Parcel in) public OperationStatus createFromParcel(Parcel in)
{ {
@@ -59,9 +56,7 @@ public class OperationStatus implements Parcelable
@Override @Override
public String toString() public String toString()
{ {
return "OperationStatus{" + return "OperationStatus{"
"mResult=" + mResult + + "mResult=" + mResult + ", mError=" + mError + '}';
", mError=" + mError +
'}';
} }
} }

View File

@@ -3,7 +3,6 @@ package app.organicmaps.car;
import android.content.ComponentName; import android.content.ComponentName;
import android.content.Intent; import android.content.Intent;
import android.net.Uri; import android.net.Uri;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.car.app.CarContext; import androidx.car.app.CarContext;
@@ -15,7 +14,6 @@ import androidx.car.app.validation.HostValidator;
import androidx.core.app.NotificationChannelCompat; import androidx.core.app.NotificationChannelCompat;
import androidx.core.app.NotificationCompat; import androidx.core.app.NotificationCompat;
import androidx.core.app.NotificationManagerCompat; import androidx.core.app.NotificationManagerCompat;
import app.organicmaps.BuildConfig; import app.organicmaps.BuildConfig;
import app.organicmaps.R; import app.organicmaps.R;
import app.organicmaps.api.Const; import app.organicmaps.api.Const;
@@ -65,12 +63,13 @@ public final class CarAppService extends androidx.car.app.CarAppService
return mCarNotificationExtender; return mCarNotificationExtender;
final Intent intent = new Intent(Intent.ACTION_VIEW) final Intent intent = new Intent(Intent.ACTION_VIEW)
.setComponent(new ComponentName(context, CarAppService.class)) .setComponent(new ComponentName(context, CarAppService.class))
.setData(Uri.fromParts(Const.API_SCHEME, CarAppService.API_CAR_HOST, CarAppService.ACTION_SHOW_NAVIGATION_SCREEN)); .setData(Uri.fromParts(Const.API_SCHEME, CarAppService.API_CAR_HOST,
CarAppService.ACTION_SHOW_NAVIGATION_SCREEN));
mCarNotificationExtender = new CarAppExtender.Builder() mCarNotificationExtender = new CarAppExtender.Builder()
.setImportance(NotificationManagerCompat.IMPORTANCE_MIN) .setImportance(NotificationManagerCompat.IMPORTANCE_MIN)
.setContentIntent(CarPendingIntent.getCarApp(context, intent.hashCode(), intent, 0)) .setContentIntent(CarPendingIntent.getCarApp(context, intent.hashCode(), intent, 0))
.build(); .build();
return mCarNotificationExtender; return mCarNotificationExtender;
} }
@@ -79,9 +78,10 @@ public final class CarAppService extends androidx.car.app.CarAppService
{ {
final NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this); final NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
final NotificationChannelCompat notificationChannel = final NotificationChannelCompat notificationChannel =
new NotificationChannelCompat.Builder(ANDROID_AUTO_NOTIFICATION_CHANNEL_ID, NotificationManagerCompat.IMPORTANCE_MIN) new NotificationChannelCompat
.Builder(ANDROID_AUTO_NOTIFICATION_CHANNEL_ID, NotificationManagerCompat.IMPORTANCE_MIN)
.setName(getString(R.string.car_notification_channel_name)) .setName(getString(R.string.car_notification_channel_name))
.setLightsEnabled(false) // less annoying .setLightsEnabled(false) // less annoying
.setVibrationEnabled(false) // less annoying .setVibrationEnabled(false) // less annoying
.build(); .build();
notificationManager.createNotificationChannel(notificationChannel); notificationManager.createNotificationChannel(notificationChannel);

View File

@@ -2,7 +2,6 @@ package app.organicmaps.car;
import android.content.Intent; import android.content.Intent;
import android.content.res.Configuration; import android.content.res.Configuration;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.car.app.Screen; import androidx.car.app.Screen;
@@ -11,11 +10,8 @@ import androidx.car.app.Session;
import androidx.car.app.SessionInfo; import androidx.car.app.SessionInfo;
import androidx.lifecycle.DefaultLifecycleObserver; import androidx.lifecycle.DefaultLifecycleObserver;
import androidx.lifecycle.LifecycleOwner; import androidx.lifecycle.LifecycleOwner;
import app.organicmaps.sdk.Framework;
import app.organicmaps.MwmApplication; import app.organicmaps.MwmApplication;
import app.organicmaps.R; import app.organicmaps.R;
import app.organicmaps.sdk.bookmarks.data.MapObject;
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;
@@ -30,23 +26,24 @@ import app.organicmaps.car.util.CurrentCountryChangedListener;
import app.organicmaps.car.util.IntentUtils; import app.organicmaps.car.util.IntentUtils;
import app.organicmaps.car.util.ThemeUtils; import app.organicmaps.car.util.ThemeUtils;
import app.organicmaps.car.util.UserActionRequired; import app.organicmaps.car.util.UserActionRequired;
import app.organicmaps.routing.RoutingController;
import app.organicmaps.sdk.Framework;
import app.organicmaps.sdk.PlacePageActivationListener;
import app.organicmaps.sdk.bookmarks.data.MapObject;
import app.organicmaps.sdk.display.DisplayChangedListener; import app.organicmaps.sdk.display.DisplayChangedListener;
import app.organicmaps.sdk.display.DisplayManager; import app.organicmaps.sdk.display.DisplayManager;
import app.organicmaps.sdk.display.DisplayType; import app.organicmaps.sdk.display.DisplayType;
import app.organicmaps.sdk.location.LocationState; import app.organicmaps.sdk.location.LocationState;
import app.organicmaps.routing.RoutingController;
import app.organicmaps.sdk.PlacePageActivationListener;
import app.organicmaps.sdk.util.Config; import app.organicmaps.sdk.util.Config;
import app.organicmaps.sdk.util.LocationUtils; import app.organicmaps.sdk.util.LocationUtils;
import app.organicmaps.sdk.util.log.Logger; import app.organicmaps.sdk.util.log.Logger;
import app.organicmaps.sdk.widget.placepage.PlacePageData; import app.organicmaps.sdk.widget.placepage.PlacePageData;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
public final class CarAppSession extends Session implements DefaultLifecycleObserver, public final class CarAppSession extends Session implements DefaultLifecycleObserver, LocationState.ModeChangeListener,
LocationState.ModeChangeListener, DisplayChangedListener, PlacePageActivationListener DisplayChangedListener, PlacePageActivationListener
{ {
private static final String TAG = CarAppSession.class.getSimpleName(); private static final String TAG = CarAppSession.class.getSimpleName();
@@ -167,9 +164,12 @@ public final class CarAppSession extends Session implements DefaultLifecycleObse
MwmApplication.from(getCarContext()).initOrganicMaps(() -> { MwmApplication.from(getCarContext()).initOrganicMaps(() -> {
Config.setFirstStartDialogSeen(getCarContext()); Config.setFirstStartDialogSeen(getCarContext());
if (DownloaderHelpers.isWorldMapsDownloadNeeded()) if (DownloaderHelpers.isWorldMapsDownloadNeeded())
mScreenManager.push(new DownloadMapsScreenBuilder(getCarContext()).setDownloaderType(DownloadMapsScreenBuilder.DownloaderType.FirstLaunch).build()); mScreenManager.push(new DownloadMapsScreenBuilder(getCarContext())
.setDownloaderType(DownloadMapsScreenBuilder.DownloaderType.FirstLaunch)
.build());
}); });
} catch (IOException e) }
catch (IOException e)
{ {
mInitFailed = true; mInitFailed = true;
Logger.e(TAG, "Failed to initialize the app."); Logger.e(TAG, "Failed to initialize the app.");
@@ -254,7 +254,8 @@ public final class CarAppSession extends Session implements DefaultLifecycleObse
Framework.nativeDeactivatePopup(); Framework.nativeDeactivatePopup();
return; return;
} }
final PlaceScreen placeScreen = new PlaceScreen.Builder(getCarContext(), mSurfaceRenderer).setMapObject(mapObject).build(); final PlaceScreen placeScreen =
new PlaceScreen.Builder(getCarContext(), mSurfaceRenderer).setMapObject(mapObject).build();
mScreenManager.popToRoot(); mScreenManager.popToRoot();
mScreenManager.push(placeScreen); mScreenManager.push(placeScreen);
} }
@@ -282,7 +283,9 @@ public final class CarAppSession extends Session implements DefaultLifecycleObse
final RoutingController routingController = RoutingController.get(); final RoutingController routingController = RoutingController.get();
if (routingController.isPlanning() || routingController.isNavigating() || routingController.hasSavedRoute()) if (routingController.isPlanning() || routingController.isNavigating() || routingController.hasSavedRoute())
{ {
final PlaceScreen placeScreen = new PlaceScreen.Builder(getCarContext(), mSurfaceRenderer).setMapObject(routingController.getEndPoint()).build(); final PlaceScreen placeScreen = new PlaceScreen.Builder(getCarContext(), mSurfaceRenderer)
.setMapObject(routingController.getEndPoint())
.build();
mScreenManager.popToRoot(); mScreenManager.popToRoot();
mScreenManager.push(placeScreen); mScreenManager.push(placeScreen);
} }

View File

@@ -4,7 +4,6 @@ import static app.organicmaps.sdk.display.DisplayType.Car;
import android.graphics.Rect; import android.graphics.Rect;
import android.view.Surface; import android.view.Surface;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.car.app.AppManager; import androidx.car.app.AppManager;
@@ -15,11 +14,10 @@ import androidx.car.app.SurfaceContainer;
import androidx.lifecycle.DefaultLifecycleObserver; import androidx.lifecycle.DefaultLifecycleObserver;
import androidx.lifecycle.Lifecycle; import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleOwner; import androidx.lifecycle.LifecycleOwner;
import app.organicmaps.R;
import app.organicmaps.sdk.Framework; import app.organicmaps.sdk.Framework;
import app.organicmaps.sdk.Map; import app.organicmaps.sdk.Map;
import app.organicmaps.sdk.MapRenderingListener; import app.organicmaps.sdk.MapRenderingListener;
import app.organicmaps.R;
import app.organicmaps.sdk.display.DisplayManager; import app.organicmaps.sdk.display.DisplayManager;
import app.organicmaps.sdk.settings.UnitLocale; import app.organicmaps.sdk.settings.UnitLocale;
import app.organicmaps.sdk.util.concurrency.UiThread; import app.organicmaps.sdk.util.concurrency.UiThread;
@@ -58,12 +56,9 @@ public class SurfaceRenderer implements DefaultLifecycleObserver, SurfaceCallbac
mSurface.release(); mSurface.release();
mSurface = surfaceContainer.getSurface(); mSurface = surfaceContainer.getSurface();
mMap.onSurfaceCreated( mMap.onSurfaceCreated(mCarContext, mSurface,
mCarContext, new Rect(0, 0, surfaceContainer.getWidth(), surfaceContainer.getHeight()),
mSurface, surfaceContainer.getDpi());
new Rect(0, 0, surfaceContainer.getWidth(), surfaceContainer.getHeight()),
surfaceContainer.getDpi()
);
mMap.updateBottomWidgetsOffset(mCarContext, -1, -1); mMap.updateBottomWidgetsOffset(mCarContext, -1, -1);
} }

View File

@@ -14,22 +14,18 @@ import androidx.car.app.model.ItemList;
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 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.SurfaceRenderer;
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.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, @DrawableRes int iconNightResId) {}
{
}
private static final List<CategoryData> CATEGORIES = Arrays.asList( private static final List<CategoryData> CATEGORIES = Arrays.asList(
new CategoryData(R.string.category_fuel, R.drawable.ic_category_fuel, R.drawable.ic_category_fuel_night), new CategoryData(R.string.category_fuel, R.drawable.ic_category_fuel, R.drawable.ic_category_fuel_night),
@@ -38,8 +34,7 @@ public class CategoriesScreen extends BaseMapScreen
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, R.drawable.ic_category_food_night),
new CategoryData(R.string.category_hotel, R.drawable.ic_category_hotel, R.drawable.ic_category_hotel_night), new CategoryData(R.string.category_hotel, R.drawable.ic_category_hotel, R.drawable.ic_category_hotel_night),
new CategoryData(R.string.category_toilet, R.drawable.ic_category_toilet, R.drawable.ic_category_toilet_night), new CategoryData(R.string.category_toilet, R.drawable.ic_category_toilet, R.drawable.ic_category_toilet_night),
new CategoryData(R.string.category_rv, R.drawable.ic_category_rv, R.drawable.ic_category_rv_night) new CategoryData(R.string.category_rv, R.drawable.ic_category_rv, R.drawable.ic_category_rv_night));
);
private final int MAX_CATEGORIES_SIZE; private final int MAX_CATEGORIES_SIZE;
@@ -79,11 +74,15 @@ 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 final int iconResId = isNightMode ? CATEGORIES.get(i).iconNightResId : CATEGORIES.get(i).iconResId; @DrawableRes
final int iconResId = isNightMode ? CATEGORIES.get(i).iconNightResId : 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());
itemBuilder.setOnClickListener(() -> getScreenManager().push(new SearchOnMapScreen.Builder(getCarContext(), getSurfaceRenderer()).setCategory(title).build())); itemBuilder.setOnClickListener(
()
-> getScreenManager().push(
new SearchOnMapScreen.Builder(getCarContext(), getSurfaceRenderer()).setCategory(title).build()));
builder.addItem(itemBuilder.build()); builder.addItem(itemBuilder.build());
} }
return new GridTemplate.Builder().setHeader(createHeader()).setSingleList(builder.build()).build(); return new GridTemplate.Builder().setHeader(createHeader()).setSingleList(builder.build()).build();

View File

@@ -8,7 +8,6 @@ import androidx.car.app.model.Action;
import androidx.car.app.model.Header; import androidx.car.app.model.Header;
import androidx.car.app.model.MessageTemplate; import androidx.car.app.model.MessageTemplate;
import androidx.car.app.model.Template; import androidx.car.app.model.Template;
import app.organicmaps.R; import app.organicmaps.R;
import app.organicmaps.car.screens.base.BaseScreen; import app.organicmaps.car.screens.base.BaseScreen;
import app.organicmaps.car.util.Colors; import app.organicmaps.car.util.Colors;
@@ -56,17 +55,17 @@ public class ErrorScreen extends BaseScreen implements UserActionRequired
if (mPositiveButtonText != -1) if (mPositiveButtonText != -1)
{ {
builder.addAction(new Action.Builder() builder.addAction(new Action.Builder()
.setBackgroundColor(Colors.BUTTON_ACCEPT) .setBackgroundColor(Colors.BUTTON_ACCEPT)
.setTitle(getCarContext().getString(mPositiveButtonText)) .setTitle(getCarContext().getString(mPositiveButtonText))
.setOnClickListener(this::onPositiveButton).build() .setOnClickListener(this::onPositiveButton)
); .build());
} }
if (mNegativeButtonText != -1) if (mNegativeButtonText != -1)
{ {
builder.addAction(new Action.Builder() builder.addAction(new Action.Builder()
.setTitle(getCarContext().getString(mNegativeButtonText)) .setTitle(getCarContext().getString(mNegativeButtonText))
.setOnClickListener(this::onNegativeButton).build() .setOnClickListener(this::onNegativeButton)
); .build());
} }
return builder.build(); return builder.build();

View File

@@ -8,7 +8,6 @@ import androidx.car.app.model.CarIcon;
import androidx.car.app.model.Template; 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.SurfaceRenderer;
import app.organicmaps.car.screens.base.BaseMapScreen; import app.organicmaps.car.screens.base.BaseMapScreen;
@@ -36,7 +35,8 @@ public class FreeDriveScreen extends BaseMapScreen
private ActionStrip createActionStrip() private ActionStrip createActionStrip()
{ {
final Action.Builder finishActionBuilder = new Action.Builder(); final Action.Builder finishActionBuilder = new Action.Builder();
finishActionBuilder.setIcon(new CarIcon.Builder(IconCompat.createWithResource(getCarContext(), R.drawable.ic_close)).build()); finishActionBuilder.setIcon(
new CarIcon.Builder(IconCompat.createWithResource(getCarContext(), R.drawable.ic_close)).build());
finishActionBuilder.setOnClickListener(this::finish); finishActionBuilder.setOnClickListener(this::finish);
final ActionStrip.Builder builder = new ActionStrip.Builder(); final ActionStrip.Builder builder = new ActionStrip.Builder();

View File

@@ -8,7 +8,6 @@ import androidx.car.app.model.Header;
import androidx.car.app.model.MessageTemplate; import androidx.car.app.model.MessageTemplate;
import androidx.car.app.model.Template; import androidx.car.app.model.Template;
import androidx.core.graphics.drawable.IconCompat; import androidx.core.graphics.drawable.IconCompat;
import app.organicmaps.R; import app.organicmaps.R;
import app.organicmaps.car.screens.base.BaseScreen; import app.organicmaps.car.screens.base.BaseScreen;
import app.organicmaps.sdk.display.DisplayManager; import app.organicmaps.sdk.display.DisplayManager;
@@ -25,15 +24,19 @@ public class MapPlaceholderScreen extends BaseScreen
@Override @Override
public Template onGetTemplate() public Template onGetTemplate()
{ {
final MessageTemplate.Builder builder = new MessageTemplate.Builder(getCarContext().getString(R.string.car_used_on_the_phone_screen)); final MessageTemplate.Builder builder =
new MessageTemplate.Builder(getCarContext().getString(R.string.car_used_on_the_phone_screen));
final Header.Builder headerBuilder = new Header.Builder(); final Header.Builder headerBuilder = new Header.Builder();
headerBuilder.setStartHeaderAction(Action.APP_ICON); headerBuilder.setStartHeaderAction(Action.APP_ICON);
headerBuilder.setTitle(getCarContext().getString(R.string.app_name)); headerBuilder.setTitle(getCarContext().getString(R.string.app_name));
builder.setHeader(headerBuilder.build()); builder.setHeader(headerBuilder.build());
builder.setIcon(new CarIcon.Builder(IconCompat.createWithResource(getCarContext(), R.drawable.ic_phone_android)).build()); builder.setIcon(
builder.addAction(new Action.Builder().setTitle(getCarContext().getString(R.string.car_continue_in_the_car)) new CarIcon.Builder(IconCompat.createWithResource(getCarContext(), R.drawable.ic_phone_android)).build());
.setOnClickListener(() -> DisplayManager.from(getCarContext()).changeDisplay(DisplayType.Car)).build()); builder.addAction(new Action.Builder()
.setTitle(getCarContext().getString(R.string.car_continue_in_the_car))
.setOnClickListener(() -> DisplayManager.from(getCarContext()).changeDisplay(DisplayType.Car))
.build());
return builder.build(); return builder.build();
} }

View File

@@ -13,7 +13,6 @@ import androidx.car.app.model.ItemList;
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 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.SurfaceRenderer;
import app.organicmaps.car.screens.base.BaseMapScreen; import app.organicmaps.car.screens.base.BaseMapScreen;
@@ -56,8 +55,10 @@ public class MapScreen extends BaseMapScreen
private ActionStrip createActionStrip() private ActionStrip createActionStrip()
{ {
final Action.Builder freeDriveScreenBuilder = new Action.Builder(); final Action.Builder freeDriveScreenBuilder = new Action.Builder();
freeDriveScreenBuilder.setIcon(new CarIcon.Builder(IconCompat.createWithResource(getCarContext(), R.drawable.ic_steering_wheel)).build()); freeDriveScreenBuilder.setIcon(
freeDriveScreenBuilder.setOnClickListener(() -> getScreenManager().push(new FreeDriveScreen(getCarContext(), getSurfaceRenderer()))); new CarIcon.Builder(IconCompat.createWithResource(getCarContext(), R.drawable.ic_steering_wheel)).build());
freeDriveScreenBuilder.setOnClickListener(
() -> getScreenManager().push(new FreeDriveScreen(getCarContext(), getSurfaceRenderer())));
final ActionStrip.Builder builder = new ActionStrip.Builder(); final ActionStrip.Builder builder = new ActionStrip.Builder();
builder.addAction(freeDriveScreenBuilder.build()); builder.addAction(freeDriveScreenBuilder.build());
@@ -83,7 +84,8 @@ public class MapScreen extends BaseMapScreen
@NonNull @NonNull
private Item createSearchItem() private Item createSearchItem()
{ {
final CarIcon iconSearch = new CarIcon.Builder(IconCompat.createWithResource(getCarContext(), R.drawable.ic_search)).build(); final CarIcon iconSearch =
new CarIcon.Builder(IconCompat.createWithResource(getCarContext(), R.drawable.ic_search)).build();
final GridItem.Builder builder = new GridItem.Builder(); final GridItem.Builder builder = new GridItem.Builder();
builder.setTitle(getCarContext().getString(R.string.search)); builder.setTitle(getCarContext().getString(R.string.search));
@@ -95,7 +97,8 @@ public class MapScreen extends BaseMapScreen
@NonNull @NonNull
private Item createCategoriesItem() private Item createCategoriesItem()
{ {
final CarIcon iconCategories = new CarIcon.Builder(IconCompat.createWithResource(getCarContext(), R.drawable.ic_address)).build(); final CarIcon iconCategories =
new CarIcon.Builder(IconCompat.createWithResource(getCarContext(), R.drawable.ic_address)).build();
final GridItem.Builder builder = new GridItem.Builder(); final GridItem.Builder builder = new GridItem.Builder();
builder.setImage(iconCategories); builder.setImage(iconCategories);
@@ -107,7 +110,8 @@ public class MapScreen extends BaseMapScreen
@NonNull @NonNull
private Item createBookmarksItem() private Item createBookmarksItem()
{ {
final CarIcon iconBookmarks = new CarIcon.Builder(IconCompat.createWithResource(getCarContext(), R.drawable.ic_bookmarks)).build(); final CarIcon iconBookmarks =
new CarIcon.Builder(IconCompat.createWithResource(getCarContext(), R.drawable.ic_bookmarks)).build();
final GridItem.Builder builder = new GridItem.Builder(); final GridItem.Builder builder = new GridItem.Builder();
builder.setImage(iconBookmarks); builder.setImage(iconBookmarks);
@@ -119,7 +123,8 @@ public class MapScreen extends BaseMapScreen
@NonNull @NonNull
private Item createSettingsItem() private Item createSettingsItem()
{ {
final CarIcon iconSettings = new CarIcon.Builder(IconCompat.createWithResource(getCarContext(), R.drawable.ic_settings)).build(); final CarIcon iconSettings =
new CarIcon.Builder(IconCompat.createWithResource(getCarContext(), R.drawable.ic_settings)).build();
final GridItem.Builder builder = new GridItem.Builder(); final GridItem.Builder builder = new GridItem.Builder();
builder.setImage(iconSettings); builder.setImage(iconSettings);

View File

@@ -17,8 +17,6 @@ import androidx.car.app.navigation.model.TravelEstimate;
import androidx.car.app.navigation.model.Trip; import androidx.car.app.navigation.model.Trip;
import androidx.core.graphics.drawable.IconCompat; import androidx.core.graphics.drawable.IconCompat;
import androidx.lifecycle.LifecycleOwner; import androidx.lifecycle.LifecycleOwner;
import app.organicmaps.sdk.Framework;
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;
@@ -29,16 +27,16 @@ import app.organicmaps.car.util.Colors;
import app.organicmaps.car.util.RoutingUtils; import app.organicmaps.car.util.RoutingUtils;
import app.organicmaps.car.util.ThemeUtils; import app.organicmaps.car.util.ThemeUtils;
import app.organicmaps.car.util.UiHelpers; import app.organicmaps.car.util.UiHelpers;
import app.organicmaps.routing.NavigationService;
import app.organicmaps.routing.RoutingController;
import app.organicmaps.sdk.Framework;
import app.organicmaps.sdk.location.LocationHelper; import app.organicmaps.sdk.location.LocationHelper;
import app.organicmaps.sdk.location.LocationListener; import app.organicmaps.sdk.location.LocationListener;
import app.organicmaps.sdk.routing.JunctionInfo; import app.organicmaps.sdk.routing.JunctionInfo;
import app.organicmaps.routing.NavigationService;
import app.organicmaps.routing.RoutingController;
import app.organicmaps.sdk.routing.RoutingInfo; import app.organicmaps.sdk.routing.RoutingInfo;
import app.organicmaps.sdk.sound.TtsPlayer; import app.organicmaps.sdk.sound.TtsPlayer;
import app.organicmaps.sdk.util.LocationUtils; import app.organicmaps.sdk.util.LocationUtils;
import app.organicmaps.sdk.util.log.Logger; import app.organicmaps.sdk.util.log.Logger;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
@@ -75,7 +73,8 @@ public class NavigationScreen extends BaseMapScreen implements RoutingController
public Template onGetTemplate() public Template onGetTemplate()
{ {
final NavigationTemplate.Builder builder = new NavigationTemplate.Builder(); final NavigationTemplate.Builder builder = new NavigationTemplate.Builder();
builder.setBackgroundColor(ThemeUtils.isNightMode(getCarContext()) ? Colors.NAVIGATION_TEMPLATE_BACKGROUND_NIGHT : Colors.NAVIGATION_TEMPLATE_BACKGROUND_DAY); builder.setBackgroundColor(ThemeUtils.isNightMode(getCarContext()) ? Colors.NAVIGATION_TEMPLATE_BACKGROUND_NIGHT
: Colors.NAVIGATION_TEMPLATE_BACKGROUND_DAY);
builder.setActionStrip(createActionStrip()); builder.setActionStrip(createActionStrip());
builder.setMapActionStrip(UiHelpers.createMapActionStrip(getCarContext(), getSurfaceRenderer())); builder.setMapActionStrip(UiHelpers.createMapActionStrip(getCarContext(), getSurfaceRenderer()));
@@ -121,7 +120,8 @@ public class NavigationScreen extends BaseMapScreen implements RoutingController
public void onNavigationCancelled() public void onNavigationCancelled()
{ {
if (!mNavigationCancelled) if (!mNavigationCancelled)
CarToast.makeText(getCarContext(), getCarContext().getString(R.string.trip_finished), CarToast.LENGTH_LONG).show(); CarToast.makeText(getCarContext(), getCarContext().getString(R.string.trip_finished), CarToast.LENGTH_LONG)
.show();
finish(); finish();
getScreenManager().popToRoot(); getScreenManager().popToRoot();
} }
@@ -137,7 +137,8 @@ public class NavigationScreen extends BaseMapScreen implements RoutingController
MwmApplication.from(getCarContext()).getLocationHelper().addListener(mLocationListener); MwmApplication.from(getCarContext()).getLocationHelper().addListener(mLocationListener);
if (LocationUtils.checkFineLocationPermission(getCarContext())) if (LocationUtils.checkFineLocationPermission(getCarContext()))
NavigationService.startForegroundService(getCarContext(), CarAppService.getCarNotificationExtender(getCarContext())); NavigationService.startForegroundService(getCarContext(),
CarAppService.getCarNotificationExtender(getCarContext()));
updateTrip(); updateTrip();
} }
@@ -166,7 +167,8 @@ public class NavigationScreen extends BaseMapScreen implements RoutingController
private ActionStrip createActionStrip() private ActionStrip createActionStrip()
{ {
final Action.Builder stopActionBuilder = new Action.Builder(); final Action.Builder stopActionBuilder = new Action.Builder();
stopActionBuilder.setIcon(new CarIcon.Builder(IconCompat.createWithResource(getCarContext(), R.drawable.ic_close)).build()); stopActionBuilder.setIcon(
new CarIcon.Builder(IconCompat.createWithResource(getCarContext(), R.drawable.ic_close)).build());
stopActionBuilder.setOnClickListener(() -> { stopActionBuilder.setOnClickListener(() -> {
mNavigationCancelled = true; mNavigationCancelled = true;
mRoutingController.cancel(); mRoutingController.cancel();
@@ -195,7 +197,8 @@ public class NavigationScreen extends BaseMapScreen implements RoutingController
@NonNull @NonNull
private NavigationTemplate.NavigationInfo getNavigationInfo() private NavigationTemplate.NavigationInfo getNavigationInfo()
{ {
final androidx.car.app.navigation.model.RoutingInfo.Builder builder = new androidx.car.app.navigation.model.RoutingInfo.Builder(); final androidx.car.app.navigation.model.RoutingInfo.Builder builder =
new androidx.car.app.navigation.model.RoutingInfo.Builder();
if (mTrip.isLoading()) if (mTrip.isLoading())
{ {
@@ -228,7 +231,8 @@ public class NavigationScreen extends BaseMapScreen implements RoutingController
private Action createTtsAction() private Action createTtsAction()
{ {
final Action.Builder ttsActionBuilder = new Action.Builder(); final Action.Builder ttsActionBuilder = new Action.Builder();
@DrawableRes final int imgRes = TtsPlayer.isEnabled() ? R.drawable.ic_voice_on : R.drawable.ic_voice_off; @DrawableRes
final int imgRes = TtsPlayer.isEnabled() ? R.drawable.ic_voice_on : R.drawable.ic_voice_off;
ttsActionBuilder.setIcon(new CarIcon.Builder(IconCompat.createWithResource(getCarContext(), imgRes)).build()); ttsActionBuilder.setIcon(new CarIcon.Builder(IconCompat.createWithResource(getCarContext(), imgRes)).build());
ttsActionBuilder.setOnClickListener(() -> { ttsActionBuilder.setOnClickListener(() -> {
TtsPlayer.setEnabled(!TtsPlayer.isEnabled()); TtsPlayer.setEnabled(!TtsPlayer.isEnabled());

View File

@@ -7,7 +7,6 @@ import android.content.Intent;
import android.net.Uri; import android.net.Uri;
import android.text.SpannableString; import android.text.SpannableString;
import android.text.TextUtils; import android.text.TextUtils;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.car.app.CarContext; import androidx.car.app.CarContext;
@@ -25,12 +24,8 @@ 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 androidx.lifecycle.LifecycleOwner; import androidx.lifecycle.LifecycleOwner;
import app.organicmaps.sdk.Framework;
import app.organicmaps.MwmApplication; import app.organicmaps.MwmApplication;
import app.organicmaps.R; import app.organicmaps.R;
import app.organicmaps.sdk.bookmarks.data.MapObject;
import app.organicmaps.sdk.bookmarks.data.Metadata;
import app.organicmaps.car.SurfaceRenderer; import app.organicmaps.car.SurfaceRenderer;
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;
@@ -41,10 +36,12 @@ import app.organicmaps.car.util.RoutingHelpers;
import app.organicmaps.car.util.UiHelpers; import app.organicmaps.car.util.UiHelpers;
import app.organicmaps.routing.ResultCodesHelper; import app.organicmaps.routing.ResultCodesHelper;
import app.organicmaps.routing.RoutingController; import app.organicmaps.routing.RoutingController;
import app.organicmaps.sdk.routing.RoutingInfo; import app.organicmaps.sdk.Framework;
import app.organicmaps.sdk.Router; import app.organicmaps.sdk.Router;
import app.organicmaps.sdk.bookmarks.data.MapObject;
import app.organicmaps.sdk.bookmarks.data.Metadata;
import app.organicmaps.sdk.routing.RoutingInfo;
import app.organicmaps.sdk.util.Config; import app.organicmaps.sdk.util.Config;
import java.util.Objects; import java.util.Objects;
public class PlaceScreen extends BaseMapScreen implements OnBackPressedCallback.Callback, RoutingController.Container public class PlaceScreen extends BaseMapScreen implements OnBackPressedCallback.Callback, RoutingController.Container
@@ -95,7 +92,8 @@ public class PlaceScreen extends BaseMapScreen implements OnBackPressedCallback.
mRoutingController.restoreRoute(); mRoutingController.restoreRoute();
else else
{ {
final boolean hasIncorrectEndPoint = mRoutingController.isPlanning() && (!MapObject.same(mMapObject, mRoutingController.getEndPoint())); final boolean hasIncorrectEndPoint =
mRoutingController.isPlanning() && (!MapObject.same(mMapObject, mRoutingController.getEndPoint()));
final boolean hasIncorrectRouterType = mRoutingController.getLastRouterType() != ROUTER; final boolean hasIncorrectRouterType = mRoutingController.getLastRouterType() != ROUTER;
final boolean isNotPlanningMode = !mRoutingController.isPlanning(); final boolean isNotPlanningMode = !mRoutingController.isPlanning();
if (hasIncorrectRouterType) if (hasIncorrectRouterType)
@@ -105,7 +103,8 @@ public class PlaceScreen extends BaseMapScreen implements OnBackPressedCallback.
} }
else if (hasIncorrectEndPoint || isNotPlanningMode) else if (hasIncorrectEndPoint || isNotPlanningMode)
{ {
mRoutingController.prepare(MwmApplication.from(getCarContext()).getLocationHelper().getMyPosition(), mMapObject); mRoutingController.prepare(MwmApplication.from(getCarContext()).getLocationHelper().getMyPosition(),
mMapObject);
} }
} }
} }
@@ -159,7 +158,8 @@ public class PlaceScreen extends BaseMapScreen implements OnBackPressedCallback.
if (routingInfo != null) if (routingInfo != null)
builder.addRow(getPlaceRouteInfo(routingInfo)); builder.addRow(getPlaceRouteInfo(routingInfo));
final Row placeOpeningHours = UiHelpers.getPlaceOpeningHoursRow(Objects.requireNonNull(mMapObject), getCarContext()); final Row placeOpeningHours =
UiHelpers.getPlaceOpeningHoursRow(Objects.requireNonNull(mMapObject), getCarContext());
if (placeOpeningHours != null) if (placeOpeningHours != null)
builder.addRow(placeOpeningHours); builder.addRow(placeOpeningHours);
@@ -195,7 +195,8 @@ public class PlaceScreen extends BaseMapScreen implements OnBackPressedCallback.
builder.setTitle(time); builder.setTitle(time);
final SpannableString distance = new SpannableString(" "); final SpannableString distance = new SpannableString(" ");
distance.setSpan(DistanceSpan.create(RoutingHelpers.createDistance(routingInfo.distToTarget)), 0, 1, SPAN_INCLUSIVE_INCLUSIVE); distance.setSpan(DistanceSpan.create(RoutingHelpers.createDistance(routingInfo.distToTarget)), 0, 1,
SPAN_INCLUSIVE_INCLUSIVE);
distance.setSpan(ForegroundCarColorSpan.create(Colors.DISTANCE), 0, 1, SPAN_EXCLUSIVE_EXCLUSIVE); distance.setSpan(ForegroundCarColorSpan.create(Colors.DISTANCE), 0, 1, SPAN_EXCLUSIVE_EXCLUSIVE);
builder.addText(distance); builder.addText(distance);
@@ -211,8 +212,10 @@ public class PlaceScreen extends BaseMapScreen implements OnBackPressedCallback.
{ {
final String phoneNumber = phones.split(";", 1)[0]; final String phoneNumber = phones.split(";", 1)[0];
final Action.Builder openDialBuilder = new Action.Builder(); final Action.Builder openDialBuilder = new Action.Builder();
openDialBuilder.setIcon(new CarIcon.Builder(IconCompat.createWithResource(getCarContext(), R.drawable.ic_phone)).build()); openDialBuilder.setIcon(
openDialBuilder.setOnClickListener(() -> getCarContext().startCarApp(new Intent(Intent.ACTION_DIAL, Uri.parse("tel:" + phoneNumber)))); new CarIcon.Builder(IconCompat.createWithResource(getCarContext(), R.drawable.ic_phone)).build());
openDialBuilder.setOnClickListener(
() -> getCarContext().startCarApp(new Intent(Intent.ACTION_DIAL, Uri.parse("tel:" + phoneNumber))));
builder.addAction(openDialBuilder.build()); builder.addAction(openDialBuilder.build());
} }
@@ -224,7 +227,8 @@ public class PlaceScreen extends BaseMapScreen implements OnBackPressedCallback.
startRouteBuilder.setBackgroundColor(Colors.START_NAVIGATION); startRouteBuilder.setBackgroundColor(Colors.START_NAVIGATION);
startRouteBuilder.setFlags(Action.FLAG_DEFAULT); startRouteBuilder.setFlags(Action.FLAG_DEFAULT);
startRouteBuilder.setTitle(getCarContext().getString(R.string.p2p_start)); startRouteBuilder.setTitle(getCarContext().getString(R.string.p2p_start));
startRouteBuilder.setIcon(new CarIcon.Builder(IconCompat.createWithResource(getCarContext(), R.drawable.ic_follow_and_rotate)).build()); startRouteBuilder.setIcon(
new CarIcon.Builder(IconCompat.createWithResource(getCarContext(), R.drawable.ic_follow_and_rotate)).build());
startRouteBuilder.setOnClickListener(() -> { startRouteBuilder.setOnClickListener(() -> {
Config.acceptRoutingDisclaimer(); Config.acceptRoutingDisclaimer();
mRoutingController.start(); mRoutingController.start();
@@ -238,7 +242,10 @@ public class PlaceScreen extends BaseMapScreen implements OnBackPressedCallback.
{ {
return new Action.Builder() return new Action.Builder()
.setIcon(new CarIcon.Builder(IconCompat.createWithResource(getCarContext(), R.drawable.ic_settings)).build()) .setIcon(new CarIcon.Builder(IconCompat.createWithResource(getCarContext(), R.drawable.ic_settings)).build())
.setOnClickListener(() -> getScreenManager().pushForResult(new DrivingOptionsScreen(getCarContext(), getSurfaceRenderer()), this::onDrivingOptionsResult)) .setOnClickListener(
()
-> getScreenManager().pushForResult(new DrivingOptionsScreen(getCarContext(), getSurfaceRenderer()),
this::onDrivingOptionsResult))
.build(); .build();
} }
@@ -310,8 +317,7 @@ public class PlaceScreen extends BaseMapScreen implements OnBackPressedCallback.
else else
mRoutingController.checkAndBuildRoute(); mRoutingController.checkAndBuildRoute();
invalidate(); invalidate();
} });
);
else else
{ {
CarToast.makeText(getCarContext(), R.string.unable_to_calc_alert_title, CarToast.LENGTH_LONG).show(); CarToast.makeText(getCarContext(), R.string.unable_to_calc_alert_title, CarToast.LENGTH_LONG).show();

View File

@@ -2,7 +2,6 @@ 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.SurfaceRenderer;
public abstract class BaseMapScreen extends BaseScreen public abstract class BaseMapScreen extends BaseScreen

View File

@@ -10,14 +10,12 @@ import androidx.car.app.model.ListTemplate;
import androidx.car.app.model.Row; 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.sdk.bookmarks.data.BookmarkCategory;
import app.organicmaps.sdk.bookmarks.data.BookmarkManager;
import app.organicmaps.car.SurfaceRenderer; import app.organicmaps.car.SurfaceRenderer;
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.BookmarkManager;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@@ -65,7 +63,8 @@ public class BookmarkCategoriesScreen extends BaseMapScreen
Row.Builder itemBuilder = new Row.Builder(); Row.Builder itemBuilder = new Row.Builder();
itemBuilder.setTitle(bookmarkCategory.getName()); itemBuilder.setTitle(bookmarkCategory.getName());
itemBuilder.addText(bookmarkCategory.getDescription()); itemBuilder.addText(bookmarkCategory.getDescription());
itemBuilder.setOnClickListener(() -> getScreenManager().push(new BookmarksScreen(getCarContext(), getSurfaceRenderer(), bookmarkCategory))); itemBuilder.setOnClickListener(
() -> getScreenManager().push(new BookmarksScreen(getCarContext(), getSurfaceRenderer(), bookmarkCategory)));
itemBuilder.setBrowsable(true); itemBuilder.setBrowsable(true);
builder.addItem(itemBuilder.build()); builder.addItem(itemBuilder.build());
} }

View File

@@ -4,7 +4,6 @@ import android.graphics.drawable.Drawable;
import android.location.Location; import android.location.Location;
import android.text.SpannableStringBuilder; import android.text.SpannableStringBuilder;
import android.text.Spanned; import android.text.Spanned;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.car.app.CarContext; import androidx.car.app.CarContext;
@@ -15,21 +14,19 @@ import androidx.car.app.model.ForegroundCarColorSpan;
import androidx.car.app.model.ItemList; import androidx.car.app.model.ItemList;
import androidx.car.app.model.Row; import androidx.car.app.model.Row;
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.util.Colors;
import app.organicmaps.car.util.RoutingHelpers;
import app.organicmaps.sdk.bookmarks.data.BookmarkCategory; import app.organicmaps.sdk.bookmarks.data.BookmarkCategory;
import app.organicmaps.sdk.bookmarks.data.BookmarkInfo; import app.organicmaps.sdk.bookmarks.data.BookmarkInfo;
import app.organicmaps.sdk.bookmarks.data.BookmarkManager; import app.organicmaps.sdk.bookmarks.data.BookmarkManager;
import app.organicmaps.sdk.bookmarks.data.Icon; import app.organicmaps.sdk.bookmarks.data.Icon;
import app.organicmaps.sdk.bookmarks.data.SortedBlock; import app.organicmaps.sdk.bookmarks.data.SortedBlock;
import app.organicmaps.car.util.Colors;
import app.organicmaps.car.util.RoutingHelpers;
import app.organicmaps.sdk.util.Distance; import app.organicmaps.sdk.util.Distance;
import app.organicmaps.util.Graphics;
import app.organicmaps.sdk.util.concurrency.ThreadPool; import app.organicmaps.sdk.util.concurrency.ThreadPool;
import app.organicmaps.sdk.util.concurrency.UiThread; import app.organicmaps.sdk.util.concurrency.UiThread;
import app.organicmaps.util.Graphics;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
@@ -63,7 +60,8 @@ class BookmarksLoader implements BookmarkManager.BookmarksSortingListener
private final long mBookmarkCategoryId; private final long mBookmarkCategoryId;
private final int mBookmarksListSize; private final int mBookmarksListSize;
public BookmarksLoader(@NonNull CarContext carContext, @NonNull BookmarkCategory bookmarkCategory, @NonNull OnBookmarksLoaded onBookmarksLoaded) public BookmarksLoader(@NonNull CarContext carContext, @NonNull BookmarkCategory bookmarkCategory,
@NonNull OnBookmarksLoaded onBookmarksLoaded)
{ {
final ConstraintManager constraintManager = carContext.getCarService(ConstraintManager.class); final ConstraintManager constraintManager = carContext.getCarService(ConstraintManager.class);
final int maxCategoriesSize = constraintManager.getContentLimit(ConstraintManager.CONTENT_LIMIT_TYPE_LIST); final int maxCategoriesSize = constraintManager.getContentLimit(ConstraintManager.CONTENT_LIMIT_TYPE_LIST);
@@ -71,7 +69,8 @@ class BookmarksLoader implements BookmarkManager.BookmarksSortingListener
mCarContext = carContext; mCarContext = carContext;
mOnBookmarksLoaded = onBookmarksLoaded; mOnBookmarksLoaded = onBookmarksLoaded;
mBookmarkCategoryId = bookmarkCategory.getId(); mBookmarkCategoryId = bookmarkCategory.getId();
mBookmarksListSize = Math.min(bookmarkCategory.getBookmarksCount(), Math.min(maxCategoriesSize, MAX_BOOKMARKS_SIZE)); mBookmarksListSize =
Math.min(bookmarkCategory.getBookmarksCount(), Math.min(maxCategoriesSize, MAX_BOOKMARKS_SIZE));
} }
public void load() public void load()
@@ -161,12 +160,10 @@ class BookmarksLoader implements BookmarkManager.BookmarksSortingListener
final Icon icon = bookmarkInfo.getIcon(); final Icon icon = bookmarkInfo.getIcon();
if (!iconsCache.containsKey(icon)) if (!iconsCache.containsKey(icon))
{ {
final Drawable drawable = Graphics.drawCircleAndImage(icon.argb(), final Drawable drawable = Graphics.drawCircleAndImage(icon.argb(), R.dimen.track_circle_size, icon.getResId(),
R.dimen.track_circle_size, R.dimen.bookmark_icon_size, mCarContext);
icon.getResId(), final CarIcon carIcon =
R.dimen.bookmark_icon_size, new CarIcon.Builder(IconCompat.createWithBitmap(Graphics.drawableToBitmap(drawable))).build();
mCarContext);
final CarIcon carIcon = new CarIcon.Builder(IconCompat.createWithBitmap(Graphics.drawableToBitmap(drawable))).build();
iconsCache.put(icon, carIcon); iconsCache.put(icon, carIcon);
} }
itemBuilder.setImage(Objects.requireNonNull(iconsCache.get(icon))); itemBuilder.setImage(Objects.requireNonNull(iconsCache.get(icon)));
@@ -184,7 +181,8 @@ class BookmarksLoader implements BookmarkManager.BookmarksSortingListener
{ {
result.append(" "); result.append(" ");
final Distance distance = bookmark.getDistance(location.getLatitude(), location.getLongitude(), 0.0); final Distance distance = bookmark.getDistance(location.getLatitude(), location.getLongitude(), 0.0);
result.setSpan(DistanceSpan.create(RoutingHelpers.createDistance(distance)), 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); result.setSpan(DistanceSpan.create(RoutingHelpers.createDistance(distance)), 0, 1,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
result.setSpan(ForegroundCarColorSpan.create(Colors.DISTANCE), 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); result.setSpan(ForegroundCarColorSpan.create(Colors.DISTANCE), 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
} }

View File

@@ -12,12 +12,11 @@ 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 androidx.lifecycle.LifecycleOwner; import androidx.lifecycle.LifecycleOwner;
import app.organicmaps.R; import app.organicmaps.R;
import app.organicmaps.sdk.bookmarks.data.BookmarkCategory;
import app.organicmaps.car.SurfaceRenderer; import app.organicmaps.car.SurfaceRenderer;
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;
public class BookmarksScreen extends BaseMapScreen public class BookmarksScreen extends BaseMapScreen
{ {
@@ -32,7 +31,8 @@ public class BookmarksScreen extends BaseMapScreen
private boolean mIsOnSortingScreen = false; private boolean mIsOnSortingScreen = false;
public BookmarksScreen(@NonNull CarContext carContext, @NonNull SurfaceRenderer surfaceRenderer, @NonNull BookmarkCategory bookmarkCategory) public BookmarksScreen(@NonNull CarContext carContext, @NonNull SurfaceRenderer surfaceRenderer,
@NonNull BookmarkCategory bookmarkCategory)
{ {
super(carContext, surfaceRenderer); super(carContext, surfaceRenderer);
mBookmarkCategory = bookmarkCategory; mBookmarkCategory = bookmarkCategory;
@@ -90,7 +90,8 @@ public class BookmarksScreen extends BaseMapScreen
builder.setIcon(new CarIcon.Builder(IconCompat.createWithResource(getCarContext(), R.drawable.ic_sort)).build()); builder.setIcon(new CarIcon.Builder(IconCompat.createWithResource(getCarContext(), R.drawable.ic_sort)).build());
builder.setOnClickListener(() -> { builder.setOnClickListener(() -> {
mIsOnSortingScreen = true; mIsOnSortingScreen = true;
getScreenManager().pushForResult(new SortingScreen(getCarContext(), getSurfaceRenderer(), mBookmarkCategory), this::onSortingResult); getScreenManager().pushForResult(new SortingScreen(getCarContext(), getSurfaceRenderer(), mBookmarkCategory),
this::onSortingResult);
}); });
return builder.build(); return builder.build();
} }

View File

@@ -1,7 +1,6 @@
package app.organicmaps.car.screens.bookmarks; package app.organicmaps.car.screens.bookmarks;
import android.location.Location; import android.location.Location;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.StringRes; import androidx.annotation.StringRes;
import androidx.car.app.CarContext; import androidx.car.app.CarContext;
@@ -15,15 +14,13 @@ 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 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.sdk.bookmarks.data.BookmarkCategory;
import app.organicmaps.sdk.bookmarks.data.BookmarkManager;
import app.organicmaps.car.SurfaceRenderer; import app.organicmaps.car.SurfaceRenderer;
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.BookmarkManager;
import java.util.Arrays; import java.util.Arrays;
import java.util.stream.IntStream; import java.util.stream.IntStream;
@@ -41,11 +38,14 @@ class SortingScreen extends BaseMapScreen
private @BookmarkManager.SortingType int mNewSortingType; private @BookmarkManager.SortingType int mNewSortingType;
public SortingScreen(@NonNull CarContext carContext, @NonNull SurfaceRenderer surfaceRenderer, @NonNull BookmarkCategory bookmarkCategory) public SortingScreen(@NonNull CarContext carContext, @NonNull SurfaceRenderer surfaceRenderer,
@NonNull BookmarkCategory bookmarkCategory)
{ {
super(carContext, surfaceRenderer); super(carContext, surfaceRenderer);
mRadioButtonIcon = new CarIcon.Builder(IconCompat.createWithResource(carContext, R.drawable.ic_radio_button_unchecked)).build(); mRadioButtonIcon =
mRadioButtonSelectedIcon = new CarIcon.Builder(IconCompat.createWithResource(carContext, R.drawable.ic_radio_button_checked)).build(); new CarIcon.Builder(IconCompat.createWithResource(carContext, R.drawable.ic_radio_button_unchecked)).build();
mRadioButtonSelectedIcon =
new CarIcon.Builder(IconCompat.createWithResource(carContext, R.drawable.ic_radio_button_checked)).build();
mBookmarkCategoryId = bookmarkCategory.getId(); mBookmarkCategoryId = bookmarkCategory.getId();
mLastSortingType = mNewSortingType = getLastSortingType(); mLastSortingType = mNewSortingType = getLastSortingType();
@@ -90,10 +90,12 @@ class SortingScreen extends BaseMapScreen
} }
@NonNull @NonNull
private ItemList createSortingTypesList(@NonNull final @BookmarkManager.SortingType int[] availableSortingTypes, final int lastSortingType) private ItemList createSortingTypesList(@NonNull final @BookmarkManager.SortingType int[] availableSortingTypes,
final int lastSortingType)
{ {
final ItemList.Builder builder = new ItemList.Builder(); final ItemList.Builder builder = new ItemList.Builder();
for (int type : IntStream.concat(IntStream.of(DEFAULT_SORTING_TYPE), Arrays.stream(availableSortingTypes)).toArray()) for (int type :
IntStream.concat(IntStream.of(DEFAULT_SORTING_TYPE), Arrays.stream(availableSortingTypes)).toArray())
{ {
final Row.Builder rowBuilder = new Row.Builder(); final Row.Builder rowBuilder = new Row.Builder();
rowBuilder.setTitle(getCarContext().getString(sortingTypeToStringRes(type))); rowBuilder.setTitle(getCarContext().getString(sortingTypeToStringRes(type)));
@@ -148,7 +150,8 @@ class SortingScreen extends BaseMapScreen
private int getLastAvailableSortingType() private int getLastAvailableSortingType()
{ {
int currentType = getLastSortingType(); int currentType = getLastSortingType();
@BookmarkManager.SortingType int[] types = getAvailableSortingTypes(); @BookmarkManager.SortingType
int[] types = getAvailableSortingTypes();
for (@BookmarkManager.SortingType int type : types) for (@BookmarkManager.SortingType int type : types)
{ {
if (type == currentType) if (type == currentType)

View File

@@ -2,11 +2,9 @@ package app.organicmaps.car.screens.download;
import android.location.Location; import android.location.Location;
import android.text.TextUtils; import android.text.TextUtils;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.car.app.model.Action; import androidx.car.app.model.Action;
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.sdk.downloader.CountryItem; import app.organicmaps.sdk.downloader.CountryItem;
@@ -25,7 +23,8 @@ class DownloadMapsForFirstLaunchScreen extends DownloadMapsScreen
@Override @Override
public void onResume(@NonNull LifecycleOwner owner) public void onResume(@NonNull LifecycleOwner owner)
{ {
// Attempting to streamline initial download by including the current country in the list of missing maps for simultaneous retrieval. // Attempting to streamline initial download by including the current country in the list of missing maps for
// simultaneous retrieval.
final Location location = MwmApplication.from(getCarContext()).getLocationHelper().getSavedLocation(); final Location location = MwmApplication.from(getCarContext()).getLocationHelper().getSavedLocation();
if (location == null) if (location == null)
return; return;

View File

@@ -2,10 +2,8 @@ package app.organicmaps.car.screens.download;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.car.app.model.Action; import androidx.car.app.model.Action;
import app.organicmaps.R; import app.organicmaps.R;
import app.organicmaps.routing.ResultCodesHelper; import app.organicmaps.routing.ResultCodesHelper;
import java.util.Objects; import java.util.Objects;
class DownloadMapsForRouteScreen extends DownloadMapsScreen class DownloadMapsForRouteScreen extends DownloadMapsScreen
@@ -17,8 +15,11 @@ class DownloadMapsForRouteScreen extends DownloadMapsScreen
{ {
super(builder); super(builder);
mTitle = ResultCodesHelper.getDialogTitleSubtitle(builder.mCarContext, builder.mResultCode, Objects.requireNonNull(builder.mMissingMaps).length) mTitle = ResultCodesHelper
.getTitleMessage().first; .getDialogTitleSubtitle(builder.mCarContext, builder.mResultCode,
Objects.requireNonNull(builder.mMissingMaps).length)
.getTitleMessage()
.first;
} }
@NonNull @NonNull
@@ -35,7 +36,8 @@ class DownloadMapsForRouteScreen extends DownloadMapsScreen
final int mapsCount = getMissingMaps().size(); final int mapsCount = getMissingMaps().size();
if (mapsCount == 1) if (mapsCount == 1)
return DownloaderHelpers.getCountryName(getMissingMaps().get(0)) + "\n" + mapsSize; return DownloaderHelpers.getCountryName(getMissingMaps().get(0)) + "\n" + mapsSize;
return getCarContext().getString(R.string.downloader_status_maps) + " (" + getMissingMaps().size() + "): " + mapsSize; return getCarContext().getString(R.string.downloader_status_maps) + " (" + getMissingMaps().size()
+ "): " + mapsSize;
} }
@NonNull @NonNull

View File

@@ -2,7 +2,6 @@ package app.organicmaps.car.screens.download;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.car.app.model.Action; import androidx.car.app.model.Action;
import app.organicmaps.R; import app.organicmaps.R;
class DownloadMapsForViewScreen extends DownloadMapsScreen class DownloadMapsForViewScreen extends DownloadMapsScreen

View File

@@ -7,13 +7,11 @@ import androidx.car.app.model.Header;
import androidx.car.app.model.MessageTemplate; import androidx.car.app.model.MessageTemplate;
import androidx.car.app.model.Template; import androidx.car.app.model.Template;
import androidx.core.graphics.drawable.IconCompat; import androidx.core.graphics.drawable.IconCompat;
import app.organicmaps.R; import app.organicmaps.R;
import app.organicmaps.car.screens.base.BaseScreen; import app.organicmaps.car.screens.base.BaseScreen;
import app.organicmaps.car.util.Colors; import app.organicmaps.car.util.Colors;
import app.organicmaps.sdk.downloader.CountryItem; import app.organicmaps.sdk.downloader.CountryItem;
import app.organicmaps.sdk.util.StringUtils; import app.organicmaps.sdk.util.StringUtils;
import java.util.List; import java.util.List;
public abstract class DownloadMapsScreen extends BaseScreen public abstract class DownloadMapsScreen extends BaseScreen
@@ -100,10 +98,11 @@ public abstract class DownloadMapsScreen extends BaseScreen
private void onDownload() private void onDownload()
{ {
getScreenManager().pushForResult(new DownloaderScreen(getCarContext(), mMissingMaps, mIsCancelActionDisabled), result -> { getScreenManager().pushForResult(new DownloaderScreen(getCarContext(), mMissingMaps, mIsCancelActionDisabled),
setResult(result); result -> {
finish(); setResult(result);
}); finish();
});
} }
@NonNull @NonNull

View File

@@ -3,9 +3,7 @@ package app.organicmaps.car.screens.download;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.car.app.CarContext; import androidx.car.app.CarContext;
import app.organicmaps.routing.ResultCodesHelper; import app.organicmaps.routing.ResultCodesHelper;
import java.util.Objects; import java.util.Objects;
public class DownloadMapsScreenBuilder public class DownloadMapsScreenBuilder

View File

@@ -1,20 +1,17 @@
package app.organicmaps.car.screens.download; package app.organicmaps.car.screens.download;
import android.text.TextUtils; import android.text.TextUtils;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import app.organicmaps.BuildConfig; import app.organicmaps.BuildConfig;
import app.organicmaps.sdk.downloader.CountryItem; import app.organicmaps.sdk.downloader.CountryItem;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
public final class DownloaderHelpers public final class DownloaderHelpers
{ {
static final String[] WORLD_MAPS = new String[]{"World", "WorldCoasts"}; static final String[] WORLD_MAPS = new String[] {"World", "WorldCoasts"};
// World maps may be missing only in the F-Droid build. // World maps may be missing only in the F-Droid build.
@SuppressWarnings("ConstantConditions") @SuppressWarnings("ConstantConditions")

View File

@@ -1,7 +1,6 @@
package app.organicmaps.car.screens.download; package app.organicmaps.car.screens.download;
import android.text.TextUtils; import android.text.TextUtils;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.car.app.CarContext; import androidx.car.app.CarContext;
import androidx.car.app.constraints.ConstraintManager; import androidx.car.app.constraints.ConstraintManager;
@@ -10,7 +9,6 @@ import androidx.car.app.model.Header;
import androidx.car.app.model.MessageTemplate; import androidx.car.app.model.MessageTemplate;
import androidx.car.app.model.Template; import androidx.car.app.model.Template;
import androidx.lifecycle.LifecycleOwner; import androidx.lifecycle.LifecycleOwner;
import app.organicmaps.R; import app.organicmaps.R;
import app.organicmaps.car.screens.ErrorScreen; import app.organicmaps.car.screens.ErrorScreen;
import app.organicmaps.car.screens.base.BaseScreen; import app.organicmaps.car.screens.base.BaseScreen;
@@ -18,7 +16,6 @@ import app.organicmaps.sdk.downloader.CountryItem;
import app.organicmaps.sdk.downloader.MapManager; import app.organicmaps.sdk.downloader.MapManager;
import app.organicmaps.sdk.util.StringUtils; import app.organicmaps.sdk.util.StringUtils;
import app.organicmaps.sdk.util.concurrency.UiThread; import app.organicmaps.sdk.util.concurrency.UiThread;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@@ -36,8 +33,7 @@ class DownloaderScreen extends BaseScreen
private boolean mIsDownloadFailed = false; private boolean mIsDownloadFailed = false;
@NonNull @NonNull
private final MapManager.StorageCallback mStorageCallback = new MapManager.StorageCallback() private final MapManager.StorageCallback mStorageCallback = new MapManager.StorageCallback() {
{
@Override @Override
public void onStatusChanged(@NonNull final List<MapManager.StorageCallbackData> data) public void onStatusChanged(@NonNull final List<MapManager.StorageCallbackData> data)
{ {
@@ -85,7 +81,8 @@ class DownloaderScreen extends BaseScreen
} }
}; };
DownloaderScreen(@NonNull final CarContext carContext, @NonNull final List<CountryItem> missingMaps, final boolean isCancelActionDisabled) DownloaderScreen(@NonNull final CarContext carContext, @NonNull final List<CountryItem> missingMaps,
final boolean isCancelActionDisabled)
{ {
super(carContext); super(carContext);
setMarker(DownloadMapsScreen.MARKER); setMarker(DownloadMapsScreen.MARKER);
@@ -171,9 +168,9 @@ class DownloaderScreen extends BaseScreen
{ {
mIsDownloadFailed = true; mIsDownloadFailed = true;
final ErrorScreen.Builder builder = new ErrorScreen.Builder(getCarContext()) final ErrorScreen.Builder builder = new ErrorScreen.Builder(getCarContext())
.setTitle(R.string.country_status_download_failed) .setTitle(R.string.country_status_download_failed)
.setErrorMessage(MapManager.getErrorCodeStrRes(data.errorCode)) .setErrorMessage(MapManager.getErrorCodeStrRes(data.errorCode))
.setPositiveButton(R.string.downloader_retry, null); .setPositiveButton(R.string.downloader_retry, null);
if (!mIsCancelActionDisabled) if (!mIsCancelActionDisabled)
builder.setNegativeButton(R.string.cancel, this::finish); builder.setNegativeButton(R.string.cancel, this::finish);
getScreenManager().push(builder.build()); getScreenManager().push(builder.build());

View File

@@ -7,21 +7,18 @@ import android.content.Intent;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.provider.Settings; import android.provider.Settings;
import androidx.activity.result.ActivityResultLauncher; import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts; import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.core.app.NotificationManagerCompat; import androidx.core.app.NotificationManagerCompat;
import app.organicmaps.R; import app.organicmaps.R;
import app.organicmaps.base.BaseMwmFragmentActivity; import app.organicmaps.base.BaseMwmFragmentActivity;
import app.organicmaps.sdk.util.LocationUtils; import app.organicmaps.sdk.util.LocationUtils;
import java.util.Objects; import java.util.Objects;
public class RequestPermissionsActivity extends BaseMwmFragmentActivity public class RequestPermissionsActivity extends BaseMwmFragmentActivity
{ {
private static final String[] LOCATION_PERMISSIONS = new String[]{ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION}; private static final String[] LOCATION_PERMISSIONS = new String[] {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION};
@Nullable @Nullable
private ActivityResultLauncher<String[]> mPermissionsRequest; private ActivityResultLauncher<String[]> mPermissionsRequest;
@@ -34,7 +31,7 @@ public class RequestPermissionsActivity extends BaseMwmFragmentActivity
findViewById(R.id.btn_grant_permissions).setOnClickListener(unused -> openAppPermissionSettings()); findViewById(R.id.btn_grant_permissions).setOnClickListener(unused -> openAppPermissionSettings());
mPermissionsRequest = registerForActivityResult(new ActivityResultContracts.RequestMultiplePermissions(), mPermissionsRequest = registerForActivityResult(new ActivityResultContracts.RequestMultiplePermissions(),
(grantedPermissions) -> closeIfPermissionsGranted()); (grantedPermissions) -> closeIfPermissionsGranted());
mPermissionsRequest.launch(LOCATION_PERMISSIONS); mPermissionsRequest.launch(LOCATION_PERMISSIONS);
} }

View File

@@ -4,12 +4,10 @@ import static android.Manifest.permission.POST_NOTIFICATIONS;
import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import android.os.Build; import android.os.Build;
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.core.content.ContextCompat; import androidx.core.content.ContextCompat;
import app.organicmaps.sdk.util.log.Logger; import app.organicmaps.sdk.util.log.Logger;
public class RequestPermissionsScreenBuilder public class RequestPermissionsScreenBuilder
@@ -18,8 +16,8 @@ public class RequestPermissionsScreenBuilder
public static Screen build(@NonNull CarContext carContext, @NonNull Runnable permissionsGrantedCallback) public static Screen build(@NonNull CarContext carContext, @NonNull Runnable permissionsGrantedCallback)
{ {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU && if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU
ContextCompat.checkSelfPermission(carContext, POST_NOTIFICATIONS) != PERMISSION_GRANTED) && ContextCompat.checkSelfPermission(carContext, POST_NOTIFICATIONS) != PERMISSION_GRANTED)
{ {
Logger.w(TAG, "Permission POST_NOTIFICATIONS is not granted, using API-based permissions request"); Logger.w(TAG, "Permission POST_NOTIFICATIONS is not granted, using API-based permissions request");
return new RequestPermissionsScreenWithApi(carContext, permissionsGrantedCallback); return new RequestPermissionsScreenWithApi(carContext, permissionsGrantedCallback);

View File

@@ -13,14 +13,12 @@ import androidx.car.app.model.ParkedOnlyOnClickListener;
import androidx.car.app.model.Template; import androidx.car.app.model.Template;
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.screens.ErrorScreen; import app.organicmaps.car.screens.ErrorScreen;
import app.organicmaps.car.screens.base.BaseScreen; import app.organicmaps.car.screens.base.BaseScreen;
import app.organicmaps.car.util.Colors; import app.organicmaps.car.util.Colors;
import app.organicmaps.car.util.UserActionRequired; import app.organicmaps.car.util.UserActionRequired;
import app.organicmaps.sdk.util.LocationUtils; import app.organicmaps.sdk.util.LocationUtils;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
@@ -41,19 +39,23 @@ public class RequestPermissionsScreenWithApi extends BaseScreen implements UserA
@Override @Override
public Template onGetTemplate() public Template onGetTemplate()
{ {
final MessageTemplate.Builder builder = new MessageTemplate.Builder(getCarContext().getString(R.string.aa_request_permission_activity_text)); final MessageTemplate.Builder builder =
final Action grantPermissions = new Action.Builder() new MessageTemplate.Builder(getCarContext().getString(R.string.aa_request_permission_activity_text));
.setTitle(getCarContext().getString(R.string.aa_grant_permissions)) final Action grantPermissions =
.setBackgroundColor(Colors.BUTTON_ACCEPT) new Action.Builder()
.setOnClickListener(ParkedOnlyOnClickListener.create(() -> getCarContext().requestPermissions(LOCATION_PERMISSIONS, this::onRequestPermissionsResult))) .setTitle(getCarContext().getString(R.string.aa_grant_permissions))
.build(); .setBackgroundColor(Colors.BUTTON_ACCEPT)
.setOnClickListener(ParkedOnlyOnClickListener.create(
() -> getCarContext().requestPermissions(LOCATION_PERMISSIONS, this::onRequestPermissionsResult)))
.build();
final Header.Builder headerBuilder = new Header.Builder(); final Header.Builder headerBuilder = new Header.Builder();
headerBuilder.setStartHeaderAction(Action.APP_ICON); headerBuilder.setStartHeaderAction(Action.APP_ICON);
headerBuilder.setTitle(getCarContext().getString(R.string.app_name)); headerBuilder.setTitle(getCarContext().getString(R.string.app_name));
builder.setHeader(headerBuilder.build()); builder.setHeader(headerBuilder.build());
builder.setIcon(new CarIcon.Builder(IconCompat.createWithResource(getCarContext(), R.drawable.ic_location_off)).build()); builder.setIcon(
new CarIcon.Builder(IconCompat.createWithResource(getCarContext(), R.drawable.ic_location_off)).build());
builder.addAction(grantPermissions); builder.addAction(grantPermissions);
return builder.build(); return builder.build();
} }
@@ -70,19 +72,19 @@ public class RequestPermissionsScreenWithApi extends BaseScreen implements UserA
} }
} }
private void onRequestPermissionsResult(@NonNull List<String> grantedPermissions, @NonNull List<String> rejectedPermissions) private void onRequestPermissionsResult(@NonNull List<String> grantedPermissions,
@NonNull List<String> rejectedPermissions)
{ {
if (grantedPermissions.isEmpty()) if (grantedPermissions.isEmpty())
{ {
getScreenManager().push(new ErrorScreen.Builder(getCarContext()) getScreenManager().push(new ErrorScreen.Builder(getCarContext())
.setErrorMessage(R.string.location_is_disabled_long_text) .setErrorMessage(R.string.location_is_disabled_long_text)
.setNegativeButton(R.string.close, null) .setNegativeButton(R.string.close, null)
.build() .build());
);
return; return;
} }
mPermissionsGrantedCallback.run(); mPermissionsGrantedCallback.run();
finish(); finish();
} }
} }

View File

@@ -5,7 +5,6 @@ import android.app.NotificationManager;
import android.app.PendingIntent; import android.app.PendingIntent;
import android.content.Intent; import android.content.Intent;
import android.os.Build; import android.os.Build;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.RequiresPermission; import androidx.annotation.RequiresPermission;
import androidx.car.app.CarContext; import androidx.car.app.CarContext;
@@ -19,7 +18,6 @@ import androidx.core.app.NotificationManagerCompat;
import androidx.core.content.ContextCompat; import androidx.core.content.ContextCompat;
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.CarAppService; import app.organicmaps.car.CarAppService;
import app.organicmaps.car.screens.base.BaseScreen; import app.organicmaps.car.screens.base.BaseScreen;
@@ -27,7 +25,6 @@ import app.organicmaps.car.util.UserActionRequired;
import app.organicmaps.sdk.util.LocationUtils; import app.organicmaps.sdk.util.LocationUtils;
import app.organicmaps.sdk.util.concurrency.ThreadPool; import app.organicmaps.sdk.util.concurrency.ThreadPool;
import app.organicmaps.sdk.util.concurrency.UiThread; import app.organicmaps.sdk.util.concurrency.UiThread;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
public class RequestPermissionsScreenWithNotification extends BaseScreen implements UserActionRequired public class RequestPermissionsScreenWithNotification extends BaseScreen implements UserActionRequired
@@ -40,7 +37,8 @@ public class RequestPermissionsScreenWithNotification extends BaseScreen impleme
@NonNull @NonNull
private final Runnable mPermissionsGrantedCallback; private final Runnable mPermissionsGrantedCallback;
public RequestPermissionsScreenWithNotification(@NonNull CarContext carContext, @NonNull Runnable permissionsGrantedCallback) public RequestPermissionsScreenWithNotification(@NonNull CarContext carContext,
@NonNull Runnable permissionsGrantedCallback)
{ {
super(carContext); super(carContext);
mBackgroundExecutor = ThreadPool.getWorker(); mBackgroundExecutor = ThreadPool.getWorker();
@@ -51,14 +49,16 @@ public class RequestPermissionsScreenWithNotification extends BaseScreen impleme
@Override @Override
public Template onGetTemplate() public Template onGetTemplate()
{ {
final MessageTemplate.Builder builder = new MessageTemplate.Builder(getCarContext().getString(R.string.aa_location_permissions_request)); final MessageTemplate.Builder builder =
new MessageTemplate.Builder(getCarContext().getString(R.string.aa_location_permissions_request));
final Header.Builder headerBuilder = new Header.Builder(); final Header.Builder headerBuilder = new Header.Builder();
headerBuilder.setStartHeaderAction(Action.APP_ICON); headerBuilder.setStartHeaderAction(Action.APP_ICON);
headerBuilder.setTitle(getCarContext().getString(R.string.aa_grant_permissions)); headerBuilder.setTitle(getCarContext().getString(R.string.aa_grant_permissions));
builder.setHeader(headerBuilder.build()); builder.setHeader(headerBuilder.build());
builder.setIcon(new CarIcon.Builder(IconCompat.createWithResource(getCarContext(), R.drawable.ic_location_off)).build()); builder.setIcon(
new CarIcon.Builder(IconCompat.createWithResource(getCarContext(), R.drawable.ic_location_off)).build());
return builder.build(); return builder.build();
} }
@@ -105,9 +105,10 @@ public class RequestPermissionsScreenWithNotification extends BaseScreen impleme
final int FLAG_IMMUTABLE = Build.VERSION.SDK_INT < Build.VERSION_CODES.M ? 0 : PendingIntent.FLAG_IMMUTABLE; final int FLAG_IMMUTABLE = Build.VERSION.SDK_INT < Build.VERSION_CODES.M ? 0 : PendingIntent.FLAG_IMMUTABLE;
final Intent contentIntent = new Intent(getCarContext(), RequestPermissionsActivity.class); final Intent contentIntent = new Intent(getCarContext(), RequestPermissionsActivity.class);
final PendingIntent pendingIntent = PendingIntent.getActivity(getCarContext(), 0, contentIntent, final PendingIntent pendingIntent = PendingIntent.getActivity(getCarContext(), 0, contentIntent,
PendingIntent.FLAG_CANCEL_CURRENT | FLAG_IMMUTABLE); PendingIntent.FLAG_CANCEL_CURRENT | FLAG_IMMUTABLE);
final NotificationCompat.Builder builder = new NotificationCompat.Builder(getCarContext(), CarAppService.ANDROID_AUTO_NOTIFICATION_CHANNEL_ID); final NotificationCompat.Builder builder =
new NotificationCompat.Builder(getCarContext(), CarAppService.ANDROID_AUTO_NOTIFICATION_CHANNEL_ID);
builder.setCategory(NotificationCompat.CATEGORY_NAVIGATION) builder.setCategory(NotificationCompat.CATEGORY_NAVIGATION)
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC) .setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
.setOngoing(true) .setOngoing(true)

View File

@@ -1,7 +1,6 @@
package app.organicmaps.car.screens.search; package app.organicmaps.car.screens.search;
import android.text.TextUtils; import android.text.TextUtils;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.car.app.CarContext; import androidx.car.app.CarContext;
@@ -16,15 +15,14 @@ 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 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.sdk.bookmarks.data.MapObject;
import app.organicmaps.car.SurfaceRenderer; import app.organicmaps.car.SurfaceRenderer;
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.search.SearchListener; import app.organicmaps.sdk.bookmarks.data.MapObject;
import app.organicmaps.sdk.search.SearchEngine; import app.organicmaps.sdk.search.SearchEngine;
import app.organicmaps.sdk.search.SearchListener;
import app.organicmaps.sdk.search.SearchRecents; import app.organicmaps.sdk.search.SearchRecents;
import app.organicmaps.sdk.search.SearchResult; import app.organicmaps.sdk.search.SearchResult;
import app.organicmaps.sdk.util.Config; import app.organicmaps.sdk.util.Config;
@@ -125,8 +123,12 @@ public class SearchOnMapScreen extends BaseMapScreen implements SearchListener
{ {
builder.setBrowsable(true); builder.setBrowsable(true);
builder.setTitle(result.suggestion); builder.setTitle(result.suggestion);
builder.setImage(new CarIcon.Builder(IconCompat.createWithResource(getCarContext(), R.drawable.ic_search)).build()); builder.setImage(
builder.setOnClickListener(() -> getScreenManager().push(new Builder(getCarContext(), getSurfaceRenderer()).setQuery(result.suggestion).build())); new CarIcon.Builder(IconCompat.createWithResource(getCarContext(), R.drawable.ic_search)).build());
builder.setOnClickListener(
()
-> getScreenManager().push(
new Builder(getCarContext(), getSurfaceRenderer()).setQuery(result.suggestion).build()));
} }
return builder.build(); return builder.build();
} }
@@ -147,7 +149,8 @@ public class SearchOnMapScreen extends BaseMapScreen implements SearchListener
final double lat = hasLocation ? location.getLat() : 0; final double lat = hasLocation ? location.getLat() : 0;
final double lon = hasLocation ? location.getLon() : 0; final double lon = hasLocation ? location.getLon() : 0;
SearchEngine.INSTANCE.searchInteractive(mQuery, mIsCategory, mLocale, System.nanoTime(), true /* isMapAndTable */, hasLocation, lat, lon); SearchEngine.INSTANCE.searchInteractive(mQuery, mIsCategory, mLocale, System.nanoTime(), true /* isMapAndTable */,
hasLocation, lat, lon);
} }
@Override @Override

View File

@@ -1,7 +1,6 @@
package app.organicmaps.car.screens.search; package app.organicmaps.car.screens.search;
import android.text.TextUtils; import android.text.TextUtils;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.car.app.CarContext; import androidx.car.app.CarContext;
@@ -15,14 +14,13 @@ import androidx.car.app.model.SearchTemplate;
import androidx.car.app.model.Template; import androidx.car.app.model.Template;
import androidx.core.graphics.drawable.IconCompat; 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.sdk.bookmarks.data.MapObject;
import app.organicmaps.car.SurfaceRenderer; import app.organicmaps.car.SurfaceRenderer;
import app.organicmaps.car.screens.base.BaseMapScreen; import app.organicmaps.car.screens.base.BaseMapScreen;
import app.organicmaps.sdk.search.SearchListener; import app.organicmaps.sdk.bookmarks.data.MapObject;
import app.organicmaps.sdk.search.SearchEngine; import app.organicmaps.sdk.search.SearchEngine;
import app.organicmaps.sdk.search.SearchListener;
import app.organicmaps.sdk.search.SearchRecents; import app.organicmaps.sdk.search.SearchRecents;
import app.organicmaps.sdk.search.SearchResult; import app.organicmaps.sdk.search.SearchResult;
import app.organicmaps.sdk.util.Config; import app.organicmaps.sdk.util.Config;
@@ -137,10 +135,9 @@ public class SearchScreen extends BaseMapScreen implements SearchTemplate.Search
if (result.type == SearchResult.TYPE_RESULT) if (result.type == SearchResult.TYPE_RESULT)
{ {
final String title = result.getTitle(getCarContext()); final String title = result.getTitle(getCarContext());
final CharSequence description = SearchUiHelpers.concatenateStrings( final CharSequence description =
SearchUiHelpers.getDistanceText(result), SearchUiHelpers.concatenateStrings(SearchUiHelpers.getDistanceText(result), result.description.description,
result.description.description, SearchUiHelpers.getOpeningHoursText(getCarContext(), result));
SearchUiHelpers.getOpeningHoursText(getCarContext(), result));
final String region = result.description.region; final String region = result.description.region;
builder.setTitle(title); builder.setTitle(title);
if (!TextUtils.isEmpty(description)) if (!TextUtils.isEmpty(description))
@@ -158,7 +155,8 @@ public class SearchScreen extends BaseMapScreen implements SearchTemplate.Search
{ {
builder.setBrowsable(true); builder.setBrowsable(true);
builder.setTitle(result.suggestion); builder.setTitle(result.suggestion);
builder.setImage(new CarIcon.Builder(IconCompat.createWithResource(getCarContext(), R.drawable.ic_search)).build()); builder.setImage(
new CarIcon.Builder(IconCompat.createWithResource(getCarContext(), R.drawable.ic_search)).build());
builder.setOnClickListener(() -> onSearchSubmitted(result.suggestion)); builder.setOnClickListener(() -> onSearchSubmitted(result.suggestion));
} }
return builder.build(); return builder.build();
@@ -166,7 +164,8 @@ public class SearchScreen extends BaseMapScreen implements SearchTemplate.Search
private boolean loadRecents() private boolean loadRecents()
{ {
final CarIcon iconRecent = new CarIcon.Builder(IconCompat.createWithResource(getCarContext(), R.drawable.ic_search_recent)).build(); final CarIcon iconRecent =
new CarIcon.Builder(IconCompat.createWithResource(getCarContext(), R.drawable.ic_search_recent)).build();
final ItemList.Builder builder = new ItemList.Builder(); final ItemList.Builder builder = new ItemList.Builder();
builder.setNoItemsMessage(getCarContext().getString(R.string.search_history_text)); builder.setNoItemsMessage(getCarContext().getString(R.string.search_history_text));
@@ -190,9 +189,14 @@ public class SearchScreen extends BaseMapScreen implements SearchTemplate.Search
private ActionStrip createActionStrip() private ActionStrip createActionStrip()
{ {
final Action.Builder builder = new Action.Builder(); final Action.Builder builder = new Action.Builder();
builder.setIcon(new CarIcon.Builder(IconCompat.createWithResource(getCarContext(), R.drawable.ic_show_on_map)).build()); builder.setIcon(
builder.setOnClickListener(() -> new CarIcon.Builder(IconCompat.createWithResource(getCarContext(), R.drawable.ic_show_on_map)).build());
getScreenManager().push(new SearchOnMapScreen.Builder(getCarContext(), getSurfaceRenderer()).setQuery(mQuery).setLocale(mLocale).build())); builder.setOnClickListener(
()
-> getScreenManager().push(new SearchOnMapScreen.Builder(getCarContext(), getSurfaceRenderer())
.setQuery(mQuery)
.setLocale(mLocale)
.build()));
return new ActionStrip.Builder().addAction(builder.build()).build(); return new ActionStrip.Builder().addAction(builder.build()).build();
} }

View File

@@ -3,18 +3,15 @@ package app.organicmaps.car.screens.search;
import android.text.SpannableStringBuilder; import android.text.SpannableStringBuilder;
import android.text.Spanned; import android.text.Spanned;
import android.text.TextUtils; import android.text.TextUtils;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.car.app.CarContext; import androidx.car.app.CarContext;
import androidx.car.app.model.CarColor; import androidx.car.app.model.CarColor;
import androidx.car.app.model.DistanceSpan; import androidx.car.app.model.DistanceSpan;
import androidx.car.app.model.ForegroundCarColorSpan; import androidx.car.app.model.ForegroundCarColorSpan;
import app.organicmaps.R; import app.organicmaps.R;
import app.organicmaps.car.util.Colors; import app.organicmaps.car.util.Colors;
import app.organicmaps.car.util.RoutingHelpers; import app.organicmaps.car.util.RoutingHelpers;
import app.organicmaps.sdk.search.SearchResult; import app.organicmaps.sdk.search.SearchResult;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@@ -50,7 +47,8 @@ public final class SearchUiHelpers
return ""; return "";
final SpannableStringBuilder distance = new SpannableStringBuilder(" "); final SpannableStringBuilder distance = new SpannableStringBuilder(" ");
distance.setSpan(DistanceSpan.create(RoutingHelpers.createDistance(searchResult.description.distance)), 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); distance.setSpan(DistanceSpan.create(RoutingHelpers.createDistance(searchResult.description.distance)), 0, 1,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
distance.setSpan(ForegroundCarColorSpan.create(Colors.DISTANCE), 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); distance.setSpan(ForegroundCarColorSpan.create(Colors.DISTANCE), 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
return distance; return distance;
} }
@@ -64,31 +62,29 @@ public final class SearchUiHelpers
CarColor color = Colors.DEFAULT; CarColor color = Colors.DEFAULT;
switch (searchResult.description.openNow) switch (searchResult.description.openNow)
{ {
case SearchResult.OPEN_NOW_YES: case SearchResult.OPEN_NOW_YES:
if (searchResult.description.minutesUntilClosed < 60) // less than 1 hour if (searchResult.description.minutesUntilClosed < 60) // less than 1 hour
{ {
final String time = searchResult.description.minutesUntilClosed + " " + final String time = searchResult.description.minutesUntilClosed + " " + carContext.getString(R.string.minute);
carContext.getString(R.string.minute); text = carContext.getString(R.string.closes_in, time);
text = carContext.getString(R.string.closes_in, time); color = Colors.OPENING_HOURS_CLOSES_SOON;
color = Colors.OPENING_HOURS_CLOSES_SOON; }
} else
else {
{ text = carContext.getString(R.string.editor_time_open);
text = carContext.getString(R.string.editor_time_open); color = Colors.OPENING_HOURS_OPEN;
color = Colors.OPENING_HOURS_OPEN; }
} break;
break; case SearchResult.OPEN_NOW_NO:
case SearchResult.OPEN_NOW_NO: if (searchResult.description.minutesUntilOpen < 60) // less than 1 hour
if (searchResult.description.minutesUntilOpen < 60) // less than 1 hour {
{ final String time = searchResult.description.minutesUntilOpen + " " + carContext.getString(R.string.minute);
final String time = searchResult.description.minutesUntilOpen + " " + text = carContext.getString(R.string.opens_in, time);
carContext.getString(R.string.minute); }
text = carContext.getString(R.string.opens_in, time); else
} text = carContext.getString(R.string.closed);
else color = Colors.OPENING_HOURS_CLOSED;
text = carContext.getString(R.string.closed); break;
color = Colors.OPENING_HOURS_CLOSED;
break;
} }
result.append(text); result.append(text);

View File

@@ -12,7 +12,6 @@ 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 androidx.lifecycle.LifecycleOwner; import androidx.lifecycle.LifecycleOwner;
import app.organicmaps.R; import app.organicmaps.R;
import app.organicmaps.car.SurfaceRenderer; import app.organicmaps.car.SurfaceRenderer;
import app.organicmaps.car.screens.base.BaseMapScreen; import app.organicmaps.car.screens.base.BaseMapScreen;
@@ -20,7 +19,6 @@ import app.organicmaps.car.util.Toggle;
import app.organicmaps.car.util.UiHelpers; import app.organicmaps.car.util.UiHelpers;
import app.organicmaps.sdk.routing.RoutingOptions; import app.organicmaps.sdk.routing.RoutingOptions;
import app.organicmaps.sdk.settings.RoadType; import app.organicmaps.sdk.settings.RoadType;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@@ -28,16 +26,12 @@ public class DrivingOptionsScreen extends BaseMapScreen
{ {
public static final Object DRIVING_OPTIONS_RESULT_CHANGED = 0x1; public static final Object DRIVING_OPTIONS_RESULT_CHANGED = 0x1;
private record DrivingOption(RoadType roadType, @StringRes int text) private record DrivingOption(RoadType roadType, @StringRes int text) {}
{
}
private final DrivingOption[] mDrivingOptions = { private final DrivingOption[] mDrivingOptions = {new DrivingOption(RoadType.Toll, R.string.avoid_tolls),
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)
};
@NonNull @NonNull
private final Map<RoadType, Boolean> mInitialDrivingOptionsState = new HashMap<>(); private final Map<RoadType, Boolean> mInitialDrivingOptionsState = new HashMap<>();
@@ -64,7 +58,8 @@ public class DrivingOptionsScreen extends BaseMapScreen
{ {
for (final DrivingOption drivingOption : mDrivingOptions) for (final DrivingOption drivingOption : mDrivingOptions)
{ {
if (Boolean.TRUE.equals(mInitialDrivingOptionsState.get(drivingOption.roadType)) != RoutingOptions.hasOption(drivingOption.roadType)) if (Boolean.TRUE.equals(mInitialDrivingOptionsState.get(drivingOption.roadType))
!= RoutingOptions.hasOption(drivingOption.roadType))
{ {
setResult(DRIVING_OPTIONS_RESULT_CHANGED); setResult(DRIVING_OPTIONS_RESULT_CHANGED);
return; return;
@@ -93,7 +88,8 @@ public class DrivingOptionsScreen extends BaseMapScreen
@NonNull @NonNull
private Row createDrivingOptionsToggle(RoadType roadType, @StringRes int title) private Row createDrivingOptionsToggle(RoadType roadType, @StringRes int title)
{ {
final OnClickListener listener = () -> { final OnClickListener listener = () ->
{
if (RoutingOptions.hasOption(roadType)) if (RoutingOptions.hasOption(roadType))
RoutingOptions.removeOption(roadType); RoutingOptions.removeOption(roadType);
else else

View File

@@ -10,13 +10,12 @@ import androidx.car.app.model.ListTemplate;
import androidx.car.app.model.Row; 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.BuildConfig; import app.organicmaps.BuildConfig;
import app.organicmaps.sdk.Framework;
import app.organicmaps.R; import app.organicmaps.R;
import app.organicmaps.car.SurfaceRenderer; import app.organicmaps.car.SurfaceRenderer;
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.util.DateUtils; import app.organicmaps.sdk.util.DateUtils;
public class HelpScreen extends BaseMapScreen public class HelpScreen extends BaseMapScreen

View File

@@ -12,14 +12,13 @@ import androidx.car.app.model.OnClickListener;
import androidx.car.app.model.Row; 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.sdk.Framework;
import app.organicmaps.R; import app.organicmaps.R;
import app.organicmaps.car.SurfaceRenderer; import app.organicmaps.car.SurfaceRenderer;
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;
import app.organicmaps.car.util.UiHelpers; import app.organicmaps.car.util.UiHelpers;
import app.organicmaps.sdk.Framework;
import app.organicmaps.sdk.util.Config; import app.organicmaps.sdk.util.Config;
public class SettingsScreen extends BaseMapScreen public class SettingsScreen extends BaseMapScreen
@@ -66,7 +65,8 @@ public class SettingsScreen extends BaseMapScreen
builder.addItem(createRoutingOptionsItem()); builder.addItem(createRoutingOptionsItem());
builder.addItem(create3dBuildingsItem()); builder.addItem(create3dBuildingsItem());
builder.addItem(createSharedPrefsToggle(R.string.big_font, Config::isLargeFontsSize, Config::setLargeFontsSize)); builder.addItem(createSharedPrefsToggle(R.string.big_font, Config::isLargeFontsSize, Config::setLargeFontsSize));
builder.addItem(createSharedPrefsToggle(R.string.transliteration_title, Config::isTransliteration, Config::setTransliteration)); builder.addItem(
createSharedPrefsToggle(R.string.transliteration_title, Config::isTransliteration, Config::setTransliteration));
builder.addItem(createHelpItem()); builder.addItem(createHelpItem());
return new ListTemplate.Builder().setHeader(createHeader()).setSingleList(builder.build()).build(); return new ListTemplate.Builder().setHeader(createHeader()).setSingleList(builder.build()).build();
} }
@@ -87,7 +87,10 @@ public class SettingsScreen extends BaseMapScreen
{ {
final Row.Builder builder = new Row.Builder(); final Row.Builder builder = new Row.Builder();
builder.setTitle(getCarContext().getString(R.string.driving_options_title)); builder.setTitle(getCarContext().getString(R.string.driving_options_title));
builder.setOnClickListener(() -> getScreenManager().pushForResult(new DrivingOptionsScreen(getCarContext(), getSurfaceRenderer()), this::setResult)); builder.setOnClickListener(
()
-> getScreenManager().pushForResult(new DrivingOptionsScreen(getCarContext(), getSurfaceRenderer()),
this::setResult));
builder.setBrowsable(true); builder.setBrowsable(true);
return builder.build(); return builder.build();
} }
@@ -98,7 +101,8 @@ public class SettingsScreen extends BaseMapScreen
final Framework.Params3dMode _3d = new Framework.Params3dMode(); final Framework.Params3dMode _3d = new Framework.Params3dMode();
Framework.nativeGet3dMode(_3d); Framework.nativeGet3dMode(_3d);
final OnClickListener listener = () -> { final OnClickListener listener = () ->
{
Framework.nativeSet3dMode(_3d.enabled, !_3d.buildings); Framework.nativeSet3dMode(_3d.enabled, !_3d.buildings);
invalidate(); invalidate();
}; };
@@ -119,7 +123,8 @@ public class SettingsScreen extends BaseMapScreen
private Row createSharedPrefsToggle(@StringRes int titleRes, @NonNull PrefsGetter getter, @NonNull PrefsSetter setter) private Row createSharedPrefsToggle(@StringRes int titleRes, @NonNull PrefsGetter getter, @NonNull PrefsSetter setter)
{ {
final boolean enabled = getter.get(); final boolean enabled = getter.get();
final OnClickListener listener = () -> { final OnClickListener listener = () ->
{
setter.set(!enabled); setter.set(!enabled);
invalidate(); invalidate();
}; };

View File

@@ -11,7 +11,6 @@ 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 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.SurfaceRenderer;
import app.organicmaps.car.screens.base.BaseMapScreen; import app.organicmaps.car.screens.base.BaseMapScreen;
@@ -28,8 +27,10 @@ public class ThemeScreen extends BaseMapScreen
public ThemeScreen(@NonNull CarContext carContext, @NonNull SurfaceRenderer surfaceRenderer) public ThemeScreen(@NonNull CarContext carContext, @NonNull SurfaceRenderer surfaceRenderer)
{ {
super(carContext, surfaceRenderer); super(carContext, surfaceRenderer);
mRadioButtonIcon = new CarIcon.Builder(IconCompat.createWithResource(carContext, R.drawable.ic_radio_button_unchecked)).build(); mRadioButtonIcon =
mRadioButtonSelectedIcon = new CarIcon.Builder(IconCompat.createWithResource(carContext, R.drawable.ic_radio_button_checked)).build(); new CarIcon.Builder(IconCompat.createWithResource(carContext, R.drawable.ic_radio_button_unchecked)).build();
mRadioButtonSelectedIcon =
new CarIcon.Builder(IconCompat.createWithResource(carContext, R.drawable.ic_radio_button_checked)).build();
} }
@NonNull @NonNull

View File

@@ -3,7 +3,6 @@ package app.organicmaps.car.util;
import static android.Manifest.permission.ACCESS_FINE_LOCATION; import static android.Manifest.permission.ACCESS_FINE_LOCATION;
import android.location.Location; import android.location.Location;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.RequiresPermission; import androidx.annotation.RequiresPermission;
import androidx.car.app.CarContext; import androidx.car.app.CarContext;
@@ -13,11 +12,9 @@ import androidx.car.app.hardware.info.CarHardwareLocation;
import androidx.car.app.hardware.info.CarSensors; import androidx.car.app.hardware.info.CarSensors;
import androidx.car.app.hardware.info.Compass; import androidx.car.app.hardware.info.Compass;
import androidx.core.content.ContextCompat; import androidx.core.content.ContextCompat;
import app.organicmaps.sdk.Map;
import app.organicmaps.MwmApplication; import app.organicmaps.MwmApplication;
import app.organicmaps.sdk.Map;
import app.organicmaps.sdk.util.log.Logger; import app.organicmaps.sdk.util.log.Logger;
import java.util.List; import java.util.List;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
@@ -53,7 +50,8 @@ public class CarSensorsManager
MwmApplication.from(mCarContext).getLocationHelper().start(); MwmApplication.from(mCarContext).getLocationHelper().start();
if (mIsCarLocationUsed) if (mIsCarLocationUsed)
mCarSensors.addCarHardwareLocationListener(CarSensors.UPDATE_RATE_FASTEST, executor, this::onCarLocationDataAvailable); mCarSensors.addCarHardwareLocationListener(CarSensors.UPDATE_RATE_FASTEST, executor,
this::onCarLocationDataAvailable);
} }
public void onStop() public void onStop()

View File

@@ -1,17 +1,15 @@
package app.organicmaps.car.util; package app.organicmaps.car.util;
import android.text.TextUtils; import android.text.TextUtils;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.car.app.CarContext; import androidx.car.app.CarContext;
import androidx.car.app.ScreenManager; import androidx.car.app.ScreenManager;
import app.organicmaps.car.screens.download.DownloadMapsScreen; import app.organicmaps.car.screens.download.DownloadMapsScreen;
import app.organicmaps.car.screens.download.DownloadMapsScreenBuilder; import app.organicmaps.car.screens.download.DownloadMapsScreenBuilder;
import app.organicmaps.routing.RoutingController;
import app.organicmaps.sdk.downloader.CountryItem; import app.organicmaps.sdk.downloader.CountryItem;
import app.organicmaps.sdk.downloader.MapManager; import app.organicmaps.sdk.downloader.MapManager;
import app.organicmaps.routing.RoutingController;
public class CurrentCountryChangedListener implements MapManager.CurrentCountryChangedListener public class CurrentCountryChangedListener implements MapManager.CurrentCountryChangedListener
{ {
@@ -45,12 +43,10 @@ public class CurrentCountryChangedListener implements MapManager.CurrentCountryC
return; return;
mPreviousCountryId = countryId; mPreviousCountryId = countryId;
screenManager.push( screenManager.push(new DownloadMapsScreenBuilder(mCarContext)
new DownloadMapsScreenBuilder(mCarContext) .setDownloaderType(DownloadMapsScreenBuilder.DownloaderType.View)
.setDownloaderType(DownloadMapsScreenBuilder.DownloaderType.View) .setMissingMaps(new String[] {countryId})
.setMissingMaps(new String[]{countryId}) .build());
.build()
);
} }
public void onStart(@NonNull final CarContext carContext) public void onStart(@NonNull final CarContext carContext)

View File

@@ -4,25 +4,23 @@ import android.app.PendingIntent;
import android.content.ComponentName; import android.content.ComponentName;
import android.content.Intent; import android.content.Intent;
import android.net.Uri; import android.net.Uri;
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.ScreenManager; import androidx.car.app.ScreenManager;
import androidx.car.app.notification.CarPendingIntent; import androidx.car.app.notification.CarPendingIntent;
import app.organicmaps.sdk.Framework;
import app.organicmaps.sdk.Map;
import app.organicmaps.api.Const; import app.organicmaps.api.Const;
import app.organicmaps.sdk.api.ParsedSearchRequest;
import app.organicmaps.sdk.api.RequestType;
import app.organicmaps.car.CarAppService; import app.organicmaps.car.CarAppService;
import app.organicmaps.car.SurfaceRenderer; import app.organicmaps.car.SurfaceRenderer;
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.routing.RoutingController;
import app.organicmaps.sdk.Framework;
import app.organicmaps.sdk.Map;
import app.organicmaps.sdk.api.ParsedSearchRequest;
import app.organicmaps.sdk.api.RequestType;
import app.organicmaps.sdk.display.DisplayManager; import app.organicmaps.sdk.display.DisplayManager;
import app.organicmaps.sdk.display.DisplayType; import app.organicmaps.sdk.display.DisplayType;
import app.organicmaps.routing.RoutingController;
import app.organicmaps.sdk.util.log.Logger; import app.organicmaps.sdk.util.log.Logger;
public final class IntentUtils public final class IntentUtils
@@ -31,7 +29,8 @@ 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, @NonNull Intent intent) public static void processIntent(@NonNull CarContext carContext, @NonNull SurfaceRenderer surfaceRenderer,
@NonNull Intent intent)
{ {
final String action = intent.getAction(); final String action = intent.getAction();
if (CarContext.ACTION_NAVIGATE.equals(action)) if (CarContext.ACTION_NAVIGATE.equals(action))
@@ -50,10 +49,11 @@ 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, @NonNull Intent intent) private static void processNavigationIntent(@NonNull CarContext carContext, @NonNull SurfaceRenderer surfaceRenderer,
@NonNull Intent intent)
{ {
// TODO (AndrewShkrob): This logic will need to be revised when we introduce support for adding stops during navigation or route planning. // TODO (AndrewShkrob): This logic will need to be revised when we introduce support for adding stops during
// Skip navigation intents during navigation // navigation or route planning. Skip navigation intents during navigation
if (RoutingController.get().isNavigating()) if (RoutingController.get().isNavigating())
return; return;
@@ -64,52 +64,43 @@ public final class IntentUtils
final ScreenManager screenManager = carContext.getCarService(ScreenManager.class); final ScreenManager screenManager = carContext.getCarService(ScreenManager.class);
switch (Framework.nativeParseAndSetApiUrl(uri.toString())) switch (Framework.nativeParseAndSetApiUrl(uri.toString()))
{ {
case RequestType.INCORRECT: case RequestType.INCORRECT: return;
return; case RequestType.MAP:
case RequestType.MAP: screenManager.popToRoot();
screenManager.popToRoot(); Map.executeMapApiRequest();
Map.executeMapApiRequest(); return;
return; case RequestType.SEARCH:
case RequestType.SEARCH: screenManager.popToRoot();
screenManager.popToRoot(); final ParsedSearchRequest request = Framework.nativeGetParsedSearchRequest();
final ParsedSearchRequest request = Framework.nativeGetParsedSearchRequest(); final double[] latlon = Framework.nativeGetParsedCenterLatLon();
final double[] latlon = Framework.nativeGetParsedCenterLatLon(); if (latlon != null)
if (latlon != null) {
{ Framework.nativeStopLocationFollow();
Framework.nativeStopLocationFollow(); Framework.nativeSetViewportCenter(latlon[0], latlon[1], SEARCH_IN_VIEWPORT_ZOOM);
Framework.nativeSetViewportCenter(latlon[0], latlon[1], SEARCH_IN_VIEWPORT_ZOOM); // We need to update viewport for search api manually because of drape engine
// We need to update viewport for search api manually because of drape engine // will not notify subscribers when search activity is shown.
// will not notify subscribers when search activity is shown. if (!request.mIsSearchOnMap)
if (!request.mIsSearchOnMap) Framework.nativeSetSearchViewport(latlon[0], latlon[1], SEARCH_IN_VIEWPORT_ZOOM);
Framework.nativeSetSearchViewport(latlon[0], latlon[1], SEARCH_IN_VIEWPORT_ZOOM); }
} final SearchScreen.Builder builder = new SearchScreen.Builder(carContext, surfaceRenderer);
final SearchScreen.Builder builder = new SearchScreen.Builder(carContext, surfaceRenderer); builder.setQuery(request.mQuery);
builder.setQuery(request.mQuery); if (request.mLocale != null)
if (request.mLocale != null) builder.setLocale(request.mLocale);
builder.setLocale(request.mLocale);
screenManager.popToRoot(); screenManager.popToRoot();
screenManager.push(builder.build()); screenManager.push(builder.build());
return; return;
case RequestType.ROUTE: case RequestType.ROUTE: Logger.e(TAG, "Route API is not supported by Android Auto: " + uri); return;
Logger.e(TAG, "Route API is not supported by Android Auto: " + uri); case RequestType.CROSSHAIR: Logger.e(TAG, "Crosshair API is not supported by Android Auto: " + uri); return;
return; case RequestType.MENU: Logger.e(TAG, "Menu API is not supported by Android Auto: " + uri); return;
case RequestType.CROSSHAIR: case RequestType.SETTINGS: Logger.e(TAG, "Settings API is not supported by Android Auto: " + uri);
Logger.e(TAG, "Crosshair API is not supported by Android Auto: " + uri);
return;
case RequestType.MENU:
Logger.e(TAG, "Menu API is not supported by Android Auto: " + uri);
return;
case RequestType.SETTINGS:
Logger.e(TAG, "Settings API is not supported by Android Auto: " + uri);
} }
} }
private static void processViewIntent(@NonNull CarContext carContext, @NonNull Intent intent) private static void processViewIntent(@NonNull CarContext carContext, @NonNull Intent intent)
{ {
final Uri uri = intent.getData(); final Uri uri = intent.getData();
if (uri != null if (uri != null && Const.API_SCHEME.equals(uri.getScheme())
&& Const.API_SCHEME.equals(uri.getScheme())
&& CarAppService.API_CAR_HOST.equals(uri.getSchemeSpecificPart()) && CarAppService.API_CAR_HOST.equals(uri.getSchemeSpecificPart())
&& CarAppService.ACTION_SHOW_NAVIGATION_SCREEN.equals(uri.getFragment())) && CarAppService.ACTION_SHOW_NAVIGATION_SCREEN.equals(uri.getFragment()))
{ {

View File

@@ -7,7 +7,6 @@ import androidx.car.app.model.Distance;
import androidx.car.app.navigation.model.LaneDirection; import androidx.car.app.navigation.model.LaneDirection;
import androidx.car.app.navigation.model.Maneuver; import androidx.car.app.navigation.model.Maneuver;
import androidx.core.graphics.drawable.IconCompat; import androidx.core.graphics.drawable.IconCompat;
import app.organicmaps.sdk.routing.CarDirection; import app.organicmaps.sdk.routing.CarDirection;
import app.organicmaps.sdk.routing.LaneWay; import app.organicmaps.sdk.routing.LaneWay;
@@ -26,30 +25,32 @@ public final class RoutingHelpers
default -> Distance.UNIT_METERS; default -> Distance.UNIT_METERS;
}; };
return Distance.create(distance.mDistance, displayUnit); return Distance.create(distance.mDistance, displayUnit);
} }
@NonNull @NonNull
public static LaneDirection createLaneDirection(@NonNull LaneWay laneWay, boolean isRecommended) public static LaneDirection createLaneDirection(@NonNull LaneWay laneWay, boolean isRecommended)
{ {
int shape = LaneDirection.SHAPE_UNKNOWN; int shape = LaneDirection.SHAPE_UNKNOWN;
shape = switch (laneWay) { shape = switch (laneWay)
case REVERSE -> LaneDirection.SHAPE_U_TURN_LEFT; {
case SHARP_LEFT -> LaneDirection.SHAPE_SHARP_LEFT; case REVERSE -> LaneDirection.SHAPE_U_TURN_LEFT;
case LEFT -> LaneDirection.SHAPE_NORMAL_LEFT; case SHARP_LEFT -> LaneDirection.SHAPE_SHARP_LEFT;
case SLIGHT_LEFT, MERGE_TO_LEFT -> LaneDirection.SHAPE_SLIGHT_LEFT; case LEFT -> LaneDirection.SHAPE_NORMAL_LEFT;
case SLIGHT_RIGHT, MERGE_TO_RIGHT -> LaneDirection.SHAPE_SLIGHT_RIGHT; case SLIGHT_LEFT, MERGE_TO_LEFT -> LaneDirection.SHAPE_SLIGHT_LEFT;
case THROUGH -> LaneDirection.SHAPE_STRAIGHT; case SLIGHT_RIGHT, MERGE_TO_RIGHT -> LaneDirection.SHAPE_SLIGHT_RIGHT;
case RIGHT -> LaneDirection.SHAPE_NORMAL_RIGHT; case THROUGH -> LaneDirection.SHAPE_STRAIGHT;
case SHARP_RIGHT -> LaneDirection.SHAPE_SHARP_RIGHT; case RIGHT -> LaneDirection.SHAPE_NORMAL_RIGHT;
default -> shape; case SHARP_RIGHT -> LaneDirection.SHAPE_SHARP_RIGHT;
}; default -> shape;
};
return LaneDirection.create(shape, isRecommended); return LaneDirection.create(shape, isRecommended);
} }
@NonNull @NonNull
public static Maneuver createManeuver(@NonNull final CarContext context, @NonNull CarDirection carDirection, int roundaboutExitNum) public static Maneuver createManeuver(@NonNull final CarContext context, @NonNull CarDirection carDirection,
int roundaboutExitNum)
{ {
int maneuverType = switch (carDirection) int maneuverType = switch (carDirection)
{ {
@@ -63,14 +64,13 @@ public final class RoutingHelpers
case U_TURN_LEFT -> Maneuver.TYPE_U_TURN_LEFT; case U_TURN_LEFT -> Maneuver.TYPE_U_TURN_LEFT;
case U_TURN_RIGHT -> Maneuver.TYPE_U_TURN_RIGHT; case U_TURN_RIGHT -> Maneuver.TYPE_U_TURN_RIGHT;
// TODO (AndrewShkrob): add support for CW (clockwise) directions // TODO (AndrewShkrob): add support for CW (clockwise) directions
case ENTER_ROUND_ABOUT, STAY_ON_ROUND_ABOUT, LEAVE_ROUND_ABOUT -> case ENTER_ROUND_ABOUT, STAY_ON_ROUND_ABOUT, LEAVE_ROUND_ABOUT -> Maneuver.TYPE_ROUNDABOUT_ENTER_AND_EXIT_CCW;
Maneuver.TYPE_ROUNDABOUT_ENTER_AND_EXIT_CCW;
case START_AT_THE_END_OF_STREET -> Maneuver.TYPE_DEPART; case START_AT_THE_END_OF_STREET -> Maneuver.TYPE_DEPART;
case REACHED_YOUR_DESTINATION -> Maneuver.TYPE_DESTINATION; case REACHED_YOUR_DESTINATION -> Maneuver.TYPE_DESTINATION;
case EXIT_HIGHWAY_TO_LEFT -> Maneuver.TYPE_OFF_RAMP_SLIGHT_LEFT; case EXIT_HIGHWAY_TO_LEFT -> Maneuver.TYPE_OFF_RAMP_SLIGHT_LEFT;
case EXIT_HIGHWAY_TO_RIGHT -> Maneuver.TYPE_OFF_RAMP_SLIGHT_RIGHT; case EXIT_HIGHWAY_TO_RIGHT -> Maneuver.TYPE_OFF_RAMP_SLIGHT_RIGHT;
}; };
final Maneuver.Builder builder = new Maneuver.Builder(maneuverType); final Maneuver.Builder builder = new Maneuver.Builder(maneuverType);
if (maneuverType == Maneuver.TYPE_ROUNDABOUT_ENTER_AND_EXIT_CCW) if (maneuverType == Maneuver.TYPE_ROUNDABOUT_ENTER_AND_EXIT_CCW)
builder.setRoundaboutExitNumber(roundaboutExitNum > 0 ? roundaboutExitNum : 1); builder.setRoundaboutExitNumber(roundaboutExitNum > 0 ? roundaboutExitNum : 1);
builder.setIcon(new CarIcon.Builder(IconCompat.createWithResource(context, carDirection.getTurnRes())).build()); builder.setIcon(new CarIcon.Builder(IconCompat.createWithResource(context, carDirection.getTurnRes())).build());

View File

@@ -2,7 +2,6 @@ package app.organicmaps.car.util;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.text.TextUtils; import android.text.TextUtils;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.car.app.CarContext; import androidx.car.app.CarContext;
@@ -13,7 +12,6 @@ import androidx.car.app.navigation.model.Step;
import androidx.car.app.navigation.model.TravelEstimate; import androidx.car.app.navigation.model.TravelEstimate;
import androidx.car.app.navigation.model.Trip; import androidx.car.app.navigation.model.Trip;
import androidx.core.graphics.drawable.IconCompat; import androidx.core.graphics.drawable.IconCompat;
import app.organicmaps.sdk.bookmarks.data.MapObject; import app.organicmaps.sdk.bookmarks.data.MapObject;
import app.organicmaps.sdk.routing.LaneWay; import app.organicmaps.sdk.routing.LaneWay;
import app.organicmaps.sdk.routing.RoutingInfo; import app.organicmaps.sdk.routing.RoutingInfo;
@@ -21,7 +19,6 @@ import app.organicmaps.sdk.routing.SingleLaneInfo;
import app.organicmaps.sdk.util.Distance; import app.organicmaps.sdk.util.Distance;
import app.organicmaps.util.Graphics; import app.organicmaps.util.Graphics;
import app.organicmaps.widget.LanesDrawable; import app.organicmaps.widget.LanesDrawable;
import java.time.ZonedDateTime; import java.time.ZonedDateTime;
import java.util.Objects; import java.util.Objects;
@@ -30,7 +27,8 @@ public final class RoutingUtils
private RoutingUtils() {} private RoutingUtils() {}
@NonNull @NonNull
public static Trip createTrip(@NonNull final CarContext context, @Nullable final RoutingInfo info, @Nullable MapObject endPoint) public static Trip createTrip(@NonNull final CarContext context, @Nullable final RoutingInfo info,
@Nullable MapObject endPoint)
{ {
final Trip.Builder builder = new Trip.Builder(); final Trip.Builder builder = new Trip.Builder();
@@ -52,7 +50,8 @@ public final class RoutingUtils
else else
destinationBuilder.setName(" "); destinationBuilder.setName(" ");
builder.addDestination(destinationBuilder.build(), createTravelEstimate(info.distToTarget, info.totalTimeInSeconds)); builder.addDestination(destinationBuilder.build(),
createTravelEstimate(info.distToTarget, info.totalTimeInSeconds));
// TODO (AndrewShkrob): Use real distance and time estimates // TODO (AndrewShkrob): Use real distance and time estimates
builder.addStep(createCurrentStep(context, info), createTravelEstimate(info.distToTurn, 0)); builder.addStep(createCurrentStep(context, info), createTravelEstimate(info.distToTurn, 0));

View File

@@ -6,10 +6,8 @@ import androidx.car.app.model.CarIcon;
import androidx.car.app.suggestion.SuggestionManager; import androidx.car.app.suggestion.SuggestionManager;
import androidx.car.app.suggestion.model.Suggestion; import androidx.car.app.suggestion.model.Suggestion;
import androidx.core.graphics.drawable.IconCompat; import androidx.core.graphics.drawable.IconCompat;
import app.organicmaps.R; import app.organicmaps.R;
import app.organicmaps.sdk.search.SearchRecents; import app.organicmaps.sdk.search.SearchRecents;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@@ -22,11 +20,13 @@ public final class SuggestionsHelpers
context.getCarService(SuggestionManager.class).updateSuggestions(createSuggestionsList(context)); context.getCarService(SuggestionManager.class).updateSuggestions(createSuggestionsList(context));
} }
// TODO: Currently utilizing search history entries; potential future addition to include "Home" and "Work" marks once supported. // TODO: Currently utilizing search history entries; potential future addition to include "Home" and "Work" marks once
// supported.
@NonNull @NonNull
private static List<Suggestion> createSuggestionsList(@NonNull final CarContext context) private static List<Suggestion> createSuggestionsList(@NonNull final CarContext context)
{ {
final CarIcon iconRecent = new CarIcon.Builder(IconCompat.createWithResource(context, R.drawable.ic_search_recent)).build(); final CarIcon iconRecent =
new CarIcon.Builder(IconCompat.createWithResource(context, R.drawable.ic_search_recent)).build();
final List<Suggestion> suggestions = new ArrayList<>(); final List<Suggestion> suggestions = new ArrayList<>();
SearchRecents.refresh(); SearchRecents.refresh();

View File

@@ -3,12 +3,10 @@ package app.organicmaps.car.util;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.content.Context; import android.content.Context;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.StringRes; import androidx.annotation.StringRes;
import androidx.annotation.UiThread; import androidx.annotation.UiThread;
import androidx.car.app.CarContext; import androidx.car.app.CarContext;
import app.organicmaps.R; import app.organicmaps.R;
import app.organicmaps.routing.RoutingController; import app.organicmaps.routing.RoutingController;
import app.organicmaps.sdk.MapStyle; import app.organicmaps.sdk.MapStyle;
@@ -58,7 +56,8 @@ public final class ThemeUtils
@UiThread @UiThread
public static void update(@NonNull CarContext context, @NonNull ThemeMode oldThemeMode) public static void update(@NonNull CarContext context, @NonNull ThemeMode oldThemeMode)
{ {
final ThemeMode newThemeMode = oldThemeMode == ThemeMode.AUTO ? (context.isDarkMode() ? ThemeMode.NIGHT : ThemeMode.LIGHT) : oldThemeMode; final ThemeMode newThemeMode =
oldThemeMode == ThemeMode.AUTO ? (context.isDarkMode() ? ThemeMode.NIGHT : ThemeMode.LIGHT) : oldThemeMode;
MapStyle newMapStyle; MapStyle newMapStyle;
if (newThemeMode == ThemeMode.NIGHT) if (newThemeMode == ThemeMode.NIGHT)

View File

@@ -9,7 +9,6 @@ import androidx.car.app.model.CarIcon;
import androidx.car.app.model.OnClickListener; import androidx.car.app.model.OnClickListener;
import androidx.car.app.model.Row; import androidx.car.app.model.Row;
import androidx.core.graphics.drawable.IconCompat; import androidx.core.graphics.drawable.IconCompat;
import app.organicmaps.R; import app.organicmaps.R;
public final class Toggle public final class Toggle
@@ -20,7 +19,8 @@ public final class Toggle
private static final int CHECKBOX_CHECKED_ICON = R.drawable.ic_checkbox_checked; private static final int CHECKBOX_CHECKED_ICON = R.drawable.ic_checkbox_checked;
@NonNull @NonNull
public static Row create(@NonNull final CarContext context, @StringRes int title, @NonNull final OnClickListener onClickListener, boolean checked) public static Row create(@NonNull final CarContext context, @StringRes int title,
@NonNull final OnClickListener onClickListener, boolean checked)
{ {
final Row.Builder row = new Row.Builder(); final Row.Builder row = new Row.Builder();
row.setTitle(context.getString(title)); row.setTitle(context.getString(title));
@@ -34,16 +34,19 @@ public final class Toggle
@RequiresCarApi(6) @RequiresCarApi(6)
@NonNull @NonNull
private static androidx.car.app.model.Toggle createToggle(@NonNull final OnClickListener onClickListener, boolean checked) private static androidx.car.app.model.Toggle createToggle(@NonNull final OnClickListener onClickListener,
boolean checked)
{ {
return new androidx.car.app.model.Toggle.Builder((unused) -> onClickListener.onClick()).setChecked(checked).build(); return new androidx.car.app.model.Toggle.Builder((unused) -> onClickListener.onClick()).setChecked(checked).build();
} }
private static void createCheckbox( private static void createCheckbox(@NonNull final Row.Builder row, @NonNull final CarContext context,
@NonNull final Row.Builder row, @NonNull final CarContext context, @NonNull final OnClickListener onClickListener, boolean checked) @NonNull final OnClickListener onClickListener, boolean checked)
{ {
row.setOnClickListener(onClickListener); row.setOnClickListener(onClickListener);
row.setImage(new CarIcon.Builder(IconCompat.createWithResource(context, checked ? CHECKBOX_CHECKED_ICON : CHECKBOX_ICON)).build()); row.setImage(
new CarIcon.Builder(IconCompat.createWithResource(context, checked ? CHECKBOX_CHECKED_ICON : CHECKBOX_ICON))
.build());
} }
private Toggle() {} private Toggle() {}

View File

@@ -13,28 +13,27 @@ import androidx.car.app.model.CarIcon;
import androidx.car.app.model.Row; import androidx.car.app.model.Row;
import androidx.car.app.navigation.model.MapController; import androidx.car.app.navigation.model.MapController;
import androidx.core.graphics.drawable.IconCompat; import androidx.core.graphics.drawable.IconCompat;
import app.organicmaps.sdk.Map;
import app.organicmaps.MwmApplication; import app.organicmaps.MwmApplication;
import app.organicmaps.R; import app.organicmaps.R;
import app.organicmaps.sdk.bookmarks.data.MapObject;
import app.organicmaps.sdk.bookmarks.data.Metadata;
import app.organicmaps.car.SurfaceRenderer; import app.organicmaps.car.SurfaceRenderer;
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.bookmarks.data.MapObject;
import app.organicmaps.sdk.bookmarks.data.Metadata;
import app.organicmaps.sdk.editor.OpeningHours; import app.organicmaps.sdk.editor.OpeningHours;
import app.organicmaps.sdk.editor.data.Timetable; import app.organicmaps.sdk.editor.data.Timetable;
import app.organicmaps.sdk.location.LocationHelper; import app.organicmaps.sdk.location.LocationHelper;
import app.organicmaps.sdk.location.LocationState; import app.organicmaps.sdk.location.LocationState;
import app.organicmaps.sdk.util.LocationUtils; import app.organicmaps.sdk.util.LocationUtils;
import app.organicmaps.util.Utils; import app.organicmaps.util.Utils;
import java.util.Calendar; import java.util.Calendar;
public final class UiHelpers public final class UiHelpers
{ {
@NonNull @NonNull
public static ActionStrip createSettingsActionStrip(@NonNull BaseMapScreen mapScreen, @NonNull SurfaceRenderer surfaceRenderer) public static ActionStrip createSettingsActionStrip(@NonNull BaseMapScreen mapScreen,
@NonNull SurfaceRenderer surfaceRenderer)
{ {
return new ActionStrip.Builder().addAction(createSettingsAction(mapScreen, surfaceRenderer)).build(); return new ActionStrip.Builder().addAction(createSettingsAction(mapScreen, surfaceRenderer)).build();
} }
@@ -48,7 +47,8 @@ public final class UiHelpers
final Action panAction = new Action.Builder(Action.PAN).build(); final Action panAction = new Action.Builder(Action.PAN).build();
final Action location = createLocationButton(context); final Action location = createLocationButton(context);
final Action zoomIn = new Action.Builder().setIcon(iconPlus).setOnClickListener(surfaceRenderer::onZoomIn).build(); final Action zoomIn = new Action.Builder().setIcon(iconPlus).setOnClickListener(surfaceRenderer::onZoomIn).build();
final Action zoomOut = new Action.Builder().setIcon(iconMinus).setOnClickListener(surfaceRenderer::onZoomOut).build(); final Action zoomOut =
new Action.Builder().setIcon(iconMinus).setOnClickListener(surfaceRenderer::onZoomOut).build();
return new ActionStrip.Builder() return new ActionStrip.Builder()
.addAction(panAction) .addAction(panAction)
.addAction(zoomIn) .addAction(zoomIn)
@@ -70,35 +70,42 @@ public final class UiHelpers
} }
@NonNull @NonNull
public static Action createSettingsActionForResult(@NonNull BaseMapScreen mapScreen, @NonNull SurfaceRenderer surfaceRenderer, @NonNull OnScreenResultListener onScreenResultListener) public static Action createSettingsActionForResult(@NonNull BaseMapScreen mapScreen,
@NonNull SurfaceRenderer surfaceRenderer,
@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, @Nullable OnScreenResultListener onScreenResultListener) private static Action createSettingsAction(@NonNull BaseMapScreen mapScreen, @NonNull SurfaceRenderer surfaceRenderer,
@Nullable OnScreenResultListener onScreenResultListener)
{ {
final CarContext context = mapScreen.getCarContext(); final CarContext context = mapScreen.getCarContext();
final CarIcon iconSettings = new CarIcon.Builder(IconCompat.createWithResource(context, R.drawable.ic_settings)).build(); final CarIcon iconSettings =
new CarIcon.Builder(IconCompat.createWithResource(context, R.drawable.ic_settings)).build();
return new Action.Builder().setIcon(iconSettings).setOnClickListener(() -> { return new Action.Builder()
// Action.onClickListener for the Screen A maybe called even if the Screen B is shown now. .setIcon(iconSettings)
// We need to check it .setOnClickListener(() -> {
// This may happen when we use PopToRootHack: // Action.onClickListener for the Screen A maybe called even if the Screen B is shown now.
// * ScreenManager.popToRoot() // We need to check it
// * The root screen (A) is shown for a while // This may happen when we use PopToRootHack:
// * User clicks on some action // * ScreenManager.popToRoot()
// * ScreenManager.push(new Screen()) // * The root screen (A) is shown for a while
// * New screen (B) is displayed now // * User clicks on some action
// * Action.onClickListener is called for action from root screen (A) // * ScreenManager.push(new Screen())
if (mapScreen.getScreenManager().getTop() != mapScreen) // * New screen (B) is displayed now
return; // * Action.onClickListener is called for action from root screen (A)
final Screen settingsScreen = new SettingsScreen(context, surfaceRenderer); if (mapScreen.getScreenManager().getTop() != mapScreen)
if (onScreenResultListener != null) return;
mapScreen.getScreenManager().pushForResult(settingsScreen, onScreenResultListener); final Screen settingsScreen = new SettingsScreen(context, surfaceRenderer);
else if (onScreenResultListener != null)
mapScreen.getScreenManager().push(settingsScreen); mapScreen.getScreenManager().pushForResult(settingsScreen, onScreenResultListener);
}).build(); else
mapScreen.getScreenManager().push(settingsScreen);
})
.build();
} }
@Nullable @Nullable
@@ -112,7 +119,8 @@ public final class UiHelpers
return null; return null;
final Row.Builder builder = new Row.Builder(); final Row.Builder builder = new Row.Builder();
builder.setImage(new CarIcon.Builder(IconCompat.createWithResource(context, R.drawable.ic_operating_hours)).build()); builder.setImage(
new CarIcon.Builder(IconCompat.createWithResource(context, R.drawable.ic_operating_hours)).build());
if (isEmptyTT) if (isEmptyTT)
builder.setTitle(ohStr); builder.setTitle(ohStr);
@@ -159,25 +167,28 @@ public final class UiHelpers
final int locationMode = Map.isEngineCreated() ? LocationState.getMode() : LocationState.NOT_FOLLOW_NO_POSITION; final int locationMode = Map.isEngineCreated() ? LocationState.getMode() : LocationState.NOT_FOLLOW_NO_POSITION;
CarColor tintColor = Colors.DEFAULT; CarColor tintColor = Colors.DEFAULT;
@DrawableRes int drawableRes; @DrawableRes
int drawableRes;
switch (locationMode) switch (locationMode)
{ {
case LocationState.PENDING_POSITION, LocationState.NOT_FOLLOW_NO_POSITION -> drawableRes = R.drawable.ic_location_off; case LocationState.PENDING_POSITION, LocationState.NOT_FOLLOW_NO_POSITION ->
case LocationState.NOT_FOLLOW -> drawableRes = R.drawable.ic_not_follow; drawableRes = R.drawable.ic_location_off;
case LocationState.FOLLOW -> case LocationState.NOT_FOLLOW -> drawableRes = R.drawable.ic_not_follow;
{ case LocationState.FOLLOW ->
drawableRes = R.drawable.ic_follow; {
tintColor = Colors.LOCATION_TINT; drawableRes = R.drawable.ic_follow;
} tintColor = Colors.LOCATION_TINT;
case LocationState.FOLLOW_AND_ROTATE -> }
{ case LocationState.FOLLOW_AND_ROTATE ->
drawableRes = R.drawable.ic_follow_and_rotate; {
tintColor = Colors.LOCATION_TINT; drawableRes = R.drawable.ic_follow_and_rotate;
} tintColor = Colors.LOCATION_TINT;
default -> throw new IllegalArgumentException("Invalid button mode: " + locationMode); }
default -> throw new IllegalArgumentException("Invalid button mode: " + locationMode);
} }
final CarIcon icon = new CarIcon.Builder(IconCompat.createWithResource(context, drawableRes)).setTint(tintColor).build(); final CarIcon icon =
new CarIcon.Builder(IconCompat.createWithResource(context, drawableRes)).setTint(tintColor).build();
builder.setIcon(icon); builder.setIcon(icon);
builder.setOnClickListener(() -> { builder.setOnClickListener(() -> {
LocationState.nativeSwitchToNextMode(); LocationState.nativeSwitchToNextMode();

View File

@@ -3,5 +3,4 @@ package app.organicmaps.car.util;
/// Marker interface for screens that require user action to proceed. /// Marker interface for screens that require user action to proceed.
/// These screens can't be dropped from AA's screen stack. /// These screens can't be dropped from AA's screen stack.
public interface UserActionRequired public interface UserActionRequired
{ {}
}

View File

@@ -10,21 +10,19 @@ import android.text.TextUtils;
import android.view.View; import android.view.View;
import android.widget.Button; import android.widget.Button;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity; import androidx.fragment.app.FragmentActivity;
import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentManager;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.google.android.material.textfield.TextInputLayout;
import com.google.android.material.textfield.TextInputEditText;
import app.organicmaps.R; import app.organicmaps.R;
import app.organicmaps.base.BaseMwmDialogFragment; import app.organicmaps.base.BaseMwmDialogFragment;
import app.organicmaps.util.InputUtils;
import app.organicmaps.sdk.util.StringUtils; import app.organicmaps.sdk.util.StringUtils;
import app.organicmaps.util.InputUtils;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.google.android.material.textfield.TextInputEditText;
import com.google.android.material.textfield.TextInputLayout;
public class EditTextDialogFragment extends BaseMwmDialogFragment public class EditTextDialogFragment extends BaseMwmDialogFragment
{ {
@@ -60,22 +58,22 @@ public class EditTextDialogFragment extends BaseMwmDialogFragment
} }
public static EditTextDialogFragment show(@Nullable String title, @Nullable String initialText, public static EditTextDialogFragment show(@Nullable String title, @Nullable String initialText,
@Nullable String positiveBtn, @Nullable String negativeBtn, @Nullable String positiveBtn, @Nullable String negativeBtn,
@NonNull Fragment parent, @Nullable Validator inputValidator) @NonNull Fragment parent, @Nullable Validator inputValidator)
{ {
return show(title, initialText, "", positiveBtn, negativeBtn, NO_LIMITED_TEXT_LENGTH, parent, inputValidator); return show(title, initialText, "", positiveBtn, negativeBtn, NO_LIMITED_TEXT_LENGTH, parent, inputValidator);
} }
public static EditTextDialogFragment show(@Nullable String title, @Nullable String initialText, @Nullable String hint, public static EditTextDialogFragment show(@Nullable String title, @Nullable String initialText, @Nullable String hint,
@Nullable String positiveBtn, @Nullable String negativeBtn, @Nullable String positiveBtn, @Nullable String negativeBtn,
@NonNull Fragment parent, @Nullable Validator inputValidator) @NonNull Fragment parent, @Nullable Validator inputValidator)
{ {
return show(title, initialText, hint, positiveBtn, negativeBtn, NO_LIMITED_TEXT_LENGTH, parent, inputValidator); return show(title, initialText, hint, positiveBtn, negativeBtn, NO_LIMITED_TEXT_LENGTH, parent, inputValidator);
} }
public static EditTextDialogFragment show(@Nullable String title, @Nullable String initialText, @Nullable String hint, public static EditTextDialogFragment show(@Nullable String title, @Nullable String initialText, @Nullable String hint,
@Nullable String positiveBtn, @Nullable String negativeBtn, int textLimit, @Nullable String positiveBtn, @Nullable String negativeBtn, int textLimit,
@NonNull Fragment parent, @Nullable Validator inputValidator) @NonNull Fragment parent, @Nullable Validator inputValidator)
{ {
final Bundle args = new Bundle(); final Bundle args = new Bundle();
args.putString(ARG_TITLE, title); args.putString(ARG_TITLE, title);
@@ -85,8 +83,8 @@ public class EditTextDialogFragment extends BaseMwmDialogFragment
args.putString(ARG_HINT, hint); args.putString(ARG_HINT, hint);
args.putInt(ARG_TEXT_LENGTH_LIMIT, textLimit); args.putInt(ARG_TEXT_LENGTH_LIMIT, textLimit);
FragmentManager fragmentManager = parent.getChildFragmentManager(); FragmentManager fragmentManager = parent.getChildFragmentManager();
final EditTextDialogFragment fragment = (EditTextDialogFragment) fragmentManager.getFragmentFactory() final EditTextDialogFragment fragment = (EditTextDialogFragment) fragmentManager.getFragmentFactory().instantiate(
.instantiate(parent.requireActivity().getClassLoader(), EditTextDialogFragment.class.getName()); parent.requireActivity().getClassLoader(), EditTextDialogFragment.class.getName());
fragment.setArguments(args); fragment.setArguments(args);
fragment.show(fragmentManager, EditTextDialogFragment.class.getName()); fragment.show(fragmentManager, EditTextDialogFragment.class.getName());
fragment.mInputValidator = inputValidator; fragment.mInputValidator = inputValidator;
@@ -117,13 +115,15 @@ 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, (dialog, which) -> { .setPositiveButton(positiveButtonText,
final String result = mEtInput.getText().toString(); (dialog, which) -> {
processInput(result); final String result = mEtInput.getText().toString();
dismiss(); processInput(result);
}).create(); dismiss();
})
.create();
// Wait till alert is shown to get mPositiveButton. // Wait till alert is shown to get mPositiveButton.
editTextDialog.setOnShowListener((dialog) -> { editTextDialog.setOnShowListener((dialog) -> {
@@ -135,8 +135,7 @@ public class EditTextDialogFragment extends BaseMwmDialogFragment
}); });
// Setup validation on input edit. // Setup validation on input edit.
mEtInput.addTextChangedListener(new StringUtils.SimpleTextWatcher() mEtInput.addTextChangedListener(new StringUtils.SimpleTextWatcher() {
{
@Override @Override
public void onTextChanged(CharSequence s, int start, int before, int count) public void onTextChanged(CharSequence s, int start, int before, int count)
{ {
@@ -173,7 +172,8 @@ public class EditTextDialogFragment extends BaseMwmDialogFragment
private View buildView() private View buildView()
{ {
@SuppressLint("InflateParams") final View root = requireActivity().getLayoutInflater().inflate(R.layout.dialog_edit_text, null); @SuppressLint("InflateParams")
final View root = requireActivity().getLayoutInflater().inflate(R.layout.dialog_edit_text, null);
mEtInputLayout = root.findViewById(R.id.et__input_layout); mEtInputLayout = root.findViewById(R.id.et__input_layout);
mEtInput = mEtInputLayout.findViewById(R.id.et__input); mEtInput = mEtInputLayout.findViewById(R.id.et__input);
mEtInput.setHint(TextUtils.isEmpty(mHint) ? getString(R.string.name) : mHint); mEtInput.setHint(TextUtils.isEmpty(mHint) ? getString(R.string.name) : mHint);

View File

@@ -2,21 +2,18 @@ package app.organicmaps.downloader;
import android.annotation.TargetApi; import android.annotation.TargetApi;
import android.content.Context; import android.content.Context;
import app.organicmaps.R;
import app.organicmaps.sdk.util.log.Logger;
import java.io.InputStream; import java.io.InputStream;
import java.net.HttpURLConnection; import java.net.HttpURLConnection;
import java.security.KeyStore; import java.security.KeyStore;
import java.security.cert.Certificate; import java.security.cert.Certificate;
import java.security.cert.CertificateFactory; import java.security.cert.CertificateFactory;
import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext; import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManagerFactory; import javax.net.ssl.TrustManagerFactory;
import app.organicmaps.R;
import app.organicmaps.sdk.util.log.Logger;
// Fix missing root certificates for HTTPS connections on Android 7 and below: // Fix missing root certificates for HTTPS connections on Android 7 and below:
// https://community.letsencrypt.org/t/letsencrypt-certificates-fails-on-android-phones-running-android-7-or-older/205686 // https://community.letsencrypt.org/t/letsencrypt-certificates-fails-on-android-phones-running-android-7-or-older/205686
@TargetApi(24) @TargetApi(24)
@@ -27,7 +24,8 @@ public class Android7RootCertificateWorkaround
@TargetApi(24) @TargetApi(24)
private static SSLSocketFactory mSslSocketFactory; private static SSLSocketFactory mSslSocketFactory;
public static void applyFixIfNeeded(HttpURLConnection connection) { public static void applyFixIfNeeded(HttpURLConnection connection)
{
// Deliberately not checking for null to have an exception from setSSLSocketFactory. // Deliberately not checking for null to have an exception from setSSLSocketFactory.
if (android.os.Build.VERSION.SDK_INT <= android.os.Build.VERSION_CODES.N if (android.os.Build.VERSION.SDK_INT <= android.os.Build.VERSION_CODES.N
&& connection.getURL().getProtocol().equals("https")) && connection.getURL().getProtocol().equals("https"))
@@ -39,8 +37,8 @@ public class Android7RootCertificateWorkaround
if (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.N) if (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.N)
return; return;
final int[] certificates = new int[]{ final int[] certificates = new int[] {R.raw.isrgrootx1, R.raw.globalsignr4, R.raw.gtsrootr1,
R.raw.isrgrootx1, R.raw.globalsignr4, R.raw.gtsrootr1, R.raw.gtsrootr2, R.raw.gtsrootr3, R.raw.gtsrootr4}; R.raw.gtsrootr2, R.raw.gtsrootr3, R.raw.gtsrootr4};
try try
{ {

View File

@@ -10,18 +10,14 @@ import static app.organicmaps.sdk.downloader.CountryItem.STATUS_PROGRESS;
import static app.organicmaps.sdk.downloader.CountryItem.STATUS_UPDATABLE; import static app.organicmaps.sdk.downloader.CountryItem.STATUS_UPDATABLE;
import android.view.View; import android.view.View;
import com.google.android.material.button.MaterialButton;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import app.organicmaps.R; import app.organicmaps.R;
import app.organicmaps.sdk.downloader.CountryItem; import app.organicmaps.sdk.downloader.CountryItem;
import app.organicmaps.sdk.downloader.MapManager; import app.organicmaps.sdk.downloader.MapManager;
import app.organicmaps.sdk.downloader.UpdateInfo; import app.organicmaps.sdk.downloader.UpdateInfo;
import app.organicmaps.sdk.util.StringUtils; import app.organicmaps.sdk.util.StringUtils;
import app.organicmaps.sdk.util.UiUtils; import app.organicmaps.sdk.util.UiUtils;
import com.google.android.material.button.MaterialButton;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
class BottomPanel class BottomPanel
{ {
@@ -29,8 +25,7 @@ class BottomPanel
private final FloatingActionButton mFab; private final FloatingActionButton mFab;
private final MaterialButton mButton; private final MaterialButton mButton;
private final View.OnClickListener mDownloadListener = new View.OnClickListener() private final View.OnClickListener mDownloadListener = new View.OnClickListener() {
{
@Override @Override
public void onClick(View v) public void onClick(View v)
{ {
@@ -38,8 +33,7 @@ class BottomPanel
} }
}; };
private final View.OnClickListener mUpdateListener = new View.OnClickListener() private final View.OnClickListener mUpdateListener = new View.OnClickListener() {
{
@Override @Override
public void onClick(View v) public void onClick(View v)
{ {
@@ -48,8 +42,7 @@ class BottomPanel
} }
}; };
private final View.OnClickListener mCancelListener = new View.OnClickListener() private final View.OnClickListener mCancelListener = new View.OnClickListener() {
{
@Override @Override
public void onClick(View v) public void onClick(View v)
{ {
@@ -58,8 +51,7 @@ class BottomPanel
} }
}; };
private final View.OnClickListener mRetryListener = new View.OnClickListener() private final View.OnClickListener mRetryListener = new View.OnClickListener() {
{
@Override @Override
public void onClick(View v) public void onClick(View v)
{ {
@@ -73,7 +65,7 @@ class BottomPanel
mFab = frame.findViewById(R.id.fab); mFab = frame.findViewById(R.id.fab);
mFab.setOnClickListener(v -> { mFab.setOnClickListener(v -> {
if (mFragment.getAdapter() != null ) if (mFragment.getAdapter() != null)
mFragment.getAdapter().setAvailableMapsMode(); mFragment.getAdapter().setAvailableMapsMode();
update(); update();
}); });
@@ -83,8 +75,9 @@ class BottomPanel
private void setUpdateAllState(UpdateInfo info) private void setUpdateAllState(UpdateInfo info)
{ {
mButton.setText(StringUtils.formatUsingUsLocale("%s (%s)", mFragment.getString(R.string.downloader_update_all_button), mButton.setText(
StringUtils.getFileSizeString(mFragment.requireContext(), info.totalSize))); StringUtils.formatUsingUsLocale("%s (%s)", mFragment.getString(R.string.downloader_update_all_button),
StringUtils.getFileSizeString(mFragment.requireContext(), info.totalSize)));
mButton.setOnClickListener(mUpdateListener); mButton.setOnClickListener(mUpdateListener);
} }
@@ -126,7 +119,7 @@ class BottomPanel
{ {
UpdateInfo info = MapManager.nativeGetUpdateInfo(root); UpdateInfo info = MapManager.nativeGetUpdateInfo(root);
setUpdateAllState(info); setUpdateAllState(info);
} // Special case for "Countries" node when no maps currently downloaded. } // Special case for "Countries" node when no maps currently downloaded.
case STATUS_DOWNLOADABLE, STATUS_DONE, STATUS_PARTLY -> show = false; case STATUS_DOWNLOADABLE, STATUS_DONE, STATUS_PARTLY -> show = false;
case STATUS_PROGRESS, STATUS_APPLYING, STATUS_ENQUEUED -> setCancelState(); case STATUS_PROGRESS, STATUS_APPLYING, STATUS_ENQUEUED -> setCancelState();
case STATUS_FAILED -> setRetryFailedStates(); case STATUS_FAILED -> setRetryFailedStates();

View File

@@ -7,23 +7,19 @@ import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.fragment.app.FragmentActivity; import androidx.fragment.app.FragmentActivity;
import com.google.android.material.button.MaterialButton;
import com.google.android.material.textview.MaterialTextView;
import app.organicmaps.MwmApplication; import app.organicmaps.MwmApplication;
import app.organicmaps.R; import app.organicmaps.R;
import app.organicmaps.base.BaseMwmFragment; import app.organicmaps.base.BaseMwmFragment;
import app.organicmaps.base.BaseMwmFragmentActivity; import app.organicmaps.base.BaseMwmFragmentActivity;
import app.organicmaps.sdk.downloader.CountryItem; import app.organicmaps.sdk.downloader.CountryItem;
import app.organicmaps.sdk.downloader.MapManager; import app.organicmaps.sdk.downloader.MapManager;
import app.organicmaps.widget.WheelProgressView;
import app.organicmaps.sdk.util.StringUtils; import app.organicmaps.sdk.util.StringUtils;
import app.organicmaps.sdk.util.UiUtils; import app.organicmaps.sdk.util.UiUtils;
import app.organicmaps.widget.WheelProgressView;
import com.google.android.material.button.MaterialButton;
import com.google.android.material.textview.MaterialTextView;
import java.util.List; import java.util.List;
public class CountrySuggestFragment extends BaseMwmFragment implements View.OnClickListener public class CountrySuggestFragment extends BaseMwmFragment implements View.OnClickListener
@@ -55,8 +51,7 @@ public class CountrySuggestFragment extends BaseMwmFragment implements View.OnCl
super.onViewCreated(view, savedInstanceState); super.onViewCreated(view, savedInstanceState);
initViews(view); initViews(view);
mListenerSlot = MapManager.nativeSubscribe(new MapManager.StorageCallback() mListenerSlot = MapManager.nativeSubscribe(new MapManager.StorageCallback() {
{
@Override @Override
public void onStatusChanged(List<MapManager.StorageCallbackData> data) public void onStatusChanged(List<MapManager.StorageCallbackData> data)
{ {
@@ -75,13 +70,9 @@ public class CountrySuggestFragment extends BaseMwmFragment implements View.OnCl
switch (item.newStatus) switch (item.newStatus)
{ {
case CountryItem.STATUS_FAILED: case CountryItem.STATUS_FAILED: updateViews(); return;
updateViews();
return;
case CountryItem.STATUS_DONE: case CountryItem.STATUS_DONE: exitFragment(); return;
exitFragment();
return;
} }
break; break;
@@ -140,9 +131,9 @@ public class CountrySuggestFragment extends BaseMwmFragment implements View.OnCl
if (mCurrentCountry == null || !isAdded()) if (mCurrentCountry == null || !isAdded())
return; return;
mBtnDownloadMap.setText(StringUtils.formatUsingUsLocale("%1$s (%2$s)", mBtnDownloadMap.setText(
getString(R.string.downloader_download_map), StringUtils.formatUsingUsLocale("%1$s (%2$s)", getString(R.string.downloader_download_map),
StringUtils.getFileSizeString(requireContext(), mCurrentCountry.totalSize))); StringUtils.getFileSizeString(requireContext(), mCurrentCountry.totalSize)));
} }
private void initViews(View view) private void initViews(View view)
@@ -195,7 +186,8 @@ public class CountrySuggestFragment extends BaseMwmFragment implements View.OnCl
private void updateProgress() private void updateProgress()
{ {
String text = getString(R.string.downloader_downloading) + " " + StringUtils.formatPercent(mDownloadingCountry.progress / 100); String text = getString(R.string.downloader_downloading) + " "
+ StringUtils.formatPercent(mDownloadingCountry.progress / 100);
mTvProgress.setText(text); mTvProgress.setText(text);
mWpvDownloadProgress.setProgress(Math.round(mDownloadingCountry.progress)); mWpvDownloadProgress.setProgress(Math.round(mDownloadingCountry.progress));
} }

View File

@@ -1,7 +1,6 @@
package app.organicmaps.downloader; package app.organicmaps.downloader;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import app.organicmaps.base.BaseMwmFragmentActivity; import app.organicmaps.base.BaseMwmFragmentActivity;
import app.organicmaps.base.OnBackPressListener; import app.organicmaps.base.OnBackPressListener;
@@ -18,7 +17,8 @@ public class DownloaderActivity extends BaseMwmFragmentActivity
@Override @Override
public void onBackPressed() public void onBackPressed()
{ {
OnBackPressListener fragment = (OnBackPressListener)getSupportFragmentManager().findFragmentById(getFragmentContentResId()); OnBackPressListener fragment =
(OnBackPressListener) getSupportFragmentManager().findFragmentById(getFragmentContentResId());
if (!fragment.onBackPressed()) if (!fragment.onBackPressed())
super.onBackPressed(); super.onBackPressed();
} }

View File

@@ -11,13 +11,11 @@ import android.text.style.StyleSpan;
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 androidx.annotation.LayoutRes; import androidx.annotation.LayoutRes;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import app.organicmaps.MwmActivity; import app.organicmaps.MwmActivity;
import app.organicmaps.MwmApplication; import app.organicmaps.MwmApplication;
import app.organicmaps.R; import app.organicmaps.R;
@@ -30,7 +28,6 @@ import app.organicmaps.util.bottomsheet.MenuBottomSheetFragment;
import app.organicmaps.util.bottomsheet.MenuBottomSheetItem; import app.organicmaps.util.bottomsheet.MenuBottomSheetItem;
import com.google.android.material.dialog.MaterialAlertDialogBuilder; import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.google.android.material.textview.MaterialTextView; import com.google.android.material.textview.MaterialTextView;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
@@ -60,7 +57,8 @@ class DownloaderAdapter extends RecyclerView.Adapter<DownloaderAdapter.ViewHolde
// Use List, because we have multiple search results now for a single country. // Use List, because we have multiple search results now for a single country.
private final Map<String, List<CountryItem>> mCountryIndex = new HashMap<>(); private final Map<String, List<CountryItem>> mCountryIndex = new HashMap<>();
private final Stack<PathEntry> mPath = new Stack<>(); // Holds navigation history. The last element is the current level. private final Stack<PathEntry> mPath =
new Stack<>(); // Holds navigation history. The last element is the current level.
private int mListenerSlot; private int mListenerSlot;
private CountryItem mSelectedItem; private CountryItem mSelectedItem;
@@ -156,20 +154,16 @@ class DownloaderAdapter extends RecyclerView.Adapter<DownloaderAdapter.ViewHolde
} }
private record PathEntry(CountryItem item, boolean myMapsMode, int topPosition, int topOffset) private record PathEntry(CountryItem item, boolean myMapsMode, int topPosition, int topOffset)
{
@Override
public String toString()
{
return item.id + " (" + item.name + "), " +
"myMapsMode: " + myMapsMode +
", topPosition: " + topPosition +
", topOffset: " + topOffset;
}
}
private final MapManager.StorageCallback mStorageCallback = new MapManager.StorageCallback()
{ {
@Override
public String toString()
{
return item.id + " (" + item.name + "), "
+ "myMapsMode: " + myMapsMode + ", topPosition: " + topPosition + ", topOffset: " + topOffset;
}
}
private final MapManager.StorageCallback mStorageCallback = new MapManager.StorageCallback() {
private void updateItem(String countryId) private void updateItem(String countryId)
{ {
List<CountryItem> lst = mCountryIndex.get(countryId); List<CountryItem> lst = mCountryIndex.get(countryId);
@@ -226,7 +220,6 @@ class DownloaderAdapter extends RecyclerView.Adapter<DownloaderAdapter.ViewHolde
return inflate(parent, R.layout.downloader_item); return inflate(parent, R.layout.downloader_item);
else else
return inflate(parent, R.layout.downloader_item_header); return inflate(parent, R.layout.downloader_item_header);
} }
class ViewHolderWrapper extends RecyclerView.ViewHolder class ViewHolderWrapper extends RecyclerView.ViewHolder
@@ -276,7 +269,7 @@ class DownloaderAdapter extends RecyclerView.Adapter<DownloaderAdapter.ViewHolde
{ {
mSelectedItem = selectedItem; mSelectedItem = selectedItem;
MenuBottomSheetFragment.newInstance(DOWNLOADER_MENU_ID, mSelectedItem.name) MenuBottomSheetFragment.newInstance(DOWNLOADER_MENU_ID, mSelectedItem.name)
.show(mFragment.getChildFragmentManager(), DOWNLOADER_MENU_ID); .show(mFragment.getChildFragmentManager(), DOWNLOADER_MENU_ID);
} }
public ArrayList<MenuBottomSheetItem> getMenuItems() public ArrayList<MenuBottomSheetItem> getMenuItems()
@@ -284,9 +277,7 @@ class DownloaderAdapter extends RecyclerView.Adapter<DownloaderAdapter.ViewHolde
ArrayList<MenuBottomSheetItem> items = new ArrayList<>(); ArrayList<MenuBottomSheetItem> items = new ArrayList<>();
switch (mSelectedItem.status) switch (mSelectedItem.status)
{ {
case CountryItem.STATUS_DOWNLOADABLE: case CountryItem.STATUS_DOWNLOADABLE: items.add(getDownloadMenuItem()); break;
items.add(getDownloadMenuItem());
break;
case CountryItem.STATUS_UPDATABLE: case CountryItem.STATUS_UPDATABLE:
items.add(getUpdateMenuItem()); items.add(getUpdateMenuItem());
@@ -325,7 +316,6 @@ class DownloaderAdapter extends RecyclerView.Adapter<DownloaderAdapter.ViewHolde
return items; return items;
} }
private MenuBottomSheetItem getDownloadMenuItem() private MenuBottomSheetItem getDownloadMenuItem()
{ {
return new MenuBottomSheetItem(R.string.downloader_download_map, R.drawable.ic_download, return new MenuBottomSheetItem(R.string.downloader_download_map, R.drawable.ic_download,
@@ -357,8 +347,7 @@ class DownloaderAdapter extends RecyclerView.Adapter<DownloaderAdapter.ViewHolde
private MenuBottomSheetItem getCancelMenuItem() private MenuBottomSheetItem getCancelMenuItem()
{ {
return new MenuBottomSheetItem(R.string.cancel, R.drawable.ic_cancel, return new MenuBottomSheetItem(R.string.cancel, R.drawable.ic_cancel, () -> onCancelActionSelected(mSelectedItem));
() -> onCancelActionSelected(mSelectedItem));
} }
private class ItemViewHolder extends BaseInnerViewHolder<CountryItem> private class ItemViewHolder extends BaseInnerViewHolder<CountryItem>
@@ -373,8 +362,9 @@ class DownloaderAdapter extends RecyclerView.Adapter<DownloaderAdapter.ViewHolde
{ {
switch (mItem.status) switch (mItem.status)
{ {
case CountryItem.STATUS_DONE, CountryItem.STATUS_PROGRESS, CountryItem.STATUS_APPLYING, CountryItem.STATUS_ENQUEUED -> case CountryItem.STATUS_DONE, CountryItem.STATUS_PROGRESS, CountryItem.STATUS_APPLYING,
processLongClick(); CountryItem.STATUS_ENQUEUED ->
processLongClick();
case CountryItem.STATUS_DOWNLOADABLE, CountryItem.STATUS_PARTLY -> case CountryItem.STATUS_DOWNLOADABLE, CountryItem.STATUS_PARTLY ->
{ {
if (clickOnStatus) if (clickOnStatus)
@@ -384,7 +374,7 @@ class DownloaderAdapter extends RecyclerView.Adapter<DownloaderAdapter.ViewHolde
} }
case CountryItem.STATUS_FAILED -> MapManager.warn3gAndRetry(mActivity, mItem.id, null); case CountryItem.STATUS_FAILED -> MapManager.warn3gAndRetry(mActivity, mItem.id, null);
case CountryItem.STATUS_UPDATABLE -> case CountryItem.STATUS_UPDATABLE ->
MapManager.warnOn3gUpdate(mActivity, mItem.id, () -> MapManager.startUpdate(mItem.id)); MapManager.warnOn3gUpdate(mActivity, mItem.id, () -> MapManager.startUpdate(mItem.id));
default -> throw new IllegalArgumentException("Inappropriate item status: " + mItem.status); default -> throw new IllegalArgumentException("Inappropriate item status: " + mItem.status);
} }
} }
@@ -396,15 +386,13 @@ class DownloaderAdapter extends RecyclerView.Adapter<DownloaderAdapter.ViewHolde
ItemViewHolder(View frame) ItemViewHolder(View frame)
{ {
mStatusIcon = new DownloaderStatusIcon(frame.findViewById(R.id.downloader_status_frame)) mStatusIcon = new DownloaderStatusIcon(frame.findViewById(R.id.downloader_status_frame)) {
{
@Override @Override
protected int selectIcon(CountryItem country) protected int selectIcon(CountryItem country)
{ {
if (country.status == CountryItem.STATUS_DOWNLOADABLE || country.status == CountryItem.STATUS_PARTLY) if (country.status == CountryItem.STATUS_DOWNLOADABLE || country.status == CountryItem.STATUS_PARTLY)
{ {
return (country.isExpandable() ? (mMyMapsMode ? R.attr.status_folder_done return (country.isExpandable() ? (mMyMapsMode ? R.attr.status_folder_done : R.attr.status_folder)
: R.attr.status_folder)
: R.attr.status_downloadable); : R.attr.status_downloadable);
} }
@@ -475,9 +463,10 @@ class DownloaderAdapter extends RecyclerView.Adapter<DownloaderAdapter.ViewHolde
if (mItem.isExpandable()) if (mItem.isExpandable())
{ {
UiUtils.setTextAndHideIfEmpty(mSubtitle, String.format("%s: %s", mActivity.getString(R.string.downloader_status_maps), UiUtils.setTextAndHideIfEmpty(
mActivity.getString(R.string.downloader_of, mItem.childCount, mSubtitle,
mItem.totalChildCount))); String.format("%s: %s", mActivity.getString(R.string.downloader_status_maps),
mActivity.getString(R.string.downloader_of, mItem.childCount, mItem.totalChildCount)));
} }
UiUtils.showIf(mSearchResultsMode && !TextUtils.isEmpty(found), mFoundName); UiUtils.showIf(mSearchResultsMode && !TextUtils.isEmpty(found), mFoundName);
@@ -490,14 +479,12 @@ class DownloaderAdapter extends RecyclerView.Adapter<DownloaderAdapter.ViewHolde
private long getMapDisplaySize() private long getMapDisplaySize()
{ {
long size; long size;
if (mItem.status == CountryItem.STATUS_ENQUEUED || if (mItem.status == CountryItem.STATUS_ENQUEUED || mItem.status == CountryItem.STATUS_PROGRESS
mItem.status == CountryItem.STATUS_PROGRESS || || mItem.status == CountryItem.STATUS_APPLYING)
mItem.status == CountryItem.STATUS_APPLYING)
{ {
size = mItem.enqueuedSize; size = mItem.enqueuedSize;
} }
else if (mItem.status == CountryItem.STATUS_FAILED || else if (mItem.status == CountryItem.STATUS_FAILED || mItem.status == CountryItem.STATUS_DOWNLOADABLE)
mItem.status == CountryItem.STATUS_DOWNLOADABLE)
{ {
size = mItem.totalSize; size = mItem.totalSize;
} }
@@ -521,7 +508,7 @@ class DownloaderAdapter extends RecyclerView.Adapter<DownloaderAdapter.ViewHolde
void bind(String text) void bind(String text)
{ {
mTitle.setText(text); mTitle.setText(text);
} }
} }
@@ -531,7 +518,7 @@ class DownloaderAdapter extends RecyclerView.Adapter<DownloaderAdapter.ViewHolde
int headerId = 0; int headerId = 0;
int prev = -1; int prev = -1;
for (CountryItem ci: mItems) for (CountryItem ci : mItems)
{ {
// Disable headers when using the search // Disable headers when using the search
if (!mSearchResultsMode) if (!mSearchResultsMode)
@@ -620,12 +607,13 @@ class DownloaderAdapter extends RecyclerView.Adapter<DownloaderAdapter.ViewHolde
collectHeaders(); collectHeaders();
mCountryIndex.clear(); mCountryIndex.clear();
for (CountryItem ci: mItems) for (CountryItem ci : mItems)
{ {
List<CountryItem> lst = mCountryIndex.get(ci.id); List<CountryItem> lst = mCountryIndex.get(ci.id);
if (lst != null) if (lst != null)
lst.add(ci); lst.add(ci);
else { else
{
lst = new ArrayList<>(); lst = new ArrayList<>();
lst.add(ci); lst.add(ci);
mCountryIndex.put(ci.id, lst); mCountryIndex.put(ci.id, lst);
@@ -682,7 +670,7 @@ class DownloaderAdapter extends RecyclerView.Adapter<DownloaderAdapter.ViewHolde
private void goDeeper(CountryItem child, boolean refresh) private void goDeeper(CountryItem child, boolean refresh)
{ {
LinearLayoutManager lm = (LinearLayoutManager)mRecycler.getLayoutManager(); LinearLayoutManager lm = (LinearLayoutManager) mRecycler.getLayoutManager();
// Save scroll positions (top item + item`s offset) for current hierarchy level // Save scroll positions (top item + item`s offset) for current hierarchy level
int position = lm.findFirstVisibleItemPosition(); int position = lm.findFirstVisibleItemPosition();
@@ -748,12 +736,14 @@ class DownloaderAdapter extends RecyclerView.Adapter<DownloaderAdapter.ViewHolde
return (canGoUpwards() ? mPath.peek().item : CountryItem.fill(CountryItem.getRootId())); return (canGoUpwards() ? mPath.peek().item : CountryItem.fill(CountryItem.getRootId()));
} }
@NonNull String getCurrentRootId() @NonNull
String getCurrentRootId()
{ {
return (canGoUpwards() ? getCurrentRootItem().id : CountryItem.getRootId()); return (canGoUpwards() ? getCurrentRootItem().id : CountryItem.getRootId());
} }
@Nullable String getCurrentRootName() @Nullable
String getCurrentRootName()
{ {
return (canGoUpwards() ? getCurrentRootItem().name : null); return (canGoUpwards() ? getCurrentRootItem().name : null);
} }

View File

@@ -4,7 +4,6 @@ import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.view.View; import android.view.View;
import android.view.WindowManager; import android.view.WindowManager;
import androidx.activity.result.ActivityResultLauncher; import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts; import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.CallSuper; import androidx.annotation.CallSuper;
@@ -13,7 +12,6 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.core.view.ViewCompat; import androidx.core.view.ViewCompat;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import app.organicmaps.R; import app.organicmaps.R;
import app.organicmaps.base.BaseMwmRecyclerFragment; import app.organicmaps.base.BaseMwmRecyclerFragment;
import app.organicmaps.base.OnBackPressListener; import app.organicmaps.base.OnBackPressListener;
@@ -21,16 +19,14 @@ import app.organicmaps.sdk.downloader.CountryItem;
import app.organicmaps.sdk.downloader.MapManager; import app.organicmaps.sdk.downloader.MapManager;
import app.organicmaps.sdk.search.MapSearchListener; import app.organicmaps.sdk.search.MapSearchListener;
import app.organicmaps.sdk.search.SearchEngine; import app.organicmaps.sdk.search.SearchEngine;
import app.organicmaps.widget.PlaceholderView;
import app.organicmaps.util.bottomsheet.MenuBottomSheetFragment; import app.organicmaps.util.bottomsheet.MenuBottomSheetFragment;
import app.organicmaps.util.bottomsheet.MenuBottomSheetItem; import app.organicmaps.util.bottomsheet.MenuBottomSheetItem;
import app.organicmaps.widget.PlaceholderView;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
public class DownloaderFragment extends BaseMwmRecyclerFragment<DownloaderAdapter> public class DownloaderFragment extends BaseMwmRecyclerFragment<DownloaderAdapter>
implements OnBackPressListener, implements OnBackPressListener, MenuBottomSheetFragment.MenuBottomSheetInterface
MenuBottomSheetFragment.MenuBottomSheetInterface
{ {
private DownloaderToolbarController mToolbarController; private DownloaderToolbarController mToolbarController;
@@ -43,7 +39,9 @@ public class DownloaderFragment extends BaseMwmRecyclerFragment<DownloaderAdapte
private int mSubscriberSlot; private int mSubscriberSlot;
final ActivityResultLauncher<Intent> startVoiceRecognitionForResult = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), activityResult -> mToolbarController.onVoiceRecognitionResult(activityResult)); final ActivityResultLauncher<Intent> startVoiceRecognitionForResult =
registerForActivityResult(new ActivityResultContracts.StartActivityForResult(),
activityResult -> mToolbarController.onVoiceRecognitionResult(activityResult));
private final RecyclerView.OnScrollListener mScrollListener = new RecyclerView.OnScrollListener() { private final RecyclerView.OnScrollListener mScrollListener = new RecyclerView.OnScrollListener() {
@Override @Override
@@ -54,8 +52,7 @@ public class DownloaderFragment extends BaseMwmRecyclerFragment<DownloaderAdapte
} }
}; };
private final MapSearchListener mSearchListener = new MapSearchListener() private final MapSearchListener mSearchListener = new MapSearchListener() {
{
@Keep @Keep
@Override @Override
public void onMapSearchResults(@NonNull Result[] results, long timestamp, boolean isLast) public void onMapSearchResults(@NonNull Result[] results, long timestamp, boolean isLast)
@@ -133,8 +130,7 @@ public class DownloaderFragment extends BaseMwmRecyclerFragment<DownloaderAdapte
ViewCompat.setOnApplyWindowInsetsListener(view, new DownloaderInsetsListener(view)); ViewCompat.setOnApplyWindowInsetsListener(view, new DownloaderInsetsListener(view));
mSubscriberSlot = MapManager.nativeSubscribe(new MapManager.StorageCallback() mSubscriberSlot = MapManager.nativeSubscribe(new MapManager.StorageCallback() {
{
@Override @Override
public void onStatusChanged(List<MapManager.StorageCallbackData> data) public void onStatusChanged(List<MapManager.StorageCallbackData> data)
{ {
@@ -143,7 +139,8 @@ public class DownloaderFragment extends BaseMwmRecyclerFragment<DownloaderAdapte
} }
@Override @Override
public void onProgress(String countryId, long localSize, long remoteSize) {} public void onProgress(String countryId, long localSize, long remoteSize)
{}
}); });
SearchEngine.INSTANCE.addMapListener(mSearchListener); SearchEngine.INSTANCE.addMapListener(mSearchListener);
@@ -214,7 +211,6 @@ public class DownloaderFragment extends BaseMwmRecyclerFragment<DownloaderAdapte
return mAdapter; return mAdapter;
} }
@NonNull @NonNull
@Override @Override
public DownloaderAdapter getAdapter() public DownloaderAdapter getAdapter()
@@ -237,7 +233,8 @@ public class DownloaderFragment extends BaseMwmRecyclerFragment<DownloaderAdapte
if (mAdapter != null && mAdapter.isSearchResultsMode()) if (mAdapter != null && mAdapter.isSearchResultsMode())
placeholder.setContent(R.string.search_not_found, R.string.search_not_found_query); placeholder.setContent(R.string.search_not_found, R.string.search_not_found_query);
else else
placeholder.setContent(R.string.downloader_no_downloaded_maps_title, R.string.downloader_no_downloaded_maps_message); placeholder.setContent(R.string.downloader_no_downloaded_maps_title,
R.string.downloader_no_downloaded_maps_message);
} }
@Override @Override

View File

@@ -3,7 +3,6 @@ package app.organicmaps.downloader;
import android.content.Context; import android.content.Context;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.core.graphics.Insets; import androidx.core.graphics.Insets;
import androidx.core.view.OnApplyWindowInsetsListener; import androidx.core.view.OnApplyWindowInsetsListener;
@@ -15,7 +14,6 @@ import app.organicmaps.util.WindowInsetUtils;
final class DownloaderInsetsListener implements OnApplyWindowInsetsListener final class DownloaderInsetsListener implements OnApplyWindowInsetsListener
{ {
@NonNull @NonNull
private final Context mContext; private final Context mContext;
@NonNull @NonNull
@@ -81,11 +79,8 @@ final class DownloaderInsetsListener implements OnApplyWindowInsetsListener
{ {
int bottomInset = isAnyButtonVisible ? 0 : insets.bottom; int bottomInset = isAnyButtonVisible ? 0 : insets.bottom;
mRecyclerView.setPadding( mRecyclerView.setPadding(mRecyclerView.getPaddingLeft(), mRecyclerView.getPaddingTop(),
mRecyclerView.getPaddingLeft(), mRecyclerView.getPaddingRight(), bottomInset);
mRecyclerView.getPaddingTop(),
mRecyclerView.getPaddingRight(),
bottomInset);
final ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) mRecyclerView.getLayoutParams(); final ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) mRecyclerView.getLayoutParams();
layoutParams.rightMargin = insets.right; layoutParams.rightMargin = insets.right;

View File

@@ -8,7 +8,6 @@ import android.app.PendingIntent;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.os.Build; import android.os.Build;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.annotation.StringRes; import androidx.annotation.StringRes;
@@ -16,7 +15,6 @@ import androidx.core.app.NotificationChannelCompat;
import androidx.core.app.NotificationCompat; import androidx.core.app.NotificationCompat;
import androidx.core.app.NotificationManagerCompat; import androidx.core.app.NotificationManagerCompat;
import androidx.core.content.ContextCompat; import androidx.core.content.ContextCompat;
import app.organicmaps.MwmActivity; import app.organicmaps.MwmActivity;
import app.organicmaps.R; import app.organicmaps.R;
import app.organicmaps.sdk.downloader.MapManager; import app.organicmaps.sdk.downloader.MapManager;
@@ -41,20 +39,20 @@ public class DownloaderNotifier
public static void createNotificationChannel(@NonNull Context context) public static void createNotificationChannel(@NonNull Context context)
{ {
final NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context); final NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);
final NotificationChannelCompat channel = new NotificationChannelCompat.Builder(CHANNEL_ID, final NotificationChannelCompat channel =
NotificationManagerCompat.IMPORTANCE_LOW) new NotificationChannelCompat.Builder(CHANNEL_ID, NotificationManagerCompat.IMPORTANCE_LOW)
.setName(context.getString(R.string.notification_channel_downloader)) .setName(context.getString(R.string.notification_channel_downloader))
.setShowBadge(true) .setShowBadge(true)
.setVibrationEnabled(false) .setVibrationEnabled(false)
.setLightsEnabled(false) .setLightsEnabled(false)
.build(); .build();
notificationManager.createNotificationChannel(channel); notificationManager.createNotificationChannel(channel);
} }
public void notifyDownloadFailed(@Nullable String countryId) public void notifyDownloadFailed(@Nullable String countryId)
{ {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU && if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU
ContextCompat.checkSelfPermission(mContext, POST_NOTIFICATIONS) != PERMISSION_GRANTED) && ContextCompat.checkSelfPermission(mContext, POST_NOTIFICATIONS) != PERMISSION_GRANTED)
{ {
Logger.w(TAG, "Permission POST_NOTIFICATIONS is not granted, skipping notification"); Logger.w(TAG, "Permission POST_NOTIFICATIONS is not granted, skipping notification");
return; return;
@@ -67,37 +65,40 @@ public class DownloaderNotifier
var contentPendingIntent = getNotificationPendingIntent(countryId); var contentPendingIntent = getNotificationPendingIntent(countryId);
final Notification notification = new NotificationCompat.Builder(mContext, CHANNEL_ID) final Notification notification = new NotificationCompat.Builder(mContext, CHANNEL_ID)
.setAutoCancel(true) .setAutoCancel(true)
.setCategory(NotificationCompat.CATEGORY_ERROR) .setCategory(NotificationCompat.CATEGORY_ERROR)
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC) .setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
.setSmallIcon(R.drawable.ic_logo_small) .setSmallIcon(R.drawable.ic_logo_small)
.setColor(ContextCompat.getColor(mContext, R.color.notification)) .setColor(ContextCompat.getColor(mContext, R.color.notification))
.setContentTitle(title) .setContentTitle(title)
.setContentText(content) .setContentText(content)
.setShowWhen(true) .setShowWhen(true)
.setTicker(getTicker(mContext, title, content)) .setTicker(getTicker(mContext, title, content))
.setContentIntent(contentPendingIntent) .setContentIntent(contentPendingIntent)
.setOnlyAlertOnce(true) .setOnlyAlertOnce(true)
.build(); .build();
Logger.i(TAG, "Notifying about failed map download"); Logger.i(TAG, "Notifying about failed map download");
final NotificationManagerCompat notificationManager = NotificationManagerCompat.from(mContext); final NotificationManagerCompat notificationManager = NotificationManagerCompat.from(mContext);
notificationManager.notify(NOTIFICATION_ID, notification); notificationManager.notify(NOTIFICATION_ID, notification);
} }
public void notifyProgress() { public void notifyProgress()
{
notifyProgress(null, 0, 0); notifyProgress(null, 0, 0);
} }
public void notifyProgress(@Nullable String countryId, int maxProgress, int progress) { public void notifyProgress(@Nullable String countryId, int maxProgress, int progress)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU && {
ContextCompat.checkSelfPermission(mContext, POST_NOTIFICATIONS) != PERMISSION_GRANTED) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU
&& ContextCompat.checkSelfPermission(mContext, POST_NOTIFICATIONS) != PERMISSION_GRANTED)
{ {
Logger.w(TAG, "Permission POST_NOTIFICATIONS is not granted, skipping notification"); Logger.w(TAG, "Permission POST_NOTIFICATIONS is not granted, skipping notification");
return; return;
} }
NotificationManagerCompat.from(mContext).notify(NOTIFICATION_ID, buildProgressNotification(countryId, maxProgress, progress)); NotificationManagerCompat.from(mContext).notify(NOTIFICATION_ID,
buildProgressNotification(countryId, maxProgress, progress));
} }
@NonNull @NonNull
@@ -123,17 +124,18 @@ public class DownloaderNotifier
final String title = mContext.getString(R.string.app_name); final String title = mContext.getString(R.string.app_name);
return new NotificationCompat.Builder(mContext, CHANNEL_ID) return new NotificationCompat.Builder(mContext, CHANNEL_ID)
.setAutoCancel(true) .setAutoCancel(true)
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC) .setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
.setSmallIcon(R.drawable.ic_logo_small) .setSmallIcon(R.drawable.ic_logo_small)
.setColor(ContextCompat.getColor(mContext, R.color.notification)) .setColor(ContextCompat.getColor(mContext, R.color.notification))
.setShowWhen(true) .setShowWhen(true)
.setContentTitle(title) .setContentTitle(title)
.setContentIntent(getNotificationPendingIntent(countryId)); .setContentIntent(getNotificationPendingIntent(countryId));
} }
@NonNull @NonNull
private PendingIntent getNotificationPendingIntent(@Nullable String countryId) { private PendingIntent getNotificationPendingIntent(@Nullable String countryId)
{
final int FLAG_IMMUTABLE = Build.VERSION.SDK_INT < Build.VERSION_CODES.M ? 0 : PendingIntent.FLAG_IMMUTABLE; final int FLAG_IMMUTABLE = Build.VERSION.SDK_INT < Build.VERSION_CODES.M ? 0 : PendingIntent.FLAG_IMMUTABLE;
final Intent contentIntent = MwmActivity.createShowMapIntent(mContext, countryId); final Intent contentIntent = MwmActivity.createShowMapIntent(mContext, countryId);
contentIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); contentIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
@@ -143,8 +145,8 @@ public class DownloaderNotifier
@NonNull @NonNull
private static CharSequence getTicker(@NonNull Context context, @NonNull String title, @NonNull String content) private static CharSequence getTicker(@NonNull Context context, @NonNull String title, @NonNull String content)
{ {
@StringRes final int templateResId = StringUtils.isRtl() ? R.string.notification_ticker_rtl @StringRes
: R.string.notification_ticker_ltr; final int templateResId = StringUtils.isRtl() ? R.string.notification_ticker_rtl : R.string.notification_ticker_ltr;
return context.getString(templateResId, title, content); return context.getString(templateResId, title, content);
} }
} }

View File

@@ -9,17 +9,14 @@ import android.content.Intent;
import android.content.pm.ServiceInfo; import android.content.pm.ServiceInfo;
import android.os.Build; import android.os.Build;
import android.os.IBinder; import android.os.IBinder;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.core.app.ServiceCompat; import androidx.core.app.ServiceCompat;
import androidx.core.content.ContextCompat; import androidx.core.content.ContextCompat;
import java.util.List;
import app.organicmaps.MwmApplication; import app.organicmaps.MwmApplication;
import app.organicmaps.sdk.downloader.CountryItem; import app.organicmaps.sdk.downloader.CountryItem;
import app.organicmaps.sdk.downloader.MapManager; import app.organicmaps.sdk.downloader.MapManager;
import app.organicmaps.sdk.util.log.Logger; import app.organicmaps.sdk.util.log.Logger;
import java.util.List;
public class DownloaderService extends Service implements MapManager.StorageCallback public class DownloaderService extends Service implements MapManager.StorageCallback
{ {
@@ -54,8 +51,7 @@ public class DownloaderService extends Service implements MapManager.StorageCall
} }
catch (Exception e) catch (Exception e)
{ {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S && if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S && e instanceof ForegroundServiceStartNotAllowedException)
e instanceof ForegroundServiceStartNotAllowedException)
{ {
// App not in a valid state to start foreground service (e.g started from bg) // App not in a valid state to start foreground service (e.g started from bg)
Logger.e(TAG, "Not in a valid state to start foreground service", e); Logger.e(TAG, "Not in a valid state to start foreground service", e);
@@ -90,7 +86,8 @@ public class DownloaderService extends Service implements MapManager.StorageCall
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
{ {
stopForeground(Service.STOP_FOREGROUND_DETACH); stopForeground(Service.STOP_FOREGROUND_DETACH);
} else }
else
{ {
stopForeground(false); stopForeground(false);
} }
@@ -102,8 +99,8 @@ public class DownloaderService extends Service implements MapManager.StorageCall
@Override @Override
public void onProgress(String countryId, long localSize, long remoteSize) public void onProgress(String countryId, long localSize, long remoteSize)
{ {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU && if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU
ContextCompat.checkSelfPermission(this, POST_NOTIFICATIONS) != PERMISSION_GRANTED) && ContextCompat.checkSelfPermission(this, POST_NOTIFICATIONS) != PERMISSION_GRANTED)
{ {
Logger.w(TAG, "Permission POST_NOTIFICATIONS is not granted, skipping notification"); Logger.w(TAG, "Permission POST_NOTIFICATIONS is not granted, skipping notification");
return; return;

View File

@@ -2,17 +2,14 @@ package app.organicmaps.downloader;
import android.util.SparseIntArray; import android.util.SparseIntArray;
import android.view.View; import android.view.View;
import androidx.annotation.AttrRes; import androidx.annotation.AttrRes;
import androidx.annotation.DrawableRes; import androidx.annotation.DrawableRes;
import com.google.android.material.imageview.ShapeableImageView;
import app.organicmaps.R; import app.organicmaps.R;
import app.organicmaps.sdk.downloader.CountryItem; import app.organicmaps.sdk.downloader.CountryItem;
import app.organicmaps.widget.WheelProgressView;
import app.organicmaps.util.ThemeUtils;
import app.organicmaps.sdk.util.UiUtils; import app.organicmaps.sdk.util.UiUtils;
import app.organicmaps.util.ThemeUtils;
import app.organicmaps.widget.WheelProgressView;
import com.google.android.material.imageview.ShapeableImageView;
public class DownloaderStatusIcon public class DownloaderStatusIcon
{ {
@@ -67,8 +64,10 @@ public class DownloaderStatusIcon
protected void updateIcon(CountryItem country) protected void updateIcon(CountryItem country)
{ {
@AttrRes int iconAttr = selectIcon(country); @AttrRes
@DrawableRes int icon = resolveIcon(iconAttr); int iconAttr = selectIcon(country);
@DrawableRes
int icon = resolveIcon(iconAttr);
mIcon.setImageResource(icon); mIcon.setImageResource(icon);
} }
@@ -76,8 +75,8 @@ public class DownloaderStatusIcon
public void update(CountryItem country) public void update(CountryItem country)
{ {
boolean pending = (country.status == CountryItem.STATUS_ENQUEUED); boolean pending = (country.status == CountryItem.STATUS_ENQUEUED);
boolean inProgress = (country.status == CountryItem.STATUS_PROGRESS || boolean inProgress =
country.status == CountryItem.STATUS_APPLYING || pending); (country.status == CountryItem.STATUS_PROGRESS || country.status == CountryItem.STATUS_APPLYING || pending);
UiUtils.showIf(inProgress, mProgress); UiUtils.showIf(inProgress, mProgress);
UiUtils.showIf(!inProgress, mIcon); UiUtils.showIf(!inProgress, mIcon);

View File

@@ -4,10 +4,9 @@ import android.app.Activity;
import android.content.Intent; import android.content.Intent;
import android.text.TextUtils; import android.text.TextUtils;
import android.view.View; import android.view.View;
import app.organicmaps.R; import app.organicmaps.R;
import app.organicmaps.widget.SearchToolbarController;
import app.organicmaps.sdk.util.UiUtils; import app.organicmaps.sdk.util.UiUtils;
import app.organicmaps.widget.SearchToolbarController;
class DownloaderToolbarController extends SearchToolbarController class DownloaderToolbarController extends SearchToolbarController
{ {

View File

@@ -4,13 +4,8 @@ import android.location.Location;
import android.text.TextUtils; import android.text.TextUtils;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.core.view.ViewCompat; import androidx.core.view.ViewCompat;
import com.google.android.material.button.MaterialButton;
import com.google.android.material.textview.MaterialTextView;
import app.organicmaps.MwmActivity; import app.organicmaps.MwmActivity;
import app.organicmaps.MwmApplication; import app.organicmaps.MwmApplication;
import app.organicmaps.R; import app.organicmaps.R;
@@ -23,7 +18,8 @@ import app.organicmaps.sdk.util.StringUtils;
import app.organicmaps.sdk.util.UiUtils; import app.organicmaps.sdk.util.UiUtils;
import app.organicmaps.util.WindowInsetUtils.PaddingInsetsListener; import app.organicmaps.util.WindowInsetUtils.PaddingInsetsListener;
import app.organicmaps.widget.WheelProgressView; import app.organicmaps.widget.WheelProgressView;
import com.google.android.material.button.MaterialButton;
import com.google.android.material.textview.MaterialTextView;
import java.util.List; import java.util.List;
public class OnmapDownloader implements MwmActivity.LeftAnimationTrackListener public class OnmapDownloader implements MwmActivity.LeftAnimationTrackListener
@@ -43,8 +39,7 @@ public class OnmapDownloader implements MwmActivity.LeftAnimationTrackListener
@Nullable @Nullable
private CountryItem mCurrentCountry; private CountryItem mCurrentCountry;
private final MapManager.StorageCallback mStorageCallback = new MapManager.StorageCallback() private final MapManager.StorageCallback mStorageCallback = new MapManager.StorageCallback() {
{
@Override @Override
public void onStatusChanged(List<MapManager.StorageCallbackData> data) public void onStatusChanged(List<MapManager.StorageCallbackData> data)
{ {
@@ -80,15 +75,15 @@ public class OnmapDownloader implements MwmActivity.LeftAnimationTrackListener
} }
}; };
private final MapManager.CurrentCountryChangedListener mCountryChangedListener = new MapManager.CurrentCountryChangedListener() private final MapManager.CurrentCountryChangedListener mCountryChangedListener =
{ new MapManager.CurrentCountryChangedListener() {
@Override @Override
public void onCurrentCountryChanged(String countryId) public void onCurrentCountryChanged(String countryId)
{ {
mCurrentCountry = (TextUtils.isEmpty(countryId) ? null : CountryItem.fill(countryId)); mCurrentCountry = (TextUtils.isEmpty(countryId) ? null : CountryItem.fill(countryId));
updateState(true); updateState(true);
} }
}; };
public void updateState(boolean shouldAutoDownload) public void updateState(boolean shouldAutoDownload)
{ {
@@ -97,7 +92,8 @@ public class OnmapDownloader implements MwmActivity.LeftAnimationTrackListener
private static boolean isMapDownloading(@Nullable CountryItem country) private static boolean isMapDownloading(@Nullable CountryItem country)
{ {
if (country == null) return false; if (country == null)
return false;
boolean enqueued = country.status == CountryItem.STATUS_ENQUEUED; boolean enqueued = country.status == CountryItem.STATUS_ENQUEUED;
boolean progress = country.status == CountryItem.STATUS_PROGRESS; boolean progress = country.status == CountryItem.STATUS_PROGRESS;
@@ -112,18 +108,16 @@ public class OnmapDownloader implements MwmActivity.LeftAnimationTrackListener
private void updateStateInternal(boolean shouldAutoDownload) private void updateStateInternal(boolean shouldAutoDownload)
{ {
boolean showFrame = (mCurrentCountry != null && boolean showFrame =
!mCurrentCountry.present && (mCurrentCountry != null && !mCurrentCountry.present && !RoutingController.get().isNavigating());
!RoutingController.get().isNavigating());
if (showFrame) if (showFrame)
{ {
boolean enqueued = (mCurrentCountry.status == CountryItem.STATUS_ENQUEUED); boolean enqueued = (mCurrentCountry.status == CountryItem.STATUS_ENQUEUED);
boolean progress = (mCurrentCountry.status == CountryItem.STATUS_PROGRESS || boolean progress = (mCurrentCountry.status == CountryItem.STATUS_PROGRESS
mCurrentCountry.status == CountryItem.STATUS_APPLYING); || mCurrentCountry.status == CountryItem.STATUS_APPLYING);
boolean failed = (mCurrentCountry.status == CountryItem.STATUS_FAILED); boolean failed = (mCurrentCountry.status == CountryItem.STATUS_FAILED);
showFrame = (enqueued || progress || failed || showFrame = (enqueued || progress || failed || mCurrentCountry.status == CountryItem.STATUS_DOWNLOADABLE);
mCurrentCountry.status == CountryItem.STATUS_DOWNLOADABLE);
if (showFrame) if (showFrame)
{ {
@@ -145,7 +139,8 @@ public class OnmapDownloader implements MwmActivity.LeftAnimationTrackListener
int roundedProgress = Math.round(mCurrentCountry.progress); int roundedProgress = Math.round(mCurrentCountry.progress);
mProgress.setPending(false); mProgress.setPending(false);
mProgress.setProgress(roundedProgress); mProgress.setProgress(roundedProgress);
sizeText = mActivity.getString(R.string.downloader_downloading) + " " + StringUtils.formatPercent(roundedProgress / 100.0); sizeText = mActivity.getString(R.string.downloader_downloading) + " "
+ StringUtils.formatPercent(roundedProgress / 100.0);
} }
else else
{ {
@@ -158,26 +153,22 @@ public class OnmapDownloader implements MwmActivity.LeftAnimationTrackListener
{ {
sizeText = StringUtils.getFileSizeString(mActivity.getApplicationContext(), mCurrentCountry.totalSize); sizeText = StringUtils.getFileSizeString(mActivity.getApplicationContext(), mCurrentCountry.totalSize);
if (shouldAutoDownload && if (shouldAutoDownload && Config.isAutodownloadEnabled() && !sAutodownloadLocked && !failed
Config.isAutodownloadEnabled() && && ConnectionState.INSTANCE.isWifiConnected())
!sAutodownloadLocked &&
!failed &&
ConnectionState.INSTANCE.isWifiConnected())
{ {
Location loc = MwmApplication.from(mActivity).getLocationHelper().getSavedLocation(); Location loc = MwmApplication.from(mActivity).getLocationHelper().getSavedLocation();
if (loc != null) if (loc != null)
{ {
String country = MapManager.nativeFindCountry(loc.getLatitude(), loc.getLongitude()); String country = MapManager.nativeFindCountry(loc.getLatitude(), loc.getLongitude());
if (TextUtils.equals(mCurrentCountry.id, country) && if (TextUtils.equals(mCurrentCountry.id, country)
MapManager.nativeHasSpaceToDownloadCountry(country)) && MapManager.nativeHasSpaceToDownloadCountry(country))
{ {
MapManager.startDownload(mCurrentCountry.id); MapManager.startDownload(mCurrentCountry.id);
} }
} }
} }
mButton.setText(failed ? R.string.downloader_retry mButton.setText(failed ? R.string.downloader_retry : R.string.download);
: R.string.download);
} }
} }
@@ -207,37 +198,39 @@ public class OnmapDownloader implements MwmActivity.LeftAnimationTrackListener
MapManager.nativeCancel(mCurrentCountry.id); MapManager.nativeCancel(mCurrentCountry.id);
setAutodownloadLocked(true); setAutodownloadLocked(true);
}); });
mButton.setOnClickListener(v -> MapManager.warnOn3g(mActivity, mCurrentCountry == null ? null : mButton.setOnClickListener(
mCurrentCountry.id, () -> { v -> MapManager.warnOn3g(mActivity, mCurrentCountry == null ? null : mCurrentCountry.id, () -> {
if (mCurrentCountry == null) if (mCurrentCountry == null)
return; return;
boolean retry = (mCurrentCountry.status == CountryItem.STATUS_FAILED); boolean retry = (mCurrentCountry.status == CountryItem.STATUS_FAILED);
if (retry) if (retry)
{ {
MapManager.retryDownload(mCurrentCountry.id); MapManager.retryDownload(mCurrentCountry.id);
} }
else else
{ {
MapManager.startDownload(mCurrentCountry.id); MapManager.startDownload(mCurrentCountry.id);
mActivity.requestPostNotificationsPermission(); mActivity.requestPostNotificationsPermission();
} }
})); }));
ViewCompat.setOnApplyWindowInsetsListener(mFrame, PaddingInsetsListener.allSides()); ViewCompat.setOnApplyWindowInsetsListener(mFrame, PaddingInsetsListener.allSides());
} }
@Override @Override
public void onTrackStarted(boolean collapsed) {} public void onTrackStarted(boolean collapsed)
{}
@Override @Override
public void onTrackFinished(boolean collapsed) {} public void onTrackFinished(boolean collapsed)
{}
@Override @Override
public void onTrackLeftAnimation(float offset) public void onTrackLeftAnimation(float offset)
{ {
ViewGroup.MarginLayoutParams lp = (ViewGroup.MarginLayoutParams)mFrame.getLayoutParams(); ViewGroup.MarginLayoutParams lp = (ViewGroup.MarginLayoutParams) mFrame.getLayoutParams();
lp.leftMargin = (int)offset; lp.leftMargin = (int) offset;
mFrame.setLayoutParams(lp); mFrame.setLayoutParams(lp);
} }

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