Merge pull request #10952 from osmandapp/master

update test branch
This commit is contained in:
Hardy 2021-02-20 00:04:14 +01:00 committed by GitHub
commit 1a4a5509a6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
37 changed files with 620 additions and 338 deletions

View file

@ -620,9 +620,7 @@ public class GeneralRouter implements VehicleRouter {
public double calculateTurnTime(RouteSegment segment, int segmentEnd, RouteSegment prev, int prevSegmentEnd) {
float ts = getPenaltyTransition(segment.getRoad());
float prevTs = getPenaltyTransition(prev.getRoad());
float totalPenalty = 0;
if (prevTs != ts) {
totalPenalty += Math.abs(ts - prevTs) / 2;
}
@ -638,7 +636,9 @@ public class GeneralRouter implements VehicleRouter {
// }
// }
// }
if (shortestRoute) {
return totalPenalty;
}
if(segment.getRoad().roundabout() && !prev.getRoad().roundabout()) {
double rt = getRoundaboutTurn();
if(rt > 0) {

View file

@ -4,7 +4,7 @@ import android.annotation.SuppressLint
import android.content.Context
import android.hardware.*
import android.location.Location
import android.os.Looper
import android.os.HandlerThread
import android.util.Log
import com.google.android.gms.location.*
import net.osmand.PlatformUtil
@ -43,11 +43,12 @@ class TelegramLocationProvider(private val app: TelegramApplication) : SensorEve
var lastKnownLocation: net.osmand.Location? = null
private set
private val locationUpdateHandlerThread = HandlerThread("LocationProviderUpdateHandlerThread")
private var fusedLocationProviderClient: FusedLocationProviderClient? = null
private val locationRequest = LocationRequest().apply {
interval = 1000
fastestInterval = 500
maxWaitTime = 2000
//fastestInterval = 500
maxWaitTime = 0
priority = LocationRequest.PRIORITY_HIGH_ACCURACY
}
private val locationCallback = object : LocationCallback() {
@ -81,6 +82,10 @@ class TelegramLocationProvider(private val app: TelegramApplication) : SensorEve
fun updateCompassValue(value: Float)
}
init {
locationUpdateHandlerThread.start()
}
@SuppressLint("MissingPermission")
fun resumeAllUpdates() {
if (AndroidUtils.isLocationPermissionAvailable(app) && fusedLocationProviderClient == null) {
@ -89,7 +94,7 @@ class TelegramLocationProvider(private val app: TelegramApplication) : SensorEve
try {
fusedLocationProviderClient?.requestLocationUpdates(
locationRequest, locationCallback, Looper.myLooper())
locationRequest, locationCallback, locationUpdateHandlerThread.looper)
} catch (unlikely: SecurityException) {
Log.d(PlatformUtil.TAG, "Lost location permissions. Couldn't request updates. $unlikely")
}

View file

@ -38,6 +38,7 @@ class TelegramService : Service(), TelegramIncomingMessagesListener,
private var updateWidgetHandler: Handler? = null
private var updateWidgetThread = HandlerThread("WidgetUpdateServiceThread")
private var locationUpdateHandlerThread = HandlerThread("LocationUpdateServiceThread")
// FusedLocationProviderClient - Main class for receiving location updates.
private lateinit var fusedLocationProviderClient: FusedLocationProviderClient
@ -62,6 +63,7 @@ class TelegramService : Service(), TelegramIncomingMessagesListener,
mHandlerThread.start()
tracksHandlerThread.start()
updateWidgetThread.start()
locationUpdateHandlerThread.start()
updateShareInfoHandler = Handler(mHandlerThread.looper)
updateTracksHandler = Handler(tracksHandlerThread.looper)
updateWidgetHandler = Handler(updateWidgetThread.looper)
@ -82,11 +84,11 @@ class TelegramService : Service(), TelegramIncomingMessagesListener,
// Sets the fastest rate for active location updates. This interval is exact, and your
// application will never receive updates more frequently than this value.
fastestInterval = 500
//fastestInterval = 500
// Sets the maximum time when batched location updates are delivered. Updates may be
// delivered sooner than this interval.
maxWaitTime = 2000
maxWaitTime = 0
priority = LocationRequest.PRIORITY_HIGH_ACCURACY
}
@ -166,6 +168,7 @@ class TelegramService : Service(), TelegramIncomingMessagesListener,
tracksHandlerThread.quit()
mHandlerThread.quit()
updateWidgetThread.quit()
locationUpdateHandlerThread.quit()
app().showLocationHelper.addOrUpdateStatusWidget(-1, false)
usedBy = 0
@ -198,7 +201,7 @@ class TelegramService : Service(), TelegramIncomingMessagesListener,
// request location updates
try {
fusedLocationProviderClient.requestLocationUpdates(
locationRequest, locationCallback, Looper.myLooper())
locationRequest, locationCallback, locationUpdateHandlerThread.looper)
} catch (unlikely: SecurityException) {
Toast.makeText(this, R.string.no_location_permission, Toast.LENGTH_LONG).show()
Log.d(PlatformUtil.TAG, "Lost location permissions. Couldn't request updates. $unlikely")

Binary file not shown.

View file

@ -109,4 +109,5 @@
<asset source="sounds/camera_click.ogg" destination="sounds/camera_click.ogg" mode="copyOnlyIfDoesNotExist" />
<asset source="World_basemap_mini.obf" destination="World_basemap_mini.obf" mode="alwaysOverwriteOrCopy" />
<asset source="Default_wikivoyage.travel.obf" destination="travel/Default_wikivoyage.travel.obf" mode="copyOnlyIfDoesNotExist" />
</assets>

View file

@ -36,9 +36,9 @@ android {
defaultConfig {
minSdkVersion System.getenv("MIN_SDK_VERSION") ? System.getenv("MIN_SDK_VERSION").toInteger() : 15
versionCode 400
versionCode 390
versionCode System.getenv("APK_NUMBER_VERSION") ? System.getenv("APK_NUMBER_VERSION").toInteger() : versionCode
versionName "4.0.0"
versionName "3.9.0"
versionName System.getenv("APK_VERSION")? System.getenv("APK_VERSION").toString(): versionName
versionName System.getenv("APK_VERSION_SUFFIX")? versionName + System.getenv("APK_VERSION_SUFFIX").toString(): versionName
}

View file

@ -12,6 +12,7 @@
android:clickable="true"
android:focusable="true"
android:gravity="center_vertical"
android:minHeight="@dimen/bottom_sheet_list_item_height"
android:orientation="horizontal"
android:paddingStart="@dimen/content_padding_small"
android:paddingLeft="@dimen/content_padding_small"
@ -34,7 +35,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:duplicateParentState="true"
android:letterSpacing="@dimen/description_letter_spacing"
android:letterSpacing="@dimen/text_button_letter_spacing"
android:textSize="@dimen/default_desc_text_size"
osmand:typeface="@string/font_roboto_medium"
tools:text="Title"
@ -45,7 +46,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:duplicateParentState="true"
android:letterSpacing="@dimen/description_letter_spacing"
android:letterSpacing="@dimen/text_button_letter_spacing"
android:textSize="@dimen/default_desc_text_size"
android:visibility="gone"
osmand:typeface="@string/font_roboto_medium"

View file

@ -78,20 +78,20 @@
<Button
android:id="@+id/button_action"
android:layout_width="wrap_content"
android:layout_height="33dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginLeft="@dimen/content_padding"
android:layout_marginStart="@dimen/content_padding"
android:background="@drawable/buy_btn_background_light"
android:minWidth="40dp"
android:paddingLeft="18dp"
android:paddingRight="18dp"
android:minWidth="@dimen/list_header_height"
android:minHeight="@dimen/list_content_padding_large"
android:paddingLeft="@dimen/bottom_sheet_exit_button_margin"
android:paddingRight="@dimen/bottom_sheet_exit_button_margin"
android:text="@string/get_plugin"
android:textColor="@color/buy_button_color"
android:textColor="@color/text_color_tab_active_light"
android:visibility="gone"
tools:visibility="visible"
android:paddingEnd="18dp"
android:paddingStart="18dp" />
android:paddingEnd="@dimen/bottom_sheet_exit_button_margin"
android:paddingStart="@dimen/bottom_sheet_exit_button_margin" />
</LinearLayout>

View file

@ -102,6 +102,19 @@
android:layout_marginRight="@dimen/content_padding"
android:layout_marginBottom="@dimen/content_padding" />
<include
android:id="@+id/button_online"
layout="@layout/bottom_sheet_button_with_icon"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/content_padding"
android:layout_marginLeft="@dimen/content_padding"
android:layout_marginTop="@dimen/content_padding_half"
android:layout_marginEnd="@dimen/content_padding"
android:layout_marginRight="@dimen/content_padding"
android:layout_marginBottom="@dimen/content_padding"
android:visibility="gone" />
<include
android:id="@+id/button_segment"
layout="@layout/bottom_sheet_button_with_icon"

View file

@ -94,13 +94,13 @@
android:layout_marginRight="@dimen/list_header_padding"
android:minWidth="@dimen/list_header_height"
android:minHeight="@dimen/list_content_padding_large"
android:paddingStart="@dimen/context_menu_progress_padding_left"
android:paddingLeft="@dimen/context_menu_progress_padding_left"
android:paddingEnd="@dimen/context_menu_progress_padding_left"
android:paddingRight="@dimen/context_menu_progress_padding_left"
android:paddingStart="@dimen/bottom_sheet_exit_button_margin"
android:paddingLeft="@dimen/bottom_sheet_exit_button_margin"
android:paddingEnd="@dimen/bottom_sheet_exit_button_margin"
android:paddingRight="@dimen/bottom_sheet_exit_button_margin"
android:text="@string/buy"
android:textColor="@color/text_color_tab_active_light"
android:visibility="gone" />
android:visibility="visible" />
</LinearLayout>

View file

@ -13,6 +13,12 @@
android:icon="@drawable/ic_map"
android:title="@string/shared_string_maps"/>
<Preference
android:key="travel_memory_used"
android:layout="@layout/data_storage_memory_used_item"
android:icon="@drawable/ic_action_wikipedia"
android:title="@string/wikivoyage_travel_guide"/>
<Preference
android:key="terrain_memory_used"
android:layout="@layout/data_storage_memory_used_item"

View file

@ -1,6 +1,7 @@
package net.osmand.plus;
import android.location.Location;
import android.os.HandlerThread;
import android.os.Looper;
import androidx.annotation.NonNull;
@ -32,6 +33,8 @@ public class LocationServiceHelperImpl extends LocationServiceHelper {
private final OsmandApplication app;
private final HandlerThread mHandlerThread = new HandlerThread("LocationServiceHelperThread");
// FusedLocationProviderClient - Main class for receiving location updates.
private final FusedLocationProviderClient fusedLocationProviderClient;
@ -46,6 +49,7 @@ public class LocationServiceHelperImpl extends LocationServiceHelper {
public LocationServiceHelperImpl(@NonNull OsmandApplication app) {
this.app = app;
mHandlerThread.start();
fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(app);
@ -100,7 +104,7 @@ public class LocationServiceHelperImpl extends LocationServiceHelper {
// request location updates
try {
fusedLocationProviderClient.requestLocationUpdates(
fusedLocationRequest, fusedLocationCallback, Looper.myLooper());
fusedLocationRequest, fusedLocationCallback, mHandlerThread.getLooper());
} catch (SecurityException e) {
LOG.debug("Location service permission not granted");
throw e;

View file

@ -66,6 +66,8 @@ import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import net.osmand.util.Algorithms;
import org.apache.commons.logging.Log;
import java.io.File;
import java.lang.reflect.Field;
import java.text.MessageFormat;
@ -84,6 +86,7 @@ import static android.util.TypedValue.COMPLEX_UNIT_DIP;
import static android.util.TypedValue.COMPLEX_UNIT_SP;
public class AndroidUtils {
private static final Log LOG = PlatformUtil.getLog(AndroidUtils.class);
public static final String STRING_PLACEHOLDER = "%s";
public static final MessageFormat formatKb = new MessageFormat("{0, number,##.#}", Locale.US);
@ -804,16 +807,24 @@ public class AndroidUtils {
public static long getAvailableSpace(@Nullable File dir) {
if (dir != null && dir.canRead()) {
StatFs fs = new StatFs(dir.getAbsolutePath());
return fs.getAvailableBlocksLong() * fs.getBlockSize();
try {
StatFs fs = new StatFs(dir.getAbsolutePath());
return fs.getAvailableBlocksLong() * fs.getBlockSize();
} catch (IllegalArgumentException e) {
LOG.error(e);
}
}
return -1;
}
public static float getFreeSpaceGb(File dir) {
if (dir.canRead()) {
StatFs fs = new StatFs(dir.getAbsolutePath());
return (float) (fs.getBlockSize()) * fs.getAvailableBlocks() / (1 << 30);
try {
StatFs fs = new StatFs(dir.getAbsolutePath());
return (float) (fs.getBlockSize()) * fs.getAvailableBlocks() / (1 << 30);
} catch (IllegalArgumentException e) {
LOG.error(e);
}
}
return -1;
}

View file

@ -11,6 +11,8 @@ import com.squareup.picasso.Picasso;
import net.osmand.plus.OsmandApplication;
import org.apache.commons.logging.Log;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
@ -23,6 +25,7 @@ import static android.os.Build.VERSION.SDK_INT;
import static android.os.Build.VERSION_CODES.JELLY_BEAN_MR2;
public class PicassoUtils {
private static final Log LOG = PlatformUtil.getLog(PicassoUtils.class);
private static final String PICASSO_CACHE = "picasso-cache";
private static final int MIN_DISK_CACHE_SIZE = 5 * 1024 * 1024; // 5MB
@ -109,7 +112,8 @@ public class PicassoUtils {
long available = blockCount * blockSize;
// Target 2% of the total space.
size = available / 50;
} catch (IllegalArgumentException ignored) {
} catch (IllegalArgumentException e) {
LOG.error(e);
}
// Bound inside min/max size for disk cache.

View file

@ -89,7 +89,7 @@ public class FavoritesTreeFragment extends OsmandExpandableListFragment implemen
public static final int IMPORT_FAVOURITES_ID = 7;
public static final String GROUP_EXPANDED_POSTFIX = "_group_expanded";
private static final int MAX_POINTS_IN_DESCRIPTION = 100;
private static final int MAX_CHARS_IN_DESCRIPTION = 100000;
private FavouritesAdapter favouritesAdapter;
private FavouritesDbHelper helper;
@ -611,37 +611,53 @@ public class FavoritesTreeFragment extends OsmandExpandableListFragment implemen
private String generateHtmlPrint(List<FavoriteGroup> groups) {
StringBuilder html = new StringBuilder();
StringBuilder buffer = new StringBuilder();
html.append("<h1>My Favorites</h1>");
int addedPoints = 0;
for (FavoriteGroup group : groups) {
html.append("<h3>").append(group.getDisplayName(app)).append("</h3>");
for (FavouritePoint fp : group.getPoints()) {
if (addedPoints >= MAX_POINTS_IN_DESCRIPTION) {
break;
}
float lat = (float) fp.getLatitude();
float lon = (float) fp.getLongitude();
String url = "geo:" + lat + "," + lon + "?m=" + fp.getName();
html.append("<p>")
.append(fp.getDisplayName(app))
.append(" - <a href=\"")
.append(url)
.append("\">geo:")
.append(lat).append(",").append(lon)
.append("</a><br></p>");
addedPoints++;
buffer.setLength(0);
buffer.append("<h3>").append(group.getDisplayName(app)).append("</h3>");
if (buffer.length() + html.length() > MAX_CHARS_IN_DESCRIPTION) {
return html.append("<p>...</p>").toString();
}
if (addedPoints >= MAX_POINTS_IN_DESCRIPTION) {
html.append("<p>...</p>");
break;
html.append(buffer);
boolean reachedLimit = generateHtmlForGroup(group.getPoints(), html);
if (reachedLimit) {
return html.append("<p>...</p>").toString();
}
}
return html.toString();
}
private boolean generateHtmlForGroup(List<FavouritePoint> points, StringBuilder html) {
StringBuilder buffer = new StringBuilder();
for (FavouritePoint fp : points) {
buffer.setLength(0);
float lat = (float) fp.getLatitude();
float lon = (float) fp.getLongitude();
String url = "geo:" + lat + "," + lon + "?m=" + fp.getName();
buffer.append("<p>")
.append(fp.getDisplayName(app))
.append(" - <a href=\"")
.append(url)
.append("\">geo:")
.append(lat).append(",").append(lon)
.append("</a><br></p>");
if (buffer.length() + html.length() > MAX_CHARS_IN_DESCRIPTION) {
return true;
}
html.append(buffer);
}
return false;
}
private void shareFavourites() {
if (favouritesAdapter.isEmpty()) {
Toast.makeText(getActivity(), R.string.no_fav_to_save, Toast.LENGTH_LONG).show();

View file

@ -384,8 +384,12 @@ public class MultimediaNotesFragment extends BaseSettingsFragment implements Cop
File dir = app.getAppPath("").getParentFile();
long size = 0;
if (dir.canRead()) {
StatFs fs = new StatFs(dir.getAbsolutePath());
size = ((long) fs.getBlockSize() * (long) fs.getBlockCount()) / (1 << 30);
try {
StatFs fs = new StatFs(dir.getAbsolutePath());
size = ((long) fs.getBlockSize() * (long) fs.getBlockCount()) / (1 << 30);
} catch (IllegalArgumentException e) {
log.error(e);
}
}
if (size > 0) {
int value = 1;

View file

@ -31,6 +31,7 @@ import androidx.fragment.app.FragmentActivity;
import net.osmand.AndroidUtils;
import net.osmand.FileUtils;
import net.osmand.PlatformUtil;
import net.osmand.ValueHolder;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.settings.backend.OsmandSettings;
@ -39,6 +40,8 @@ import net.osmand.plus.R;
import net.osmand.plus.download.DownloadActivity;
import net.osmand.util.Algorithms;
import org.apache.commons.logging.Log;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
@ -52,7 +55,7 @@ import java.util.Locale;
import gnu.trove.list.array.TIntArrayList;
public class DashChooseAppDirFragment {
private static final Log LOG = PlatformUtil.getLog(DashChooseAppDirFragment.class);
public static class ChooseAppDirFragment {
public static final int VERSION_DEFAULTLOCATION_CHANGED = 19;
@ -92,8 +95,12 @@ public class DashChooseAppDirFragment {
private String getFreeSpace(File dir) {
if (dir.canRead()) {
StatFs fs = new StatFs(dir.getAbsolutePath());
return AndroidUtils.formatSize(activity, (long) fs.getAvailableBlocks() * fs.getBlockSize() );
try {
StatFs fs = new StatFs(dir.getAbsolutePath());
return AndroidUtils.formatSize(activity, (long) fs.getAvailableBlocks() * fs.getBlockSize());
} catch (IllegalArgumentException e) {
LOG.error(e);
}
}
return "";
}

View file

@ -22,6 +22,8 @@ import android.widget.ProgressBar;
import android.widget.Space;
import android.widget.TextView;
import com.ibm.icu.impl.IllegalIcuArgumentException;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.UiThread;
@ -653,9 +655,13 @@ public class DownloadActivity extends AbstractDownloadActivity implements Downlo
String size = "";
int percent = 0;
if (dir.canRead()) {
StatFs fs = new StatFs(dir.getAbsolutePath());
size = AndroidUtils.formatSize(activity, ((long) fs.getAvailableBlocks()) * fs.getBlockSize());
percent = 100 - (int) ((long) fs.getAvailableBlocks() * 100 / fs.getBlockCount());
try {
StatFs fs = new StatFs(dir.getAbsolutePath());
size = AndroidUtils.formatSize(activity, ((long) fs.getAvailableBlocks()) * fs.getBlockSize());
percent = 100 - (int) ((long) fs.getAvailableBlocks() * 100 / fs.getBlockCount());
} catch (IllegalIcuArgumentException e) {
LOG.error(e);
}
}
sizeProgress.setIndeterminate(false);
sizeProgress.setProgress(percent);

View file

@ -304,8 +304,12 @@ public class DownloadIndexesThread {
File dir = app.getAppPath("").getParentFile();
double asz = -1;
if (dir.canRead()) {
StatFs fs = new StatFs(dir.getAbsolutePath());
asz = (((long) fs.getAvailableBlocks()) * fs.getBlockSize()) / (1 << 20);
try {
StatFs fs = new StatFs(dir.getAbsolutePath());
asz = (((long) fs.getAvailableBlocks()) * fs.getBlockSize()) / (1 << 20);
} catch (IllegalArgumentException e) {
LOG.error(e);
}
}
return asz;
}

View file

@ -50,10 +50,10 @@ public class DownloadResources extends DownloadResourceGroup {
public static final String WORLD_SEAMARKS_NAME = "World_seamarks";
public static final String WORLD_SEAMARKS_OLD_KEY = "world_seamarks_basemap";
public static final String WORLD_SEAMARKS_OLD_NAME = "World_seamarks_basemap";
public static final String WIKIVOYAGE_FILE_FILTER = "wikivoyage";
private static final Log LOG = PlatformUtil.getLog(DownloadResources.class);
public DownloadResources(OsmandApplication app) {
super(null, DownloadResourceGroupType.WORLD, "");
this.region = app.getRegions().getWorldRegion();
@ -369,7 +369,9 @@ public class DownloadResources extends DownloadResourceGroup {
continue;
}
if (ii.getType() == DownloadActivityType.TRAVEL_FILE) {
wikivoyageMaps.addItem(ii);
if (ii.getFileName().contains(WIKIVOYAGE_FILE_FILTER)) {
wikivoyageMaps.addItem(ii);
}
continue;
}
String basename = ii.getBasename().toLowerCase();

View file

@ -17,12 +17,15 @@ import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import com.ibm.icu.impl.IllegalIcuArgumentException;
import androidx.annotation.NonNull;
import androidx.fragment.app.FragmentManager;
import net.osmand.AndroidUtils;
import net.osmand.FileUtils;
import net.osmand.IProgress;
import net.osmand.PlatformUtil;
import net.osmand.plus.OnDismissDialogFragmentListener;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.settings.backend.OsmandSettings;
@ -32,9 +35,12 @@ import net.osmand.plus.dashboard.DashChooseAppDirFragment;
import net.osmand.plus.download.DownloadActivity;
import net.osmand.plus.download.DownloadIndexesThread;
import org.apache.commons.logging.Log;
import java.io.File;
public class DataStoragePlaceDialogFragment extends BottomSheetDialogFragment {
private static final Log LOG = PlatformUtil.getLog(DataStoragePlaceDialogFragment.class);
public static final String TAG = "DataStoragePlaceDialogFragment";
private static final String STORAGE_READOLNY_KEY = "storage_readolny_key";
@ -189,11 +195,15 @@ public class DataStoragePlaceDialogFragment extends BottomSheetDialogFragment {
private String getFreeSpace(File dir) {
String sz = "";
if (dir != null && dir.canRead()) {
StatFs fs = new StatFs(dir.getAbsolutePath());
@SuppressWarnings("deprecation")
long size = (long) fs.getAvailableBlocks() * fs.getBlockSize();
if (size > 0) {
sz = AndroidUtils.formatSize(getActivity(), size);
try {
StatFs fs = new StatFs(dir.getAbsolutePath());
@SuppressWarnings("deprecation")
long size = (long) fs.getAvailableBlocks() * fs.getBlockSize();
if (size > 0) {
sz = AndroidUtils.formatSize(getActivity(), size);
}
} catch (IllegalIcuArgumentException e) {
LOG.error(e);
}
}
return sz;

View file

@ -335,7 +335,8 @@ public class ItemViewHolder {
clickAction = RightButtonAction.ASK_FOR_SRTM_PLUGIN_ENABLE;
}
} else if (item.getType() == DownloadActivityType.WIKIPEDIA_FILE
} else if ((item.getType() == DownloadActivityType.WIKIPEDIA_FILE
|| item.getType() == DownloadActivityType.TRAVEL_FILE)
&& !Version.isPaidVersion(context.getMyApplication())) {
clickAction = RightButtonAction.ASK_FOR_FULL_VERSION_PURCHASE;
} else if (item.getType() == DownloadActivityType.DEPTH_CONTOUR_FILE && !depthContoursPurchased) {

View file

@ -26,6 +26,7 @@ import androidx.fragment.app.FragmentActivity;
import net.osmand.AndroidNetworkUtils;
import net.osmand.AndroidUtils;
import net.osmand.Location;
import net.osmand.PlatformUtil;
import net.osmand.ValueHolder;
import net.osmand.binary.BinaryMapDataObject;
import net.osmand.data.LatLon;
@ -67,6 +68,8 @@ import java.util.TimerTask;
public class FirstUsageWizardFragment extends BaseOsmAndFragment implements OsmAndLocationListener,
AppInitializeListener, DownloadEvents {
private static final org.apache.commons.logging.Log LOG = PlatformUtil.getLog(FirstUsageWizardFragment.class);
public static final String TAG = "FirstUsageWizardFrag";
public static final int FIRST_USAGE_LOCATION_PERMISSION = 300;
public static final int FIRST_USAGE_REQUEST_WRITE_EXTERNAL_STORAGE_PERMISSION = 400;
@ -736,8 +739,12 @@ public class FirstUsageWizardFragment extends BaseOsmAndFragment implements OsmA
private String getFreeSpace(File dir) {
if (dir.canRead()) {
StatFs fs = new StatFs(dir.getAbsolutePath());
return AndroidUtils.formatSize(getActivity(), (long) fs.getAvailableBlocks() * fs.getBlockSize() );
try {
StatFs fs = new StatFs(dir.getAbsolutePath());
return AndroidUtils.formatSize(getActivity(), (long) fs.getAvailableBlocks() * fs.getBlockSize());
} catch (IllegalArgumentException e) {
LOG.error(e);
}
}
return "";
}

View file

@ -23,12 +23,23 @@ public class ClearRecordedDataBottomSheetFragment extends MenuBottomSheetDialogF
private OsmandApplication app;
public static void showInstance(@NonNull FragmentManager fragmentManager, @NonNull Fragment target) {
if (!fragmentManager.isStateSaved()) {
ClearRecordedDataBottomSheetFragment fragment = new ClearRecordedDataBottomSheetFragment();
fragment.setTargetFragment(target, 0);
fragment.show(fragmentManager, TAG);
}
}
@Override
public void createMenuItems(Bundle savedInstanceState) {
app = requiredMyApplication();
LayoutInflater inflater = UiUtilities.getInflater(app, nightMode);
int verticalBig = getResources().getDimensionPixelSize(R.dimen.dialog_content_margin);
int verticalSmall = getResources().getDimensionPixelSize(R.dimen.content_padding_small);
int verticalNormal = getResources().getDimensionPixelSize(R.dimen.content_padding);
final View buttonClear = createItem(inflater, ItemType.CLEAR_DATA);
final View buttonCancel = createItem(inflater, ItemType.CANCEL);
items.add(new BottomSheetItemWithDescription.Builder()
.setDescription(app.getString(R.string.clear_recorded_data_warning))
@ -41,7 +52,7 @@ public class ClearRecordedDataBottomSheetFragment extends MenuBottomSheetDialogF
items.add(new DividerSpaceItem(app, verticalBig));
items.add(new BaseBottomSheetItem.Builder()
.setCustomView(TripRecordingActiveBottomSheet.createButton(inflater, ItemType.CLEAR_DATA, nightMode))
.setCustomView(buttonClear)
.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
@ -54,7 +65,7 @@ public class ClearRecordedDataBottomSheetFragment extends MenuBottomSheetDialogF
items.add(new DividerSpaceItem(app, verticalBig));
items.add(new BaseBottomSheetItem.Builder()
.setCustomView(TripRecordingActiveBottomSheet.createButton(inflater, ItemType.CANCEL, nightMode))
.setCustomView(buttonCancel)
.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
@ -63,7 +74,11 @@ public class ClearRecordedDataBottomSheetFragment extends MenuBottomSheetDialogF
})
.create());
items.add(new DividerSpaceItem(app, verticalSmall));
items.add(new DividerSpaceItem(app, verticalNormal));
}
private View createItem(LayoutInflater inflater, ItemType type) {
return TripRecordingActiveBottomSheet.createItem(app, nightMode, inflater, type);
}
@Override
@ -88,12 +103,4 @@ public class ClearRecordedDataBottomSheetFragment extends MenuBottomSheetDialogF
protected boolean hideButtonsContainer() {
return true;
}
public static void showInstance(@NonNull FragmentManager fragmentManager, @NonNull Fragment target) {
if (!fragmentManager.isStateSaved()) {
ClearRecordedDataBottomSheetFragment fragment = new ClearRecordedDataBottomSheetFragment();
fragment.setTargetFragment(target, 0);
fragment.show(fragmentManager, TAG);
}
}
}

View file

@ -34,6 +34,15 @@ public class StopTrackRecordingBottomFragment extends MenuBottomSheetDialogFragm
this.mapActivity = mapActivity;
}
public static void showInstance(MapActivity mapActivity, @NonNull FragmentManager fragmentManager, @NonNull Fragment target) {
if (!fragmentManager.isStateSaved()) {
StopTrackRecordingBottomFragment fragment = new StopTrackRecordingBottomFragment();
fragment.setMapActivity(mapActivity);
fragment.setTargetFragment(target, 0);
fragment.show(fragmentManager, TAG);
}
}
@Override
public void createMenuItems(Bundle savedInstanceState) {
app = requiredMyApplication();
@ -41,7 +50,11 @@ public class StopTrackRecordingBottomFragment extends MenuBottomSheetDialogFragm
plugin = OsmandPlugin.getPlugin(OsmandMonitoringPlugin.class);
LayoutInflater inflater = UiUtilities.getInflater(app, nightMode);
int verticalBig = getResources().getDimensionPixelSize(R.dimen.dialog_content_margin);
int verticalSmall = getResources().getDimensionPixelSize(R.dimen.content_padding_small);
int verticalNormal = getResources().getDimensionPixelSize(R.dimen.content_padding);
// final View buttonDiscard = createItem(inflater, ItemType.STOP_AND_DISCARD);
final View buttonSave = createItem(inflater, ItemType.STOP_AND_SAVE);
final View buttonCancel = createItem(inflater, ItemType.CANCEL);
items.add(new BottomSheetItemWithDescription.Builder()
.setDescription(app.getString(R.string.track_recording_description))
@ -53,12 +66,12 @@ public class StopTrackRecordingBottomFragment extends MenuBottomSheetDialogFragm
items.add(new DividerSpaceItem(app, verticalBig));
items.add(new BaseBottomSheetItem.Builder()
.setCustomView(TripRecordingActiveBottomSheet.createButton(inflater, ItemType.STOP_AND_DISCARD, nightMode))
/*items.add(new BaseBottomSheetItem.Builder()
.setCustomView(buttonDiscard)
.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
tag = ItemType.STOP_AND_DISCARD;
tag = (ItemType) buttonDiscard.getTag();
if (plugin != null && settings.SAVE_GLOBAL_TRACK_TO_GPX.get()) {
plugin.stopRecording();
app.getNotificationHelper().refreshNotifications();
@ -69,14 +82,14 @@ public class StopTrackRecordingBottomFragment extends MenuBottomSheetDialogFragm
})
.create());
items.add(new DividerSpaceItem(app, verticalBig));
items.add(new DividerSpaceItem(app, verticalBig));*/
items.add(new BaseBottomSheetItem.Builder()
.setCustomView(TripRecordingActiveBottomSheet.createButton(inflater, ItemType.SAVE_AND_STOP, nightMode))
.setCustomView(buttonSave)
.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
tag = ItemType.SAVE_AND_STOP;
tag = (ItemType) buttonSave.getTag();
if (plugin != null && settings.SAVE_GLOBAL_TRACK_TO_GPX.get()) {
plugin.saveCurrentTrack(null, mapActivity);
app.getNotificationHelper().refreshNotifications();
@ -86,20 +99,24 @@ public class StopTrackRecordingBottomFragment extends MenuBottomSheetDialogFragm
})
.create());
items.add(new DividerSpaceItem(app, verticalSmall));
items.add(new DividerSpaceItem(app, verticalNormal));
items.add(new BaseBottomSheetItem.Builder()
.setCustomView(TripRecordingActiveBottomSheet.createButton(inflater, ItemType.CANCEL, nightMode))
.setCustomView(buttonCancel)
.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
tag = ItemType.CANCEL;
tag = (ItemType) buttonCancel.getTag();
dismiss();
}
})
.create());
items.add(new DividerSpaceItem(app, verticalSmall));
items.add(new DividerSpaceItem(app, verticalNormal));
}
private View createItem(LayoutInflater inflater, ItemType type) {
return TripRecordingActiveBottomSheet.createItem(app, nightMode, inflater, type);
}
@Override
@ -114,10 +131,13 @@ public class StopTrackRecordingBottomFragment extends MenuBottomSheetDialogFragm
@Override
public void onPause() {
super.onPause();
if (tag == ItemType.CANCEL) {
Fragment target = getTargetFragment();
if (target instanceof TripRecordingActiveBottomSheet) {
((TripRecordingActiveBottomSheet) target).show();
Fragment target = getTargetFragment();
if (target instanceof TripRecordingActiveBottomSheet) {
TripRecordingActiveBottomSheet tripRec = (TripRecordingActiveBottomSheet) target;
if (tag == ItemType.CANCEL) {
tripRec.show();
} else {
tripRec.dismiss();
}
}
}
@ -126,13 +146,4 @@ public class StopTrackRecordingBottomFragment extends MenuBottomSheetDialogFragm
protected boolean hideButtonsContainer() {
return true;
}
public static void showInstance(MapActivity mapActivity, @NonNull FragmentManager fragmentManager, @NonNull Fragment target) {
if (!fragmentManager.isStateSaved()) {
StopTrackRecordingBottomFragment fragment = new StopTrackRecordingBottomFragment();
fragment.setMapActivity(mapActivity);
fragment.setTargetFragment(target, 0);
fragment.show(fragmentManager, TAG);
}
}
}

View file

@ -43,7 +43,6 @@ import net.osmand.plus.GpxSelectionHelper.SelectedGpxFile;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import net.osmand.plus.UiUtilities;
import net.osmand.plus.UiUtilities.DialogButtonType;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.activities.SavingTrackHelper;
import net.osmand.plus.activities.SavingTrackHelper.SaveGpxResult;
@ -62,6 +61,8 @@ import net.osmand.util.Algorithms;
import org.apache.commons.logging.Log;
import java.lang.ref.WeakReference;
import java.util.Arrays;
import java.util.List;
import static net.osmand.plus.UiUtilities.CompoundButtonType.PROFILE_DEPENDENT;
@ -79,6 +80,7 @@ public class TripRecordingActiveBottomSheet extends MenuBottomSheetDialogFragmen
private SelectedGpxFile selectedGpxFile;
private View statusContainer;
private LinearLayout buttonAppearance;
private View buttonSave;
private GpxBlockStatisticsBuilder blockStatisticsBuilder;
@ -128,15 +130,19 @@ public class TripRecordingActiveBottomSheet extends MenuBottomSheetDialogFragmen
.create());
View buttonClear = itemView.findViewById(R.id.button_clear);
final View buttonOnline = itemView.findViewById(R.id.button_online);
View buttonSegment = itemView.findViewById(R.id.button_segment);
buttonSave = itemView.findViewById(R.id.button_save);
final View buttonPause = itemView.findViewById(R.id.button_pause);
View buttonStop = itemView.findViewById(R.id.button_stop);
createItem(buttonClear, ItemType.CLEAR_DATA, hasDataToSave(), null);
createItem(buttonSegment, ItemType.START_SEGMENT, wasTrackMonitored(), null);
createItem(buttonPause, wasTrackMonitored() ? ItemType.PAUSE : ItemType.RESUME, true, null);
createItem(buttonStop, ItemType.STOP, true, null);
createItem(buttonClear, ItemType.CLEAR_DATA, hasDataToSave());
createItem(buttonOnline, ItemType.STOP_ONLINE, hasDataToSave());
createItem(buttonSegment, ItemType.START_SEGMENT, wasTrackMonitored());
createItem(buttonPause, wasTrackMonitored() ? ItemType.PAUSE : ItemType.RESUME, true);
createItem(buttonStop, ItemType.STOP, true);
AndroidUiHelper.updateVisibility(buttonOnline, app.getLiveMonitoringHelper().isLiveMonitoringEnabled());
statusContainer = itemView.findViewById(R.id.status_container);
updateStatus();
@ -162,31 +168,25 @@ public class TripRecordingActiveBottomSheet extends MenuBottomSheetDialogFragmen
if (showTitle != null) {
showTrackTitle.setText(showTitle);
}
AndroidUtils.setPadding(buttonShow, AndroidUtils.dpToPx(app, 12f), 0, buttonShow.getPaddingRight(), 0);
showTrackTitle.setTextColor(ContextCompat.getColor(app, getActiveIconColorId(nightMode)));
showTrackTitle.setTextSize(TypedValue.COMPLEX_UNIT_PX, getResources().getDimensionPixelSize(R.dimen.default_desc_text_size));
Typeface typeface = FontCache.getFont(app, app.getResources().getString(R.string.font_roboto_medium));
showTrackTitle.setTypeface(typeface);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
float letterSpacing = AndroidUtils.getFloatValueFromRes(app, R.dimen.description_letter_spacing);
float letterSpacing = AndroidUtils.getFloatValueFromRes(app, R.dimen.text_button_letter_spacing);
showTrackTitle.setLetterSpacing(letterSpacing);
}
final SwitchCompat showTrackOnMapButton = buttonShow.findViewById(R.id.switch_button);
showTrackOnMapButton.setChecked(app.getSelectedGpxHelper().getSelectedCurrentRecordingTrack() != null);
UiUtilities.setupCompoundButton(showTrackOnMapButton, nightMode, PROFILE_DEPENDENT);
final LinearLayout buttonAppearance = showTrackContainer.findViewById(R.id.additional_button);
buttonAppearance = showTrackContainer.findViewById(R.id.additional_button);
View divider = buttonAppearance.getChildAt(0);
AndroidUiHelper.setVisibility(View.GONE, divider);
int marginS = app.getResources().getDimensionPixelSize(R.dimen.context_menu_padding_margin_small);
UiUtilities.setMargins(buttonAppearance, marginS, 0, 0, 0);
String width = settings.CURRENT_TRACK_WIDTH.get();
boolean showArrows = settings.CURRENT_TRACK_SHOW_ARROWS.get();
int color = settings.CURRENT_TRACK_COLOR.get();
Drawable appearanceDrawable = TrackAppearanceFragment.getTrackIcon(app, width, showArrows, color);
AppCompatImageView appearanceIcon = buttonAppearance.findViewById(R.id.icon_after_divider);
int marginTrackIconH = app.getResources().getDimensionPixelSize(R.dimen.content_padding_small);
UiUtilities.setMargins(appearanceIcon, marginTrackIconH, 0, marginTrackIconH, 0);
appearanceIcon.setImageDrawable(appearanceDrawable);
updateTrackIcon(buttonAppearance);
buttonAppearance.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
@ -200,7 +200,7 @@ public class TripRecordingActiveBottomSheet extends MenuBottomSheetDialogFragmen
}
}
});
createItem(buttonAppearance, ItemType.APPEARANCE, showTrackOnMapButton.isChecked(), null);
createItem(buttonAppearance, ItemType.APPEARANCE, showTrackOnMapButton.isChecked());
setShowOnMapBackground(buttonShow, app, showTrackOnMapButton.isChecked(), nightMode);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
buttonShow.setBackgroundTintList(null);
@ -211,7 +211,7 @@ public class TripRecordingActiveBottomSheet extends MenuBottomSheetDialogFragmen
boolean checked = !showTrackOnMapButton.isChecked();
showTrackOnMapButton.setChecked(checked);
app.getSelectedGpxHelper().selectGpxFile(app.getSavingTrackHelper().getCurrentGpx(), checked, false);
createItem(buttonAppearance, ItemType.APPEARANCE, checked, null);
createItem(buttonAppearance, ItemType.APPEARANCE, checked);
setShowOnMapBackground(buttonShow, app, checked, nightMode);
}
});
@ -225,6 +225,14 @@ public class TripRecordingActiveBottomSheet extends MenuBottomSheetDialogFragmen
}
});
buttonOnline.findViewById(R.id.button_container).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
settings.LIVE_MONITORING.set(false);
AndroidUiHelper.updateVisibility(buttonOnline, false);
}
});
buttonSegment.findViewById(R.id.button_container).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
@ -265,7 +273,7 @@ public class TripRecordingActiveBottomSheet extends MenuBottomSheetDialogFragmen
}
settings.SAVE_GLOBAL_TRACK_TO_GPX.set(wasTrackMonitored);
updateStatus();
createItem(buttonPause, wasTrackMonitored ? ItemType.PAUSE : ItemType.RESUME, true, null);
createItem(buttonPause, wasTrackMonitored ? ItemType.PAUSE : ItemType.RESUME, true);
}
});
@ -279,12 +287,6 @@ public class TripRecordingActiveBottomSheet extends MenuBottomSheetDialogFragmen
});
}
@Override
public void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState);
outState.putBoolean(UPDATE_CURRENT_GPX_FILE, true);
}
private void updateStatus() {
TextView statusTitle = statusContainer.findViewById(R.id.text_status);
AppCompatImageView statusIcon = statusContainer.findViewById(R.id.icon_status);
@ -304,72 +306,67 @@ public class TripRecordingActiveBottomSheet extends MenuBottomSheetDialogFragmen
}
}
private void updateTrackIcon(View buttonAppearance) {
String width = settings.CURRENT_TRACK_WIDTH.get();
boolean showArrows = settings.CURRENT_TRACK_SHOW_ARROWS.get();
int color = settings.CURRENT_TRACK_COLOR.get();
Drawable appearanceDrawable = TrackAppearanceFragment.getTrackIcon(app, width, showArrows, color);
AppCompatImageView appearanceIcon = buttonAppearance.findViewById(R.id.icon_after_divider);
int marginTrackIconH = app.getResources().getDimensionPixelSize(R.dimen.content_padding_small);
UiUtilities.setMargins(appearanceIcon, marginTrackIconH, 0, marginTrackIconH, 0);
appearanceIcon.setImageDrawable(appearanceDrawable);
}
private void createItem(View view, ItemType type, boolean enabled) {
createItem(app, nightMode, view, type, enabled, null);
}
private void createItem(View view, ItemType type, boolean enabled, @Nullable String description) {
createItem(app, nightMode, view, type, enabled, description);
}
public static View createItem(Context context, boolean nightMode, LayoutInflater inflater, ItemType type) {
View button = inflater.inflate(R.layout.bottom_sheet_button_with_icon, null);
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.WRAP_CONTENT);
int horizontal = context.getResources().getDimensionPixelSize(R.dimen.content_padding);
params.setMargins(horizontal, 0, horizontal, 0);
button.setLayoutParams(params);
LinearLayout container = button.findViewById(R.id.button_container);
container.setClickable(false);
container.setFocusable(false);
createItem(context, nightMode, button, type, true, null);
return button;
}
public static void createItem(Context context, boolean nightMode, View view, ItemType type, boolean enabled, @Nullable String description) {
view.setTag(type);
LinearLayout button = view.findViewById(R.id.button_container);
AppCompatImageView icon = view.findViewById(R.id.icon);
if (icon != null) {
setTintedIcon(icon, enabled, nightMode, type);
setTintedIcon(context, icon, enabled, nightMode, type);
}
TextView title = view.findViewById(R.id.button_text);
Integer titleId = type.getTitleId();
if (title != null && titleId != null) {
title.setText(titleId);
setTextColor(title, enabled, nightMode, type);
setTextColor(context, title, enabled, nightMode, type);
}
TextViewEx desc = view.findViewById(R.id.desc);
if (desc != null) {
boolean isShowDesc = !Algorithms.isBlank(description);
int marginDesc = isShowDesc ? 0 : app.getResources().getDimensionPixelSize(R.dimen.context_menu_padding_margin_medium);
int marginDesc = isShowDesc ? 0 : context.getResources().getDimensionPixelSize(R.dimen.context_menu_padding_margin_medium);
AndroidUiHelper.updateVisibility(desc, isShowDesc);
if (title != null) {
UiUtilities.setMargins(title, 0, marginDesc, 0, marginDesc);
}
desc.setText(description);
setTextColor(desc, false, nightMode, type);
setTextColor(context, desc, false, nightMode, type);
}
setItemBackground(button != null ? button : (LinearLayout) view, enabled);
}
protected static View createButton(LayoutInflater inflater, ItemType type, boolean nightMode) {
View button = inflater.inflate(R.layout.bottom_sheet_button_with_icon, null);
button.setTag(type);
Context context = button.getContext();
LinearLayout container = button.findViewById(R.id.button_container);
container.setClickable(false);
container.setFocusable(false);
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.WRAP_CONTENT);
int horizontal = context.getResources().getDimensionPixelSize(R.dimen.content_padding);
params.setMargins(horizontal, 0, horizontal, 0);
button.setLayoutParams(params);
if (type.getTitleId() != null) {
UiUtilities.setupDialogButton(nightMode, button, type.getEffect(), type.getTitleId());
}
TextViewEx title = button.findViewById(R.id.button_text);
int margin = context.getResources().getDimensionPixelSize(R.dimen.context_menu_padding_margin_medium);
UiUtilities.setMargins(title, 0, margin, 0, margin);
int colorRes;
if (type.getEffect() == UiUtilities.DialogButtonType.SECONDARY_HARMFUL) {
colorRes = R.color.color_osm_edit_delete;
} else {
colorRes = nightMode ? R.color.dlg_btn_secondary_text_dark : R.color.dlg_btn_secondary_text_light;
}
AppCompatImageView icon = button.findViewById(R.id.icon);
if (type.getIconId() != null) {
Drawable drawable = AppCompatResources.getDrawable(context, type.getIconId());
UiUtilities.tintDrawable(drawable, ContextCompat.getColor(context, colorRes));
icon.setImageDrawable(drawable);
}
return button;
setItemBackground(context, nightMode, button != null ? button : (LinearLayout) view, enabled);
}
private String getTimeTrackSaved() {
@ -383,6 +380,12 @@ public class TripRecordingActiveBottomSheet extends MenuBottomSheetDialogFragmen
}
}
@Override
public void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState);
outState.putBoolean(UPDATE_CURRENT_GPX_FILE, true);
}
@Override
public void onResume() {
super.onResume();
@ -489,6 +492,13 @@ public class TripRecordingActiveBottomSheet extends MenuBottomSheetDialogFragmen
}
}
public void show(boolean updateTrackIcon) {
show();
if (updateTrackIcon && buttonAppearance != null) {
updateTrackIcon(buttonAppearance);
}
}
public void hide() {
Dialog dialog = getDialog();
if (dialog != null) {
@ -497,31 +507,31 @@ public class TripRecordingActiveBottomSheet extends MenuBottomSheetDialogFragmen
}
public enum ItemType {
SHOW_TRACK(R.string.shared_string_show_on_map, null, null),
APPEARANCE(null, null, null),
SEARCHING_GPS(R.string.searching_gps, R.drawable.ic_action_gps_info, null),
RECORDING(R.string.recording_default_name, R.drawable.ic_action_track_recordable, null),
ON_PAUSE(R.string.on_pause, R.drawable.ic_pause, null),
CLEAR_DATA(R.string.clear_recorded_data, R.drawable.ic_action_delete_dark, UiUtilities.DialogButtonType.SECONDARY_HARMFUL),
START_SEGMENT(R.string.gpx_start_new_segment, R.drawable.ic_action_new_segment, null),
SAVE(R.string.shared_string_save, R.drawable.ic_action_save_to_file, null),
PAUSE(R.string.shared_string_pause, R.drawable.ic_pause, null),
RESUME(R.string.shared_string_resume, R.drawable.ic_play_dark, null),
STOP(R.string.shared_string_control_stop, R.drawable.ic_action_rec_stop, null),
STOP_AND_DISCARD(R.string.track_recording_stop_without_saving, R.drawable.ic_action_rec_stop, DialogButtonType.SECONDARY_HARMFUL),
SAVE_AND_STOP(R.string.track_recording_save_and_stop, R.drawable.ic_action_save_to_file, DialogButtonType.SECONDARY),
CANCEL(R.string.shared_string_cancel, R.drawable.ic_action_close, DialogButtonType.SECONDARY);
SHOW_TRACK(R.string.shared_string_show_on_map, null),
APPEARANCE(null, null),
SEARCHING_GPS(R.string.searching_gps, R.drawable.ic_action_gps_info),
RECORDING(R.string.recording_default_name, R.drawable.ic_action_track_recordable),
ON_PAUSE(R.string.on_pause, R.drawable.ic_pause),
CLEAR_DATA(R.string.clear_recorded_data, R.drawable.ic_action_delete_dark),
START_SEGMENT(R.string.gpx_start_new_segment, R.drawable.ic_action_new_segment),
SAVE(R.string.shared_string_save, R.drawable.ic_action_save_to_file),
PAUSE(R.string.shared_string_pause, R.drawable.ic_pause),
RESUME(R.string.shared_string_resume, R.drawable.ic_play_dark),
STOP(R.string.shared_string_control_stop, R.drawable.ic_action_rec_stop),
STOP_AND_DISCARD(R.string.track_recording_stop_without_saving, R.drawable.ic_action_rec_stop),
STOP_AND_SAVE(R.string.track_recording_save_and_stop, R.drawable.ic_action_save_to_file),
STOP_ONLINE(R.string.live_monitoring_stop, R.drawable.ic_world_globe_dark),
CANCEL(R.string.shared_string_cancel, R.drawable.ic_action_close);
@StringRes
private final Integer titleId;
@DrawableRes
private final Integer iconId;
private final DialogButtonType effect;
private static final List<ItemType> negative = Arrays.asList(CLEAR_DATA, STOP_AND_DISCARD);
ItemType(@Nullable @StringRes Integer titleId, @Nullable @DrawableRes Integer iconId, @Nullable DialogButtonType effect) {
ItemType(@Nullable @StringRes Integer titleId, @Nullable @DrawableRes Integer iconId) {
this.titleId = titleId;
this.iconId = iconId;
this.effect = effect;
}
@Nullable
@ -534,53 +544,52 @@ public class TripRecordingActiveBottomSheet extends MenuBottomSheetDialogFragmen
return iconId;
}
@Nullable
public DialogButtonType getEffect() {
return effect;
public boolean isNegative() {
return negative.contains(this);
}
}
private void setItemBackground(LinearLayout view, boolean enabled) {
Drawable background = AppCompatResources.getDrawable(app, R.drawable.btn_background_inactive_light);
public static void setItemBackground(Context context, boolean nightMode, LinearLayout view, boolean enabled) {
Drawable background = AppCompatResources.getDrawable(context, R.drawable.btn_background_inactive_light);
if (background != null && enabled) {
ColorStateList iconColorStateList = AndroidUtils.createPressedColorStateList(
app, getInactiveButtonColorId(nightMode), getActiveButtonColorId(nightMode)
context, getInactiveButtonColorId(nightMode), getActiveButtonColorId(nightMode)
);
DrawableCompat.setTintList(background, iconColorStateList);
} else {
UiUtilities.tintDrawable(background, ContextCompat.getColor(app, getInactiveButtonColorId(nightMode)));
UiUtilities.tintDrawable(background, ContextCompat.getColor(context, getInactiveButtonColorId(nightMode)));
}
view.setBackgroundDrawable(background);
}
private static void setShowOnMapBackground(LinearLayout view, Context context, boolean checked, boolean nightMode) {
public static void setShowOnMapBackground(LinearLayout view, Context context, boolean checked, boolean nightMode) {
Drawable background = AppCompatResources.getDrawable(context,
nightMode ? checked ? R.drawable.btn_background_inactive_dark : R.drawable.btn_background_stroked_inactive_dark
: checked ? R.drawable.btn_background_inactive_light : R.drawable.btn_background_stroked_inactive_light);
view.setBackgroundDrawable(background);
}
public void setTextColor(TextView tv, boolean enabled, boolean nightMode, ItemType type) {
public static void setTextColor(Context context, TextView tv, boolean enabled, boolean nightMode, ItemType type) {
if (tv != null) {
int activeColorId = type == ItemType.CLEAR_DATA ? R.color.color_osm_edit_delete : getActiveTextColorId(nightMode);
int activeColorId = type.isNegative() ? R.color.color_osm_edit_delete : getActiveTextColorId(nightMode);
int normalColorId = enabled ? activeColorId : getSecondaryTextColorId(nightMode);
ColorStateList textColorStateList = AndroidUtils.createPressedColorStateList(app, normalColorId, getPressedColorId(nightMode));
ColorStateList textColorStateList = AndroidUtils.createPressedColorStateList(context, normalColorId, getPressedColorId(nightMode));
tv.setTextColor(textColorStateList);
}
}
public void setTintedIcon(AppCompatImageView iv, boolean enabled, boolean nightMode, ItemType type) {
public static void setTintedIcon(Context context, AppCompatImageView iv, boolean enabled, boolean nightMode, ItemType type) {
Integer iconId = type.getIconId();
if (iv != null && iconId != null) {
Drawable icon = AppCompatResources.getDrawable(app, iconId);
int activeColorId = type == ItemType.CLEAR_DATA ? R.color.color_osm_edit_delete : getActiveIconColorId(nightMode);
Drawable icon = AppCompatResources.getDrawable(context, iconId);
int activeColorId = type.isNegative() ? R.color.color_osm_edit_delete : getActiveIconColorId(nightMode);
int normalColorId = enabled ? activeColorId : getSecondaryIconColorId(nightMode);
ColorStateList iconColorStateList = AndroidUtils.createPressedColorStateList(app, normalColorId, getPressedColorId(nightMode));
ColorStateList iconColorStateList = AndroidUtils.createPressedColorStateList(context, normalColorId, getPressedColorId(nightMode));
if (icon != null) {
DrawableCompat.setTintList(icon, iconColorStateList);
}
iv.setImageDrawable(icon);
if (type == ItemType.STOP) {
if (type.iconId == R.drawable.ic_action_rec_stop) {
int stopSize = iv.getResources().getDimensionPixelSize(R.dimen.bottom_sheet_icon_margin_large);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(stopSize, stopSize);
iv.setLayoutParams(params);
@ -589,42 +598,42 @@ public class TripRecordingActiveBottomSheet extends MenuBottomSheetDialogFragmen
}
@ColorRes
private static int getActiveTextColorId(boolean nightMode) {
public static int getActiveTextColorId(boolean nightMode) {
return nightMode ? R.color.active_color_primary_dark : R.color.active_color_primary_light;
}
@ColorRes
private static int getSecondaryTextColorId(boolean nightMode) {
public static int getSecondaryTextColorId(boolean nightMode) {
return nightMode ? R.color.text_color_secondary_dark : R.color.text_color_secondary_light;
}
@ColorRes
private static int getActiveIconColorId(boolean nightMode) {
public static int getActiveIconColorId(boolean nightMode) {
return nightMode ? R.color.icon_color_active_dark : R.color.icon_color_active_light;
}
@ColorRes
private static int getSecondaryIconColorId(boolean nightMode) {
public static int getSecondaryIconColorId(boolean nightMode) {
return nightMode ? R.color.icon_color_secondary_dark : R.color.icon_color_secondary_light;
}
@ColorRes
private static int getActiveButtonColorId(boolean nightMode) {
public static int getActiveButtonColorId(boolean nightMode) {
return nightMode ? R.color.active_buttons_and_links_bg_pressed_dark : R.color.active_buttons_and_links_bg_pressed_light;
}
@ColorRes
private static int getInactiveButtonColorId(boolean nightMode) {
public static int getInactiveButtonColorId(boolean nightMode) {
return nightMode ? R.color.inactive_buttons_and_links_bg_dark : R.color.inactive_buttons_and_links_bg_light;
}
@ColorRes
private static int getOsmandIconColorId(boolean nightMode) {
public static int getOsmandIconColorId(boolean nightMode) {
return nightMode ? R.color.icon_color_osmand_dark : R.color.icon_color_osmand_light;
}
@ColorRes
private static int getPressedColorId(boolean nightMode) {
public static int getPressedColorId(boolean nightMode) {
return nightMode ? R.color.active_buttons_and_links_text_dark : R.color.active_buttons_and_links_text_light;
}

View file

@ -88,6 +88,7 @@ public class ResourceManager {
public static final String VECTOR_MAP = "#vector_map"; //$NON-NLS-1$
private static final String INDEXES_CACHE = "ind.cache";
public static final String DEFAULT_WIKIVOYAGE_TRAVEL_OBF = "Default_wikivoyage.travel.obf";
private static final Log log = PlatformUtil.getLog(ResourceManager.class);
@ -638,6 +639,8 @@ public class ResourceManager {
if (Version.isPaidVersion(context)) {
collectFiles(context.getAppPath(IndexConstants.WIKI_INDEX_DIR), IndexConstants.BINARY_MAP_INDEX_EXT, files);
collectFiles(context.getAppPath(IndexConstants.WIKIVOYAGE_INDEX_DIR), IndexConstants.BINARY_TRAVEL_GUIDE_MAP_INDEX_EXT, files);
} else {
collectFiles(context.getAppPath(IndexConstants.WIKIVOYAGE_INDEX_DIR), DEFAULT_WIKIVOYAGE_TRAVEL_OBF, files);
}
if (OsmandPlugin.getEnabledPlugin(SRTMPlugin.class) != null || InAppPurchaseHelper.isContourLinesPurchased(context)) {
collectFiles(context.getAppPath(IndexConstants.SRTM_INDEX_DIR), IndexConstants.BINARY_MAP_INDEX_EXT, files);
@ -701,7 +704,7 @@ public class ResourceManager {
}
boolean wikiMap = (f.getName().contains("_wiki") || f.getName().contains(IndexConstants.BINARY_WIKI_MAP_INDEX_EXT));
boolean srtmMap = f.getName().contains(IndexConstants.BINARY_SRTM_MAP_INDEX_EXT);
if (mapReader == null || (!Version.isPaidVersion(context) && wikiMap)) {
if (mapReader == null || (!Version.isPaidVersion(context) && wikiMap && !f.getName().equals(DEFAULT_WIKIVOYAGE_TRAVEL_OBF))) {
warnings.add(MessageFormat.format(context.getString(R.string.version_index_is_not_supported), f.getName())); //$NON-NLS-1$
} else {
if (mapReader.isBasemap()) {

View file

@ -424,16 +424,13 @@ public class RouteProvider {
if (gpxParams.reverse && gpxParams.routePoints.size() > 1) {
List<Location> gpxRouteLocations = new ArrayList<>();
List<RouteSegmentResult> gpxRoute = new ArrayList<>();
Location start = null;
for (int i = 0; i < gpxParams.routePoints.size(); i++) {
WptPt pt = gpxParams.routePoints.get(i);
ApplicationMode appMode = ApplicationMode.valueOfStringKey(pt.getProfileType(), ApplicationMode.DEFAULT);
LatLon end = new LatLon(pt.getLatitude(), pt.getLongitude());
if (start == null) {
start = new Location("");
start.setLatitude(routeParams.start.getLatitude());
start.setLongitude(routeParams.start.getLongitude());
}
WptPt firstGpxPoint = gpxParams.routePoints.get(0);
Location start = new Location("", firstGpxPoint.getLatitude(), firstGpxPoint.getLongitude());
for (int i = 1; i < gpxParams.routePoints.size(); i++) {
WptPt gpxPoint = gpxParams.routePoints.get(i);
ApplicationMode appMode = ApplicationMode.valueOfStringKey(gpxPoint.getProfileType(), ApplicationMode.DEFAULT);
LatLon end = new LatLon(gpxPoint.getLatitude(), gpxPoint.getLongitude());
RouteCalculationParams params = new RouteCalculationParams();
params.inSnapToRoadMode = true;
@ -457,7 +454,7 @@ public class RouteProvider {
routeParams.mode.getDefaultSpeed(), new LocationsHolder(locations).getLatLonList()));
}
gpxRouteLocations.addAll(locations);
if (i > 0 && !gpxRouteLocations.isEmpty()) {
if (!gpxRouteLocations.isEmpty()) {
gpxRouteLocations.remove(gpxRouteLocations.size() - 1);
}
gpxRoute.addAll(route);
@ -478,29 +475,29 @@ public class RouteProvider {
RouteCalculationResult result = new RouteCalculationResult(gpxRouteResult, routeParams.start, routeParams.end,
routeParams.intermediates, routeParams.ctx, routeParams.leftSide, null, null, routeParams.mode, false);
List<Location> gpxRouteLocations = result.getImmutableAllLocations();
int gpxNextIndex = calcWholeRoute ? 0 : findStartIndexFromRoute(gpxRouteLocations, routeParams.start, calculateOsmAndRouteParts);
Location gpxNextLocation = null;
int nearestGpxPointInd = calcWholeRoute ? 0 : findNearestGpxPointIndexFromRoute(gpxRouteLocations, routeParams.start, calculateOsmAndRouteParts);
Location nearestGpxLocation = null;
Location gpxLastLocation = !gpxRouteLocations.isEmpty() ? gpxRouteLocations.get(gpxRouteLocations.size() - 1) : null;
List<RouteSegmentResult> firstSegmentRoute = null;
List<RouteSegmentResult> lastSegmentRoute = null;
List<RouteSegmentResult> gpxRoute;
if (gpxNextIndex > 0) {
gpxNextLocation = gpxRouteLocations.get(gpxNextIndex);
gpxRoute = result.getOriginalRoute(gpxNextIndex);
if (nearestGpxPointInd > 0) {
nearestGpxLocation = gpxRouteLocations.get(nearestGpxPointInd);
gpxRoute = result.getOriginalRoute(nearestGpxPointInd);
if (gpxRoute.size() > 0) {
gpxRoute.remove(0);
}
} else {
if (!gpxRouteLocations.isEmpty()) {
gpxNextLocation = gpxRouteLocations.get(0);
nearestGpxLocation = gpxRouteLocations.get(0);
}
gpxRoute = result.getOriginalRoute();
}
if (calculateOsmAndRouteParts
&& routeParams.start != null && gpxNextLocation != null
&& gpxNextLocation.distanceTo(routeParams.start) > MIN_DISTANCE_FOR_INSERTING_ROUTE_SEGMENT) {
&& routeParams.start != null && nearestGpxLocation != null
&& nearestGpxLocation.distanceTo(routeParams.start) > MIN_DISTANCE_FOR_INSERTING_ROUTE_SEGMENT) {
RouteCalculationResult firstSegmentResult = findOfflineRouteSegment(
routeParams, routeParams.start, new LatLon(gpxNextLocation.getLatitude(), gpxNextLocation.getLongitude()));
routeParams, routeParams.start, new LatLon(nearestGpxLocation.getLatitude(), nearestGpxLocation.getLongitude()));
firstSegmentRoute = firstSegmentResult.getOriginalRoute();
}
if (calculateOsmAndRouteParts
@ -750,28 +747,28 @@ public class RouteProvider {
return sublist;
}
private int findStartIndexFromRoute(List<Location> route, Location startLoc, boolean calculateOsmAndRouteParts) {
private int findNearestGpxPointIndexFromRoute(List<Location> route, Location startLoc, boolean calculateOsmAndRouteParts) {
float minDist = Integer.MAX_VALUE;
int start = 0;
int nearestPointIndex = 0;
if (startLoc != null) {
for (int i = 0; i < route.size(); i++) {
float d = route.get(i).distanceTo(startLoc);
if (d < minDist) {
start = i;
nearestPointIndex = i;
minDist = d;
}
}
}
if (start > 0 && calculateOsmAndRouteParts) {
Location newStartLoc = route.get(start);
for (int i = start + 1; i < route.size(); i++) {
Location loc = route.get(i);
if (loc.distanceTo(newStartLoc) >= ADDITIONAL_DISTANCE_FOR_START_POINT) {
if (nearestPointIndex > 0 && calculateOsmAndRouteParts) {
Location nearestLocation = route.get(nearestPointIndex);
for (int i = nearestPointIndex + 1; i < route.size(); i++) {
Location nextLocation = route.get(i);
if (nextLocation.distanceTo(nearestLocation) >= ADDITIONAL_DISTANCE_FOR_START_POINT) {
return i;
}
}
}
return start;
return nearestPointIndex;
}
protected String getString(Context ctx, int resId){

View file

@ -39,6 +39,7 @@ public class DataStorageHelper {
public final static String MANUALLY_SPECIFIED = "manually_specified";
public final static String MAPS_MEMORY = "maps_memory_used";
public final static String TRAVEL_MEMORY = "travel_memory_used";
public final static String TERRAIN_MEMORY = "terrain_memory_used";
public final static String TRACKS_MEMORY = "tracks_memory_used";
public final static String NOTES_MEMORY = "notes_memory_used";
@ -52,6 +53,7 @@ public class DataStorageHelper {
private ArrayList<MemoryItem> memoryItems = new ArrayList<>();
private MemoryItem mapsMemory;
private MemoryItem travelMemory;
private MemoryItem terrainMemory;
private MemoryItem tracksMemory;
private MemoryItem notesMemory;
@ -184,11 +186,18 @@ public class DataStorageHelper {
createDirectory(MAPS_PATH, false, EXTENSIONS, true),
createDirectory(ROADS_INDEX_DIR, true, EXTENSIONS, true),
createDirectory(WIKI_INDEX_DIR, true, EXTENSIONS, true),
createDirectory(WIKIVOYAGE_INDEX_DIR, true, EXTENSIONS, true),
createDirectory(BACKUP_INDEX_DIR, true, EXTENSIONS, true))
.createItem();
memoryItems.add(mapsMemory);
travelMemory = MemoryItem.builder()
.setKey(TRAVEL_MEMORY)
.setExtensions(IndexConstants.BINARY_TRAVEL_GUIDE_MAP_INDEX_EXT)
.setDirectories(
createDirectory(WIKIVOYAGE_INDEX_DIR, true, EXTENSIONS, true))
.createItem();
memoryItems.add(travelMemory);
terrainMemory = MemoryItem.builder()
.setKey(TERRAIN_MEMORY)
.setExtensions(IndexConstants.BINARY_SRTM_MAP_INDEX_EXT)
@ -270,7 +279,7 @@ public class DataStorageHelper {
public RefreshUsedMemoryTask calculateMemoryUsedInfo(UpdateMemoryInfoUIAdapter uiAdapter) {
File rootDir = new File(currentStoragePath);
RefreshUsedMemoryTask task = new RefreshUsedMemoryTask(uiAdapter, otherMemory, rootDir, null, null, OTHER_MEMORY);
task.execute(mapsMemory, terrainMemory, tracksMemory, notesMemory);
task.execute(mapsMemory, travelMemory, terrainMemory, tracksMemory, notesMemory);
return task;
}

View file

@ -1,6 +1,7 @@
package net.osmand.plus.track;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Handler;
import android.view.LayoutInflater;
import android.view.View;
@ -250,7 +251,11 @@ public class GpxBlockStatisticsBuilder {
holder.valueText.setTextColor(activeColor);
holder.titleText.setText(item.title);
holder.titleText.setTextColor(app.getResources().getColor(R.color.text_color_secondary_light));
holder.titleText.setWidth(calculateWidthWithin(item.title, item.value));
float letterSpacing = 0.00f;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
letterSpacing = Math.max(holder.valueText.getLetterSpacing(), holder.titleText.getLetterSpacing());
}
holder.titleText.setMinWidth(calculateWidthWithin(letterSpacing, item.title, item.value));
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
@ -283,8 +288,11 @@ public class GpxBlockStatisticsBuilder {
notifyDataSetChanged();
}
public int calculateWidthWithin(String... texts) {
public int calculateWidthWithin(float letterSpacing, String... texts) {
int textWidth = AndroidUtils.getTextMaxWidth(textSize, Arrays.asList(texts));
if (letterSpacing != 0.00f) {
textWidth += Math.ceil(textWidth * letterSpacing);
}
return Math.min(maxWidthPx, Math.max(minWidthPx, textWidth));
}
}

View file

@ -385,7 +385,7 @@ public class TrackAppearanceFragment extends ContextMenuScrollFragment implement
if (target instanceof TripRecordingBottomSheet) {
((TripRecordingBottomSheet) target).show();
} else if (target instanceof TripRecordingActiveBottomSheet) {
((TripRecordingActiveBottomSheet) target).show();
((TripRecordingActiveBottomSheet) target).show(true);
}
}

View file

@ -83,6 +83,7 @@ import net.osmand.plus.routepreparationmenu.cards.BaseCard;
import net.osmand.plus.routepreparationmenu.cards.BaseCard.CardListener;
import net.osmand.plus.routing.RouteProvider;
import net.osmand.plus.track.SaveGpxAsyncTask.SaveGpxListener;
import net.osmand.plus.track.TrackSelectSegmentBottomSheet.OnSegmentSelectedListener;
import net.osmand.plus.views.AddGpxPointBottomSheetHelper.NewGpxPoint;
import net.osmand.plus.widgets.IconPopupMenu;
import net.osmand.util.Algorithms;
@ -94,6 +95,8 @@ import java.io.File;
import java.lang.ref.WeakReference;
import java.util.List;
import static net.osmand.plus.activities.MapActivityActions.KEY_LATITUDE;
import static net.osmand.plus.activities.MapActivityActions.KEY_LONGITUDE;
import static net.osmand.plus.activities.TrackActivity.CURRENT_RECORDING;
import static net.osmand.plus.activities.TrackActivity.TRACK_FILE_NAME;
import static net.osmand.plus.myplaces.TrackActivityFragmentAdapter.isGpxFileSelected;
@ -115,7 +118,7 @@ import static net.osmand.plus.track.TrackPointsCard.OPEN_WAYPOINT_INDEX;
public class TrackMenuFragment extends ContextMenuScrollFragment implements CardListener,
SegmentActionsListener, RenameCallback, OnTrackFileMoveListener, OnPointsDeleteListener,
OsmAndLocationListener, OsmAndCompassListener, TrackSelectSegmentBottomSheet.OnSegmentSelectedListener {
OsmAndLocationListener, OsmAndCompassListener, OnSegmentSelectedListener {
public static final String OPEN_TRACK_MENU = "open_track_menu";
public static final String RETURN_SCREEN_NAME = "return_screen_name";
@ -226,18 +229,32 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
app = requireMyApplication();
displayHelper = new TrackDisplayHelper(app);
updateLocationViewCache = app.getUIUtilities().getUpdateLocationViewCache();
if (!selectedGpxFile.isShowCurrentTrack()) {
File file = new File(selectedGpxFile.getGpxFile().path);
displayHelper.setFile(file);
displayHelper.setGpxDataItem(app.getGpxDbHelper().getItem(file));
}
displayHelper.setGpx(selectedGpxFile.getGpxFile());
String fileName = Algorithms.getFileWithoutDirs(getGpx().path);
gpxTitle = !isCurrentRecordingTrack() ? GpxUiHelper.getGpxTitle(fileName)
: app.getResources().getString(R.string.shared_string_currently_recording_track);
toolbarHeightPx = getResources().getDimensionPixelSize(R.dimen.dashboard_map_toolbar);
if (selectedGpxFile == null && savedInstanceState != null) {
String path = savedInstanceState.getString(TRACK_FILE_NAME);
boolean showCurrentTrack = savedInstanceState.getBoolean(CURRENT_RECORDING);
MapActivity mapActivity = requireMapActivity();
loadSelectedGpxFile(mapActivity, path, showCurrentTrack, new CallbackWithObject<SelectedGpxFile>() {
@Override
public boolean processResult(SelectedGpxFile result) {
selectedGpxFile = result;
setupDisplayHelper();
if (getView() != null) {
initContent(getView());
}
return true;
}
});
if (savedInstanceState.containsKey(KEY_LATITUDE) && savedInstanceState.containsKey(KEY_LONGITUDE)) {
double latitude = savedInstanceState.getDouble(KEY_LATITUDE);
double longitude = savedInstanceState.getDouble(KEY_LONGITUDE);
latLon = new LatLon(latitude, longitude);
}
} else if (selectedGpxFile != null) {
setupDisplayHelper();
}
FragmentActivity activity = requireMyActivity();
activity.getOnBackPressedDispatcher().addCallback(this, new OnBackPressedCallback(true) {
public void handleOnBackPressed() {
@ -261,6 +278,18 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
});
}
private void setupDisplayHelper() {
if (!selectedGpxFile.isShowCurrentTrack()) {
File file = new File(selectedGpxFile.getGpxFile().path);
displayHelper.setFile(file);
displayHelper.setGpxDataItem(app.getGpxDbHelper().getItem(file));
}
displayHelper.setGpx(selectedGpxFile.getGpxFile());
String fileName = Algorithms.getFileWithoutDirs(getGpx().path);
gpxTitle = !isCurrentRecordingTrack() ? GpxUiHelper.getGpxTitle(fileName)
: app.getResources().getString(R.string.shared_string_currently_recording_track);
}
public GPXFile getGpx() {
return displayHelper.getGpx();
}
@ -300,21 +329,26 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
params.gravity = Gravity.BOTTOM | Gravity.START;
bottomNav.setLayoutParams(params);
}
setupCards();
setupToolbar();
updateHeader();
setupButtons(view);
updateCardsLayout();
if (menuType == TrackMenuType.OVERVIEW && isPortrait()) {
calculateLayoutAndShowHeader();
} else {
calculateLayoutAndUpdateMenuState();
if (selectedGpxFile != null) {
initContent(view);
}
}
return view;
}
private void initContent(@NonNull View view) {
setupCards();
setupToolbar();
updateHeader();
setupButtons(view);
updateCardsLayout();
if (menuType == TrackMenuType.OVERVIEW && isPortrait()) {
calculateLayoutAndShowHeader();
} else {
calculateLayoutAndUpdateMenuState();
}
}
private void setHeaderTitle(String text, boolean iconVisibility) {
headerTitle.setText(text);
AndroidUiHelper.updateVisibility(headerIcon, iconVisibility);
@ -553,9 +587,8 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
}
updateControlsVisibility(true);
startLocationUpdate();
GpxBlockStatisticsBuilder blockStats = overviewCard.getBlockStatisticsBuilder();
if (menuType == TrackMenuType.OVERVIEW && isCurrentRecordingTrack()) {
blockStats.runUpdatingStatBlocksIfNeeded();
if (overviewCard != null && menuType == TrackMenuType.OVERVIEW && isCurrentRecordingTrack()) {
overviewCard.getBlockStatisticsBuilder().runUpdatingStatBlocksIfNeeded();
}
}
@ -568,7 +601,9 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
}
updateControlsVisibility(false);
stopLocationUpdate();
overviewCard.getBlockStatisticsBuilder().stopUpdatingStatBlocks();
if (overviewCard != null) {
overviewCard.getBlockStatisticsBuilder().stopUpdatingStatBlocks();
}
}
@Override
@ -603,8 +638,8 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
private void updateDistanceDirection() {
MapActivity mapActivity = getMapActivity();
View view = overviewCard.getView();
if (mapActivity != null && view != null) {
if (mapActivity != null && overviewCard != null && overviewCard.getView() != null) {
View view = overviewCard.getView();
TextView distanceText = view.findViewById(R.id.distance);
ImageView direction = view.findViewById(R.id.direction);
app.getUIUtilities().updateLocationView(updateLocationViewCache, direction, distanceText, latLon);
@ -677,6 +712,10 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
public void onSaveInstanceState(@NonNull Bundle outState) {
outState.putString(TRACK_FILE_NAME, getGpx().path);
outState.putBoolean(CURRENT_RECORDING, selectedGpxFile.isShowCurrentTrack());
if (latLon != null) {
outState.putDouble(KEY_LATITUDE, latLon.getLatitude());
outState.putDouble(KEY_LONGITUDE, latLon.getLongitude());
}
super.onSaveInstanceState(outState);
}
@ -763,7 +802,7 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
segment = segments.get(0);
}
}
GpxDisplayItemType[] filterTypes = new GpxDisplayItemType[]{GpxDisplayItemType.TRACK_SEGMENT};
GpxDisplayItemType[] filterTypes = new GpxDisplayItemType[] {GpxDisplayItemType.TRACK_SEGMENT};
List<GpxDisplayItem> items = TrackDisplayHelper.flatten(displayHelper.getOriginalGroups(filterTypes));
if (segment != null && !Algorithms.isEmpty(items)) {
SplitSegmentDialogFragment.showInstance(fragmentManager, displayHelper, items.get(0), segment);
@ -888,9 +927,9 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
}
private void adjustMapPosition(int y) {
GPXFile gpxFile = getGpx();
MapActivity mapActivity = getMapActivity();
if (mapActivity != null && mapActivity.getMapView() != null) {
GPXFile gpxFile = getGpx();
if (mapActivity != null && mapActivity.getMapView() != null && gpxFile != null) {
QuadRect r = gpxFile.getRect();
RotatedTileBox tb = mapActivity.getMapView().getCurrentRotatedTileBox().copy();
@ -1148,7 +1187,7 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
@Override
public void gpxSavingFinished(Exception errorMessage) {
if (selectedGpxFile != null) {
List<GpxDisplayGroup> groups = displayHelper.getDisplayGroups(new GpxDisplayItemType[]{GpxDisplayItemType.TRACK_SEGMENT});
List<GpxDisplayGroup> groups = displayHelper.getDisplayGroups(new GpxDisplayItemType[] {GpxDisplayItemType.TRACK_SEGMENT});
selectedGpxFile.setDisplayGroups(groups, app);
selectedGpxFile.processPoints(app);
}
@ -1204,8 +1243,8 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
}
}
public static void showInstance(@NonNull MapActivity mapActivity, @Nullable String path,
boolean showCurrentTrack, @Nullable final LatLon latLon, @Nullable final String returnScreenName) {
private static void loadSelectedGpxFile(@NonNull MapActivity mapActivity, @Nullable String path,
boolean showCurrentTrack, final CallbackWithObject<SelectedGpxFile> callback) {
OsmandApplication app = mapActivity.getMyApplication();
SelectedGpxFile selectedGpxFile;
if (showCurrentTrack) {
@ -1214,7 +1253,7 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
selectedGpxFile = app.getSelectedGpxHelper().getSelectedFileByPath(path);
}
if (selectedGpxFile != null) {
showInstance(mapActivity, selectedGpxFile, latLon, returnScreenName);
callback.processResult(selectedGpxFile);
} else if (!Algorithms.isEmpty(path)) {
String title = app.getString(R.string.loading_smth, "");
final ProgressDialog progress = ProgressDialog.show(mapActivity, title, app.getString(R.string.loading_data));
@ -1228,7 +1267,7 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
OsmandApplication app = mapActivity.getMyApplication();
SelectedGpxFile selectedGpxFile = app.getSelectedGpxHelper().selectGpxFile(result, true, false);
if (selectedGpxFile != null) {
showInstance(mapActivity, selectedGpxFile, latLon, returnScreenName);
callback.processResult(selectedGpxFile);
}
}
if (progress != null && AndroidUtils.isActivityNotDestroyed(mapActivity)) {
@ -1241,6 +1280,21 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
}
}
public static void showInstance(@NonNull MapActivity mapActivity, @Nullable String path,
boolean showCurrentTrack, @Nullable final LatLon latLon, @Nullable final String returnScreenName) {
final WeakReference<MapActivity> mapActivityRef = new WeakReference<>(mapActivity);
loadSelectedGpxFile(mapActivity, path, showCurrentTrack, new CallbackWithObject<SelectedGpxFile>() {
@Override
public boolean processResult(SelectedGpxFile selectedGpxFile) {
MapActivity mapActivity = mapActivityRef.get();
if (mapActivity != null && selectedGpxFile != null) {
showInstance(mapActivity, selectedGpxFile, latLon, returnScreenName);
}
return true;
}
});
}
public static boolean showInstance(@NonNull MapActivity mapActivity, @NonNull SelectedGpxFile selectedGpxFile,
@Nullable LatLon latLon, @Nullable String returnScreenName) {
try {

View file

@ -0,0 +1,48 @@
package net.osmand.plus.wikivoyage.data;
import androidx.annotation.NonNull;
import java.util.ArrayList;
import java.util.List;
public class PopularArticles {
public static final int ARTICLES_PER_PAGE = 30;
private List<TravelArticle> articles;
public PopularArticles() {
this.articles = new ArrayList<>();
}
public PopularArticles(@NonNull PopularArticles articles) {
this.articles = articles.articles;
}
public void clear() {
articles = new ArrayList<>();
}
@NonNull
public List<TravelArticle> getArticles() {
return new ArrayList<>(articles);
}
public boolean add(@NonNull TravelArticle article) {
articles.add(article);
return articles.size() % ARTICLES_PER_PAGE != 0;
}
public boolean contains(@NonNull TravelArticle article) {
return articles.contains(article);
}
public boolean containsByRouteId(@NonNull String routeId) {
for (TravelArticle article : articles) {
if (article.getRouteId().equals(routeId)) {
return true;
}
}
return false;
}
}

View file

@ -55,6 +55,7 @@ import static net.osmand.GPXUtilities.TrkSegment;
import static net.osmand.GPXUtilities.WptPt;
import static net.osmand.GPXUtilities.writeGpxFile;
import static net.osmand.plus.helpers.GpxUiHelper.getGpxTitle;
import static net.osmand.plus.wikivoyage.data.PopularArticles.ARTICLES_PER_PAGE;
import static net.osmand.plus.wikivoyage.data.TravelGpx.DIFF_ELE_DOWN;
import static net.osmand.plus.wikivoyage.data.TravelGpx.DIFF_ELE_UP;
import static net.osmand.plus.wikivoyage.data.TravelGpx.DISTANCE;
@ -69,16 +70,16 @@ public class TravelObfHelper implements TravelHelper {
public static final String ROUTE_ARTICLE = "route_article";
public static final String ROUTE_ARTICLE_POINT = "route_article_point";
public static final String ROUTE_TRACK = "route_track";
public static final int ARTICLE_SEARCH_RADIUS = 50000;
public static final int SAVED_ARTICLE_SEARCH_RADIUS = 30000;
public static final int MAX_POPULAR_ARTICLES_COUNT = 30;
public static final int ARTICLE_SEARCH_RADIUS = 50 * 1000;
public static final int SAVED_ARTICLE_SEARCH_RADIUS = 30 * 1000;
public static final int MAX_SEARCH_RADIUS = 10000 * 1000;
public static final String REF_TAG = "ref";
public static final String NAME_TAG = "name";
private final OsmandApplication app;
private final Collator collator;
private List<TravelArticle> popularArticles = new ArrayList<>();
private PopularArticles popularArticles = new PopularArticles();
private final Map<TravelArticleIdentifier, Map<String, TravelArticle>> cachedArticles = new ConcurrentHashMap<>();
private final TravelLocalDataHelper localDataHelper;
private int searchRadius = ARTICLE_SEARCH_RADIUS;
@ -113,13 +114,13 @@ public class TravelObfHelper implements TravelHelper {
}
@NonNull
public synchronized List<TravelArticle> loadPopularArticles() {
public synchronized PopularArticles loadPopularArticles() {
String lang = app.getLanguage();
List<TravelArticle> popularArticles = new ArrayList<>(this.popularArticles);
int pagesCount;
PopularArticles popularArticles = new PopularArticles(this.popularArticles);
if (isAnyTravelBookPresent()) {
boolean articlesLimitReached = false;
do {
if (foundAmenities.size() - foundAmenitiesIndex < MAX_POPULAR_ARTICLES_COUNT) {
if (foundAmenities.size() - foundAmenitiesIndex < ARTICLES_PER_PAGE) {
final LatLon location = app.getMapViewTrackingUtilities().getMapLocation();
for (final BinaryMapIndexReader reader : getReaders()) {
try {
@ -145,21 +146,25 @@ public class TravelObfHelper implements TravelHelper {
}
searchRadius *= 2;
}
pagesCount = popularArticles.size() / MAX_POPULAR_ARTICLES_COUNT;
while (foundAmenitiesIndex < foundAmenities.size() - 1) {
Pair<File, Amenity> amenity = foundAmenities.get(foundAmenitiesIndex);
if (!Algorithms.isEmpty(amenity.second.getName(lang))) {
TravelArticle article = cacheTravelArticles(amenity.first, amenity.second, lang, false, null);
if (article != null && !popularArticles.contains(article)) {
popularArticles.add(article);
if (popularArticles.size() >= (pagesCount + 1) * MAX_POPULAR_ARTICLES_COUNT) {
break;
Pair<File, Amenity> fileAmenity = foundAmenities.get(foundAmenitiesIndex);
File file = fileAmenity.first;
Amenity amenity = fileAmenity.second;
if (!Algorithms.isEmpty(amenity.getName(lang))) {
String routeId = amenity.getAdditionalInfo(Amenity.ROUTE_ID);
if (!popularArticles.containsByRouteId(routeId)) {
TravelArticle article = cacheTravelArticles(file, amenity, lang, false, null);
if (article != null && !popularArticles.contains(article)) {
if (!popularArticles.add(article)) {
articlesLimitReached = true;
break;
}
}
}
}
foundAmenitiesIndex++;
}
} while (popularArticles.size() < (pagesCount + 1) * MAX_POPULAR_ARTICLES_COUNT);
} while (!articlesLimitReached && searchRadius < MAX_SEARCH_RADIUS);
}
this.popularArticles = popularArticles;
return popularArticles;
@ -526,7 +531,7 @@ public class TravelObfHelper implements TravelHelper {
@NonNull
@Override
public List<TravelArticle> getPopularArticles() {
return popularArticles;
return popularArticles.getArticles();
}
@NonNull

View file

@ -156,7 +156,7 @@ public class ExploreRvAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
public void addNeededMapsCard(TravelNeededMapsCard card) {
this.neededMapsCard = card;
if (neededMapsCardExists(getNeededMapsCardPosition())) {
if (isCardExists(getNeededMapsCardPosition(), TravelNeededMapsCard.TYPE)) {
updateNeededMapsCard(false);
} else if (addItem(getNeededMapsCardPosition(), card)) {
notifyDataSetChanged();
@ -164,15 +164,15 @@ public class ExploreRvAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
}
public void updateNeededMapsCard(boolean onlyProgress) {
if(onlyProgress) {
if (onlyProgress) {
TravelNeededMapsCard nd = this.neededMapsCard;
if(nd != null) {
if (nd != null) {
nd.updateView();
}
return;
}
int pos = getNeededMapsCardPosition();
if (neededMapsCardExists(pos)) {
if (isCardExists(pos, TravelNeededMapsCard.TYPE)) {
notifyItemChanged(pos);
}
}
@ -180,42 +180,39 @@ public class ExploreRvAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
public void removeNeededMapsCard() {
this.neededMapsCard = null;
int pos = getNeededMapsCardPosition();
if (neededMapsCardExists(pos)) {
if (isCardExists(pos, TravelNeededMapsCard.TYPE)) {
removeItem(pos);
notifyItemRemoved(pos);
}
}
private int getNeededMapsCardPosition() {
if (downloadUpdateCardExists(FIRST_POSITION)) {
if (isCardExists(FIRST_POSITION, TravelDownloadUpdateCard.TYPE)) {
return SECOND_POSITION;
}
return FIRST_POSITION;
}
private boolean neededMapsCardExists(int position) {
return items.size() > position && items.get(position).getCardType() == TravelNeededMapsCard.TYPE;
}
public void addDownloadUpdateCard(TravelDownloadUpdateCard card) {
this.downloadCard = card;
if (downloadUpdateCardExists(getDownloadUpdateCardPosition())) {
int pos = getDownloadUpdateCardPosition();
if (isCardExists(pos, TravelDownloadUpdateCard.TYPE)) {
updateDownloadUpdateCard(false);
} else if (addItem(getDownloadUpdateCardPosition(), card)) {
} else if (addItem(pos, card)) {
notifyDataSetChanged();
}
}
public void updateDownloadUpdateCard(boolean onlyProgress) {
if(onlyProgress) {
if (onlyProgress) {
TravelDownloadUpdateCard dc = this.downloadCard;
if(dc != null) {
if (dc != null) {
dc.updateView();
}
return;
}
int pos = getDownloadUpdateCardPosition();
if (downloadUpdateCardExists(pos)) {
if (isCardExists(pos, TravelDownloadUpdateCard.TYPE)) {
notifyItemChanged(pos);
}
}
@ -223,7 +220,7 @@ public class ExploreRvAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
public void removeDownloadUpdateCard() {
this.downloadCard = null;
int pos = getDownloadUpdateCardPosition();
if (downloadUpdateCardExists(pos)) {
if (isCardExists(pos, TravelDownloadUpdateCard.TYPE)) {
removeItem(pos);
notifyItemRemoved(pos);
}
@ -233,7 +230,7 @@ public class ExploreRvAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
return FIRST_POSITION;
}
private boolean downloadUpdateCardExists(int position) {
return items.size() > position && items.get(position).getCardType() == TravelDownloadUpdateCard.TYPE;
private boolean isCardExists(int position, int cardType) {
return items.size() > position && items.get(position).getCardType() == cardType;
}
}

View file

@ -15,6 +15,7 @@ import androidx.fragment.app.FragmentManager;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import net.osmand.binary.BinaryMapIndexReader;
import net.osmand.data.LatLon;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
@ -46,6 +47,8 @@ import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
import static net.osmand.plus.download.DownloadResources.WIKIVOYAGE_FILE_FILTER;
import static net.osmand.plus.resources.ResourceManager.DEFAULT_WIKIVOYAGE_TRAVEL_OBF;
import static net.osmand.plus.wikivoyage.explore.WikivoyageExploreActivity.*;
public class ExploreTabFragment extends BaseOsmAndFragment implements DownloadEvents, TravelLocalDataHelper.Listener {
@ -186,7 +189,7 @@ public class ExploreTabFragment extends BaseOsmAndFragment implements DownloadEv
}
}
}
if (app.getTravelHelper().isAnyTravelBookPresent()) {
if (!isOnlyDefaultTravelBookPresent()) {
TravelButtonCard travelButtonCard = new TravelButtonCard(app, nightMode);
travelButtonCard.setListener(new TravelNeededMapsCard.CardListener() {
@Override
@ -248,8 +251,7 @@ public class ExploreTabFragment extends BaseOsmAndFragment implements DownloadEv
}
private void addIndexItemCards(List<IndexItem> mainIndexItem, List<IndexItem> neededIndexItems) {
final OsmandApplication app = getMyApplication();
if (app != null && !app.getTravelHelper().isAnyTravelBookPresent()) {
if (isOnlyDefaultTravelBookPresent()) {
this.mainIndexItems.clear();
this.mainIndexItems.addAll(mainIndexItem);
addDownloadUpdateCard();
@ -259,6 +261,18 @@ public class ExploreTabFragment extends BaseOsmAndFragment implements DownloadEv
addNeededMapsCard();
}
private boolean isOnlyDefaultTravelBookPresent() {
OsmandApplication app = getMyApplication();
if (app != null && !app.isApplicationInitializing()) {
for (BinaryMapIndexReader reader : app.getResourceManager().getTravelRepositories()) {
if (!reader.getFile().getName().equals(DEFAULT_WIKIVOYAGE_TRAVEL_OBF)) {
return false;
}
}
}
return true;
}
private void addDownloadUpdateCard() {
final OsmandApplication app = getMyApplication();
if (app != null && !mainIndexItems.isEmpty() && SHOW_TRAVEL_UPDATE_CARD) {
@ -286,7 +300,8 @@ public class ExploreTabFragment extends BaseOsmAndFragment implements DownloadEv
@Override
public void onIndexItemClick(IndexItem item) {
if (item.getType() == DownloadActivityType.WIKIPEDIA_FILE && !Version.isPaidVersion(app)) {
if ((item.getType() == DownloadActivityType.WIKIPEDIA_FILE
|| item.getType() == DownloadActivityType.TRAVEL_FILE) && !Version.isPaidVersion(app)) {
FragmentManager fm = getFragmentManager();
if (fm != null) {
ChoosePlanDialogFragment.showWikipediaInstance(fm);
@ -341,7 +356,8 @@ public class ExploreTabFragment extends BaseOsmAndFragment implements DownloadEv
@Override
public void onIndexItemClick(IndexItem item) {
if (item.getType() == DownloadActivityType.WIKIPEDIA_FILE && !Version.isPaidVersion(app)) {
if ((item.getType() == DownloadActivityType.WIKIPEDIA_FILE
|| item.getType() == DownloadActivityType.TRAVEL_FILE) && !Version.isPaidVersion(app)) {
FragmentManager fm = getFragmentManager();
if (fm != null) {
ChoosePlanDialogFragment.showWikipediaInstance(fm);
@ -403,7 +419,9 @@ public class ExploreTabFragment extends BaseOsmAndFragment implements DownloadEv
List<IndexItem> allWikivoyageItems = app.getDownloadThread().getIndexes().getWikivoyageItems();
if (allWikivoyageItems != null) {
for (IndexItem item : allWikivoyageItems) {
if (!item.isDownloaded() && !mainItems.contains(item)) {
if (!item.isDownloaded()
&& !mainItems.contains(item)
&& item.getFileName().contains(WIKIVOYAGE_FILE_FILTER)) {
mainItems.add(item);
}
}

View file

@ -111,7 +111,7 @@ public class TravelNeededMapsCard extends BaseTravelCard {
boolean downloading = downloadThread.isDownloading(item);
boolean currentDownloading = downloading && downloadThread.getCurrentDownloadingItem() == item;
boolean lastItem = i == items.size() - 1;
View view = holder.itemsContainer.getChildAt(i);
final View view = holder.itemsContainer.getChildAt(i);
if (item.isDownloaded()) {
view.setOnClickListener(null);
@ -131,12 +131,23 @@ public class TravelNeededMapsCard extends BaseTravelCard {
if (item.isDownloaded()) {
iconAction.setVisibility(View.GONE);
buttonAction.setVisibility(View.GONE);
} else {
boolean showBtn = !paidVersion && item.getType() == DownloadActivityType.WIKIPEDIA_FILE;
boolean showBtn = !paidVersion
&& (item.getType() == DownloadActivityType.WIKIPEDIA_FILE
|| item.getType() == DownloadActivityType.TRAVEL_FILE);
iconAction.setVisibility(showBtn ? View.GONE : View.VISIBLE);
buttonAction.setVisibility(showBtn ? View.VISIBLE : View.GONE);
if (!showBtn) {
if (showBtn) {
buttonAction.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
view.callOnClick();
}
});
} else {
iconAction.setImageDrawable(downloading ? cancelIcon : downloadIcon);
buttonAction.setOnClickListener(null);
}
}
@ -195,7 +206,7 @@ public class TravelNeededMapsCard extends BaseTravelCard {
* @return true if button is visible, false otherwise.
*/
private boolean updatePrimaryButton(NeededMapsVH vh) {
if (showPrimaryButton()) {
if (showPrimaryButton() && Version.isPaidVersion(app)) {
boolean enabled = isInternetAvailable();
vh.primaryBtnContainer.setVisibility(View.VISIBLE);
vh.primaryBtnContainer.setBackgroundResource(getPrimaryBtnBgRes(enabled));