From 99ae414d1d36cad58759bdc98bb28f205509da09 Mon Sep 17 00:00:00 2001 From: Nekromanser <78290702+Nekromanser@users.noreply.github.com> Date: Mon, 1 Feb 2021 10:17:32 +0000 Subject: [PATCH 01/65] Update phrases.xml Improved finnish translation and fixed typos. --- OsmAnd/res/values-fi/phrases.xml | 42 ++++++++++++++++---------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/OsmAnd/res/values-fi/phrases.xml b/OsmAnd/res/values-fi/phrases.xml index 7751c5bb95..6453253dd4 100644 --- a/OsmAnd/res/values-fi/phrases.xml +++ b/OsmAnd/res/values-fi/phrases.xml @@ -17,7 +17,7 @@ Bussipysäkki Trollibussin pysäkki Raitiovaunupysäkki - Piknic paikka + Piknik-paikka Merkittävä kivi Ankkurointipaikka Majakka/linjavalo @@ -311,8 +311,8 @@ Ei Visa Electron -kortteja Shekit Shekkejä ei hyväksytä - Visa Debit -kortit - Ei Visa Debit -kortteja + Visa Debit-kortit + Ei Visa Debit-kortteja Muut Muita maksutapoja ei hyväksytä Bancomat @@ -1139,28 +1139,28 @@ Ei MasterCard-kortteja Maestro-kortit Ei Maestro-kortteja - Ei American Express (AMEX) -kortteja - Ei Diners Club -kortteja + Ei American Express (AMEX)-kortteja + Ei Diners Club-kortteja Ei DKV-kortteja Ei UTA-kortteja Ei Efectivo-maksua Ei Girocard-kortteja Discover Card - Ei Discover Card -kortteja + Ei Discover Card-kortteja Ei Litecoinia Ei PIKEPASS-maksua Ei kryptovaluuttaa - Ei Routex -tankkauskortteja - Ei IC Stored Fare -kortteja + Ei Routex-tankkauskortteja + Ei IC Stored Fare-kortteja Ei JCB-kortteja Ei Laser-kortteja Ei Quick-kortteja Ei Eurowag-kortteja - Ei E-ZPass -maksua + Ei E-ZPass-maksua Ei Euroshell-tankkauskortteja Ei KITCard-maksua Ei Westfalen-kortteja - Ei V PAY -kortteja + Ei V PAY-kortteja Ei Dogecoinia Ei Cibus-kortteja Ei maksua tilisiirrolla @@ -1172,7 +1172,7 @@ Ei Minipay-maksua Ei MiniCash-maksua Ei Moneo-maksua - Ei Monedero 4B -maksua + Ei Monedero 4B-maksua Ei Monedero-maksua Ei BankAxess-maksua Ei Coinkite-maksua @@ -1182,20 +1182,20 @@ Ei tekstiviestimaksua Ei Oyster-kortteja Ei SUBE-kortteja - Ei Via Verde -maksua + Ei Via Verde-maksua Lounassetelit Ei lounasseteleitä Ei PayPal-maksua - Ei U-Key -maksua + Ei U-Key-maksua Poletit Ei poletteja Ei lahjakorttimaksua - Ei Golden Crown -kortteja + Ei Golden Crown-kortteja Ei PRO100-kortteja - Ei Union Card -kortteja + Ei Union Card-kortteja Ei MTS-Money -maksua - Ei Yandex.Money -maksua - Ei OV-Chipkaart -kortteja + Ei Yandex.Money-maksua + Ei OV-Chipkaart-kortteja Tapahtumapaikka Vain kasvisruokaa Kasvisruokaa @@ -1245,9 +1245,9 @@ Sisätilat Ulkona Ei wc-tiloja - Inva-wc: kyllä - Inva-wc: ei - Asiakas-wc + Inva-WC: kyllä + Inva-WC: ei + Asiakas-WC WC:n käyttö: yhteisö WC:n käyttö: julkinen Vauvan vaihtopöytä @@ -1522,4 +1522,4 @@ Vieras talo Majapaikka Vuoristorata - \ No newline at end of file + From cfa202c3d4d459e0cf67b6f4310f1ea76e64935a Mon Sep 17 00:00:00 2001 From: nazar-kutz Date: Mon, 1 Feb 2021 12:44:49 +0200 Subject: [PATCH 02/65] refactor server wrong response checking move OnlineRoutingResponse class to OnlineRoutingEngine --- .../onlinerouting/OnlineRoutingHelper.java | 1 + .../onlinerouting/OnlineRoutingResponse.java | 24 ------ .../engine/GraphhopperEngine.java | 23 +++--- .../engine/OnlineRoutingEngine.java | 76 ++++++++++++++++--- .../plus/onlinerouting/engine/OrsEngine.java | 24 +++--- .../plus/onlinerouting/engine/OsrmEngine.java | 26 +++---- .../ui/OnlineRoutingEngineFragment.java | 8 +- .../osmand/plus/routing/RouteProvider.java | 2 +- 8 files changed, 103 insertions(+), 81 deletions(-) delete mode 100644 OsmAnd/src/net/osmand/plus/onlinerouting/OnlineRoutingResponse.java diff --git a/OsmAnd/src/net/osmand/plus/onlinerouting/OnlineRoutingHelper.java b/OsmAnd/src/net/osmand/plus/onlinerouting/OnlineRoutingHelper.java index ab56cade13..de36b87449 100644 --- a/OsmAnd/src/net/osmand/plus/onlinerouting/OnlineRoutingHelper.java +++ b/OsmAnd/src/net/osmand/plus/onlinerouting/OnlineRoutingHelper.java @@ -9,6 +9,7 @@ import net.osmand.osm.io.NetworkUtils; import net.osmand.plus.OsmandApplication; import net.osmand.plus.Version; import net.osmand.plus.onlinerouting.engine.OnlineRoutingEngine; +import net.osmand.plus.onlinerouting.engine.OnlineRoutingEngine.OnlineRoutingResponse; import net.osmand.plus.settings.backend.OsmandSettings; import net.osmand.util.Algorithms; diff --git a/OsmAnd/src/net/osmand/plus/onlinerouting/OnlineRoutingResponse.java b/OsmAnd/src/net/osmand/plus/onlinerouting/OnlineRoutingResponse.java deleted file mode 100644 index 02a6a8f53c..0000000000 --- a/OsmAnd/src/net/osmand/plus/onlinerouting/OnlineRoutingResponse.java +++ /dev/null @@ -1,24 +0,0 @@ -package net.osmand.plus.onlinerouting; - -import net.osmand.Location; -import net.osmand.plus.routing.RouteDirectionInfo; - -import java.util.List; - -public class OnlineRoutingResponse { - private List route; - private List directions; - - public OnlineRoutingResponse(List route, List directions) { - this.route = route; - this.directions = directions; - } - - public List getRoute() { - return route; - } - - public List getDirections() { - return directions; - } -} diff --git a/OsmAnd/src/net/osmand/plus/onlinerouting/engine/GraphhopperEngine.java b/OsmAnd/src/net/osmand/plus/onlinerouting/engine/GraphhopperEngine.java index 20bbfaa70e..930ebcab8d 100644 --- a/OsmAnd/src/net/osmand/plus/onlinerouting/engine/GraphhopperEngine.java +++ b/OsmAnd/src/net/osmand/plus/onlinerouting/engine/GraphhopperEngine.java @@ -8,7 +8,6 @@ import net.osmand.data.LatLon; import net.osmand.plus.OsmandApplication; import net.osmand.plus.R; import net.osmand.plus.onlinerouting.EngineParameter; -import net.osmand.plus.onlinerouting.OnlineRoutingResponse; import net.osmand.plus.onlinerouting.VehicleType; import net.osmand.plus.routing.RouteDirectionInfo; import net.osmand.router.TurnType; @@ -84,12 +83,9 @@ public class GraphhopperEngine extends OnlineRoutingEngine { @Nullable @Override - public OnlineRoutingResponse parseServerResponse(@NonNull String content, + public OnlineRoutingResponse parseServerResponse(@NonNull JSONObject root, @NonNull OsmandApplication app, boolean leftSideNavigation) throws JSONException { - JSONObject obj = new JSONObject(content); - JSONObject root = obj.getJSONArray("paths").getJSONObject(0); - String encoded = root.getString("points"); List points = GeoPolylineParserUtil.parse(encoded, GeoPolylineParserUtil.PRECISION_5); if (isEmpty(points)) return null; @@ -216,14 +212,15 @@ public class GraphhopperEngine extends OnlineRoutingEngine { return id != null ? TurnType.valueOf(id, leftSide) : null; } + @NonNull @Override - public boolean parseServerMessage(@NonNull StringBuilder sb, - @NonNull String content) throws JSONException { - JSONObject obj = new JSONObject(content); - if (obj.has("message")) { - String message = obj.getString("message"); - sb.append(message); - } - return obj.has("paths"); + protected String getErrorMessageKey() { + return "message"; + } + + @NonNull + @Override + protected String getRootArrayKey() { + return "paths"; } } diff --git a/OsmAnd/src/net/osmand/plus/onlinerouting/engine/OnlineRoutingEngine.java b/OsmAnd/src/net/osmand/plus/onlinerouting/engine/OnlineRoutingEngine.java index 24e5db7d5d..0752282c70 100644 --- a/OsmAnd/src/net/osmand/plus/onlinerouting/engine/OnlineRoutingEngine.java +++ b/OsmAnd/src/net/osmand/plus/onlinerouting/engine/OnlineRoutingEngine.java @@ -12,12 +12,14 @@ import net.osmand.plus.OsmandApplication; import net.osmand.plus.R; import net.osmand.plus.onlinerouting.EngineParameter; import net.osmand.plus.onlinerouting.OnlineRoutingFactory; -import net.osmand.plus.onlinerouting.OnlineRoutingResponse; import net.osmand.plus.onlinerouting.VehicleType; +import net.osmand.plus.routing.RouteDirectionInfo; import net.osmand.plus.routing.RouteProvider; import net.osmand.util.Algorithms; +import org.json.JSONArray; import org.json.JSONException; +import org.json.JSONObject; import java.util.ArrayList; import java.util.Arrays; @@ -98,10 +100,31 @@ public abstract class OnlineRoutingEngine implements Cloneable { @NonNull public abstract String getStandardUrl(); + public OnlineRoutingResponse parseServerResponse(@NonNull String content, + @NonNull OsmandApplication app, + boolean leftSideNavigation) throws JSONException { + JSONObject root = parseRootResponseObject(content); + return root != null ? parseServerResponse(root, app, leftSideNavigation) : null; + } + @Nullable - public abstract OnlineRoutingResponse parseServerResponse(@NonNull String content, - @NonNull OsmandApplication app, - boolean leftSideNavigation) throws JSONException; + protected abstract OnlineRoutingResponse parseServerResponse(@NonNull JSONObject root, + @NonNull OsmandApplication app, + boolean leftSideNavigation) throws JSONException; + + @Nullable + protected JSONObject parseRootResponseObject(@NonNull String content) throws JSONException { + JSONObject fullJSON = new JSONObject(content); + String responseArrayKey = getRootArrayKey(); + JSONArray array = null; + if (fullJSON.has(responseArrayKey)) { + array = fullJSON.getJSONArray(responseArrayKey); + } + return array != null && array.length() > 0 ? array.getJSONObject(0) : null; + } + + @NonNull + protected abstract String getRootArrayKey(); @NonNull protected List convertRouteToLocationsList(@NonNull List route) { @@ -161,7 +184,7 @@ public abstract class OnlineRoutingEngine implements Cloneable { return allowedParameters.contains(key); } - protected void allowParameters(@NonNull EngineParameter ... allowedParams) { + protected void allowParameters(@NonNull EngineParameter... allowedParams) { allowedParameters.addAll(Arrays.asList(allowedParams)); } @@ -193,8 +216,19 @@ public abstract class OnlineRoutingEngine implements Cloneable { return CUSTOM_VEHICLE; } - public abstract boolean parseServerMessage(@NonNull StringBuilder sb, - @NonNull String content) throws JSONException; + public boolean checkServerResponse(@NonNull StringBuilder errorMessage, + @NonNull String content) throws JSONException { + JSONObject obj = new JSONObject(content); + String messageKey = getErrorMessageKey(); + if (obj.has(messageKey)) { + String message = obj.getString(messageKey); + errorMessage.append(message); + } + return obj.has(getRootArrayKey()); + } + + @NonNull + protected abstract String getErrorMessageKey(); @NonNull @Override @@ -202,11 +236,6 @@ public abstract class OnlineRoutingEngine implements Cloneable { return OnlineRoutingFactory.createEngine(getType(), getParams()); } - @NonNull - public static String generateKey() { - return ONLINE_ROUTING_ENGINE_PREFIX + System.currentTimeMillis(); - } - @Override public boolean equals(Object o) { if (this == o) return true; @@ -216,4 +245,27 @@ public abstract class OnlineRoutingEngine implements Cloneable { if (getType() != engine.getType()) return false; return Algorithms.objectEquals(getParams(), engine.getParams()); } + + @NonNull + public static String generateKey() { + return ONLINE_ROUTING_ENGINE_PREFIX + System.currentTimeMillis(); + } + + public static class OnlineRoutingResponse { + private List route; + private List directions; + + public OnlineRoutingResponse(List route, List directions) { + this.route = route; + this.directions = directions; + } + + public List getRoute() { + return route; + } + + public List getDirections() { + return directions; + } + } } diff --git a/OsmAnd/src/net/osmand/plus/onlinerouting/engine/OrsEngine.java b/OsmAnd/src/net/osmand/plus/onlinerouting/engine/OrsEngine.java index 5f8c2a5108..ed9168ccf9 100644 --- a/OsmAnd/src/net/osmand/plus/onlinerouting/engine/OrsEngine.java +++ b/OsmAnd/src/net/osmand/plus/onlinerouting/engine/OrsEngine.java @@ -8,7 +8,6 @@ import net.osmand.data.LatLon; import net.osmand.plus.OsmandApplication; import net.osmand.plus.R; import net.osmand.plus.onlinerouting.EngineParameter; -import net.osmand.plus.onlinerouting.OnlineRoutingResponse; import net.osmand.plus.onlinerouting.VehicleType; import org.json.JSONArray; @@ -81,12 +80,10 @@ public class OrsEngine extends OnlineRoutingEngine { @Nullable @Override - public OnlineRoutingResponse parseServerResponse(@NonNull String content, + public OnlineRoutingResponse parseServerResponse(@NonNull JSONObject root, @NonNull OsmandApplication app, boolean leftSideNavigation) throws JSONException { - JSONObject obj = new JSONObject(content); - JSONArray array = obj.getJSONArray("features").getJSONObject(0) - .getJSONObject("geometry").getJSONArray("coordinates"); + JSONArray array = root.getJSONObject("geometry").getJSONArray("coordinates"); List points = new ArrayList<>(); for (int i = 0; i < array.length(); i++) { JSONArray point = array.getJSONArray(i); @@ -101,14 +98,15 @@ public class OrsEngine extends OnlineRoutingEngine { return null; } + @NonNull @Override - public boolean parseServerMessage(@NonNull StringBuilder sb, - @NonNull String content) throws JSONException { - JSONObject obj = new JSONObject(content); - if (obj.has("error")) { - String message = obj.getString("error"); - sb.append(message); - } - return obj.has("features"); + protected String getErrorMessageKey() { + return "error"; + } + + @NonNull + @Override + protected String getRootArrayKey() { + return "features"; } } diff --git a/OsmAnd/src/net/osmand/plus/onlinerouting/engine/OsrmEngine.java b/OsmAnd/src/net/osmand/plus/onlinerouting/engine/OsrmEngine.java index 2e892d2aa6..4d75b2b440 100644 --- a/OsmAnd/src/net/osmand/plus/onlinerouting/engine/OsrmEngine.java +++ b/OsmAnd/src/net/osmand/plus/onlinerouting/engine/OsrmEngine.java @@ -8,7 +8,6 @@ import net.osmand.data.LatLon; import net.osmand.plus.OsmandApplication; import net.osmand.plus.R; import net.osmand.plus.onlinerouting.EngineParameter; -import net.osmand.plus.onlinerouting.OnlineRoutingResponse; import net.osmand.plus.onlinerouting.VehicleType; import net.osmand.plus.routing.RouteCalculationResult; import net.osmand.plus.routing.RouteDirectionInfo; @@ -77,19 +76,17 @@ public class OsrmEngine extends OnlineRoutingEngine { @Nullable @Override - public OnlineRoutingResponse parseServerResponse(@NonNull String content, + public OnlineRoutingResponse parseServerResponse(@NonNull JSONObject root, @NonNull OsmandApplication app, boolean leftSideNavigation) throws JSONException { - JSONObject obj = new JSONObject(content); - JSONObject routeInfo = obj.getJSONArray("routes").getJSONObject(0); - String encodedPoints = routeInfo.getString("geometry"); + String encodedPoints = root.getString("geometry"); List points = GeoPolylineParserUtil.parse(encodedPoints, GeoPolylineParserUtil.PRECISION_5); if (isEmpty(points)) return null; List route = convertRouteToLocationsList(points); List directions = new ArrayList<>(); int startSearchingId = 0; - JSONArray legs = routeInfo.getJSONArray("legs"); + JSONArray legs = root.getJSONArray("legs"); for (int i = 0; i < legs.length(); i++) { JSONObject leg = legs.getJSONObject(i); if (!leg.has("steps")) continue; @@ -226,14 +223,15 @@ public class OsrmEngine extends OnlineRoutingEngine { return id != null ? TurnType.valueOf(id, leftSide) : null; } + @NonNull @Override - public boolean parseServerMessage(@NonNull StringBuilder sb, - @NonNull String content) throws JSONException { - JSONObject obj = new JSONObject(content); - if (obj.has("message")) { - String message = obj.getString("message"); - sb.append(message); - } - return obj.has("routes"); + protected String getErrorMessageKey() { + return "message"; + } + + @NonNull + @Override + protected String getRootArrayKey() { + return "routes"; } } diff --git a/OsmAnd/src/net/osmand/plus/onlinerouting/ui/OnlineRoutingEngineFragment.java b/OsmAnd/src/net/osmand/plus/onlinerouting/ui/OnlineRoutingEngineFragment.java index 84856139b2..008bb75852 100644 --- a/OsmAnd/src/net/osmand/plus/onlinerouting/ui/OnlineRoutingEngineFragment.java +++ b/OsmAnd/src/net/osmand/plus/onlinerouting/ui/OnlineRoutingEngineFragment.java @@ -458,15 +458,15 @@ public class OnlineRoutingEngineFragment extends BaseOsmAndFragment { new Thread(new Runnable() { @Override public void run() { - StringBuilder message = new StringBuilder(); + StringBuilder errorMessage = new StringBuilder(); boolean resultOk = false; try { String response = helper.makeRequest(exampleCard.getEditedText()); - resultOk = requestedEngine.parseServerMessage(message, response); + resultOk = requestedEngine.checkServerResponse(errorMessage, response); } catch (IOException | JSONException e) { - message.append(e.toString()); + errorMessage.append(e.toString()); } - showTestResults(resultOk, message.toString(), location); + showTestResults(resultOk, errorMessage.toString(), location); } }).start(); } diff --git a/OsmAnd/src/net/osmand/plus/routing/RouteProvider.java b/OsmAnd/src/net/osmand/plus/routing/RouteProvider.java index 0d2564eb3e..b3b2a11ab6 100644 --- a/OsmAnd/src/net/osmand/plus/routing/RouteProvider.java +++ b/OsmAnd/src/net/osmand/plus/routing/RouteProvider.java @@ -21,7 +21,7 @@ import net.osmand.data.LocationPoint; import net.osmand.data.WptLocationPoint; import net.osmand.plus.OsmandApplication; import net.osmand.plus.onlinerouting.OnlineRoutingHelper; -import net.osmand.plus.onlinerouting.OnlineRoutingResponse; +import net.osmand.plus.onlinerouting.engine.OnlineRoutingEngine.OnlineRoutingResponse; import net.osmand.plus.settings.backend.OsmandSettings; import net.osmand.plus.settings.backend.CommonPreference; import net.osmand.plus.R; From 353c2d167619b6f968493d2d82047b62e571d79a Mon Sep 17 00:00:00 2001 From: nazar-kutz Date: Mon, 1 Feb 2021 17:43:20 +0200 Subject: [PATCH 03/65] Data storage refactoring, step 1 --- OsmAnd/res/xml/global_settings.xml | 2 +- .../osmand/plus/activities/MapActivity.java | 2 +- .../ChangeDataStorageBottomSheet.java | 16 +- .../DataStorageFragment.java | 253 ++------- .../datastorage/DataStorageHelper.java | 318 ++++++++++++ .../datastorage/item/DirectoryItem.java | 40 ++ .../item/MemoryItem.java} | 60 +-- .../item/StorageItem.java} | 30 +- .../datastorage/task/MoveFilesTask.java | 173 +++++++ .../task/RefreshUsedMemoryTask.java | 184 +++++++ .../datastorage/task/ReloadDataTask.java | 50 ++ .../fragments/BaseSettingsFragment.java | 1 + .../settings/fragments/DataStorageHelper.java | 485 ------------------ .../fragments/GlobalSettingsFragment.java | 4 +- 14 files changed, 841 insertions(+), 777 deletions(-) rename OsmAnd/src/net/osmand/plus/settings/{fragments => datastorage}/DataStorageFragment.java (70%) create mode 100644 OsmAnd/src/net/osmand/plus/settings/datastorage/DataStorageHelper.java create mode 100644 OsmAnd/src/net/osmand/plus/settings/datastorage/item/DirectoryItem.java rename OsmAnd/src/net/osmand/plus/settings/{fragments/DataStorageMemoryItem.java => datastorage/item/MemoryItem.java} (52%) rename OsmAnd/src/net/osmand/plus/settings/{fragments/DataStorageMenuItem.java => datastorage/item/StorageItem.java} (78%) create mode 100644 OsmAnd/src/net/osmand/plus/settings/datastorage/task/MoveFilesTask.java create mode 100644 OsmAnd/src/net/osmand/plus/settings/datastorage/task/RefreshUsedMemoryTask.java create mode 100644 OsmAnd/src/net/osmand/plus/settings/datastorage/task/ReloadDataTask.java delete mode 100644 OsmAnd/src/net/osmand/plus/settings/fragments/DataStorageHelper.java diff --git a/OsmAnd/res/xml/global_settings.xml b/OsmAnd/res/xml/global_settings.xml index 7ba1dce420..1cb0e2e93d 100644 --- a/OsmAnd/res/xml/global_settings.xml +++ b/OsmAnd/res/xml/global_settings.xml @@ -22,7 +22,7 @@ android:layout="@layout/preference_with_descr" android:persistent="false" android:title="@string/application_dir" - app:fragment="net.osmand.plus.settings.fragments.DataStorageFragment" + app:fragment="net.osmand.plus.settings.datastorage.DataStorageFragment" tools:icon="@drawable/ic_action_folder" /> menuItems; - private ArrayList memoryItems; + private ArrayList storageItems; + private ArrayList memoryItems; private ArrayList dataStorageRadioButtonsGroup; private Preference changeButton; - private DataStorageMenuItem currentDataStorage; + private StorageItem currentDataStorage; private String tmpManuallySpecifiedPath; private DataStorageHelper dataStorageHelper; private boolean calculateTilesBtnPressed; - private DataStorageHelper.RefreshMemoryUsedInfo calculateMemoryTask; - private DataStorageHelper.RefreshMemoryUsedInfo calculateTilesMemoryTask; + private RefreshUsedMemoryTask calculateMemoryTask; + private RefreshUsedMemoryTask calculateTilesMemoryTask; private OsmandApplication app; private OsmandActionBarActivity activity; @@ -95,11 +94,11 @@ public class DataStorageFragment extends BaseSettingsFragment implements DataSto return; } - menuItems = dataStorageHelper.getStorageItems(); + storageItems = dataStorageHelper.getStorageItems(); memoryItems = dataStorageHelper.getMemoryInfoItems(); dataStorageRadioButtonsGroup = new ArrayList<>(); - for (DataStorageMenuItem item : menuItems) { + for (StorageItem item : storageItems) { CheckBoxPreference preference = new CheckBoxPreference(activity); preference.setKey(item.getKey()); preference.setTitle(item.getTitle()); @@ -136,7 +135,7 @@ public class DataStorageFragment extends BaseSettingsFragment implements DataSto Bundle resultData = (Bundle) newValue; if (resultData.containsKey(ChangeDataStorageBottomSheet.TAG)) { boolean moveMaps = resultData.getBoolean(MOVE_DATA); - DataStorageMenuItem newDataStorage = resultData.getParcelable(CHOSEN_DIRECTORY); + StorageItem newDataStorage = resultData.getParcelable(CHOSEN_DIRECTORY); if (newDataStorage != null) { if (tmpManuallySpecifiedPath != null) { String directory = tmpManuallySpecifiedPath; @@ -154,9 +153,9 @@ public class DataStorageFragment extends BaseSettingsFragment implements DataSto if (pathChanged) { tmpManuallySpecifiedPath = resultData.getString(NEW_PATH); if (tmpManuallySpecifiedPath != null) { - DataStorageMenuItem manuallySpecified = null; + StorageItem manuallySpecified = null; try { - manuallySpecified = (DataStorageMenuItem) dataStorageHelper.getManuallySpecified().clone(); + manuallySpecified = (StorageItem) dataStorageHelper.getManuallySpecified().clone(); manuallySpecified.setDirectory(tmpManuallySpecifiedPath); } catch (CloneNotSupportedException e) { return false; @@ -170,7 +169,7 @@ public class DataStorageFragment extends BaseSettingsFragment implements DataSto //show necessary dialog String key = preference.getKey(); if (key != null) { - DataStorageMenuItem newDataStorage = dataStorageHelper.getStorage(key); + StorageItem newDataStorage = dataStorageHelper.getStorage(key); if (newDataStorage != null) { if (!currentDataStorage.getKey().equals(newDataStorage.getKey())) { if (newDataStorage.getType() == OsmandSettings.EXTERNAL_STORAGE_TYPE_DEFAULT @@ -212,7 +211,7 @@ public class DataStorageFragment extends BaseSettingsFragment implements DataSto final View itemView = holder.itemView; if (preference instanceof CheckBoxPreference) { - DataStorageMenuItem item = dataStorageHelper.getStorage(key); + StorageItem item = dataStorageHelper.getStorage(key); if (item != null) { TextView tvTitle = itemView.findViewById(android.R.id.title); TextView tvSummary = itemView.findViewById(R.id.summary); @@ -267,7 +266,7 @@ public class DataStorageFragment extends BaseSettingsFragment implements DataSto TextView tvSummary = itemView.findViewById(R.id.summary); tvSummary.setText(DataStorageHelper.getFormattedMemoryInfo(totalUsageBytes, memoryUnitsFormats)); } else { - for (DataStorageMemoryItem mi : memoryItems) { + for (MemoryItem mi : memoryItems) { if (key.equals(mi.getKey())) { TextView tvMemory = itemView.findViewById(R.id.memory); String summary = ""; @@ -326,7 +325,7 @@ public class DataStorageFragment extends BaseSettingsFragment implements DataSto } private void showFolderSelectionDialog() { - DataStorageMenuItem manuallySpecified = dataStorageHelper.getManuallySpecified(); + StorageItem manuallySpecified = dataStorageHelper.getManuallySpecified(); if (manuallySpecified != null) { SelectFolderBottomSheet.showInstance(getFragmentManager(), manuallySpecified.getKey(), manuallySpecified.getDirectory(), DataStorageFragment.this, @@ -335,11 +334,11 @@ public class DataStorageFragment extends BaseSettingsFragment implements DataSto } } - private void moveData(final DataStorageMenuItem currentStorage, final DataStorageMenuItem newStorage) { + private void moveData(final StorageItem currentStorage, final StorageItem newStorage) { File fromDirectory = new File(currentStorage.getDirectory()); File toDirectory = new File(newStorage.getDirectory()); @SuppressLint("StaticFieldLeak") - MoveFilesToDifferentDirectory task = new MoveFilesToDifferentDirectory(activity, fromDirectory, toDirectory) { + MoveFilesTask task = new MoveFilesTask(activity, fromDirectory, toDirectory) { @NonNull @@ -405,7 +404,7 @@ public class DataStorageFragment extends BaseSettingsFragment implements DataSto task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } - private void confirm(OsmandApplication app, OsmandActionBarActivity activity, DataStorageMenuItem newStorageDirectory, boolean silentRestart) { + private void confirm(OsmandApplication app, OsmandActionBarActivity activity, StorageItem newStorageDirectory, boolean silentRestart) { String newDirectory = newStorageDirectory.getDirectory(); int type = newStorageDirectory.getType(); File newDirectoryFile = new File(newDirectory); @@ -454,7 +453,7 @@ public class DataStorageFragment extends BaseSettingsFragment implements DataSto } protected void reloadData() { - new ReloadData(activity, app).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void) null); + new ReloadDataTask(activity, app).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void) null); } @Override @@ -469,198 +468,4 @@ public class DataStorageFragment extends BaseSettingsFragment implements DataSto app.getSettings().OSMAND_USAGE_SPACE.set(dataStorageHelper.getTotalUsedBytes()); } } - - public static class MoveFilesToDifferentDirectory extends AsyncTask { - - protected WeakReference activity; - private WeakReference context; - private File from; - private File to; - protected ProgressImplementation progress; - private Runnable runOnSuccess; - private int movedCount; - private long movedSize; - private int copiedCount; - private long copiedSize; - private int failedCount; - private long failedSize; - private String exceptionMessage; - - public MoveFilesToDifferentDirectory(OsmandActionBarActivity activity, File from, File to) { - this.activity = new WeakReference<>(activity); - this.context = new WeakReference<>((Context) activity); - this.from = from; - this.to = to; - } - - public void setRunOnSuccess(Runnable runOnSuccess) { - this.runOnSuccess = runOnSuccess; - } - - public int getMovedCount() { - return movedCount; - } - - public int getCopiedCount() { - return copiedCount; - } - - public int getFailedCount() { - return failedCount; - } - - public long getMovedSize() { - return movedSize; - } - - public long getCopiedSize() { - return copiedSize; - } - - public long getFailedSize() { - return failedSize; - } - - @Override - protected void onPreExecute() { - Context ctx = context.get(); - if (context == null) { - return; - } - movedCount = 0; - copiedCount = 0; - failedCount = 0; - progress = ProgressImplementation.createProgressDialog( - ctx, ctx.getString(R.string.copying_osmand_files), - ctx.getString(R.string.copying_osmand_files_descr, to.getPath()), - ProgressDialog.STYLE_HORIZONTAL); - } - - @Override - protected void onPostExecute(Boolean result) { - Context ctx = context.get(); - if (ctx == null) { - return; - } - if (result != null) { - if (result.booleanValue() && runOnSuccess != null) { - runOnSuccess.run(); - } else if (!result.booleanValue()) { - Toast.makeText(ctx, ctx.getString(R.string.shared_string_io_error) + ": " + exceptionMessage, Toast.LENGTH_LONG).show(); - } - } - try { - if (progress.getDialog().isShowing()) { - progress.getDialog().dismiss(); - } - } catch (Exception e) { - //ignored - } - } - - private void movingFiles(File f, File t, int depth) throws IOException { - Context ctx = context.get(); - if (ctx == null) { - return; - } - if (depth <= 2) { - progress.startTask(ctx.getString(R.string.copying_osmand_one_file_descr, t.getName()), -1); - } - if (f.isDirectory()) { - t.mkdirs(); - File[] lf = f.listFiles(); - if (lf != null) { - for (int i = 0; i < lf.length; i++) { - if (lf[i] != null) { - movingFiles(lf[i], new File(t, lf[i].getName()), depth + 1); - } - } - } - f.delete(); - } else if (f.isFile()) { - if (t.exists()) { - Algorithms.removeAllFiles(t); - } - boolean rnm = false; - long fileSize = f.length(); - try { - rnm = f.renameTo(t); - movedCount++; - movedSize += fileSize; - } catch (RuntimeException e) { - } - if (!rnm) { - FileInputStream fin = new FileInputStream(f); - FileOutputStream fout = new FileOutputStream(t); - try { - progress.startTask(ctx.getString(R.string.copying_osmand_one_file_descr, t.getName()), (int) (f.length() / 1024)); - Algorithms.streamCopy(fin, fout, progress, 1024); - copiedCount++; - copiedSize += fileSize; - } catch (IOException e) { - failedCount++; - failedSize += fileSize; - } finally { - fin.close(); - fout.close(); - } - f.delete(); - } - } - if (depth <= 2) { - progress.finishTask(); - } - } - - @Override - protected Boolean doInBackground(Void... params) { - to.mkdirs(); - try { - movingFiles(from, to, 0); - } catch (IOException e) { - exceptionMessage = e.getMessage(); - return false; - } - return true; - } - - } - - public static class ReloadData extends AsyncTask { - private WeakReference ctx; - protected ProgressImplementation progress; - private OsmandApplication app; - - public ReloadData(Context ctx, OsmandApplication app) { - this.ctx = new WeakReference<>(ctx); - this.app = app; - } - - @Override - protected void onPreExecute() { - Context c = ctx.get(); - if (c == null) { - return; - } - progress = ProgressImplementation.createProgressDialog(c, c.getString(R.string.loading_data), - c.getString(R.string.loading_data), ProgressDialog.STYLE_HORIZONTAL); - } - - @Override - protected void onPostExecute(Boolean result) { - try { - if (progress.getDialog().isShowing()) { - progress.getDialog().dismiss(); - } - } catch (Exception e) { - //ignored - } - } - - @Override - protected Boolean doInBackground(Void... params) { - app.getResourceManager().reloadIndexes(progress, new ArrayList()); - return true; - } - } } \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/settings/datastorage/DataStorageHelper.java b/OsmAnd/src/net/osmand/plus/settings/datastorage/DataStorageHelper.java new file mode 100644 index 0000000000..96a939eae3 --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/settings/datastorage/DataStorageHelper.java @@ -0,0 +1,318 @@ +package net.osmand.plus.settings.datastorage; + +import android.os.Build; + +import androidx.annotation.NonNull; + +import net.osmand.IndexConstants; +import net.osmand.ValueHolder; +import net.osmand.plus.OsmandApplication; +import net.osmand.plus.settings.backend.OsmandSettings; +import net.osmand.plus.R; +import net.osmand.plus.settings.datastorage.item.DirectoryItem; +import net.osmand.plus.settings.datastorage.item.DirectoryItem.CheckingType; +import net.osmand.plus.settings.datastorage.item.MemoryItem; +import net.osmand.plus.settings.datastorage.item.StorageItem; +import net.osmand.plus.settings.datastorage.task.RefreshUsedMemoryTask; + +import java.io.File; +import java.text.DecimalFormat; +import java.util.ArrayList; + +import static net.osmand.IndexConstants.AV_INDEX_DIR; +import static net.osmand.IndexConstants.BACKUP_INDEX_DIR; +import static net.osmand.IndexConstants.GPX_INDEX_DIR; +import static net.osmand.IndexConstants.MAPS_PATH; +import static net.osmand.IndexConstants.ROADS_INDEX_DIR; +import static net.osmand.IndexConstants.SRTM_INDEX_DIR; +import static net.osmand.IndexConstants.TILES_INDEX_DIR; +import static net.osmand.IndexConstants.WIKIVOYAGE_INDEX_DIR; +import static net.osmand.IndexConstants.WIKI_INDEX_DIR; +import static net.osmand.plus.settings.datastorage.item.DirectoryItem.CheckingType.EXTENSIONS; +import static net.osmand.plus.settings.datastorage.item.DirectoryItem.CheckingType.PREFIX; + +public class DataStorageHelper { + public final static String INTERNAL_STORAGE = "internal_storage"; + public final static String EXTERNAL_STORAGE = "external_storage"; + public final static String SHARED_STORAGE = "shared_storage"; + public final static String MULTIUSER_STORAGE = "multiuser_storage"; + public final static String MANUALLY_SPECIFIED = "manually_specified"; + + public final static String MAPS_MEMORY = "maps_memory_used"; + public final static String SRTM_AND_HILLSHADE_MEMORY = "contour_lines_and_hillshade_memory"; + public final static String TRACKS_MEMORY = "tracks_memory_used"; + public final static String NOTES_MEMORY = "notes_memory_used"; + public final static String TILES_MEMORY = "tiles_memory_used"; + public final static String OTHER_MEMORY = "other_memory_used"; + + private OsmandApplication app; + private ArrayList storageItems = new ArrayList<>(); + private StorageItem currentDataStorage; + private StorageItem manuallySpecified; + + private ArrayList memoryItems = new ArrayList<>(); + private MemoryItem mapsMemory; + private MemoryItem srtmAndHillshadeMemory; + private MemoryItem tracksMemory; + private MemoryItem notesMemory; + private MemoryItem tilesMemory; + private MemoryItem otherMemory; + + private int currentStorageType; + private String currentStoragePath; + + public DataStorageHelper(@NonNull OsmandApplication app) { + this.app = app; + prepareData(); + } + + private void prepareData() { + OsmandSettings settings = app.getSettings(); + if (settings.getExternalStorageDirectoryTypeV19() >= 0) { + currentStorageType = settings.getExternalStorageDirectoryTypeV19(); + } else { + ValueHolder vh = new ValueHolder(); + if (vh.value != null && vh.value >= 0) { + currentStorageType = vh.value; + } else { + currentStorageType = 0; + } + } + currentStoragePath = settings.getExternalStorageDirectory().getAbsolutePath(); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + + //internal storage + String path = settings.getInternalAppPath().getAbsolutePath(); + File dir = new File(path); + int iconId = R.drawable.ic_action_phone; + + StorageItem internalStorageItem = StorageItem.builder() + .setKey(INTERNAL_STORAGE) + .setTitle(app.getString(R.string.storage_directory_internal_app)) + .setDirectory(path) + .setDescription(app.getString(R.string.internal_app_storage_description)) + .setType(OsmandSettings.EXTERNAL_STORAGE_TYPE_INTERNAL_FILE) + .setIconResId(iconId) + .createItem(); + addItem(internalStorageItem); + + //shared storage + dir = settings.getDefaultInternalStorage(); + path = dir.getAbsolutePath(); + iconId = R.drawable.ic_action_phone; + + StorageItem sharedStorageItem = StorageItem.builder() + .setKey(SHARED_STORAGE) + .setTitle(app.getString(R.string.storage_directory_shared)) + .setDirectory(path) + .setType(OsmandSettings.EXTERNAL_STORAGE_TYPE_DEFAULT) + .setIconResId(iconId) + .createItem(); + addItem(sharedStorageItem); + + //external storage + File[] externals = app.getExternalFilesDirs(null); + if (externals != null) { + int i = 0; + for (File external : externals) { + if (external != null) { + ++i; + dir = external; + path = dir.getAbsolutePath(); + iconId = getIconForStorageType(dir); + StorageItem externalStorageItem = StorageItem.builder() + .setKey(EXTERNAL_STORAGE + i) + .setTitle(app.getString(R.string.storage_directory_external) + " " + i) + .setDirectory(path) + .setType(OsmandSettings.EXTERNAL_STORAGE_TYPE_EXTERNAL_FILE) + .setIconResId(iconId) + .createItem(); + addItem(externalStorageItem); + } + } + } + + //multi user storage + File[] obbDirs = app.getObbDirs(); + if (obbDirs != null) { + int i = 0; + for (File obb : obbDirs) { + if (obb != null) { + ++i; + dir = obb; + path = dir.getAbsolutePath(); + iconId = getIconForStorageType(dir); + StorageItem multiuserStorageItem = StorageItem.builder() + .setKey(MULTIUSER_STORAGE + i) + .setTitle(app.getString(R.string.storage_directory_multiuser) + " " + i) + .setDirectory(path) + .setType(OsmandSettings.EXTERNAL_STORAGE_TYPE_OBB) + .setIconResId(iconId) + .createItem(); + addItem(multiuserStorageItem); + } + } + } + } + + //manually specified storage + manuallySpecified = StorageItem.builder() + .setKey(MANUALLY_SPECIFIED) + .setTitle(app.getString(R.string.storage_directory_manual)) + .setDirectory(currentStoragePath) + .setType(OsmandSettings.EXTERNAL_STORAGE_TYPE_SPECIFIED) + .setIconResId(R.drawable.ic_action_folder) + .createItem(); + storageItems.add(manuallySpecified); + + if (currentDataStorage == null) { + currentDataStorage = manuallySpecified; + } + + initMemoryUsed(); + } + + private void initMemoryUsed() { + mapsMemory = MemoryItem.builder() + .setKey(MAPS_MEMORY) + .setExtensions(IndexConstants.BINARY_MAP_INDEX_EXT) + .setDirectories( + createDirectory((MAPS_PATH), false, EXTENSIONS, false), + createDirectory((ROADS_INDEX_DIR), true, EXTENSIONS, false), + createDirectory((WIKI_INDEX_DIR), true, EXTENSIONS, false), + createDirectory((WIKIVOYAGE_INDEX_DIR), true, EXTENSIONS, false), + createDirectory((BACKUP_INDEX_DIR), true, EXTENSIONS, false)) + .createItem(); + memoryItems.add(mapsMemory); + + srtmAndHillshadeMemory = MemoryItem.builder() + .setKey(SRTM_AND_HILLSHADE_MEMORY) + .setExtensions(IndexConstants.BINARY_SRTM_MAP_INDEX_EXT) + .setDirectories( + createDirectory((SRTM_INDEX_DIR), true, EXTENSIONS, false), + createDirectory((TILES_INDEX_DIR), false, PREFIX, true)) + .setPrefixes("Hillshade") + .createItem(); + memoryItems.add(srtmAndHillshadeMemory); + + tracksMemory = MemoryItem.builder() + .setKey(TRACKS_MEMORY) +// .setExtensions(IndexConstants.GPX_FILE_EXT, ".gpx.bz2") + .setDirectories( + createDirectory((GPX_INDEX_DIR), true, EXTENSIONS, false)) + .createItem(); + memoryItems.add(tracksMemory); + + notesMemory = MemoryItem.builder() + .setKey(NOTES_MEMORY) +// .setExtensions("") + .setDirectories( + createDirectory((AV_INDEX_DIR), true, EXTENSIONS, false)) + .createItem(); + memoryItems.add(notesMemory); + + tilesMemory = MemoryItem.builder() + .setKey(TILES_MEMORY) +// .setExtensions("") + .setDirectories( + createDirectory((TILES_INDEX_DIR), true, EXTENSIONS, false)) + .createItem(); + memoryItems.add(tilesMemory); + + otherMemory = MemoryItem.builder() + .setKey(OTHER_MEMORY) + .createItem(); + memoryItems.add(otherMemory); + } + + public ArrayList getStorageItems() { + return storageItems; + } + + private int getIconForStorageType(File dir) { + return R.drawable.ic_action_folder; + } + + public StorageItem getCurrentStorage() { + return currentDataStorage; + } + + private void addItem(StorageItem item) { + if (currentStorageType == item.getType() && currentStoragePath.equals(item.getDirectory())) { + currentDataStorage = item; + } + storageItems.add(item); + } + + public StorageItem getManuallySpecified() { + return manuallySpecified; + } + + public StorageItem getStorage(String key) { + if (storageItems != null && key != null) { + for (StorageItem storageItem : storageItems) { + if (key.equals(storageItem.getKey())) { + return storageItem; + } + } + } + return null; + } + + public ArrayList getMemoryInfoItems() { + return memoryItems; + } + + public RefreshUsedMemoryTask calculateMemoryUsedInfo(UpdateMemoryInfoUIAdapter listener) { + File rootDir = new File(currentStoragePath); + RefreshUsedMemoryTask task = new RefreshUsedMemoryTask(listener, otherMemory, rootDir, null, null, OTHER_MEMORY); + task.execute(mapsMemory, srtmAndHillshadeMemory, tracksMemory, notesMemory); + return task; + } + + public RefreshUsedMemoryTask calculateTilesMemoryUsed(UpdateMemoryInfoUIAdapter listener) { + File rootDir = new File(tilesMemory.getDirectories()[0].getAbsolutePath()); + RefreshUsedMemoryTask task = new RefreshUsedMemoryTask(listener, otherMemory, rootDir, null, srtmAndHillshadeMemory.getPrefixes(), TILES_MEMORY); + task.execute(tilesMemory); + return task; + } + + public long getTotalUsedBytes() { + long total = 0; + if (memoryItems != null && memoryItems.size() > 0) { + for (MemoryItem mi : memoryItems) { + total += mi.getUsedMemoryBytes(); + } + return total; + } + return -1; + } + + public DirectoryItem createDirectory(@NonNull String relativePath, + boolean goDeeper, + CheckingType checkingType, + boolean skipOther) { + String path = app.getAppPath(relativePath).getAbsolutePath(); + return new DirectoryItem(path, goDeeper, checkingType, skipOther); + } + + public static String getFormattedMemoryInfo(long bytes, String[] formatStrings) { + int type = 0; + double memory = (double) bytes / 1024; + while (memory > 1024 && type < formatStrings.length) { + ++type; + memory = memory / 1024; + } + String formattedUsed = new DecimalFormat("#.##").format(memory); + return String.format(formatStrings[type], formattedUsed); + } + + public interface UpdateMemoryInfoUIAdapter { + + void onMemoryInfoUpdate(); + + void onFinishUpdating(String taskKey); + + } +} \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/settings/datastorage/item/DirectoryItem.java b/OsmAnd/src/net/osmand/plus/settings/datastorage/item/DirectoryItem.java new file mode 100644 index 0000000000..e1d7e1cad4 --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/settings/datastorage/item/DirectoryItem.java @@ -0,0 +1,40 @@ +package net.osmand.plus.settings.datastorage.item; + +public class DirectoryItem { + + private final String absolutePath; + private final boolean goDeeper; + private final CheckingType checkingType; + private final boolean skipOther; + + public enum CheckingType { + EXTENSIONS, + PREFIX + } + + public DirectoryItem(String absolutePath, + boolean goDeeper, + CheckingType checkingType, + boolean skipOther) { + this.absolutePath = absolutePath; + this.goDeeper = goDeeper; + this.checkingType = checkingType; + this.skipOther = skipOther; + } + + public String getAbsolutePath() { + return absolutePath; + } + + public boolean isGoDeeper() { + return goDeeper; + } + + public CheckingType getCheckingType() { + return checkingType; + } + + public boolean isSkipOther() { + return skipOther; + } +} diff --git a/OsmAnd/src/net/osmand/plus/settings/fragments/DataStorageMemoryItem.java b/OsmAnd/src/net/osmand/plus/settings/datastorage/item/MemoryItem.java similarity index 52% rename from OsmAnd/src/net/osmand/plus/settings/fragments/DataStorageMemoryItem.java rename to OsmAnd/src/net/osmand/plus/settings/datastorage/item/MemoryItem.java index f7f955f89a..8fb65f99c3 100644 --- a/OsmAnd/src/net/osmand/plus/settings/fragments/DataStorageMemoryItem.java +++ b/OsmAnd/src/net/osmand/plus/settings/datastorage/item/MemoryItem.java @@ -1,16 +1,18 @@ -package net.osmand.plus.settings.fragments; +package net.osmand.plus.settings.datastorage.item; + +public class MemoryItem { -public class DataStorageMemoryItem { - public final static int EXTENSIONS = 0; - public final static int PREFIX = 1; - private String key; - private String[] extensions; - private String[] prefixes; - private Directory[] directories; + private final String[] extensions; + private final String[] prefixes; + private final DirectoryItem[] directories; private long usedMemoryBytes; - private DataStorageMemoryItem(String key, String[] extensions, String[] prefixes, long usedMemoryBytes, Directory[] directories) { + private MemoryItem(String key, + String[] extensions, + String[] prefixes, + long usedMemoryBytes, + DirectoryItem[] directories) { this.key = key; this.extensions = extensions; this.prefixes = prefixes; @@ -42,7 +44,7 @@ public class DataStorageMemoryItem { return prefixes; } - public Directory[] getDirectories() { + public DirectoryItem[] getDirectories() { return directories; } @@ -54,7 +56,7 @@ public class DataStorageMemoryItem { private String key; private String[] extensions; private String[] prefixes; - private Directory[] directories; + private DirectoryItem[] directories; private long usedMemoryBytes; public DataStorageMemoryItemBuilder setKey(String key) { @@ -72,7 +74,7 @@ public class DataStorageMemoryItem { return this; } - public DataStorageMemoryItemBuilder setDirectories(Directory ... directories) { + public DataStorageMemoryItemBuilder setDirectories(DirectoryItem... directories) { this.directories = directories; return this; } @@ -82,38 +84,8 @@ public class DataStorageMemoryItem { return this; } - public DataStorageMemoryItem createItem() { - return new DataStorageMemoryItem(key, extensions, prefixes, usedMemoryBytes, directories); - } - } - - public static class Directory { - private String absolutePath; - private boolean goDeeper; - private int checkingType; - private boolean skipOther; - - public Directory(String absolutePath, boolean goDeeper, int checkingType, boolean skipOther) { - this.absolutePath = absolutePath; - this.goDeeper = goDeeper; - this.checkingType = checkingType; - this.skipOther = skipOther; - } - - public String getAbsolutePath() { - return absolutePath; - } - - public boolean isGoDeeper() { - return goDeeper; - } - - public int getCheckingType() { - return checkingType; - } - - public boolean isSkipOther() { - return skipOther; + public MemoryItem createItem() { + return new MemoryItem(key, extensions, prefixes, usedMemoryBytes, directories); } } } diff --git a/OsmAnd/src/net/osmand/plus/settings/fragments/DataStorageMenuItem.java b/OsmAnd/src/net/osmand/plus/settings/datastorage/item/StorageItem.java similarity index 78% rename from OsmAnd/src/net/osmand/plus/settings/fragments/DataStorageMenuItem.java rename to OsmAnd/src/net/osmand/plus/settings/datastorage/item/StorageItem.java index f965b95fb1..717bcbd5e7 100644 --- a/OsmAnd/src/net/osmand/plus/settings/fragments/DataStorageMenuItem.java +++ b/OsmAnd/src/net/osmand/plus/settings/datastorage/item/StorageItem.java @@ -1,11 +1,11 @@ -package net.osmand.plus.settings.fragments; +package net.osmand.plus.settings.datastorage.item; import android.os.Parcel; import android.os.Parcelable; import androidx.annotation.IdRes; -public class DataStorageMenuItem implements Parcelable, Cloneable { +public class StorageItem implements Parcelable, Cloneable { private String key; private int type; @@ -15,8 +15,12 @@ public class DataStorageMenuItem implements Parcelable, Cloneable { @IdRes private int iconResId; - private DataStorageMenuItem(String key, int type, String title, String description, - String directory, int iconResId) { + private StorageItem(String key, + int type, + String title, + String description, + String directory, + int iconResId) { this.key = key; this.type = type; this.title = title; @@ -25,7 +29,7 @@ public class DataStorageMenuItem implements Parcelable, Cloneable { this.iconResId = iconResId; } - private DataStorageMenuItem(Parcel in) { + private StorageItem(Parcel in) { key = in.readString(); type = in.readInt(); title = in.readString(); @@ -99,16 +103,16 @@ public class DataStorageMenuItem implements Parcelable, Cloneable { dest.writeString(directory); } - public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { + public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { @Override - public DataStorageMenuItem createFromParcel(Parcel source) { - return new DataStorageMenuItem(source); + public StorageItem createFromParcel(Parcel source) { + return new StorageItem(source); } @Override - public DataStorageMenuItem[] newArray(int size) { - return new DataStorageMenuItem[size]; + public StorageItem[] newArray(int size) { + return new StorageItem[size]; } }; @@ -151,14 +155,14 @@ public class DataStorageMenuItem implements Parcelable, Cloneable { return this; } - public DataStorageMenuItem createItem() { - return new DataStorageMenuItem(key, type, title, description, directory, iconResId); + public StorageItem createItem() { + return new StorageItem(key, type, title, description, directory, iconResId); } } @Override public Object clone() throws CloneNotSupportedException { - return DataStorageMenuItem.builder() + return StorageItem.builder() .setKey(this.key) .setTitle(this.title) .setDescription(this.description) diff --git a/OsmAnd/src/net/osmand/plus/settings/datastorage/task/MoveFilesTask.java b/OsmAnd/src/net/osmand/plus/settings/datastorage/task/MoveFilesTask.java new file mode 100644 index 0000000000..b6fc45d93c --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/settings/datastorage/task/MoveFilesTask.java @@ -0,0 +1,173 @@ +package net.osmand.plus.settings.datastorage.task; + +import android.app.ProgressDialog; +import android.content.Context; +import android.os.AsyncTask; +import android.widget.Toast; + +import net.osmand.plus.ProgressImplementation; +import net.osmand.plus.R; +import net.osmand.plus.activities.OsmandActionBarActivity; +import net.osmand.util.Algorithms; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.lang.ref.WeakReference; + +public class MoveFilesTask extends AsyncTask { + + protected WeakReference activity; + private WeakReference context; + private File from; + private File to; + protected ProgressImplementation progress; + private Runnable runOnSuccess; + private int movedCount; + private long movedSize; + private int copiedCount; + private long copiedSize; + private int failedCount; + private long failedSize; + private String exceptionMessage; + + public MoveFilesTask(OsmandActionBarActivity activity, File from, File to) { + this.activity = new WeakReference<>(activity); + this.context = new WeakReference<>((Context) activity); + this.from = from; + this.to = to; + } + + public void setRunOnSuccess(Runnable runOnSuccess) { + this.runOnSuccess = runOnSuccess; + } + + public int getMovedCount() { + return movedCount; + } + + public int getCopiedCount() { + return copiedCount; + } + + public int getFailedCount() { + return failedCount; + } + + public long getMovedSize() { + return movedSize; + } + + public long getCopiedSize() { + return copiedSize; + } + + public long getFailedSize() { + return failedSize; + } + + @Override + protected void onPreExecute() { + Context ctx = context.get(); + if (context == null) { + return; + } + movedCount = 0; + copiedCount = 0; + failedCount = 0; + progress = ProgressImplementation.createProgressDialog( + ctx, ctx.getString(R.string.copying_osmand_files), + ctx.getString(R.string.copying_osmand_files_descr, to.getPath()), + ProgressDialog.STYLE_HORIZONTAL); + } + + @Override + protected void onPostExecute(Boolean result) { + Context ctx = context.get(); + if (ctx == null) { + return; + } + if (result != null) { + if (result.booleanValue() && runOnSuccess != null) { + runOnSuccess.run(); + } else if (!result.booleanValue()) { + Toast.makeText(ctx, ctx.getString(R.string.shared_string_io_error) + ": " + exceptionMessage, Toast.LENGTH_LONG).show(); + } + } + try { + if (progress.getDialog().isShowing()) { + progress.getDialog().dismiss(); + } + } catch (Exception e) { + //ignored + } + } + + private void movingFiles(File f, File t, int depth) throws IOException { + Context ctx = context.get(); + if (ctx == null) { + return; + } + if (depth <= 2) { + progress.startTask(ctx.getString(R.string.copying_osmand_one_file_descr, t.getName()), -1); + } + if (f.isDirectory()) { + t.mkdirs(); + File[] lf = f.listFiles(); + if (lf != null) { + for (int i = 0; i < lf.length; i++) { + if (lf[i] != null) { + movingFiles(lf[i], new File(t, lf[i].getName()), depth + 1); + } + } + } + f.delete(); + } else if (f.isFile()) { + if (t.exists()) { + Algorithms.removeAllFiles(t); + } + boolean rnm = false; + long fileSize = f.length(); + try { + rnm = f.renameTo(t); + movedCount++; + movedSize += fileSize; + } catch (RuntimeException e) { + } + if (!rnm) { + FileInputStream fin = new FileInputStream(f); + FileOutputStream fout = new FileOutputStream(t); + try { + progress.startTask(ctx.getString(R.string.copying_osmand_one_file_descr, t.getName()), (int) (f.length() / 1024)); + Algorithms.streamCopy(fin, fout, progress, 1024); + copiedCount++; + copiedSize += fileSize; + } catch (IOException e) { + failedCount++; + failedSize += fileSize; + } finally { + fin.close(); + fout.close(); + } + f.delete(); + } + } + if (depth <= 2) { + progress.finishTask(); + } + } + + @Override + protected Boolean doInBackground(Void... params) { + to.mkdirs(); + try { + movingFiles(from, to, 0); + } catch (IOException e) { + exceptionMessage = e.getMessage(); + return false; + } + return true; + } + +} diff --git a/OsmAnd/src/net/osmand/plus/settings/datastorage/task/RefreshUsedMemoryTask.java b/OsmAnd/src/net/osmand/plus/settings/datastorage/task/RefreshUsedMemoryTask.java new file mode 100644 index 0000000000..ad1dbb4bf5 --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/settings/datastorage/task/RefreshUsedMemoryTask.java @@ -0,0 +1,184 @@ +package net.osmand.plus.settings.datastorage.task; + +import android.os.AsyncTask; + +import net.osmand.plus.settings.datastorage.DataStorageHelper.UpdateMemoryInfoUIAdapter; +import net.osmand.plus.settings.datastorage.item.DirectoryItem; +import net.osmand.plus.settings.datastorage.item.DirectoryItem.CheckingType; +import net.osmand.plus.settings.datastorage.item.MemoryItem; + +import java.io.File; + +import static net.osmand.plus.settings.datastorage.DataStorageFragment.UI_REFRESH_TIME_MS; + +public class RefreshUsedMemoryTask extends AsyncTask { + private UpdateMemoryInfoUIAdapter listener; + private File rootDir; + private MemoryItem otherMemory; + private String[] directoriesToAvoid; + private String[] prefixesToAvoid; + private String taskKey; + private long lastRefreshTime; + + public RefreshUsedMemoryTask(UpdateMemoryInfoUIAdapter listener, MemoryItem otherMemory, File rootDir, String[] directoriesToAvoid, String[] prefixesToAvoid, String taskKey) { + this.listener = listener; + this.otherMemory = otherMemory; + this.rootDir = rootDir; + this.directoriesToAvoid = directoriesToAvoid; + this.prefixesToAvoid = prefixesToAvoid; + this.taskKey = taskKey; + } + + @Override + protected Void doInBackground(MemoryItem... items) { + lastRefreshTime = System.currentTimeMillis(); + if (rootDir.canRead()) { + calculateMultiTypes(rootDir, items); + } + return null; + } + + private void calculateMultiTypes(File rootDir, MemoryItem... items) { + File[] subFiles = rootDir.listFiles(); + + for (File file : subFiles) { + if (isCancelled()) { + break; + } + nextFile : { + if (file.isDirectory()) { + //check current directory should be avoid + if (directoriesToAvoid != null) { + for (String directoryToAvoid : directoriesToAvoid) { + if (file.getAbsolutePath().equals(directoryToAvoid)) { + break nextFile; + } + } + } + //check current directory matched items type + for (MemoryItem item : items) { + DirectoryItem[] directories = item.getDirectories(); + if (directories == null) { + continue; + } + for (DirectoryItem dir : directories) { + if (file.getAbsolutePath().equals(dir.getAbsolutePath()) + || (file.getAbsolutePath().startsWith(dir.getAbsolutePath()))) { + if (dir.isGoDeeper()) { + calculateMultiTypes(file, items); + break nextFile; + } else if (dir.isSkipOther()) { + break nextFile; + } + } + } + } + //current directory did not match to any type + otherMemory.addBytes(getDirectorySize(file)); + } else if (file.isFile()) { + //check current file should be avoid + if (prefixesToAvoid != null) { + for (String prefixToAvoid : prefixesToAvoid) { + if (file.getName().toLowerCase().startsWith(prefixToAvoid.toLowerCase())) { + break nextFile; + } + } + } + //check current file matched items type + for (MemoryItem item : items) { + DirectoryItem[] directories = item.getDirectories(); + if (directories == null) { + continue; + } + for (DirectoryItem dir : directories) { + if (rootDir.getAbsolutePath().equals(dir.getAbsolutePath()) + || (rootDir.getAbsolutePath().startsWith(dir.getAbsolutePath()) && dir.isGoDeeper())) { + CheckingType checkingType = dir.getCheckingType(); + switch (checkingType) { + case EXTENSIONS : { + String[] extensions = item.getExtensions(); + if (extensions != null) { + for (String extension : extensions) { + if (file.getAbsolutePath().endsWith(extension)) { + item.addBytes(file.length()); + break nextFile; + } + } + } else { + item.addBytes(file.length()); + break nextFile; + } + break ; + } + case PREFIX : { + String[] prefixes = item.getPrefixes(); + if (prefixes != null) { + for (String prefix : prefixes) { + if (file.getName().toLowerCase().startsWith(prefix.toLowerCase())) { + item.addBytes(file.length()); + break nextFile; + } + } + } else { + item.addBytes(file.length()); + break nextFile; + } + break ; + } + } + if (dir.isSkipOther()) { + break nextFile; + } + } + } + } + //current file did not match any type + otherMemory.addBytes(file.length()); + } + } + refreshUI(); + } + } + + private long getDirectorySize(File dir) { + long bytes = 0; + if (dir.isDirectory()) { + File[] files = dir.listFiles(); + for (File file : files) { + if (isCancelled()) { + break; + } + if (file.isDirectory()) { + bytes += getDirectorySize(file); + } else if (file.isFile()) { + bytes += file.length(); + } + } + } + return bytes; + } + + @Override + protected void onProgressUpdate(Void... values) { + super.onProgressUpdate(values); + if (listener != null) { + listener.onMemoryInfoUpdate(); + } + } + + @Override + protected void onPostExecute(Void aVoid) { + super.onPostExecute(aVoid); + if (listener != null) { + listener.onFinishUpdating(taskKey); + } + } + + private void refreshUI() { + long currentTime = System.currentTimeMillis(); + if ((currentTime - lastRefreshTime) > UI_REFRESH_TIME_MS) { + lastRefreshTime = currentTime; + publishProgress(); + } + } +} diff --git a/OsmAnd/src/net/osmand/plus/settings/datastorage/task/ReloadDataTask.java b/OsmAnd/src/net/osmand/plus/settings/datastorage/task/ReloadDataTask.java new file mode 100644 index 0000000000..4e097b9df2 --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/settings/datastorage/task/ReloadDataTask.java @@ -0,0 +1,50 @@ +package net.osmand.plus.settings.datastorage.task; + +import android.app.ProgressDialog; +import android.content.Context; +import android.os.AsyncTask; + +import net.osmand.plus.OsmandApplication; +import net.osmand.plus.ProgressImplementation; +import net.osmand.plus.R; + +import java.lang.ref.WeakReference; +import java.util.ArrayList; + +public class ReloadDataTask extends AsyncTask { + private WeakReference ctx; + protected ProgressImplementation progress; + private OsmandApplication app; + + public ReloadDataTask(Context ctx, OsmandApplication app) { + this.ctx = new WeakReference<>(ctx); + this.app = app; + } + + @Override + protected void onPreExecute() { + Context c = ctx.get(); + if (c == null) { + return; + } + progress = ProgressImplementation.createProgressDialog(c, c.getString(R.string.loading_data), + c.getString(R.string.loading_data), ProgressDialog.STYLE_HORIZONTAL); + } + + @Override + protected void onPostExecute(Boolean result) { + try { + if (progress.getDialog().isShowing()) { + progress.getDialog().dismiss(); + } + } catch (Exception e) { + //ignored + } + } + + @Override + protected Boolean doInBackground(Void... params) { + app.getResourceManager().reloadIndexes(progress, new ArrayList()); + return true; + } +} diff --git a/OsmAnd/src/net/osmand/plus/settings/fragments/BaseSettingsFragment.java b/OsmAnd/src/net/osmand/plus/settings/fragments/BaseSettingsFragment.java index e2d3244f26..947a331290 100644 --- a/OsmAnd/src/net/osmand/plus/settings/fragments/BaseSettingsFragment.java +++ b/OsmAnd/src/net/osmand/plus/settings/fragments/BaseSettingsFragment.java @@ -73,6 +73,7 @@ import net.osmand.plus.settings.bottomsheets.ChangeGeneralProfilesPrefBottomShee import net.osmand.plus.settings.bottomsheets.EditTextPreferenceBottomSheet; import net.osmand.plus.settings.bottomsheets.MultiSelectPreferencesBottomSheet; import net.osmand.plus.settings.bottomsheets.SingleSelectPreferenceBottomSheet; +import net.osmand.plus.settings.datastorage.DataStorageFragment; import net.osmand.plus.settings.preferences.ListPreferenceEx; import net.osmand.plus.settings.preferences.MultiSelectBooleanPreference; import net.osmand.plus.settings.preferences.SwitchPreferenceEx; diff --git a/OsmAnd/src/net/osmand/plus/settings/fragments/DataStorageHelper.java b/OsmAnd/src/net/osmand/plus/settings/fragments/DataStorageHelper.java deleted file mode 100644 index b270175d86..0000000000 --- a/OsmAnd/src/net/osmand/plus/settings/fragments/DataStorageHelper.java +++ /dev/null @@ -1,485 +0,0 @@ -package net.osmand.plus.settings.fragments; - -import android.os.AsyncTask; -import android.os.Build; - -import net.osmand.IndexConstants; -import net.osmand.ValueHolder; -import net.osmand.plus.OsmandApplication; -import net.osmand.plus.settings.backend.OsmandSettings; -import net.osmand.plus.R; - -import java.io.File; -import java.text.DecimalFormat; -import java.util.ArrayList; - -import static net.osmand.plus.settings.fragments.DataStorageFragment.UI_REFRESH_TIME_MS; -import static net.osmand.plus.settings.fragments.DataStorageMemoryItem.Directory; -import static net.osmand.plus.settings.fragments.DataStorageMemoryItem.EXTENSIONS; -import static net.osmand.plus.settings.fragments.DataStorageMemoryItem.PREFIX; - -public class DataStorageHelper { - public final static String INTERNAL_STORAGE = "internal_storage"; - public final static String EXTERNAL_STORAGE = "external_storage"; - public final static String SHARED_STORAGE = "shared_storage"; - public final static String MULTIUSER_STORAGE = "multiuser_storage"; - public final static String MANUALLY_SPECIFIED = "manually_specified"; - - public final static String MAPS_MEMORY = "maps_memory_used"; - public final static String SRTM_AND_HILLSHADE_MEMORY = "contour_lines_and_hillshade_memory"; - public final static String TRACKS_MEMORY = "tracks_memory_used"; - public final static String NOTES_MEMORY = "notes_memory_used"; - public final static String TILES_MEMORY = "tiles_memory_used"; - public final static String OTHER_MEMORY = "other_memory_used"; - - private ArrayList menuItems = new ArrayList<>(); - private DataStorageMenuItem currentDataStorage; - private DataStorageMenuItem manuallySpecified; - - private ArrayList memoryItems = new ArrayList<>(); - private DataStorageMemoryItem mapsMemory; - private DataStorageMemoryItem srtmAndHillshadeMemory; - private DataStorageMemoryItem tracksMemory; - private DataStorageMemoryItem notesMemory; - private DataStorageMemoryItem tilesMemory; - private DataStorageMemoryItem otherMemory; - - private int currentStorageType; - private String currentStoragePath; - - public DataStorageHelper(OsmandApplication app) { - prepareData(app); - } - - private void prepareData(OsmandApplication app) { - - if (app == null) { - return; - } - - OsmandSettings settings = app.getSettings(); - - if (settings.getExternalStorageDirectoryTypeV19() >= 0) { - currentStorageType = settings.getExternalStorageDirectoryTypeV19(); - } else { - ValueHolder vh = new ValueHolder(); - if (vh.value != null && vh.value >= 0) { - currentStorageType = vh.value; - } else { - currentStorageType = 0; - } - } - currentStoragePath = settings.getExternalStorageDirectory().getAbsolutePath(); - - String path; - File dir; - int iconId; - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { - - //internal storage - path = settings.getInternalAppPath().getAbsolutePath(); - dir = new File(path); - iconId = R.drawable.ic_action_phone; - - DataStorageMenuItem internalStorageItem = DataStorageMenuItem.builder() - .setKey(INTERNAL_STORAGE) - .setTitle(app.getString(R.string.storage_directory_internal_app)) - .setDirectory(path) - .setDescription(app.getString(R.string.internal_app_storage_description)) - .setType(OsmandSettings.EXTERNAL_STORAGE_TYPE_INTERNAL_FILE) - .setIconResId(iconId) - .createItem(); - addItem(internalStorageItem); - - //shared_storage - dir = settings.getDefaultInternalStorage(); - path = dir.getAbsolutePath(); - iconId = R.drawable.ic_action_phone; - - DataStorageMenuItem sharedStorageItem = DataStorageMenuItem.builder() - .setKey(SHARED_STORAGE) - .setTitle(app.getString(R.string.storage_directory_shared)) - .setDirectory(path) - .setType(OsmandSettings.EXTERNAL_STORAGE_TYPE_DEFAULT) - .setIconResId(iconId) - .createItem(); - addItem(sharedStorageItem); - - //external storage - File[] externals = app.getExternalFilesDirs(null); - if (externals != null) { - int i = 0; - for (File external : externals) { - if (external != null) { - ++i; - dir = external; - path = dir.getAbsolutePath(); - iconId = getIconForStorageType(dir); - DataStorageMenuItem externalStorageItem = DataStorageMenuItem.builder() - .setKey(EXTERNAL_STORAGE + i) - .setTitle(app.getString(R.string.storage_directory_external) + " " + i) - .setDirectory(path) - .setType(OsmandSettings.EXTERNAL_STORAGE_TYPE_EXTERNAL_FILE) - .setIconResId(iconId) - .createItem(); - addItem(externalStorageItem); - } - } - } - - //multi user storage - File[] obbDirs = app.getObbDirs(); - if (obbDirs != null) { - int i = 0; - for (File obb : obbDirs) { - if (obb != null) { - ++i; - dir = obb; - path = dir.getAbsolutePath(); - iconId = getIconForStorageType(dir); - DataStorageMenuItem multiuserStorageItem = DataStorageMenuItem.builder() - .setKey(MULTIUSER_STORAGE + i) - .setTitle(app.getString(R.string.storage_directory_multiuser) + " " + i) - .setDirectory(path) - .setType(OsmandSettings.EXTERNAL_STORAGE_TYPE_OBB) - .setIconResId(iconId) - .createItem(); - addItem(multiuserStorageItem); - } - } - } - } - - //manually specified storage - manuallySpecified = DataStorageMenuItem.builder() - .setKey(MANUALLY_SPECIFIED) - .setTitle(app.getString(R.string.storage_directory_manual)) - .setDirectory(currentStoragePath) - .setType(OsmandSettings.EXTERNAL_STORAGE_TYPE_SPECIFIED) - .setIconResId(R.drawable.ic_action_folder) - .createItem(); - menuItems.add(manuallySpecified); - - if (currentDataStorage == null) { - currentDataStorage = manuallySpecified; - } - - initMemoryUsed(app); - } - - private void initMemoryUsed(OsmandApplication app) { - mapsMemory = DataStorageMemoryItem.builder() - .setKey(MAPS_MEMORY) - .setExtensions(IndexConstants.BINARY_MAP_INDEX_EXT) - .setDirectories( - new Directory(app.getAppPath(IndexConstants.MAPS_PATH).getAbsolutePath(), false, EXTENSIONS, false), - new Directory(app.getAppPath(IndexConstants.ROADS_INDEX_DIR).getAbsolutePath(), true, EXTENSIONS, false), - new Directory(app.getAppPath(IndexConstants.WIKI_INDEX_DIR).getAbsolutePath(), true, EXTENSIONS, false), - new Directory(app.getAppPath(IndexConstants.WIKIVOYAGE_INDEX_DIR).getAbsolutePath(), true, EXTENSIONS, false), - new Directory(app.getAppPath(IndexConstants.BACKUP_INDEX_DIR).getAbsolutePath(), true, EXTENSIONS, false)) - .createItem(); - memoryItems.add(mapsMemory); - - srtmAndHillshadeMemory = DataStorageMemoryItem.builder() - .setKey(SRTM_AND_HILLSHADE_MEMORY) - .setExtensions(IndexConstants.BINARY_SRTM_MAP_INDEX_EXT) - .setDirectories( - new Directory(app.getAppPath(IndexConstants.SRTM_INDEX_DIR).getAbsolutePath(), true, EXTENSIONS, false), - new Directory(app.getAppPath(IndexConstants.TILES_INDEX_DIR).getAbsolutePath(), false, PREFIX, true)) - .setPrefixes("Hillshade") - .createItem(); - memoryItems.add(srtmAndHillshadeMemory); - - tracksMemory = DataStorageMemoryItem.builder() - .setKey(TRACKS_MEMORY) -// .setExtensions(IndexConstants.GPX_FILE_EXT, ".gpx.bz2") - .setDirectories( - new Directory(app.getAppPath(IndexConstants.GPX_INDEX_DIR).getAbsolutePath(), true, EXTENSIONS, false)) - .createItem(); - memoryItems.add(tracksMemory); - - notesMemory = DataStorageMemoryItem.builder() - .setKey(NOTES_MEMORY) -// .setExtensions("") - .setDirectories( - new Directory(app.getAppPath(IndexConstants.AV_INDEX_DIR).getAbsolutePath(), true, EXTENSIONS, false)) - .createItem(); - memoryItems.add(notesMemory); - - tilesMemory = DataStorageMemoryItem.builder() - .setKey(TILES_MEMORY) -// .setExtensions("") - .setDirectories( - new Directory(app.getAppPath(IndexConstants.TILES_INDEX_DIR).getAbsolutePath(), true, EXTENSIONS, false)) - .createItem(); - memoryItems.add(tilesMemory); - - otherMemory = DataStorageMemoryItem.builder() - .setKey(OTHER_MEMORY) - .createItem(); - memoryItems.add(otherMemory); - } - - public ArrayList getStorageItems() { - return menuItems; - } - - private int getIconForStorageType(File dir) { - return R.drawable.ic_action_folder; - } - - public DataStorageMenuItem getCurrentStorage() { - return currentDataStorage; - } - - private void addItem(DataStorageMenuItem item) { - if (currentStorageType == item.getType() && currentStoragePath.equals(item.getDirectory())) { - currentDataStorage = item; - } - menuItems.add(item); - } - - public DataStorageMenuItem getManuallySpecified() { - return manuallySpecified; - } - - public DataStorageMenuItem getStorage(String key) { - if (menuItems != null && key != null) { - for (DataStorageMenuItem menuItem : menuItems) { - if (key.equals(menuItem.getKey())) { - return menuItem; - } - } - } - return null; - } - - public int getCurrentType() { - return currentStorageType; - } - - public String getCurrentPath() { - return currentStoragePath; - } - - public ArrayList getMemoryInfoItems() { - return memoryItems; - } - - public RefreshMemoryUsedInfo calculateMemoryUsedInfo(UpdateMemoryInfoUIAdapter listener) { - File rootDir = new File(currentStoragePath); - RefreshMemoryUsedInfo task = new RefreshMemoryUsedInfo(listener, otherMemory, rootDir, null, null, OTHER_MEMORY); - task.execute(mapsMemory, srtmAndHillshadeMemory, tracksMemory, notesMemory); - return task; - } - - public RefreshMemoryUsedInfo calculateTilesMemoryUsed(UpdateMemoryInfoUIAdapter listener) { - File rootDir = new File(tilesMemory.getDirectories()[0].getAbsolutePath()); - RefreshMemoryUsedInfo task = new RefreshMemoryUsedInfo(listener, otherMemory, rootDir, null, srtmAndHillshadeMemory.getPrefixes(), TILES_MEMORY); - task.execute(tilesMemory); - return task; - } - - public static class RefreshMemoryUsedInfo extends AsyncTask { - private UpdateMemoryInfoUIAdapter listener; - private File rootDir; - private DataStorageMemoryItem otherMemory; - private String[] directoriesToAvoid; - private String[] prefixesToAvoid; - private String taskKey; - private long lastRefreshTime; - - public RefreshMemoryUsedInfo(UpdateMemoryInfoUIAdapter listener, DataStorageMemoryItem otherMemory, File rootDir, String[] directoriesToAvoid, String[] prefixesToAvoid, String taskKey) { - this.listener = listener; - this.otherMemory = otherMemory; - this.rootDir = rootDir; - this.directoriesToAvoid = directoriesToAvoid; - this.prefixesToAvoid = prefixesToAvoid; - this.taskKey = taskKey; - } - - @Override - protected Void doInBackground(DataStorageMemoryItem... items) { - lastRefreshTime = System.currentTimeMillis(); - if (rootDir.canRead()) { - calculateMultiTypes(rootDir, items); - } - return null; - } - - private void calculateMultiTypes(File rootDir, DataStorageMemoryItem... items) { - File[] subFiles = rootDir.listFiles(); - - for (File file : subFiles) { - if (isCancelled()) { - break; - } - nextFile : { - if (file.isDirectory()) { - //check current directory should be avoid - if (directoriesToAvoid != null) { - for (String directoryToAvoid : directoriesToAvoid) { - if (file.getAbsolutePath().equals(directoryToAvoid)) { - break nextFile; - } - } - } - //check current directory matched items type - for (DataStorageMemoryItem item : items) { - Directory[] directories = item.getDirectories(); - if (directories == null) { - continue; - } - for (Directory dir : directories) { - if (file.getAbsolutePath().equals(dir.getAbsolutePath()) - || (file.getAbsolutePath().startsWith(dir.getAbsolutePath()))) { - if (dir.isGoDeeper()) { - calculateMultiTypes(file, items); - break nextFile; - } else if (dir.isSkipOther()) { - break nextFile; - } - } - } - } - //current directory did not match to any type - otherMemory.addBytes(getDirectorySize(file)); - } else if (file.isFile()) { - //check current file should be avoid - if (prefixesToAvoid != null) { - for (String prefixToAvoid : prefixesToAvoid) { - if (file.getName().toLowerCase().startsWith(prefixToAvoid.toLowerCase())) { - break nextFile; - } - } - } - //check current file matched items type - for (DataStorageMemoryItem item : items) { - Directory[] directories = item.getDirectories(); - if (directories == null) { - continue; - } - for (Directory dir : directories) { - if (rootDir.getAbsolutePath().equals(dir.getAbsolutePath()) - || (rootDir.getAbsolutePath().startsWith(dir.getAbsolutePath()) && dir.isGoDeeper())) { - int checkingType = dir.getCheckingType(); - switch (checkingType) { - case EXTENSIONS : { - String[] extensions = item.getExtensions(); - if (extensions != null) { - for (String extension : extensions) { - if (file.getAbsolutePath().endsWith(extension)) { - item.addBytes(file.length()); - break nextFile; - } - } - } else { - item.addBytes(file.length()); - break nextFile; - } - break ; - } - case PREFIX : { - String[] prefixes = item.getPrefixes(); - if (prefixes != null) { - for (String prefix : prefixes) { - if (file.getName().toLowerCase().startsWith(prefix.toLowerCase())) { - item.addBytes(file.length()); - break nextFile; - } - } - } else { - item.addBytes(file.length()); - break nextFile; - } - break ; - } - } - if (dir.isSkipOther()) { - break nextFile; - } - } - } - } - //current file did not match any type - otherMemory.addBytes(file.length()); - } - } - refreshUI(); - } - } - - private long getDirectorySize(File dir) { - long bytes = 0; - if (dir.isDirectory()) { - File[] files = dir.listFiles(); - for (File file : files) { - if (isCancelled()) { - break; - } - if (file.isDirectory()) { - bytes += getDirectorySize(file); - } else if (file.isFile()) { - bytes += file.length(); - } - } - } - return bytes; - } - - @Override - protected void onProgressUpdate(Void... values) { - super.onProgressUpdate(values); - if (listener != null) { - listener.onMemoryInfoUpdate(); - } - } - - @Override - protected void onPostExecute(Void aVoid) { - super.onPostExecute(aVoid); - if (listener != null) { - listener.onFinishUpdating(taskKey); - } - } - - private void refreshUI() { - long currentTime = System.currentTimeMillis(); - if ((currentTime - lastRefreshTime) > UI_REFRESH_TIME_MS) { - lastRefreshTime = currentTime; - publishProgress(); - } - } - } - - public long getTotalUsedBytes() { - long total = 0; - if (memoryItems != null && memoryItems.size() > 0) { - for (DataStorageMemoryItem mi : memoryItems) { - total += mi.getUsedMemoryBytes(); - } - return total; - } - return -1; - } - - public static String getFormattedMemoryInfo(long bytes, String[] formatStrings) { - int type = 0; - double memory = (double) bytes / 1024; - while (memory > 1024 && type < formatStrings.length) { - ++type; - memory = memory / 1024; - } - String formattedUsed = new DecimalFormat("#.##").format(memory); - return String.format(formatStrings[type], formattedUsed); - } - - public interface UpdateMemoryInfoUIAdapter { - - void onMemoryInfoUpdate(); - - void onFinishUpdating(String taskKey); - - } -} \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/settings/fragments/GlobalSettingsFragment.java b/OsmAnd/src/net/osmand/plus/settings/fragments/GlobalSettingsFragment.java index fa7383228c..071d7be709 100644 --- a/OsmAnd/src/net/osmand/plus/settings/fragments/GlobalSettingsFragment.java +++ b/OsmAnd/src/net/osmand/plus/settings/fragments/GlobalSettingsFragment.java @@ -22,6 +22,8 @@ import net.osmand.plus.profiles.SelectProfileBottomSheet.DialogMode; import net.osmand.plus.profiles.SelectProfileBottomSheet.OnSelectProfileCallback; import net.osmand.plus.settings.backend.ApplicationMode; import net.osmand.plus.settings.backend.OsmandSettings; +import net.osmand.plus.settings.datastorage.DataStorageHelper; +import net.osmand.plus.settings.datastorage.item.StorageItem; import net.osmand.plus.settings.preferences.ListPreferenceEx; import net.osmand.plus.settings.preferences.SwitchPreferenceEx; @@ -181,7 +183,7 @@ public class GlobalSettingsFragment extends BaseSettingsFragment externalStorageDir.setIcon(getActiveIcon(R.drawable.ic_action_folder)); DataStorageHelper holder = new DataStorageHelper(app); - DataStorageMenuItem currentStorage = holder.getCurrentStorage(); + StorageItem currentStorage = holder.getCurrentStorage(); long totalUsed = app.getSettings().OSMAND_USAGE_SPACE.get(); if (totalUsed > 0) { String[] usedMemoryFormats = new String[] { From 7041c4ecc98886ca8457d28629b855266e0d1e33 Mon Sep 17 00:00:00 2001 From: nazar-kutz Date: Mon, 1 Feb 2021 20:30:59 +0200 Subject: [PATCH 04/65] Data storage refactoring, step 2 --- OsmAnd/res/xml/data_storage.xml | 2 +- .../datastorage/DataStorageHelper.java | 20 +- .../datastorage/item/DirectoryItem.java | 20 +- .../task/RefreshUsedMemoryTask.java | 269 ++++++++++-------- 4 files changed, 178 insertions(+), 133 deletions(-) diff --git a/OsmAnd/res/xml/data_storage.xml b/OsmAnd/res/xml/data_storage.xml index a153ec4cd1..95168ac3ce 100644 --- a/OsmAnd/res/xml/data_storage.xml +++ b/OsmAnd/res/xml/data_storage.xml @@ -14,7 +14,7 @@ android:title="@string/shared_string_maps"/> diff --git a/OsmAnd/src/net/osmand/plus/settings/datastorage/DataStorageHelper.java b/OsmAnd/src/net/osmand/plus/settings/datastorage/DataStorageHelper.java index 96a939eae3..fd66cd3e58 100644 --- a/OsmAnd/src/net/osmand/plus/settings/datastorage/DataStorageHelper.java +++ b/OsmAnd/src/net/osmand/plus/settings/datastorage/DataStorageHelper.java @@ -39,7 +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 SRTM_AND_HILLSHADE_MEMORY = "contour_lines_and_hillshade_memory"; + 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"; public final static String TILES_MEMORY = "tiles_memory_used"; @@ -52,7 +52,7 @@ public class DataStorageHelper { private ArrayList memoryItems = new ArrayList<>(); private MemoryItem mapsMemory; - private MemoryItem srtmAndHillshadeMemory; + private MemoryItem terrainMemory; private MemoryItem tracksMemory; private MemoryItem notesMemory; private MemoryItem tilesMemory; @@ -186,15 +186,15 @@ public class DataStorageHelper { .createItem(); memoryItems.add(mapsMemory); - srtmAndHillshadeMemory = MemoryItem.builder() - .setKey(SRTM_AND_HILLSHADE_MEMORY) + terrainMemory = MemoryItem.builder() + .setKey(TERRAIN_MEMORY) .setExtensions(IndexConstants.BINARY_SRTM_MAP_INDEX_EXT) .setDirectories( createDirectory((SRTM_INDEX_DIR), true, EXTENSIONS, false), createDirectory((TILES_INDEX_DIR), false, PREFIX, true)) .setPrefixes("Hillshade") .createItem(); - memoryItems.add(srtmAndHillshadeMemory); + memoryItems.add(terrainMemory); tracksMemory = MemoryItem.builder() .setKey(TRACKS_MEMORY) @@ -267,13 +267,13 @@ public class DataStorageHelper { public RefreshUsedMemoryTask calculateMemoryUsedInfo(UpdateMemoryInfoUIAdapter listener) { File rootDir = new File(currentStoragePath); RefreshUsedMemoryTask task = new RefreshUsedMemoryTask(listener, otherMemory, rootDir, null, null, OTHER_MEMORY); - task.execute(mapsMemory, srtmAndHillshadeMemory, tracksMemory, notesMemory); + task.execute(mapsMemory, terrainMemory, tracksMemory, notesMemory); return task; } public RefreshUsedMemoryTask calculateTilesMemoryUsed(UpdateMemoryInfoUIAdapter listener) { File rootDir = new File(tilesMemory.getDirectories()[0].getAbsolutePath()); - RefreshUsedMemoryTask task = new RefreshUsedMemoryTask(listener, otherMemory, rootDir, null, srtmAndHillshadeMemory.getPrefixes(), TILES_MEMORY); + RefreshUsedMemoryTask task = new RefreshUsedMemoryTask(listener, otherMemory, rootDir, null, terrainMemory.getPrefixes(), TILES_MEMORY); task.execute(tilesMemory); return task; } @@ -290,11 +290,11 @@ public class DataStorageHelper { } public DirectoryItem createDirectory(@NonNull String relativePath, - boolean goDeeper, + boolean processInternalDirectories, CheckingType checkingType, - boolean skipOther) { + boolean skipUnmatchedInDirectory) { String path = app.getAppPath(relativePath).getAbsolutePath(); - return new DirectoryItem(path, goDeeper, checkingType, skipOther); + return new DirectoryItem(path, processInternalDirectories, checkingType, skipUnmatchedInDirectory); } public static String getFormattedMemoryInfo(long bytes, String[] formatStrings) { diff --git a/OsmAnd/src/net/osmand/plus/settings/datastorage/item/DirectoryItem.java b/OsmAnd/src/net/osmand/plus/settings/datastorage/item/DirectoryItem.java index e1d7e1cad4..0f15e39f58 100644 --- a/OsmAnd/src/net/osmand/plus/settings/datastorage/item/DirectoryItem.java +++ b/OsmAnd/src/net/osmand/plus/settings/datastorage/item/DirectoryItem.java @@ -3,9 +3,9 @@ package net.osmand.plus.settings.datastorage.item; public class DirectoryItem { private final String absolutePath; - private final boolean goDeeper; + private final boolean processInternalDirectories; private final CheckingType checkingType; - private final boolean skipOther; + private final boolean skipUnmatchedInDirectory; public enum CheckingType { EXTENSIONS, @@ -13,28 +13,28 @@ public class DirectoryItem { } public DirectoryItem(String absolutePath, - boolean goDeeper, + boolean processInternalDirectories, CheckingType checkingType, - boolean skipOther) { + boolean skipUnmatchedInDirectory) { this.absolutePath = absolutePath; - this.goDeeper = goDeeper; + this.processInternalDirectories = processInternalDirectories; this.checkingType = checkingType; - this.skipOther = skipOther; + this.skipUnmatchedInDirectory = skipUnmatchedInDirectory; } public String getAbsolutePath() { return absolutePath; } - public boolean isGoDeeper() { - return goDeeper; + public boolean shouldProcessInternalDirectories() { + return processInternalDirectories; } public CheckingType getCheckingType() { return checkingType; } - public boolean isSkipOther() { - return skipOther; + public boolean shouldSkipUnmatchedInDirectory() { + return skipUnmatchedInDirectory; } } diff --git a/OsmAnd/src/net/osmand/plus/settings/datastorage/task/RefreshUsedMemoryTask.java b/OsmAnd/src/net/osmand/plus/settings/datastorage/task/RefreshUsedMemoryTask.java index ad1dbb4bf5..dc84c97dbc 100644 --- a/OsmAnd/src/net/osmand/plus/settings/datastorage/task/RefreshUsedMemoryTask.java +++ b/OsmAnd/src/net/osmand/plus/settings/datastorage/task/RefreshUsedMemoryTask.java @@ -2,6 +2,8 @@ package net.osmand.plus.settings.datastorage.task; import android.os.AsyncTask; +import androidx.annotation.NonNull; + import net.osmand.plus.settings.datastorage.DataStorageHelper.UpdateMemoryInfoUIAdapter; import net.osmand.plus.settings.datastorage.item.DirectoryItem; import net.osmand.plus.settings.datastorage.item.DirectoryItem.CheckingType; @@ -10,146 +12,189 @@ import net.osmand.plus.settings.datastorage.item.MemoryItem; import java.io.File; import static net.osmand.plus.settings.datastorage.DataStorageFragment.UI_REFRESH_TIME_MS; +import static net.osmand.util.Algorithms.objectEquals; public class RefreshUsedMemoryTask extends AsyncTask { - private UpdateMemoryInfoUIAdapter listener; - private File rootDir; - private MemoryItem otherMemory; - private String[] directoriesToAvoid; - private String[] prefixesToAvoid; - private String taskKey; + private final UpdateMemoryInfoUIAdapter uiAdapter; + private final File root; + private final MemoryItem otherMemoryItem; + private final String[] directoriesToSkip; + private final String[] filePrefixesToSkip; + private final String tag; private long lastRefreshTime; - public RefreshUsedMemoryTask(UpdateMemoryInfoUIAdapter listener, MemoryItem otherMemory, File rootDir, String[] directoriesToAvoid, String[] prefixesToAvoid, String taskKey) { - this.listener = listener; - this.otherMemory = otherMemory; - this.rootDir = rootDir; - this.directoriesToAvoid = directoriesToAvoid; - this.prefixesToAvoid = prefixesToAvoid; - this.taskKey = taskKey; + public RefreshUsedMemoryTask(UpdateMemoryInfoUIAdapter uiAdapter, + MemoryItem otherMemoryItem, + File root, + String[] directoriesToSkip, + String[] filePrefixesToSkip, + String tag) { + this.uiAdapter = uiAdapter; + this.otherMemoryItem = otherMemoryItem; + this.root = root; + this.directoriesToSkip = directoriesToSkip; + this.filePrefixesToSkip = filePrefixesToSkip; + this.tag = tag; } @Override protected Void doInBackground(MemoryItem... items) { lastRefreshTime = System.currentTimeMillis(); - if (rootDir.canRead()) { - calculateMultiTypes(rootDir, items); + if (root.canRead()) { + calculateMultiTypes(root, items); } return null; } - private void calculateMultiTypes(File rootDir, MemoryItem... items) { + private void calculateMultiTypes(File rootDir, + MemoryItem... items) { File[] subFiles = rootDir.listFiles(); + if (subFiles != null) { + for (File file : subFiles) { + if (isCancelled()) break; - for (File file : subFiles) { - if (isCancelled()) { - break; - } - nextFile : { if (file.isDirectory()) { - //check current directory should be avoid - if (directoriesToAvoid != null) { - for (String directoryToAvoid : directoriesToAvoid) { - if (file.getAbsolutePath().equals(directoryToAvoid)) { - break nextFile; - } - } + if (!shouldSkipDirectory(file)) { + processDirectory(file, items); } - //check current directory matched items type - for (MemoryItem item : items) { - DirectoryItem[] directories = item.getDirectories(); - if (directories == null) { - continue; - } - for (DirectoryItem dir : directories) { - if (file.getAbsolutePath().equals(dir.getAbsolutePath()) - || (file.getAbsolutePath().startsWith(dir.getAbsolutePath()))) { - if (dir.isGoDeeper()) { - calculateMultiTypes(file, items); - break nextFile; - } else if (dir.isSkipOther()) { - break nextFile; - } - } - } - } - //current directory did not match to any type - otherMemory.addBytes(getDirectorySize(file)); + } else if (file.isFile()) { - //check current file should be avoid - if (prefixesToAvoid != null) { - for (String prefixToAvoid : prefixesToAvoid) { - if (file.getName().toLowerCase().startsWith(prefixToAvoid.toLowerCase())) { - break nextFile; - } - } + if (!shouldSkipFile(file)) { + processFile(rootDir, file, items); } - //check current file matched items type - for (MemoryItem item : items) { - DirectoryItem[] directories = item.getDirectories(); - if (directories == null) { - continue; - } - for (DirectoryItem dir : directories) { - if (rootDir.getAbsolutePath().equals(dir.getAbsolutePath()) - || (rootDir.getAbsolutePath().startsWith(dir.getAbsolutePath()) && dir.isGoDeeper())) { - CheckingType checkingType = dir.getCheckingType(); - switch (checkingType) { - case EXTENSIONS : { - String[] extensions = item.getExtensions(); - if (extensions != null) { - for (String extension : extensions) { - if (file.getAbsolutePath().endsWith(extension)) { - item.addBytes(file.length()); - break nextFile; - } - } - } else { - item.addBytes(file.length()); - break nextFile; - } - break ; - } - case PREFIX : { - String[] prefixes = item.getPrefixes(); - if (prefixes != null) { - for (String prefix : prefixes) { - if (file.getName().toLowerCase().startsWith(prefix.toLowerCase())) { - item.addBytes(file.length()); - break nextFile; - } - } - } else { - item.addBytes(file.length()); - break nextFile; - } - break ; - } - } - if (dir.isSkipOther()) { - break nextFile; - } - } - } - } - //current file did not match any type - otherMemory.addBytes(file.length()); } + refreshUI(); } - refreshUI(); } } - private long getDirectorySize(File dir) { + private boolean shouldSkipDirectory(@NonNull File dir) { + if (directoriesToSkip != null) { + for (String dirToSkipPath : directoriesToSkip) { + String dirPath = dir.getAbsolutePath(); + if (objectEquals(dirPath, dirToSkipPath)) { + return true; + } + } + } + return false; + } + + private boolean shouldSkipFile(@NonNull File file) { + if (filePrefixesToSkip != null) { + String fileName = file.getName().toLowerCase(); + for (String prefixToAvoid : filePrefixesToSkip) { + String prefix = prefixToAvoid.toLowerCase(); + if (fileName.startsWith(prefix)) { + return true; + } + } + } + return false; + } + + private void processDirectory(@NonNull File directory, + @NonNull MemoryItem... items) { + String directoryPath = directory.getAbsolutePath(); + for (MemoryItem memoryItem : items) { + DirectoryItem[] allowedDirectories = memoryItem.getDirectories(); + if (allowedDirectories != null) { + for (DirectoryItem allowedDir : allowedDirectories) { + String allowedDirPath = allowedDir.getAbsolutePath(); + if (objectEquals(directoryPath, allowedDirPath) + || (directoryPath.startsWith(allowedDirPath))) { + if (allowedDir.shouldProcessInternalDirectories()) { + calculateMultiTypes(directory, items); + return; + } else if (allowedDir.shouldSkipUnmatchedInDirectory()) { + return; + } + } + } + } + } + // Current directory did not match to any type + otherMemoryItem.addBytes(calculateFolderSize(directory)); + } + + private void processFile(@NonNull File rootDir, + @NonNull File file, + @NonNull MemoryItem... items) { + for (MemoryItem item : items) { + DirectoryItem[] allowedDirectories = item.getDirectories(); + if (allowedDirectories == null) continue; + String rootDirPath = rootDir.getAbsolutePath(); + + for (DirectoryItem allowedDir : allowedDirectories) { + String allowedDirPath = allowedDir.getAbsolutePath(); + boolean processInternal = allowedDir.shouldProcessInternalDirectories(); + if (objectEquals(rootDirPath, allowedDirPath) + || (rootDirPath.startsWith(allowedDirPath) && processInternal)) { + CheckingType checkingType = allowedDir.getCheckingType(); + switch (checkingType) { + case EXTENSIONS: { + if (isSuitableExtension(file, item)) { + item.addBytes(file.length()); + return; + } + break; + } + case PREFIX: { + if (isSuitablePrefix(file, item)) { + item.addBytes(file.length()); + return; + } + break; + } + } + if (allowedDir.shouldSkipUnmatchedInDirectory()) { + return; + } + } + } + } + // Current file did not match any type + otherMemoryItem.addBytes(file.length()); + } + + private boolean isSuitableExtension(@NonNull File file, + @NonNull MemoryItem item) { + String[] extensions = item.getExtensions(); + if (extensions != null) { + for (String extension : extensions) { + if (file.getAbsolutePath().endsWith(extension)) { + return true; + } + } + } + return extensions == null; + } + + private boolean isSuitablePrefix(@NonNull File file, + @NonNull MemoryItem item) { + String[] prefixes = item.getPrefixes(); + if (prefixes != null) { + for (String prefix : prefixes) { + if (file.getName().toLowerCase().startsWith(prefix.toLowerCase())) { + return true; + } + } + } + return prefixes == null; + } + + private long calculateFolderSize(@NonNull File dir) { long bytes = 0; if (dir.isDirectory()) { File[] files = dir.listFiles(); + if (files == null) return 0; + for (File file : files) { if (isCancelled()) { break; } if (file.isDirectory()) { - bytes += getDirectorySize(file); + bytes += calculateFolderSize(file); } else if (file.isFile()) { bytes += file.length(); } @@ -161,16 +206,16 @@ public class RefreshUsedMemoryTask extends AsyncTask { @Override protected void onProgressUpdate(Void... values) { super.onProgressUpdate(values); - if (listener != null) { - listener.onMemoryInfoUpdate(); + if (uiAdapter != null) { + uiAdapter.onMemoryInfoUpdate(); } } @Override protected void onPostExecute(Void aVoid) { super.onPostExecute(aVoid); - if (listener != null) { - listener.onFinishUpdating(taskKey); + if (uiAdapter != null) { + uiAdapter.onFinishUpdating(tag); } } From 5d3d9500bf5393039fd68ef25dc42186550cd965 Mon Sep 17 00:00:00 2001 From: solokot Date: Mon, 1 Feb 2021 18:47:04 +0000 Subject: [PATCH 05/65] Translated using Weblate (Russian) Currently translated at 99.5% (3639 of 3656 strings) --- OsmAnd/res/values-ru/strings.xml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/OsmAnd/res/values-ru/strings.xml b/OsmAnd/res/values-ru/strings.xml index a0a8f5fdea..5747a78d85 100644 --- a/OsmAnd/res/values-ru/strings.xml +++ b/OsmAnd/res/values-ru/strings.xml @@ -3986,4 +3986,10 @@ Читать полностью Редактировать описание Удалить путевые точки + HGV + Отправка + Отправка завершена + Отправка %1$d из %2$d + Отправлено %1$d из %2$d + Выберите правки для отправки \ No newline at end of file From 601e8c36702d86178891b604436c7ae0022615b6 Mon Sep 17 00:00:00 2001 From: Matej U Date: Sun, 31 Jan 2021 17:24:39 +0000 Subject: [PATCH 06/65] Translated using Weblate (Slovenian) Currently translated at 74.1% (2710 of 3656 strings) --- OsmAnd/res/values-sl/strings.xml | 53 ++++++++++++++++++++++++++++++-- 1 file changed, 50 insertions(+), 3 deletions(-) diff --git a/OsmAnd/res/values-sl/strings.xml b/OsmAnd/res/values-sl/strings.xml index 0cb17c35f4..b453cd4b40 100644 --- a/OsmAnd/res/values-sl/strings.xml +++ b/OsmAnd/res/values-sl/strings.xml @@ -3275,14 +3275,14 @@ Izberi mapo Izberi mapo ali dodaj novo Prazno - Analiziraj po intervalih (razdelitveni interval) + Preuči po intervalih (razdelitveni interval) Naloži v OpenStreetMap Uredi sled Preimenuj sled Spremeni mapo sek Pristop - Pripravi se + Pripravljanje Izven poti Prihod na cilj Zavoj @@ -3296,7 +3296,7 @@ Električno kolesarjenje Gorsko kolesarjenje Cestno kolesarjenje - Redno kolesarjenje + Mestno kolesarjenje Težko tovorno vozilo Majhno tovorno vozilo Tovorno vozilo @@ -3309,4 +3309,51 @@ Uredi opis Brisanje točk Kopiraj na oznake na zemljevidu + Na napravi ni dovolj prostora. + Izbor skupin za uvoz. + Izbor predmetov za uvoz. + Dodaj na Mapillary + Dodaj na OpenPlaceReviews + Za preizkušanje pošiljanja sporočil, točk in sledi GPX preklopi iz openstreetmap.org na preizkusni dev.openstreetmap.org. + Uporabi dev.openstreetmap.org + Program podpira prikaz fotografij različnih virov: +\nOpenPlaceReviews – fotografije točk POI; +\nMapillary – ulična fotografija; +\nSplet / Wikimedia – fotografije točk POI in OpenStreetMap. + %1$s * %2$s + Dodaj nov del poti + Lahko letalo + Združi dele poti + Razdeli pred + Razdeli po + Profil OsmAnd + Uporabniški profil + Obrni vse točke + Izbor profila, ki bo prikazan ob zagonu programa. + Nazadnje uporabljeno + Podvrsta + Vozilo + Ključ API + Naslov URL strežnika + Vpis parametrov + Naslov URL z vsemi parametri bo zapisan kot: + Preizkusi izračun poti + Vožnja + Hoja + Kolo + Avto + Kopiraj naslov + Dolgo pripravljanje + Pokaži sled na zemljevidu + Raven približanja + Prosojnost + Legenda + Prikaz višinskega senčenja na zemljevidu. Več o tem je mogoče prebrati na spletni strani programa. + Senčenje + Kopiraj med priljubljene + Poteka pošiljanje + Pošiljanje je končano + Poteka pošiljanje %1$d od %2$d + Poslano %1$d od %2$d + Izbor sprememb za pošiljanje \ No newline at end of file From 4baed45334b62d3b3fde3314c23cfff6ea6a38da Mon Sep 17 00:00:00 2001 From: Oliver Date: Sun, 31 Jan 2021 09:45:16 +0000 Subject: [PATCH 07/65] Translated using Weblate (German) Currently translated at 99.9% (3653 of 3656 strings) --- OsmAnd/res/values-de/strings.xml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/OsmAnd/res/values-de/strings.xml b/OsmAnd/res/values-de/strings.xml index 620e4a10ea..6fec463772 100644 --- a/OsmAnd/res/values-de/strings.xml +++ b/OsmAnd/res/values-de/strings.xml @@ -4008,4 +4008,9 @@ Wegpunkte löschen In Favoriten kopieren In Kartenmarkierungen kopieren + Lade hoch + Hochladen abgeschlossen + Lade %1$d von %2$d hoch + %1$d von %2$d hochgeladen + Bearbeitungen zum Hochladen auswählen \ No newline at end of file From cb59ac4589a3cde374e2de13bfea162f22ddbff8 Mon Sep 17 00:00:00 2001 From: Ahmad Alfrhood Date: Sun, 31 Jan 2021 18:52:23 +0000 Subject: [PATCH 08/65] Translated using Weblate (Arabic) Currently translated at 100.0% (3656 of 3656 strings) --- OsmAnd/res/values-ar/strings.xml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/OsmAnd/res/values-ar/strings.xml b/OsmAnd/res/values-ar/strings.xml index 4b91263f2d..d12d0a4de4 100644 --- a/OsmAnd/res/values-ar/strings.xml +++ b/OsmAnd/res/values-ar/strings.xml @@ -4069,4 +4069,9 @@ حذف نقاط الطريق نسخ لعلامات الخريطة نسخ للمفضلة + يتم الرفع + اكتمال الرفع + رفع %1$d من %2$d + تم رفع %1$d من %2$d + تحديد التعديلات للتحميل \ No newline at end of file From 9dc5d32c06f336e36911e17b44541c846d0c48f0 Mon Sep 17 00:00:00 2001 From: Jukefox Date: Sun, 31 Jan 2021 19:12:35 +0000 Subject: [PATCH 09/65] Translated using Weblate (Finnish) Currently translated at 63.8% (2334 of 3656 strings) --- OsmAnd/res/values-fi/strings.xml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/OsmAnd/res/values-fi/strings.xml b/OsmAnd/res/values-fi/strings.xml index 95df84bf3e..c188b64182 100644 --- a/OsmAnd/res/values-fi/strings.xml +++ b/OsmAnd/res/values-fi/strings.xml @@ -2739,4 +2739,15 @@ Jos pidät OsmAndista ja OSMsta ja haluat tukea niitä, on tämä täydellinen t Kävely Polkupyörä Auto + Palvelimen virhe: %1$s + Nimi on jo käytössä + Lue kaikki + Muokkaa kuvausta + Kopioi karttamerkkeihin + Kopioi suosikkeihin + Lähetetään + Lähetys valmis + Lähetetty %1$d muutosta %2$d muutoksesta + Lähetettiin %1$d muutosta %2$d muutoksesta + Valitse lähetettävät muutokset \ No newline at end of file From 870efe218392c4826b29f9c2633d2de2214d954c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Babos=20G=C3=A1bor?= Date: Sun, 31 Jan 2021 22:27:22 +0000 Subject: [PATCH 10/65] Translated using Weblate (Hungarian) Currently translated at 99.9% (3878 of 3881 strings) --- OsmAnd/res/values-hu/phrases.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/OsmAnd/res/values-hu/phrases.xml b/OsmAnd/res/values-hu/phrases.xml index 488f760a80..b4ca7f9b08 100644 --- a/OsmAnd/res/values-hu/phrases.xml +++ b/OsmAnd/res/values-hu/phrases.xml @@ -708,7 +708,7 @@ Autó Kerékpár Radioaktívhulladék-lerakó - Vízgyűjtő + Vízgyűjtő medence Megfigyelőállomás Daru Építkezés @@ -2633,7 +2633,7 @@ Lottózó Szerencsejáték-helyszín Típus - Lottózó + Lottó Játékgépek Fogadás E-cigaretta-bolt @@ -3446,7 +3446,7 @@ Motorszerelés Biztosítás Gumiszerelés - Kötélpálya + Csúszópálya Kalandpark Via ferrata (vasalt út) Sodronyok száma @@ -3524,7 +3524,7 @@ akadémiai gyermekkönyv Atoll - Útdíjellenőrző kapu + Automatikus útdíjbeszedő kapu Gyermekgondozás (bölcsőde) Természeti emlék Tájékozódási pont From 7454c740653c15f71369b9084cd4979759c4dd53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Priit=20J=C3=B5er=C3=BC=C3=BCt?= Date: Mon, 1 Feb 2021 17:56:18 +0000 Subject: [PATCH 11/65] Translated using Weblate (Estonian) Currently translated at 98.1% (3590 of 3656 strings) --- OsmAnd/res/values-et/strings.xml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/OsmAnd/res/values-et/strings.xml b/OsmAnd/res/values-et/strings.xml index 3bd15abafa..1375440bb8 100644 --- a/OsmAnd/res/values-et/strings.xml +++ b/OsmAnd/res/values-et/strings.xml @@ -3948,4 +3948,9 @@ Viimati kasutatud Serveri viga: %1$s Selline nimi on juba olemas + Vali tehtud muudatused üleslaadimiseks + Üleslaaditud %1$d/%2$d + Laadin üles muudatusi %1$d/%2$d + Sai üleslaaditud + Laadin üles \ No newline at end of file From e4f99aeacee3bd3cf78a6dc19912e1c91a8d23d2 Mon Sep 17 00:00:00 2001 From: eol Date: Mon, 1 Feb 2021 17:35:59 +0000 Subject: [PATCH 12/65] Translated using Weblate (Dutch) Currently translated at 96.1% (3517 of 3656 strings) --- OsmAnd/res/values-nl/strings.xml | 51 ++++++++++++++++++-------------- 1 file changed, 28 insertions(+), 23 deletions(-) diff --git a/OsmAnd/res/values-nl/strings.xml b/OsmAnd/res/values-nl/strings.xml index c9d8e87306..6d4c127831 100644 --- a/OsmAnd/res/values-nl/strings.xml +++ b/OsmAnd/res/values-nl/strings.xml @@ -931,7 +931,7 @@ %1$d resterende bestanden %1$d resterende bestanden nog te downloaden Volledige versie - Annuleer route + Annuleer route \? Stop navigatie Bestemming wissen Gebruik magnetische sensor in plaats van oriëntatiesensor voor het kompas. @@ -3726,31 +3726,31 @@ Plan een route Gebruik de twee-fase A* route berekening methode Grafiek - Wacht op de herberekening van de route. -\nDe grafiek is beschikbaar na herberekening. + Wacht totdat route herberekend is. +\nNa herberekening is de grafiek zichtbaar. %1$s — %2$s Kies een trackbestand om te volgen of importeer het, vanaf uw apparaat. Onderbreking Aangepast Voer een OAuth-login uit om osm edit functies te gebruiken - "• Bijgewerkte app- en profielinstellingen: instellingen zijn nu gerangschikt op type. Elk profiel kan afzonderlijk worden aangepast. + • Bijgewerkte app- en profielinstellingen: instellingen zijn nu gerangschikt op type. Elk profiel kan afzonderlijk worden aangepast. \n -\n • Nieuw dialoogvenster voor het downloaden van kaarten waarin wordt voorgesteld een kaart te downloaden tijdens het browsen +\n • Nieuw dialoogvenster voor het downloaden van kaarten waarin wordt voorgesteld een kaart te downloaden tijdens het browsen \n -\n • Donkere thema-fixes +\n • Donkere thema-fixes \n -\n • Verschillende routeringsproblemen over de hele wereld opgelost +\n • Verschillende routeringsproblemen over de hele wereld opgelost \n -\n • Bijgewerkte basiskaart met meer gedetailleerd wegennet +\n • Bijgewerkte basiskaart met meer gedetailleerd wegennet \n -\n • Vaste overstroomde gebieden over de hele wereld +\n • Vaste overstroomde gebieden over de hele wereld \n -\n • Skirouting: hoogteprofiel en routecomplexiteit toegevoegd aan de routedetails +\n • Skirouting: hoogteprofiel en routecomplexiteit toegevoegd aan de routedetails \n -\n • Andere bugs opgelost +\n • Andere bugs opgelost \n -\n" - "• Profielen: nu kunt u de volgorde wijzigen, het pictogram voor de kaart instellen, alle instellingen voor basisprofielen wijzigen en ze terugzetten naar de standaardinstellingen +\n + • Profielen: nu kunt u de volgorde wijzigen, het pictogram voor de kaart instellen, alle instellingen voor basisprofielen wijzigen en ze terugzetten naar de standaardinstellingen \n \n • Exitnummer toegevoegd in de navigatie \n @@ -3758,23 +3758,23 @@ \n \n • Herwerkt instellingenscherm voor snelle toegang tot alle profielen \n -\n • Optie toegevoegd om instellingen van een ander profiel te kopiëren +\n • Optie toegevoegd om instellingen van een ander profiel te kopiëren \n -\n • Mogelijkheid toegevoegd om een volgorde te wijzigen of POI-categorieën in Zoeken te verbergen +\n • Mogelijkheid toegevoegd om een volgorde te wijzigen of POI-categorieën in Zoeken te verbergen \n -\n • Correct uitgelijnde POI-pictogrammen op de kaart +\n • Correct uitgelijnde POI-pictogrammen op de kaart \n -\n • Zonsondergang / zonsopganggegevens toegevoegd om de kaart te configureren +\n • Zonsondergang / zonsopganggegevens toegevoegd om de kaart te configureren \n -\n • Thuis/werk-pictogrammen toegevoegd op de kaart +\n • Thuis/werk-pictogrammen toegevoegd op de kaart \n -\n • Ondersteuning toegevoegd voor meerdere regels beschrijving bij Instellingen +\n • Ondersteuning toegevoegd voor meerdere regels beschrijving bij Instellingen \n \n • Correcte transliteratie toegevoegd aan de kaart van Japan \n -\n • Antarctica-kaart toegevoegd +\n • Antarctica-kaart toegevoegd \n -\n" +\n Wat is er nieuw Voor sneeuwscooter, rijden met speciale wegen en tracks. Stel aantal werkdagen in om door te gaan @@ -3837,7 +3837,7 @@ Uitloggen gelukt Bestand is reeds geïmporteerd in OsmAnd Lokale kaarten - Aangenaam + Voorziening Speciaal Transport Onderhoud @@ -3856,7 +3856,7 @@ U moet inloggen om wijzigingen te uploaden. \n \nU kunt inloggen met de veilige OAuth-methode of uw loginnaam en wachtwoord gebruiken. - Inloggen met gebruikersnaam en wachtwoord. + Inloggen met gebruikersnaam en wachtwoord Account Gebruikersnaam Abonnement beheren @@ -3993,4 +3993,9 @@ Waypoints verwijderen Kopiëren naar Markeervlaggetjes Kopiëren naar Favorieten + Opladen + Opladen voltooid + Aan het opladen %1$d van %2$d + Opgeladen %1$d van %2$d + Selecteer de op te laden wijzigingen \ No newline at end of file From c517b730e4beeaa07dad52695bb72a7aaafaf6b8 Mon Sep 17 00:00:00 2001 From: Dima-1 Date: Mon, 1 Feb 2021 23:40:35 +0200 Subject: [PATCH 13/65] Fix piste type --- .../main/java/net/osmand/router/RouteStatisticsHelper.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/OsmAnd-java/src/main/java/net/osmand/router/RouteStatisticsHelper.java b/OsmAnd-java/src/main/java/net/osmand/router/RouteStatisticsHelper.java index 4fe500de2b..43022a1a37 100644 --- a/OsmAnd-java/src/main/java/net/osmand/router/RouteStatisticsHelper.java +++ b/OsmAnd-java/src/main/java/net/osmand/router/RouteStatisticsHelper.java @@ -367,8 +367,9 @@ public class RouteStatisticsHelper { RouteDataObject obj = segment.obj; for (int type : obj.getTypes()) { BinaryMapRouteReaderAdapter.RouteTypeRule tp = obj.region.quickGetEncodingRule(type); - if (tp.getTag().equals("highway") || tp.getTag().equals("route") || - tp.getTag().equals("railway") || tp.getTag().equals("aeroway") || tp.getTag().equals("aerialway")) { + if (tp.getTag().equals("highway") || tp.getTag().equals("route") + || tp.getTag().equals("railway") || tp.getTag().equals("aeroway") + || tp.getTag().equals("aerialway") || tp.getTag().equals("piste:type")) { if (!mainTagAdded) { req.setStringFilter(rrs.PROPS.R_TAG, tp.getTag()); req.setStringFilter(rrs.PROPS.R_VALUE, tp.getValue()); From 56e8f85c04510ea75fb8ab242860b18a9533d639 Mon Sep 17 00:00:00 2001 From: nnngrach Date: Tue, 2 Feb 2021 04:02:43 +0300 Subject: [PATCH 14/65] add default profile name for unnamed or missing improted profiles --- .../settings/backend/backup/ProfileSettingsItem.java | 3 ++- .../settings/fragments/DuplicatesSettingsAdapter.java | 7 ++++++- .../plus/settings/fragments/ExportItemsBottomSheet.java | 9 ++++++++- 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/OsmAnd/src/net/osmand/plus/settings/backend/backup/ProfileSettingsItem.java b/OsmAnd/src/net/osmand/plus/settings/backend/backup/ProfileSettingsItem.java index b0bfd5be61..5590d306c6 100644 --- a/OsmAnd/src/net/osmand/plus/settings/backend/backup/ProfileSettingsItem.java +++ b/OsmAnd/src/net/osmand/plus/settings/backend/backup/ProfileSettingsItem.java @@ -26,6 +26,7 @@ import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; +import org.apache.commons.lang3.StringUtils; public class ProfileSettingsItem extends OsmandSettingsItem { @@ -124,7 +125,7 @@ public class ProfileSettingsItem extends OsmandSettingsItem { if (Algorithms.isEmpty(modeBean.userProfileName)) { ApplicationMode appMode = ApplicationMode.valueOfStringKey(modeBean.stringKey, null); if (appMode != null) { - modeBean.userProfileName = app.getString(appMode.getNameKeyResource()); + modeBean.userProfileName = appMode.toHumanString(); } } int number = 0; diff --git a/OsmAnd/src/net/osmand/plus/settings/fragments/DuplicatesSettingsAdapter.java b/OsmAnd/src/net/osmand/plus/settings/fragments/DuplicatesSettingsAdapter.java index 5d9e3af28a..7e7e52f340 100644 --- a/OsmAnd/src/net/osmand/plus/settings/fragments/DuplicatesSettingsAdapter.java +++ b/OsmAnd/src/net/osmand/plus/settings/fragments/DuplicatesSettingsAdapter.java @@ -33,6 +33,7 @@ import net.osmand.plus.settings.backend.ApplicationMode; import net.osmand.plus.settings.backend.ApplicationMode.ApplicationModeBean; import net.osmand.util.Algorithms; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import java.io.File; @@ -91,7 +92,11 @@ public class DuplicatesSettingsAdapter extends RecyclerView.Adapter Date: Tue, 2 Feb 2021 04:03:51 +0300 Subject: [PATCH 15/65] Revert "add default profile name for unnamed or missing improted profiles" This reverts commit 56e8f85c04510ea75fb8ab242860b18a9533d639. --- .../settings/backend/backup/ProfileSettingsItem.java | 3 +-- .../settings/fragments/DuplicatesSettingsAdapter.java | 7 +------ .../plus/settings/fragments/ExportItemsBottomSheet.java | 9 +-------- 3 files changed, 3 insertions(+), 16 deletions(-) diff --git a/OsmAnd/src/net/osmand/plus/settings/backend/backup/ProfileSettingsItem.java b/OsmAnd/src/net/osmand/plus/settings/backend/backup/ProfileSettingsItem.java index 5590d306c6..b0bfd5be61 100644 --- a/OsmAnd/src/net/osmand/plus/settings/backend/backup/ProfileSettingsItem.java +++ b/OsmAnd/src/net/osmand/plus/settings/backend/backup/ProfileSettingsItem.java @@ -26,7 +26,6 @@ import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; -import org.apache.commons.lang3.StringUtils; public class ProfileSettingsItem extends OsmandSettingsItem { @@ -125,7 +124,7 @@ public class ProfileSettingsItem extends OsmandSettingsItem { if (Algorithms.isEmpty(modeBean.userProfileName)) { ApplicationMode appMode = ApplicationMode.valueOfStringKey(modeBean.stringKey, null); if (appMode != null) { - modeBean.userProfileName = appMode.toHumanString(); + modeBean.userProfileName = app.getString(appMode.getNameKeyResource()); } } int number = 0; diff --git a/OsmAnd/src/net/osmand/plus/settings/fragments/DuplicatesSettingsAdapter.java b/OsmAnd/src/net/osmand/plus/settings/fragments/DuplicatesSettingsAdapter.java index 7e7e52f340..5d9e3af28a 100644 --- a/OsmAnd/src/net/osmand/plus/settings/fragments/DuplicatesSettingsAdapter.java +++ b/OsmAnd/src/net/osmand/plus/settings/fragments/DuplicatesSettingsAdapter.java @@ -33,7 +33,6 @@ import net.osmand.plus.settings.backend.ApplicationMode; import net.osmand.plus.settings.backend.ApplicationMode.ApplicationModeBean; import net.osmand.util.Algorithms; -import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import java.io.File; @@ -92,11 +91,7 @@ public class DuplicatesSettingsAdapter extends RecyclerView.Adapter Date: Tue, 2 Feb 2021 04:04:07 +0300 Subject: [PATCH 16/65] Revert "Merge branch 'master' of https://github.com/osmandapp/Osmand" This reverts commit c2a88ef523a02b5708f68c350f0c407bf038a5fc, reversing changes made to 56e8f85c04510ea75fb8ab242860b18a9533d639. --- OsmAnd/res/values-fi/phrases.xml | 42 ++++++++++++++++---------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/OsmAnd/res/values-fi/phrases.xml b/OsmAnd/res/values-fi/phrases.xml index 6453253dd4..7751c5bb95 100644 --- a/OsmAnd/res/values-fi/phrases.xml +++ b/OsmAnd/res/values-fi/phrases.xml @@ -17,7 +17,7 @@ Bussipysäkki Trollibussin pysäkki Raitiovaunupysäkki - Piknik-paikka + Piknic paikka Merkittävä kivi Ankkurointipaikka Majakka/linjavalo @@ -311,8 +311,8 @@ Ei Visa Electron -kortteja Shekit Shekkejä ei hyväksytä - Visa Debit-kortit - Ei Visa Debit-kortteja + Visa Debit -kortit + Ei Visa Debit -kortteja Muut Muita maksutapoja ei hyväksytä Bancomat @@ -1139,28 +1139,28 @@ Ei MasterCard-kortteja Maestro-kortit Ei Maestro-kortteja - Ei American Express (AMEX)-kortteja - Ei Diners Club-kortteja + Ei American Express (AMEX) -kortteja + Ei Diners Club -kortteja Ei DKV-kortteja Ei UTA-kortteja Ei Efectivo-maksua Ei Girocard-kortteja Discover Card - Ei Discover Card-kortteja + Ei Discover Card -kortteja Ei Litecoinia Ei PIKEPASS-maksua Ei kryptovaluuttaa - Ei Routex-tankkauskortteja - Ei IC Stored Fare-kortteja + Ei Routex -tankkauskortteja + Ei IC Stored Fare -kortteja Ei JCB-kortteja Ei Laser-kortteja Ei Quick-kortteja Ei Eurowag-kortteja - Ei E-ZPass-maksua + Ei E-ZPass -maksua Ei Euroshell-tankkauskortteja Ei KITCard-maksua Ei Westfalen-kortteja - Ei V PAY-kortteja + Ei V PAY -kortteja Ei Dogecoinia Ei Cibus-kortteja Ei maksua tilisiirrolla @@ -1172,7 +1172,7 @@ Ei Minipay-maksua Ei MiniCash-maksua Ei Moneo-maksua - Ei Monedero 4B-maksua + Ei Monedero 4B -maksua Ei Monedero-maksua Ei BankAxess-maksua Ei Coinkite-maksua @@ -1182,20 +1182,20 @@ Ei tekstiviestimaksua Ei Oyster-kortteja Ei SUBE-kortteja - Ei Via Verde-maksua + Ei Via Verde -maksua Lounassetelit Ei lounasseteleitä Ei PayPal-maksua - Ei U-Key-maksua + Ei U-Key -maksua Poletit Ei poletteja Ei lahjakorttimaksua - Ei Golden Crown-kortteja + Ei Golden Crown -kortteja Ei PRO100-kortteja - Ei Union Card-kortteja + Ei Union Card -kortteja Ei MTS-Money -maksua - Ei Yandex.Money-maksua - Ei OV-Chipkaart-kortteja + Ei Yandex.Money -maksua + Ei OV-Chipkaart -kortteja Tapahtumapaikka Vain kasvisruokaa Kasvisruokaa @@ -1245,9 +1245,9 @@ Sisätilat Ulkona Ei wc-tiloja - Inva-WC: kyllä - Inva-WC: ei - Asiakas-WC + Inva-wc: kyllä + Inva-wc: ei + Asiakas-wc WC:n käyttö: yhteisö WC:n käyttö: julkinen Vauvan vaihtopöytä @@ -1522,4 +1522,4 @@ Vieras talo Majapaikka Vuoristorata - + \ No newline at end of file From 8f302f8558dc94086d316bd5edeaad08dc790190 Mon Sep 17 00:00:00 2001 From: nazar-kutz Date: Tue, 2 Feb 2021 09:41:34 +0200 Subject: [PATCH 17/65] Data storage refactoring, step 3 --- .../datastorage/DataStorageFragment.java | 4 +- .../datastorage/DataStorageHelper.java | 39 ++++++++++--------- .../datastorage/item/DirectoryItem.java | 10 ++--- .../task/RefreshUsedMemoryTask.java | 26 ++++++------- 4 files changed, 41 insertions(+), 38 deletions(-) diff --git a/OsmAnd/src/net/osmand/plus/settings/datastorage/DataStorageFragment.java b/OsmAnd/src/net/osmand/plus/settings/datastorage/DataStorageFragment.java index bba6898aaf..7fd96b8185 100644 --- a/OsmAnd/src/net/osmand/plus/settings/datastorage/DataStorageFragment.java +++ b/OsmAnd/src/net/osmand/plus/settings/datastorage/DataStorageFragment.java @@ -462,9 +462,9 @@ public class DataStorageFragment extends BaseSettingsFragment implements DataSto } @Override - public void onFinishUpdating(String taskKey) { + public void onFinishUpdating(String tag) { updateAllSettings(); - if (taskKey != null && taskKey.equals(TILES_MEMORY)) { + if (tag != null && tag.equals(TILES_MEMORY)) { app.getSettings().OSMAND_USAGE_SPACE.set(dataStorageHelper.getTotalUsedBytes()); } } diff --git a/OsmAnd/src/net/osmand/plus/settings/datastorage/DataStorageHelper.java b/OsmAnd/src/net/osmand/plus/settings/datastorage/DataStorageHelper.java index fd66cd3e58..b97da17a4c 100644 --- a/OsmAnd/src/net/osmand/plus/settings/datastorage/DataStorageHelper.java +++ b/OsmAnd/src/net/osmand/plus/settings/datastorage/DataStorageHelper.java @@ -67,6 +67,11 @@ public class DataStorageHelper { } private void prepareData() { + initStorageItems(); + initUsedMemoryItems(); + } + + private void initStorageItems() { OsmandSettings settings = app.getSettings(); if (settings.getExternalStorageDirectoryTypeV19() >= 0) { currentStorageType = settings.getExternalStorageDirectoryTypeV19(); @@ -169,20 +174,18 @@ public class DataStorageHelper { if (currentDataStorage == null) { currentDataStorage = manuallySpecified; } - - initMemoryUsed(); } - private void initMemoryUsed() { + private void initUsedMemoryItems() { mapsMemory = MemoryItem.builder() .setKey(MAPS_MEMORY) .setExtensions(IndexConstants.BINARY_MAP_INDEX_EXT) .setDirectories( - createDirectory((MAPS_PATH), false, EXTENSIONS, false), - createDirectory((ROADS_INDEX_DIR), true, EXTENSIONS, false), - createDirectory((WIKI_INDEX_DIR), true, EXTENSIONS, false), - createDirectory((WIKIVOYAGE_INDEX_DIR), true, EXTENSIONS, false), - createDirectory((BACKUP_INDEX_DIR), true, EXTENSIONS, false)) + 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); @@ -190,8 +193,8 @@ public class DataStorageHelper { .setKey(TERRAIN_MEMORY) .setExtensions(IndexConstants.BINARY_SRTM_MAP_INDEX_EXT) .setDirectories( - createDirectory((SRTM_INDEX_DIR), true, EXTENSIONS, false), - createDirectory((TILES_INDEX_DIR), false, PREFIX, true)) + createDirectory(SRTM_INDEX_DIR, true, EXTENSIONS, true), + createDirectory(TILES_INDEX_DIR, false, PREFIX, false)) .setPrefixes("Hillshade") .createItem(); memoryItems.add(terrainMemory); @@ -200,7 +203,7 @@ public class DataStorageHelper { .setKey(TRACKS_MEMORY) // .setExtensions(IndexConstants.GPX_FILE_EXT, ".gpx.bz2") .setDirectories( - createDirectory((GPX_INDEX_DIR), true, EXTENSIONS, false)) + createDirectory(GPX_INDEX_DIR, true, EXTENSIONS, true)) .createItem(); memoryItems.add(tracksMemory); @@ -208,7 +211,7 @@ public class DataStorageHelper { .setKey(NOTES_MEMORY) // .setExtensions("") .setDirectories( - createDirectory((AV_INDEX_DIR), true, EXTENSIONS, false)) + createDirectory(AV_INDEX_DIR, true, EXTENSIONS, true)) .createItem(); memoryItems.add(notesMemory); @@ -216,7 +219,7 @@ public class DataStorageHelper { .setKey(TILES_MEMORY) // .setExtensions("") .setDirectories( - createDirectory((TILES_INDEX_DIR), true, EXTENSIONS, false)) + createDirectory(TILES_INDEX_DIR, true, EXTENSIONS, true)) .createItem(); memoryItems.add(tilesMemory); @@ -264,9 +267,9 @@ public class DataStorageHelper { return memoryItems; } - public RefreshUsedMemoryTask calculateMemoryUsedInfo(UpdateMemoryInfoUIAdapter listener) { + public RefreshUsedMemoryTask calculateMemoryUsedInfo(UpdateMemoryInfoUIAdapter uiAdapter) { File rootDir = new File(currentStoragePath); - RefreshUsedMemoryTask task = new RefreshUsedMemoryTask(listener, otherMemory, rootDir, null, null, OTHER_MEMORY); + RefreshUsedMemoryTask task = new RefreshUsedMemoryTask(uiAdapter, otherMemory, rootDir, null, null, OTHER_MEMORY); task.execute(mapsMemory, terrainMemory, tracksMemory, notesMemory); return task; } @@ -292,9 +295,9 @@ public class DataStorageHelper { public DirectoryItem createDirectory(@NonNull String relativePath, boolean processInternalDirectories, CheckingType checkingType, - boolean skipUnmatchedInDirectory) { + boolean addUnmatchedToOtherMemory) { String path = app.getAppPath(relativePath).getAbsolutePath(); - return new DirectoryItem(path, processInternalDirectories, checkingType, skipUnmatchedInDirectory); + return new DirectoryItem(path, processInternalDirectories, checkingType, addUnmatchedToOtherMemory); } public static String getFormattedMemoryInfo(long bytes, String[] formatStrings) { @@ -312,7 +315,7 @@ public class DataStorageHelper { void onMemoryInfoUpdate(); - void onFinishUpdating(String taskKey); + void onFinishUpdating(String tag); } } \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/settings/datastorage/item/DirectoryItem.java b/OsmAnd/src/net/osmand/plus/settings/datastorage/item/DirectoryItem.java index 0f15e39f58..f316a47920 100644 --- a/OsmAnd/src/net/osmand/plus/settings/datastorage/item/DirectoryItem.java +++ b/OsmAnd/src/net/osmand/plus/settings/datastorage/item/DirectoryItem.java @@ -5,7 +5,7 @@ public class DirectoryItem { private final String absolutePath; private final boolean processInternalDirectories; private final CheckingType checkingType; - private final boolean skipUnmatchedInDirectory; + private final boolean addUnmatchedToOtherMemory; public enum CheckingType { EXTENSIONS, @@ -15,11 +15,11 @@ public class DirectoryItem { public DirectoryItem(String absolutePath, boolean processInternalDirectories, CheckingType checkingType, - boolean skipUnmatchedInDirectory) { + boolean addUnmatchedToOtherMemory) { this.absolutePath = absolutePath; this.processInternalDirectories = processInternalDirectories; this.checkingType = checkingType; - this.skipUnmatchedInDirectory = skipUnmatchedInDirectory; + this.addUnmatchedToOtherMemory = addUnmatchedToOtherMemory; } public String getAbsolutePath() { @@ -34,7 +34,7 @@ public class DirectoryItem { return checkingType; } - public boolean shouldSkipUnmatchedInDirectory() { - return skipUnmatchedInDirectory; + public boolean shouldAddUnmatchedToOtherMemory() { + return addUnmatchedToOtherMemory; } } diff --git a/OsmAnd/src/net/osmand/plus/settings/datastorage/task/RefreshUsedMemoryTask.java b/OsmAnd/src/net/osmand/plus/settings/datastorage/task/RefreshUsedMemoryTask.java index dc84c97dbc..6f45676888 100644 --- a/OsmAnd/src/net/osmand/plus/settings/datastorage/task/RefreshUsedMemoryTask.java +++ b/OsmAnd/src/net/osmand/plus/settings/datastorage/task/RefreshUsedMemoryTask.java @@ -97,16 +97,16 @@ public class RefreshUsedMemoryTask extends AsyncTask { @NonNull MemoryItem... items) { String directoryPath = directory.getAbsolutePath(); for (MemoryItem memoryItem : items) { - DirectoryItem[] allowedDirectories = memoryItem.getDirectories(); - if (allowedDirectories != null) { - for (DirectoryItem allowedDir : allowedDirectories) { - String allowedDirPath = allowedDir.getAbsolutePath(); + DirectoryItem[] targetDirectories = memoryItem.getDirectories(); + if (targetDirectories != null) { + for (DirectoryItem targetDirectory : targetDirectories) { + String allowedDirPath = targetDirectory.getAbsolutePath(); if (objectEquals(directoryPath, allowedDirPath) || (directoryPath.startsWith(allowedDirPath))) { - if (allowedDir.shouldProcessInternalDirectories()) { + if (targetDirectory.shouldProcessInternalDirectories()) { calculateMultiTypes(directory, items); return; - } else if (allowedDir.shouldSkipUnmatchedInDirectory()) { + } else if (!targetDirectory.shouldAddUnmatchedToOtherMemory()) { return; } } @@ -121,16 +121,16 @@ public class RefreshUsedMemoryTask extends AsyncTask { @NonNull File file, @NonNull MemoryItem... items) { for (MemoryItem item : items) { - DirectoryItem[] allowedDirectories = item.getDirectories(); - if (allowedDirectories == null) continue; + DirectoryItem[] targetDirectories = item.getDirectories(); + if (targetDirectories == null) continue; String rootDirPath = rootDir.getAbsolutePath(); - for (DirectoryItem allowedDir : allowedDirectories) { - String allowedDirPath = allowedDir.getAbsolutePath(); - boolean processInternal = allowedDir.shouldProcessInternalDirectories(); + for (DirectoryItem targetDirectory : targetDirectories) { + String allowedDirPath = targetDirectory.getAbsolutePath(); + boolean processInternal = targetDirectory.shouldProcessInternalDirectories(); if (objectEquals(rootDirPath, allowedDirPath) || (rootDirPath.startsWith(allowedDirPath) && processInternal)) { - CheckingType checkingType = allowedDir.getCheckingType(); + CheckingType checkingType = targetDirectory.getCheckingType(); switch (checkingType) { case EXTENSIONS: { if (isSuitableExtension(file, item)) { @@ -147,7 +147,7 @@ public class RefreshUsedMemoryTask extends AsyncTask { break; } } - if (allowedDir.shouldSkipUnmatchedInDirectory()) { + if (!targetDirectory.shouldAddUnmatchedToOtherMemory()) { return; } } From bba9ed1f26a883c4d7094696781e06fc34ff3a18 Mon Sep 17 00:00:00 2001 From: nazar-kutz Date: Tue, 2 Feb 2021 10:13:01 +0200 Subject: [PATCH 18/65] Improve calculation algorithm of memory usage / fix "used memory of Hillshade doesn't calculated" --- .../task/RefreshUsedMemoryTask.java | 25 +++++++++++-------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/OsmAnd/src/net/osmand/plus/settings/datastorage/task/RefreshUsedMemoryTask.java b/OsmAnd/src/net/osmand/plus/settings/datastorage/task/RefreshUsedMemoryTask.java index 6f45676888..0af4cf34cb 100644 --- a/OsmAnd/src/net/osmand/plus/settings/datastorage/task/RefreshUsedMemoryTask.java +++ b/OsmAnd/src/net/osmand/plus/settings/datastorage/task/RefreshUsedMemoryTask.java @@ -99,16 +99,19 @@ public class RefreshUsedMemoryTask extends AsyncTask { for (MemoryItem memoryItem : items) { DirectoryItem[] targetDirectories = memoryItem.getDirectories(); if (targetDirectories != null) { - for (DirectoryItem targetDirectory : targetDirectories) { - String allowedDirPath = targetDirectory.getAbsolutePath(); - if (objectEquals(directoryPath, allowedDirPath) - || (directoryPath.startsWith(allowedDirPath))) { - if (targetDirectory.shouldProcessInternalDirectories()) { - calculateMultiTypes(directory, items); - return; - } else if (!targetDirectory.shouldAddUnmatchedToOtherMemory()) { - return; - } + for (DirectoryItem dir : targetDirectories) { + String allowedDirPath = dir.getAbsolutePath(); + boolean isPerfectlyMatch = objectEquals(directoryPath, allowedDirPath); + boolean isParentDirectory = !isPerfectlyMatch && (directoryPath.startsWith(allowedDirPath)); + boolean isMatchDirectory = isPerfectlyMatch || isParentDirectory; + if (isPerfectlyMatch) { + calculateMultiTypes(directory, items); + return; + } else if (isParentDirectory && dir.shouldProcessInternalDirectories()) { + calculateMultiTypes(directory, items); + return; + } else if (isMatchDirectory && !dir.shouldAddUnmatchedToOtherMemory()) { + return; } } } @@ -122,7 +125,7 @@ public class RefreshUsedMemoryTask extends AsyncTask { @NonNull MemoryItem... items) { for (MemoryItem item : items) { DirectoryItem[] targetDirectories = item.getDirectories(); - if (targetDirectories == null) continue; + if (targetDirectories == null) return; String rootDirPath = rootDir.getAbsolutePath(); for (DirectoryItem targetDirectory : targetDirectories) { From 1030bc67cb58cb178509e0ec87e2a21b0a9938ea Mon Sep 17 00:00:00 2001 From: nazar-kutz Date: Tue, 2 Feb 2021 10:29:14 +0200 Subject: [PATCH 19/65] Fix #10665 Slope and Hillshade maps separated in the OsmAnd storage overview --- OsmAnd/res/layout/data_storage_memory_used_item.xml | 11 ++++++++--- OsmAnd/res/values/strings.xml | 1 + OsmAnd/res/xml/data_storage.xml | 2 +- .../plus/settings/datastorage/DataStorageHelper.java | 2 +- 4 files changed, 11 insertions(+), 5 deletions(-) diff --git a/OsmAnd/res/layout/data_storage_memory_used_item.xml b/OsmAnd/res/layout/data_storage_memory_used_item.xml index 0edf24f056..72f49226e8 100644 --- a/OsmAnd/res/layout/data_storage_memory_used_item.xml +++ b/OsmAnd/res/layout/data_storage_memory_used_item.xml @@ -9,7 +9,8 @@ + android:layout_height="wrap_content" + android:minHeight="@dimen/card_row_min_height"> + tools:text="Internal application memory" /> + Hillshade / Slope / Contour lines Select edits for upload Uploaded %1$d of %2$d Uploading %1$d of %2$d diff --git a/OsmAnd/res/xml/data_storage.xml b/OsmAnd/res/xml/data_storage.xml index 95168ac3ce..173907c8b0 100644 --- a/OsmAnd/res/xml/data_storage.xml +++ b/OsmAnd/res/xml/data_storage.xml @@ -17,7 +17,7 @@ android:key="terrain_memory_used" android:layout="@layout/data_storage_memory_used_item" android:icon="@drawable/ic_map" - android:title="@string/contour_lines_and_hillshade"/> + android:title="@string/hillshade_slope_contour_lines"/> Date: Tue, 2 Feb 2021 12:42:40 +0200 Subject: [PATCH 20/65] small fix --- .../plus/settings/datastorage/task/RefreshUsedMemoryTask.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OsmAnd/src/net/osmand/plus/settings/datastorage/task/RefreshUsedMemoryTask.java b/OsmAnd/src/net/osmand/plus/settings/datastorage/task/RefreshUsedMemoryTask.java index 0af4cf34cb..123aac1b2b 100644 --- a/OsmAnd/src/net/osmand/plus/settings/datastorage/task/RefreshUsedMemoryTask.java +++ b/OsmAnd/src/net/osmand/plus/settings/datastorage/task/RefreshUsedMemoryTask.java @@ -125,7 +125,7 @@ public class RefreshUsedMemoryTask extends AsyncTask { @NonNull MemoryItem... items) { for (MemoryItem item : items) { DirectoryItem[] targetDirectories = item.getDirectories(); - if (targetDirectories == null) return; + if (targetDirectories == null) continue; String rootDirPath = rootDir.getAbsolutePath(); for (DirectoryItem targetDirectory : targetDirectories) { From a0d57b39cf8dbc4bb7ca4020043c8e887b930669 Mon Sep 17 00:00:00 2001 From: androiddevkotlin <64539346+androiddevkotlin@users.noreply.github.com> Date: Tue, 2 Feb 2021 13:28:19 +0200 Subject: [PATCH 21/65] hillshade/terrain toggle fix --- OsmAnd/res/layout/center_button_container.xml | 2 +- OsmAnd/res/layout/custom_radio_buttons.xml | 5 +++-- OsmAnd/res/layout/left_button_container.xml | 2 +- OsmAnd/res/layout/right_button_container.xml | 2 +- OsmAnd/src/net/osmand/plus/UiUtilities.java | 21 +++++++++++-------- .../plus/myplaces/GPXItemPagerAdapter.java | 6 +++++- 6 files changed, 23 insertions(+), 15 deletions(-) diff --git a/OsmAnd/res/layout/center_button_container.xml b/OsmAnd/res/layout/center_button_container.xml index 99858650dc..05fa83eae0 100644 --- a/OsmAnd/res/layout/center_button_container.xml +++ b/OsmAnd/res/layout/center_button_container.xml @@ -8,7 +8,7 @@ android:layout_weight="1"> @@ -22,7 +22,8 @@ layout="@layout/center_button_container" android:layout_width="0dp" android:layout_height="match_parent" - android:layout_weight="1" /> + android:layout_weight="1" + android:visibility="gone" /> Date: Tue, 2 Feb 2021 15:56:57 +0500 Subject: [PATCH 22/65] Fix #10540 --- .../activities/FavoritesTreeFragment.java | 58 ++++++++++--------- 1 file changed, 32 insertions(+), 26 deletions(-) diff --git a/OsmAnd/src/net/osmand/plus/activities/FavoritesTreeFragment.java b/OsmAnd/src/net/osmand/plus/activities/FavoritesTreeFragment.java index 866503f477..06e71c1bfd 100644 --- a/OsmAnd/src/net/osmand/plus/activities/FavoritesTreeFragment.java +++ b/OsmAnd/src/net/osmand/plus/activities/FavoritesTreeFragment.java @@ -10,6 +10,7 @@ import android.os.AsyncTask; import android.os.Build; import android.os.Bundle; import android.text.Html; +import android.text.Spanned; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; @@ -606,29 +607,34 @@ public class FavoritesTreeFragment extends OsmandExpandableListFragment implemen } } - private StringBuilder generateHtmlPrint(List groups) { + private String generateHtmlPrint(List groups) { StringBuilder html = new StringBuilder(); html.append("

My Favorites

"); + + int MAX_AMOUNT_OF_POINTS = 100; + int addedPoints = 0; for (FavoriteGroup group : groups) { html.append("

" + group.getDisplayName(app) + "

"); for (FavouritePoint fp : group.getPoints()) { - String url = "geo:" + ((float) fp.getLatitude()) + "," + ((float) fp.getLongitude()) + "?m=" + fp.getName(); - html.append("

" + fp.getDisplayName(app) + " - " + "geo:" - + ((float) fp.getLatitude()) + "," + ((float) fp.getLongitude()) + "
"); - if (fp.isAddressSpecified()) { - html.append(": " + fp.getAddress()); - html.append("
"); + if (addedPoints >= MAX_AMOUNT_OF_POINTS) { + break; } - if (!Algorithms.isEmpty(fp.getDescription())) { - html.append(": " + fp.getDescription()); - } - html.append("

"); + + float lat = (float) fp.getLatitude(); + float lon = (float) fp.getLongitude(); + String url = "geo:" + lat + "," + lon + "?m=" + fp.getName(); + html.append("

" + fp.getDisplayName(app) + " - geo:" + + lat + "," + lon + "

"); + addedPoints++; + } + if (addedPoints >= MAX_AMOUNT_OF_POINTS) { + html.append("

...

"); + break; } } - return html; + return html.toString(); } - private void shareFavourites() { if (favouritesAdapter.isEmpty()) { Toast.makeText(getActivity(), R.string.no_fav_to_save, Toast.LENGTH_LONG).show(); @@ -646,6 +652,7 @@ public class FavoritesTreeFragment extends OsmandExpandableListFragment implemen File src = null; File dst = null; + Spanned descriptionOfPoints; @Override protected void onPreExecute() { @@ -662,9 +669,15 @@ public class FavoritesTreeFragment extends OsmandExpandableListFragment implemen @Override protected Void doInBackground(Void... params) { + List groups; if (group != null) { helper.saveFile(group.getPoints(), dst); + groups = new ArrayList<>(); + groups.add(group); + } else { + groups = getMyApplication().getFavorites().getFavoriteGroups(); } + descriptionOfPoints = Html.fromHtml(generateHtmlPrint(groups)); return null; } @@ -680,19 +693,12 @@ public class FavoritesTreeFragment extends OsmandExpandableListFragment implemen Algorithms.fileCopy(src, dst); } final Intent sendIntent = new Intent(); - sendIntent.setAction(Intent.ACTION_SEND); - List groups; - if (group != null) { - groups = new ArrayList<>(); - groups.add(group); - } else { - groups = getMyApplication().getFavorites().getFavoriteGroups(); - } - sendIntent.putExtra(Intent.EXTRA_TEXT, Html.fromHtml(generateHtmlPrint(groups).toString())); - sendIntent.putExtra(Intent.EXTRA_SUBJECT, getString(R.string.share_fav_subject)); - sendIntent.putExtra(Intent.EXTRA_STREAM, AndroidUtils.getUriForFile(getMyApplication(), dst)); - sendIntent.setType("text/plain"); - sendIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); + sendIntent.setAction(Intent.ACTION_SEND) + .putExtra(Intent.EXTRA_SUBJECT, getString(R.string.share_fav_subject)) + .putExtra(Intent.EXTRA_TEXT, descriptionOfPoints) + .putExtra(Intent.EXTRA_STREAM, AndroidUtils.getUriForFile(getMyApplication(), dst)) + .setType("text/plain") + .addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); startActivity(sendIntent); } catch (IOException e) { Toast.makeText(getActivity(), "Error sharing favorites: " + e.getMessage(), Toast.LENGTH_SHORT).show(); From bc63b01ad2bd682b399deeba371433022b04651b Mon Sep 17 00:00:00 2001 From: androiddevkotlin <64539346+androiddevkotlin@users.noreply.github.com> Date: Tue, 2 Feb 2021 14:15:42 +0200 Subject: [PATCH 23/65] toggle hilshade fix --- OsmAnd/res/layout/center_button_container.xml | 2 +- OsmAnd/res/layout/custom_radio_buttons.xml | 5 +++-- OsmAnd/res/layout/left_button_container.xml | 2 +- OsmAnd/res/layout/right_button_container.xml | 2 +- OsmAnd/src/net/osmand/plus/UiUtilities.java | 21 +++++++++++-------- .../plus/myplaces/GPXItemPagerAdapter.java | 6 +++++- 6 files changed, 23 insertions(+), 15 deletions(-) diff --git a/OsmAnd/res/layout/center_button_container.xml b/OsmAnd/res/layout/center_button_container.xml index 99858650dc..05fa83eae0 100644 --- a/OsmAnd/res/layout/center_button_container.xml +++ b/OsmAnd/res/layout/center_button_container.xml @@ -8,7 +8,7 @@ android:layout_weight="1"> @@ -22,7 +22,8 @@ layout="@layout/center_button_container" android:layout_width="0dp" android:layout_height="match_parent" - android:layout_weight="1" /> + android:layout_weight="1" + android:visibility="gone" /> Date: Tue, 2 Feb 2021 13:43:45 +0100 Subject: [PATCH 24/65] clean up setup files --- .gitignore | 3 ++- plugins/Osmand-Nautical/.classpath | 9 ------- plugins/Osmand-Nautical/.project | 33 ------------------------- plugins/Osmand-ParkingPlugin/.classpath | 9 ------- plugins/Osmand-ParkingPlugin/.project | 33 ------------------------- plugins/Osmand-SRTMPlugin/.classpath | 9 ------- plugins/Osmand-SRTMPlugin/.project | 33 ------------------------- plugins/Osmand-Skimaps/.classpath | 9 ------- plugins/Osmand-Skimaps/.project | 33 ------------------------- 9 files changed, 2 insertions(+), 169 deletions(-) delete mode 100644 plugins/Osmand-Nautical/.classpath delete mode 100644 plugins/Osmand-Nautical/.project delete mode 100644 plugins/Osmand-ParkingPlugin/.classpath delete mode 100644 plugins/Osmand-ParkingPlugin/.project delete mode 100644 plugins/Osmand-SRTMPlugin/.classpath delete mode 100644 plugins/Osmand-SRTMPlugin/.project delete mode 100644 plugins/Osmand-Skimaps/.classpath delete mode 100644 plugins/Osmand-Skimaps/.project diff --git a/.gitignore b/.gitignore index 33e746a3d6..7386d5e61e 100644 --- a/.gitignore +++ b/.gitignore @@ -16,7 +16,8 @@ OsmAndCore_*.aar *.iml .settings .idea -.project +**/.project +**/.classpath out/ # Huawei diff --git a/plugins/Osmand-Nautical/.classpath b/plugins/Osmand-Nautical/.classpath deleted file mode 100644 index 7bc01d9a9c..0000000000 --- a/plugins/Osmand-Nautical/.classpath +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/plugins/Osmand-Nautical/.project b/plugins/Osmand-Nautical/.project deleted file mode 100644 index 69d5b60769..0000000000 --- a/plugins/Osmand-Nautical/.project +++ /dev/null @@ -1,33 +0,0 @@ - - - Osmand-Nautical - - - - - - com.android.ide.eclipse.adt.ResourceManagerBuilder - - - - - com.android.ide.eclipse.adt.PreCompilerBuilder - - - - - org.eclipse.jdt.core.javabuilder - - - - - com.android.ide.eclipse.adt.ApkBuilder - - - - - - com.android.ide.eclipse.adt.AndroidNature - org.eclipse.jdt.core.javanature - - diff --git a/plugins/Osmand-ParkingPlugin/.classpath b/plugins/Osmand-ParkingPlugin/.classpath deleted file mode 100644 index 7bc01d9a9c..0000000000 --- a/plugins/Osmand-ParkingPlugin/.classpath +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/plugins/Osmand-ParkingPlugin/.project b/plugins/Osmand-ParkingPlugin/.project deleted file mode 100644 index 1c708327e5..0000000000 --- a/plugins/Osmand-ParkingPlugin/.project +++ /dev/null @@ -1,33 +0,0 @@ - - - Osmand-ParkingPlugin - - - - - - com.android.ide.eclipse.adt.ResourceManagerBuilder - - - - - com.android.ide.eclipse.adt.PreCompilerBuilder - - - - - org.eclipse.jdt.core.javabuilder - - - - - com.android.ide.eclipse.adt.ApkBuilder - - - - - - com.android.ide.eclipse.adt.AndroidNature - org.eclipse.jdt.core.javanature - - diff --git a/plugins/Osmand-SRTMPlugin/.classpath b/plugins/Osmand-SRTMPlugin/.classpath deleted file mode 100644 index 7bc01d9a9c..0000000000 --- a/plugins/Osmand-SRTMPlugin/.classpath +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/plugins/Osmand-SRTMPlugin/.project b/plugins/Osmand-SRTMPlugin/.project deleted file mode 100644 index 6c3b83059d..0000000000 --- a/plugins/Osmand-SRTMPlugin/.project +++ /dev/null @@ -1,33 +0,0 @@ - - - Osmand-SRTMPlugin - - - - - - com.android.ide.eclipse.adt.ResourceManagerBuilder - - - - - com.android.ide.eclipse.adt.PreCompilerBuilder - - - - - org.eclipse.jdt.core.javabuilder - - - - - com.android.ide.eclipse.adt.ApkBuilder - - - - - - com.android.ide.eclipse.adt.AndroidNature - org.eclipse.jdt.core.javanature - - diff --git a/plugins/Osmand-Skimaps/.classpath b/plugins/Osmand-Skimaps/.classpath deleted file mode 100644 index 7bc01d9a9c..0000000000 --- a/plugins/Osmand-Skimaps/.classpath +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/plugins/Osmand-Skimaps/.project b/plugins/Osmand-Skimaps/.project deleted file mode 100644 index 852dfb35a5..0000000000 --- a/plugins/Osmand-Skimaps/.project +++ /dev/null @@ -1,33 +0,0 @@ - - - Osmand-SkiMaps - - - - - - com.android.ide.eclipse.adt.ResourceManagerBuilder - - - - - com.android.ide.eclipse.adt.PreCompilerBuilder - - - - - org.eclipse.jdt.core.javabuilder - - - - - com.android.ide.eclipse.adt.ApkBuilder - - - - - - com.android.ide.eclipse.adt.AndroidNature - org.eclipse.jdt.core.javanature - - From 9c08af0ecb4b4e59bb36de9a60b0a7d906b743ca Mon Sep 17 00:00:00 2001 From: Skalii Date: Tue, 2 Feb 2021 14:55:41 +0200 Subject: [PATCH 25/65] fix speed unit setting for "min/km" to show seconds instead of fractional minutes --- OsmAnd/src/net/osmand/plus/OsmAndFormatter.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/OsmAnd/src/net/osmand/plus/OsmAndFormatter.java b/OsmAnd/src/net/osmand/plus/OsmAndFormatter.java index 11267b0286..6a52fe9804 100644 --- a/OsmAnd/src/net/osmand/plus/OsmAndFormatter.java +++ b/OsmAnd/src/net/osmand/plus/OsmAndFormatter.java @@ -344,8 +344,8 @@ public class OsmAndFormatter { if (minperkm >= 10) { return ((int) Math.round(minperkm)) + " " + mc.toShortString(ctx); } else { - int mph10 = (int) Math.round(minperkm * 10f); - return (mph10 / 10f) + " " + mc.toShortString(ctx); + int seconds = Math.round(minperkm * 60); + return Algorithms.formatDuration(seconds, false) + " " + mc.toShortString(ctx); } } else if (mc == SpeedConstants.MINUTES_PER_MILE) { if (metersperseconds < 0.111111111) { From 31d31f10235ea674cccdb8a5ecf1aea76a7af1ce Mon Sep 17 00:00:00 2001 From: cepprice Date: Tue, 2 Feb 2021 18:41:11 +0500 Subject: [PATCH 26/65] Small edit --- .../activities/FavoritesTreeFragment.java | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/OsmAnd/src/net/osmand/plus/activities/FavoritesTreeFragment.java b/OsmAnd/src/net/osmand/plus/activities/FavoritesTreeFragment.java index 06e71c1bfd..823cb4b740 100644 --- a/OsmAnd/src/net/osmand/plus/activities/FavoritesTreeFragment.java +++ b/OsmAnd/src/net/osmand/plus/activities/FavoritesTreeFragment.java @@ -89,6 +89,8 @@ 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 FavouritesAdapter favouritesAdapter; private FavouritesDbHelper helper; @@ -611,23 +613,28 @@ public class FavoritesTreeFragment extends OsmandExpandableListFragment implemen StringBuilder html = new StringBuilder(); html.append("

My Favorites

"); - int MAX_AMOUNT_OF_POINTS = 100; int addedPoints = 0; for (FavoriteGroup group : groups) { - html.append("

" + group.getDisplayName(app) + "

"); + html.append("

").append(group.getDisplayName(app)).append("

"); for (FavouritePoint fp : group.getPoints()) { - if (addedPoints >= MAX_AMOUNT_OF_POINTS) { + 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("

" + fp.getDisplayName(app) + " - geo:" - + lat + "," + lon + "

"); + html.append("

") + .append(fp.getDisplayName(app)) + .append(" - geo:") + .append(lat).append(",").append(lon) + .append("

"); addedPoints++; } - if (addedPoints >= MAX_AMOUNT_OF_POINTS) { + + if (addedPoints >= MAX_POINTS_IN_DESCRIPTION) { html.append("

...

"); break; } From bb9a05766593a4f05f702801944be496ed7ba484 Mon Sep 17 00:00:00 2001 From: Victor Shcherb Date: Tue, 2 Feb 2021 15:40:48 +0100 Subject: [PATCH 27/65] Add route activity type class --- .../net/osmand/osm/RouteActivityType.java | 218 ++++++++++++++++++ 1 file changed, 218 insertions(+) create mode 100644 OsmAnd-java/src/main/java/net/osmand/osm/RouteActivityType.java diff --git a/OsmAnd-java/src/main/java/net/osmand/osm/RouteActivityType.java b/OsmAnd-java/src/main/java/net/osmand/osm/RouteActivityType.java new file mode 100644 index 0000000000..28c9b11551 --- /dev/null +++ b/OsmAnd-java/src/main/java/net/osmand/osm/RouteActivityType.java @@ -0,0 +1,218 @@ +package net.osmand.osm; + +public enum RouteActivityType { + WATER("Water", "yellow"), WINTER("Winter", "yellow"), SNOWMOBILE("Snowmobile", "yellow"), RIDING("Riding", "yellow"), RACING("Racing", "yellow"), + MOUNTAINBIKE("Mountainbike", "blue"), CYCLING("Cycling", "blue"), + HIKING("Hiking", "orange"), RUNNING("Running", "orange"), WALKING("Walking", "orange"), + OFFROAD("Off-road", "yellow"), + MOTORBIKE("Motorbike", "green"), CAR("Car", "green"); + // less specific bottom order + + String name; + String color; + + private RouteActivityType(String nm, String clr) { + this.name = nm; + this.color = clr; + } + + public String getName() { + return name; + } + + public String getColor() { + return color; + } + + public static RouteActivityType getTypeFromTags(String[] tags) { + RouteActivityType activityType = null; + for (String tg : tags) { + RouteActivityType rat = RouteActivityType.convertFromOsmGPXTag(tg); + if (rat != null) { + if (activityType == null || activityType.ordinal() > rat.ordinal()) { + activityType = rat; + } + } + } + return activityType; + } + + public static RouteActivityType convertFromOsmGPXTag(String tg) { + String t = tg.toLowerCase(); + if ("mountain hiking".equalsIgnoreCase(t)) { + return HIKING; + } + if ("motorcar".equalsIgnoreCase(t)) { + return CAR; + } + if ("laufen".equalsIgnoreCase(t)) { + return RUNNING; + } + if ("pedestrian".equalsIgnoreCase(t)) { + return WALKING; + } + switch (t) { + case "mountainbiking": + case "mtb": + case "mountainbike": + case "mountain bike": + case "mountain biking": + case "mountbarker": + case "mtb-tour": + case "ciclismo-mtb-gravel": + case "vtt": + case "btt": + case "vth": + case "mtb ride": + return MOUNTAINBIKE; + case "hiking": + case "route=hiking": + case "mountain hiking": + case "hiking trail": + case "wandern": + case "hike": + case "randonnée": + case "trekking": + case "climbing": + return HIKING; + case "bike": + case "biking": + case "bicycling": + case "bicycle": + case "cycling": + case "cycle": + case "cycleway": + case "cykel": + case "handcycle": + case "cyclotourisme": + case "route=bicycle": + case "cyclotourism": + case "fietsen": + case "вело": + case "велосипед": + case "rower": + case "trasa rowerem": + case "vélo": + case "velo": + case "radtour": + case "bici": + case "fiets": + case "fahrrad": + case "ncn": + case "icn": + case "lcn": + case "network=ncn": + case "network=icn": + case "network=lcn": + return CYCLING; + case "car": + case "motorcar": + case "by car": + case "auto": + case "автомобиль": + case "automobile": + case "autós": + case "driving": + case "drive": + case "van": + case "авто": + case "на автомобиле": + case "bus": + case "truck": + case "taxi": + return CAR; + case "running": + case "run": + case "rungis": + case "trail running": + case "trailrunning": + case "бег": + case "laufen": + case "langlauf": + case "lauf": + case "course": + case "jogging": + case "fitotrack": + return RUNNING; + case "wanderung": + case "walking": + case "walk": + case "nightwalk": + case "walkway": + case "пешком": + case "пеший": + case "pěšky": + case "marche": + case "pedestrian": + case "foot": + case "footing": + case "on_foot": + case "byfoot": + case "onfoot": + case "sightseeing": + case "geocaching": + case "etnanatura": + case "etna": + case "iwn": + case "lwn": + case "rwn": + case "network=iwn": + case "network=lwn": + case "network=rwn": + return WALKING; + case "ling-moto": + case "motorbiking": + case "motorcycle": + case "motorrad": + case "motorbike": + case "motor bike": + case "FVbike": + case "Motorrad": + return MOTORBIKE; + case "offroad": + case "off-road": + case "off road": + case "4x4": + case "terrain": + case "quad": + case "enduro": + case "feldwege": + case "feldweg": + return OFFROAD; + case "boat": + case "water": + case "boating": + case "kayak": + case "river": + case "lake": + case "lakes": + case "canal": + return WATER; + case "ski": + case "skiing": + case "skating": + case "skitour": + case "winter": + case "wintersports": + case "snowboard": + case "лыжи": + case "лыжня": + case "nordic": + case "piste": + return WINTER; + case "snowmobile=designated": + case "snowmobile=permissive": + case "snowmobile=yes": + case "snowmobile": + return SNOWMOBILE; + case "ride": + case "horse": + case "horse trail": + return RIDING; + case "racing": + return RACING; + } + return null; + } + +} \ No newline at end of file From e57404470dde5d2e7106f5dfaa59ad9f192e6258 Mon Sep 17 00:00:00 2001 From: nnngrach Date: Tue, 2 Feb 2021 18:40:12 +0300 Subject: [PATCH 28/65] add default profile name for unnamed or missing improted profiles. --- .../plus/settings/backend/backup/ProfileSettingsItem.java | 2 +- .../plus/settings/fragments/DuplicatesSettingsAdapter.java | 7 ++++++- .../plus/settings/fragments/ExportItemsBottomSheet.java | 7 ++++++- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/OsmAnd/src/net/osmand/plus/settings/backend/backup/ProfileSettingsItem.java b/OsmAnd/src/net/osmand/plus/settings/backend/backup/ProfileSettingsItem.java index b0bfd5be61..88405fd010 100644 --- a/OsmAnd/src/net/osmand/plus/settings/backend/backup/ProfileSettingsItem.java +++ b/OsmAnd/src/net/osmand/plus/settings/backend/backup/ProfileSettingsItem.java @@ -124,7 +124,7 @@ public class ProfileSettingsItem extends OsmandSettingsItem { if (Algorithms.isEmpty(modeBean.userProfileName)) { ApplicationMode appMode = ApplicationMode.valueOfStringKey(modeBean.stringKey, null); if (appMode != null) { - modeBean.userProfileName = app.getString(appMode.getNameKeyResource()); + modeBean.userProfileName = appMode.toHumanString(); } } int number = 0; diff --git a/OsmAnd/src/net/osmand/plus/settings/fragments/DuplicatesSettingsAdapter.java b/OsmAnd/src/net/osmand/plus/settings/fragments/DuplicatesSettingsAdapter.java index 5d9e3af28a..078197da4f 100644 --- a/OsmAnd/src/net/osmand/plus/settings/fragments/DuplicatesSettingsAdapter.java +++ b/OsmAnd/src/net/osmand/plus/settings/fragments/DuplicatesSettingsAdapter.java @@ -34,6 +34,7 @@ import net.osmand.plus.settings.backend.ApplicationMode.ApplicationModeBean; import net.osmand.util.Algorithms; import org.apache.commons.logging.Log; +import org.apache.commons.lang3.StringUtils; import java.io.File; import java.util.List; @@ -91,7 +92,11 @@ public class DuplicatesSettingsAdapter extends RecyclerView.Adapter Date: Tue, 2 Feb 2021 22:25:17 +0200 Subject: [PATCH 29/65] Fix possible npe --- ...gureAppModesBottomSheetDialogFragment.java | 21 +++++++++++++--- .../MapRouteInfoMenu.java | 24 ++++++++++--------- 2 files changed, 31 insertions(+), 14 deletions(-) diff --git a/OsmAnd/src/net/osmand/plus/profiles/ConfigureAppModesBottomSheetDialogFragment.java b/OsmAnd/src/net/osmand/plus/profiles/ConfigureAppModesBottomSheetDialogFragment.java index ab59432b01..687cd342bf 100644 --- a/OsmAnd/src/net/osmand/plus/profiles/ConfigureAppModesBottomSheetDialogFragment.java +++ b/OsmAnd/src/net/osmand/plus/profiles/ConfigureAppModesBottomSheetDialogFragment.java @@ -1,7 +1,11 @@ package net.osmand.plus.profiles; -import net.osmand.plus.settings.backend.ApplicationMode; +import androidx.annotation.NonNull; +import androidx.fragment.app.FragmentManager; + import net.osmand.plus.R; +import net.osmand.plus.profiles.ConfigureProfileMenuAdapter.ProfileSelectedListener; +import net.osmand.plus.settings.backend.ApplicationMode; import java.util.ArrayList; import java.util.HashSet; @@ -9,8 +13,8 @@ import java.util.LinkedHashSet; import java.util.List; import java.util.Set; -public class ConfigureAppModesBottomSheetDialogFragment extends AppModesBottomSheetDialogFragment - implements ConfigureProfileMenuAdapter.ProfileSelectedListener { +public class ConfigureAppModesBottomSheetDialogFragment extends AppModesBottomSheetDialogFragment + implements ProfileSelectedListener { public static final String TAG = "ConfigureAppModesBottomSheetDialogFragment"; @@ -56,4 +60,15 @@ public class ConfigureAppModesBottomSheetDialogFragment extends AppModesBottomSh } ApplicationMode.changeProfileAvailability(item, isChecked, getMyApplication()); } + + public static void showInstance(@NonNull FragmentManager fragmentManager, boolean usedOnMap, UpdateMapRouteMenuListener listener) { + if (fragmentManager.findFragmentByTag(TAG) == null) { + ConfigureAppModesBottomSheetDialogFragment fragment = new ConfigureAppModesBottomSheetDialogFragment(); + fragment.setUsedOnMap(usedOnMap); + fragment.setUpdateMapRouteMenuListener(listener); + fragmentManager.beginTransaction() + .add(fragment, TAG) + .commitAllowingStateLoss(); + } + } } \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/routepreparationmenu/MapRouteInfoMenu.java b/OsmAnd/src/net/osmand/plus/routepreparationmenu/MapRouteInfoMenu.java index a6b69ba124..83a866c49e 100644 --- a/OsmAnd/src/net/osmand/plus/routepreparationmenu/MapRouteInfoMenu.java +++ b/OsmAnd/src/net/osmand/plus/routepreparationmenu/MapRouteInfoMenu.java @@ -29,6 +29,8 @@ import androidx.appcompat.content.res.AppCompatResources; import androidx.appcompat.widget.AppCompatImageView; import androidx.core.content.ContextCompat; import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentActivity; +import androidx.fragment.app.FragmentManager; import androidx.transition.AutoTransition; import androidx.transition.Scene; import androidx.transition.Transition; @@ -71,7 +73,7 @@ import net.osmand.plus.mapcontextmenu.other.TrackDetailsMenuFragment; import net.osmand.plus.mapmarkers.MapMarker; import net.osmand.plus.mapmarkers.MapMarkerSelectionFragment; import net.osmand.plus.poi.PoiUIFilter; -import net.osmand.plus.profiles.AppModesBottomSheetDialogFragment; +import net.osmand.plus.profiles.AppModesBottomSheetDialogFragment.UpdateMapRouteMenuListener; import net.osmand.plus.profiles.ConfigureAppModesBottomSheetDialogFragment; import net.osmand.plus.routepreparationmenu.RoutingOptionsHelper.AvoidPTTypesRoutingParameter; import net.osmand.plus.routepreparationmenu.RoutingOptionsHelper.AvoidRoadsRoutingParameter; @@ -870,16 +872,16 @@ public class MapRouteInfoMenu implements IRouteInformationListener, CardListener } private void showProfileBottomSheetDialog() { - final AppModesBottomSheetDialogFragment fragment = new ConfigureAppModesBottomSheetDialogFragment(); - fragment.setUsedOnMap(true); - fragment.setUpdateMapRouteMenuListener(new AppModesBottomSheetDialogFragment.UpdateMapRouteMenuListener() { - @Override - public void updateAppModeMenu() { - updateApplicationModes(); - } - }); - getMapActivity().getSupportFragmentManager().beginTransaction() - .add(fragment, ConfigureAppModesBottomSheetDialogFragment.TAG).commitAllowingStateLoss(); + FragmentActivity activity = getMapActivity(); + if (activity != null) { + FragmentManager manager = activity.getSupportFragmentManager(); + ConfigureAppModesBottomSheetDialogFragment.showInstance(manager, true, new UpdateMapRouteMenuListener() { + @Override + public void updateAppModeMenu() { + updateApplicationModes(); + } + }); + } } private void updateApplicationMode(ApplicationMode mode, ApplicationMode next) { From 6a38b44e5fff8dd8de62e9e40c84fcd67c5f42f9 Mon Sep 17 00:00:00 2001 From: Vitaliy Date: Tue, 2 Feb 2021 23:25:45 +0200 Subject: [PATCH 30/65] Fix possible npe --- .../net/osmand/plus/osmedit/DashOsmEditsFragment.java | 6 ++++-- .../net/osmand/plus/osmedit/EditPOIMenuController.java | 10 +++++----- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/OsmAnd/src/net/osmand/plus/osmedit/DashOsmEditsFragment.java b/OsmAnd/src/net/osmand/plus/osmedit/DashOsmEditsFragment.java index de5e538554..ddd601731a 100644 --- a/OsmAnd/src/net/osmand/plus/osmedit/DashOsmEditsFragment.java +++ b/OsmAnd/src/net/osmand/plus/osmedit/DashOsmEditsFragment.java @@ -28,7 +28,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; -import static net.osmand.plus.osmedit.oauth.OsmOAuthHelper.*; +import static net.osmand.plus.osmedit.oauth.OsmOAuthHelper.OsmAuthorizationListener; /** * Created by Denis @@ -149,7 +149,9 @@ public class DashOsmEditsFragment extends DashBaseFragment @Override public void authorizationCompleted() { - SendPoiBottomSheetFragment.showInstance(getChildFragmentManager(), new OsmPoint[]{selectedPoint}); + if (selectedPoint != null) { + SendPoiBottomSheetFragment.showInstance(getChildFragmentManager(), new OsmPoint[] {selectedPoint}); + } } @Override diff --git a/OsmAnd/src/net/osmand/plus/osmedit/EditPOIMenuController.java b/OsmAnd/src/net/osmand/plus/osmedit/EditPOIMenuController.java index 3c64fb12d7..877ebae773 100644 --- a/OsmAnd/src/net/osmand/plus/osmedit/EditPOIMenuController.java +++ b/OsmAnd/src/net/osmand/plus/osmedit/EditPOIMenuController.java @@ -5,6 +5,7 @@ import android.graphics.drawable.Drawable; import androidx.annotation.NonNull; import androidx.appcompat.app.AlertDialog; +import androidx.fragment.app.FragmentManager; import net.osmand.data.PointDescription; import net.osmand.osm.PoiType; @@ -54,16 +55,15 @@ public class EditPOIMenuController extends MenuController { || !Algorithms.isEmpty(settings.USER_NAME.get()) && !Algorithms.isEmpty(settings.USER_PASSWORD.get()); + FragmentManager fragmentManager = activity.getSupportFragmentManager(); if (point instanceof OpenstreetmapPoint) { if (isLogged) { - SendPoiBottomSheetFragment.showInstance(activity.getSupportFragmentManager(), - new OsmPoint[]{getOsmPoint()}); + SendPoiBottomSheetFragment.showInstance(fragmentManager, new OsmPoint[] {point}); } else { - LoginBottomSheetFragment.showInstance(activity.getSupportFragmentManager(), null); + LoginBottomSheetFragment.showInstance(fragmentManager, null); } } else if (point instanceof OsmNotesPoint) { - SendOsmNoteBottomSheetFragment.showInstance(activity.getSupportFragmentManager(), - new OsmPoint[]{getOsmPoint()}); + SendOsmNoteBottomSheetFragment.showInstance(fragmentManager, new OsmPoint[] {point}); } } } From 6dcde54ace36f6668fd8e43f8f4b2b2267932355 Mon Sep 17 00:00:00 2001 From: Vitaliy Date: Wed, 3 Feb 2021 11:41:56 +0200 Subject: [PATCH 31/65] Fix check for default profile --- .../net/osmand/plus/settings/backend/ApplicationMode.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/OsmAnd/src/net/osmand/plus/settings/backend/ApplicationMode.java b/OsmAnd/src/net/osmand/plus/settings/backend/ApplicationMode.java index 59d8172bb1..efb02fefc0 100644 --- a/OsmAnd/src/net/osmand/plus/settings/backend/ApplicationMode.java +++ b/OsmAnd/src/net/osmand/plus/settings/backend/ApplicationMode.java @@ -301,7 +301,12 @@ public class ApplicationMode { } public boolean isCustomProfile() { - return !defaultValues.contains(this); + for (ApplicationMode mode : defaultValues) { + if (Algorithms.stringsEqual(mode.getStringKey(), getStringKey())) { + return false; + } + } + return true; } public boolean isDerivedRoutingFrom(ApplicationMode mode) { From 95cc20b022bc7fe2374d8bd361ebcd9342a90030 Mon Sep 17 00:00:00 2001 From: Vitaliy Date: Wed, 3 Feb 2021 11:52:51 +0200 Subject: [PATCH 32/65] Add check for available oauth request token --- .../oauth/OsmOAuthAuthorizationClient.java | 4 ++++ .../oauth/OsmOAuthAuthorizationAdapter.java | 20 ++++++------------- 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/OsmAnd-java/src/main/java/net/osmand/osm/oauth/OsmOAuthAuthorizationClient.java b/OsmAnd-java/src/main/java/net/osmand/osm/oauth/OsmOAuthAuthorizationClient.java index cf2f5a5acc..02a576db5a 100644 --- a/OsmAnd-java/src/main/java/net/osmand/osm/oauth/OsmOAuthAuthorizationClient.java +++ b/OsmAnd-java/src/main/java/net/osmand/osm/oauth/OsmOAuthAuthorizationClient.java @@ -94,6 +94,10 @@ public class OsmOAuthAuthorizationClient { return accessToken; } + public OAuth1RequestToken getRequestToken() { + return requestToken; + } + public Response performRequestWithoutAuth(String url, String requestMethod, String requestBody) throws InterruptedException, ExecutionException, IOException { Verb verb = parseRequestMethod(requestMethod); diff --git a/OsmAnd/src/net/osmand/plus/osmedit/oauth/OsmOAuthAuthorizationAdapter.java b/OsmAnd/src/net/osmand/plus/osmedit/oauth/OsmOAuthAuthorizationAdapter.java index abc5d1f407..c45ebaaf5e 100644 --- a/OsmAnd/src/net/osmand/plus/osmedit/oauth/OsmOAuthAuthorizationAdapter.java +++ b/OsmAnd/src/net/osmand/plus/osmedit/oauth/OsmOAuthAuthorizationAdapter.java @@ -1,19 +1,10 @@ package net.osmand.plus.osmedit.oauth; import android.content.Context; -import android.content.Intent; import android.net.TrafficStats; import android.net.Uri; import android.os.AsyncTask; -import android.os.Build; -import android.view.View; import android.view.ViewGroup; -import android.webkit.WebView; -import android.webkit.WebViewClient; - -import androidx.annotation.NonNull; -import androidx.browser.customtabs.CustomTabsIntent; -import androidx.core.content.ContextCompat; import com.github.scribejava.core.builder.api.DefaultApi10a; import com.github.scribejava.core.model.OAuth1AccessToken; @@ -24,7 +15,6 @@ import com.github.scribejava.core.model.Verb; import net.osmand.PlatformUtil; import net.osmand.osm.oauth.OsmOAuthAuthorizationClient; -import net.osmand.plus.OsmAndConstants; import net.osmand.plus.OsmandApplication; import net.osmand.plus.R; import net.osmand.plus.wikipedia.WikipediaDialogFragment; @@ -137,7 +127,7 @@ public class OsmOAuthAuthorizationAdapter { } @Override - protected void onPostExecute(@NonNull OAuth1RequestToken requestToken) { + protected void onPostExecute(OAuth1RequestToken requestToken) { if (requestToken != null) { loadWebView(rootLayout, nightMode, client.getService().getAuthorizationUrl(requestToken)); } else { @@ -156,9 +146,11 @@ public class OsmOAuthAuthorizationAdapter { @Override protected Void doInBackground(String... oauthVerifier) { - client.authorize(oauthVerifier[0]); - saveToken(); - updateUserName(); + if (client.getRequestToken() != null) { + client.authorize(oauthVerifier[0]); + saveToken(); + updateUserName(); + } return null; } From 638489fcdf60e42c8949f5caee71f3e932c09239 Mon Sep 17 00:00:00 2001 From: Vitaliy Date: Wed, 3 Feb 2021 12:30:54 +0200 Subject: [PATCH 33/65] Fix possible npe after new wpt point was added --- .../res/layout/map_context_menu_fragment.xml | 7 +++++++ .../MapContextMenuFragment.java | 21 ++++++++++++++----- 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/OsmAnd/res/layout/map_context_menu_fragment.xml b/OsmAnd/res/layout/map_context_menu_fragment.xml index 7a57679825..998123115d 100644 --- a/OsmAnd/res/layout/map_context_menu_fragment.xml +++ b/OsmAnd/res/layout/map_context_menu_fragment.xml @@ -61,6 +61,13 @@ android:layout_gravity="center_vertical" android:text="@string/amenity_type_finance"/> + +
diff --git a/OsmAnd/src/net/osmand/plus/mapcontextmenu/MapContextMenuFragment.java b/OsmAnd/src/net/osmand/plus/mapcontextmenu/MapContextMenuFragment.java index 7977a9ddc6..a3026eda83 100644 --- a/OsmAnd/src/net/osmand/plus/mapcontextmenu/MapContextMenuFragment.java +++ b/OsmAnd/src/net/osmand/plus/mapcontextmenu/MapContextMenuFragment.java @@ -58,6 +58,7 @@ import net.osmand.plus.ContextMenuItem; import net.osmand.plus.LockableScrollView; import net.osmand.plus.OsmAndFormatter; import net.osmand.plus.OsmandApplication; +import net.osmand.plus.helpers.AndroidUiHelper; import net.osmand.plus.settings.backend.MainContextMenuItemsSettings; import net.osmand.plus.settings.backend.OsmandSettings; import net.osmand.plus.R; @@ -1674,6 +1675,12 @@ public class MapContextMenuFragment extends BaseOsmAndFragment implements Downlo line2MeasuredHeight = line2.getMeasuredHeight(); } + int customAddressLineHeight = 0; + View customAddressLine = view.findViewById(R.id.context_menu_custom_address_line); + if (customAddressLine.getVisibility() == View.VISIBLE) { + customAddressLineHeight = customAddressLine.getMeasuredHeight(); + } + int line3Height = 0; View line3Container = view.findViewById(R.id.additional_info_row_container); if (line3Container.getVisibility() == View.VISIBLE) { @@ -1717,12 +1724,12 @@ public class MapContextMenuFragment extends BaseOsmAndFragment implements Downlo titleHeight = line1.getMeasuredHeight() + line2MeasuredHeight; } newMenuTopViewHeight = menuTopViewHeightExcludingTitle + titleHeight - + titleButtonHeight + downloadButtonsHeight + + titleButtonHeight + customAddressLineHeight + downloadButtonsHeight + titleBottomButtonHeight + additionalButtonsHeight + titleProgressHeight + line3Height; dy = Math.max(0, newMenuTopViewHeight - menuTopViewHeight - (newMenuTopShadowAllHeight - menuTopShadowAllHeight)); } else { - menuTopViewHeightExcludingTitle = newMenuTopViewHeight - line1.getMeasuredHeight() - line2MeasuredHeight + menuTopViewHeightExcludingTitle = newMenuTopViewHeight - line1.getMeasuredHeight() - line2MeasuredHeight - customAddressLineHeight - titleButtonHeight - downloadButtonsHeight - titleBottomButtonHeight - additionalButtonsHeight - titleProgressHeight - line3Height; menuTitleTopBottomPadding = (line1.getMeasuredHeight() - line1.getLineCount() * line1.getLineHeight()) + (line2MeasuredHeight - line2LineCount * line2LineHeight); @@ -1818,12 +1825,16 @@ public class MapContextMenuFragment extends BaseOsmAndFragment implements Downlo line1.setText(menu.getTitleStr()); toolbarTextView.setText(menu.getTitleStr()); // Text line 2 - LinearLayout line2layout = view.findViewById(R.id.context_menu_line2_layout); TextView line2 = view.findViewById(R.id.context_menu_line2); + LinearLayout customAddressLine = view.findViewById(R.id.context_menu_custom_address_line); + customAddressLine.removeAllViews(); if (menu.hasCustomAddressLine()) { - line2layout.removeAllViews(); - menu.buildCustomAddressLine(line2layout); + menu.buildCustomAddressLine(customAddressLine); + AndroidUiHelper.updateVisibility(line2, false); + AndroidUiHelper.updateVisibility(customAddressLine, true); } else { + AndroidUiHelper.updateVisibility(line2, true); + AndroidUiHelper.updateVisibility(customAddressLine, false); String typeStr = menu.getTypeStr(); String streetStr = menu.getStreetStr(); StringBuilder line2Str = new StringBuilder(); From 6b92f064ecd69edc0fa0988df9aaca2086c1de9a Mon Sep 17 00:00:00 2001 From: Steve Lee Date: Tue, 2 Feb 2021 10:31:08 +0000 Subject: [PATCH 34/65] Translated using Weblate (Chinese (Simplified)) Currently translated at 67.7% (2476 of 3656 strings) --- OsmAnd/res/values-zh-rCN/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OsmAnd/res/values-zh-rCN/strings.xml b/OsmAnd/res/values-zh-rCN/strings.xml index 6b188df900..c21fc6f733 100644 --- a/OsmAnd/res/values-zh-rCN/strings.xml +++ b/OsmAnd/res/values-zh-rCN/strings.xml @@ -1219,7 +1219,7 @@ 显示缩放等级:%1$s 在线地图 仅道路 - 设备内存 + 设备储存 初次使用 常见问题、最近修改和其它内容。 常见问题 From 2ef2ba43d6d3362f09789132359d10139ecc6192 Mon Sep 17 00:00:00 2001 From: Dmitry Date: Fri, 29 Jan 2021 18:29:54 +0200 Subject: [PATCH 35/65] Added image for OpenPlaceReviews plugins screen (cherry picked from commit 24c69f0a878c48b972bed241ea4e446d077ce7ec) --- .../img_plugin_openplacereviews.webp | Bin 0 -> 23698 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 OsmAnd/res/drawable-xxhdpi/img_plugin_openplacereviews.webp diff --git a/OsmAnd/res/drawable-xxhdpi/img_plugin_openplacereviews.webp b/OsmAnd/res/drawable-xxhdpi/img_plugin_openplacereviews.webp new file mode 100644 index 0000000000000000000000000000000000000000..97e0b2e58ddc623cb109bbf0ca08ef656e52a8d7 GIT binary patch literal 23698 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 Date: Wed, 3 Feb 2021 13:07:34 +0200 Subject: [PATCH 36/65] Rename osm preferences --- OsmAnd/res/values/strings.xml | 4 ++++ .../development/OsmandDevelopmentPlugin.java | 4 ++-- .../plus/osmedit/EditPOIMenuController.java | 4 ++-- .../plus/osmedit/OpenstreetmapRemoteUtil.java | 8 ++++---- .../plus/osmedit/OsmBugsRemoteUtil.java | 2 +- .../plus/osmedit/OsmEditingFragment.java | 12 +++++------ .../osmand/plus/osmedit/OsmEditingPlugin.java | 6 +++--- .../osmedit/ValidateOsmLoginDetailsTask.java | 4 ++-- .../dialogs/SendGpxBottomSheetFragment.java | 6 +++--- .../SendOsmNoteBottomSheetFragment.java | 10 +++++----- .../dialogs/SendPoiBottomSheetFragment.java | 6 +++--- .../oauth/OsmOAuthAuthorizationAdapter.java | 20 ++++++------------- .../plus/osmedit/oauth/OsmOAuthHelper.java | 10 +++++----- .../plus/settings/backend/OsmandSettings.java | 14 ++++++------- .../bottomsheets/OsmLoginDataBottomSheet.java | 9 ++++----- 15 files changed, 57 insertions(+), 62 deletions(-) diff --git a/OsmAnd/res/values/strings.xml b/OsmAnd/res/values/strings.xml index 3ecf1ade26..52e836e5e1 100644 --- a/OsmAnd/res/values/strings.xml +++ b/OsmAnd/res/values/strings.xml @@ -12,6 +12,10 @@ --> + Login to OpenPlaceReviews + Use test.openplacereviews.org + OpenPlaceReviews + OpenPlaceReviews is a community-driven project about public places such as restaurants, hotels, museums, waypoints. It collects all public information about them such as photos, reviews, links to other systems link OpenStreetMap, Wikipedia.\n\nAll OpenPlaceReview data is open and available to everyone: http://openplacereviews.org/data.\n\nYou can read more at: http://openplacereviews.org Hillshade / Slope / Contour lines Select edits for upload Uploaded %1$d of %2$d diff --git a/OsmAnd/src/net/osmand/plus/development/OsmandDevelopmentPlugin.java b/OsmAnd/src/net/osmand/plus/development/OsmandDevelopmentPlugin.java index 10997d0f07..33d6fed3ac 100644 --- a/OsmAnd/src/net/osmand/plus/development/OsmandDevelopmentPlugin.java +++ b/OsmAnd/src/net/osmand/plus/development/OsmandDevelopmentPlugin.java @@ -143,8 +143,8 @@ public class OsmandDevelopmentPlugin extends OsmandPlugin { @Override public void disable(OsmandApplication app) { - if (app.getSettings().USE_DEV_URL.get()) { - app.getSettings().USE_DEV_URL.set(false); + if (app.getSettings().OSM_USE_DEV_URL.get()) { + app.getSettings().OSM_USE_DEV_URL.set(false); app.getOsmOAuthHelper().resetAuthorization(); } super.disable(app); diff --git a/OsmAnd/src/net/osmand/plus/osmedit/EditPOIMenuController.java b/OsmAnd/src/net/osmand/plus/osmedit/EditPOIMenuController.java index 3c64fb12d7..d57f8aea28 100644 --- a/OsmAnd/src/net/osmand/plus/osmedit/EditPOIMenuController.java +++ b/OsmAnd/src/net/osmand/plus/osmedit/EditPOIMenuController.java @@ -51,8 +51,8 @@ public class EditPOIMenuController extends MenuController { OsmandSettings settings = app.getSettings(); OsmOAuthAuthorizationAdapter client = new OsmOAuthAuthorizationAdapter(app); boolean isLogged = client.isValidToken() - || !Algorithms.isEmpty(settings.USER_NAME.get()) - && !Algorithms.isEmpty(settings.USER_PASSWORD.get()); + || !Algorithms.isEmpty(settings.OSM_USER_NAME.get()) + && !Algorithms.isEmpty(settings.OSM_USER_PASSWORD.get()); if (point instanceof OpenstreetmapPoint) { if (isLogged) { diff --git a/OsmAnd/src/net/osmand/plus/osmedit/OpenstreetmapRemoteUtil.java b/OsmAnd/src/net/osmand/plus/osmedit/OpenstreetmapRemoteUtil.java index 8cefebd9ad..a35661b3a4 100644 --- a/OsmAnd/src/net/osmand/plus/osmedit/OpenstreetmapRemoteUtil.java +++ b/OsmAnd/src/net/osmand/plus/osmedit/OpenstreetmapRemoteUtil.java @@ -84,7 +84,7 @@ public class OpenstreetmapRemoteUtil implements OpenstreetmapUtil { additionalData.put("tags", tagstring); additionalData.put("visibility", visibility); return NetworkUtils.uploadFile(url, f, - settings.USER_NAME.get() + ":" + settings.USER_PASSWORD.get(), + settings.OSM_USER_NAME.get() + ":" + settings.OSM_USER_PASSWORD.get(), adapter.getClient(), "file", true, additionalData); @@ -138,7 +138,7 @@ public class OpenstreetmapRemoteUtil implements OpenstreetmapUtil { connection.setRequestMethod(requestMethod); connection.setRequestProperty("User-Agent", Version.getFullVersion(ctx)); //$NON-NLS-1$ StringBuilder responseBody = new StringBuilder(); - String token = settings.USER_NAME.get() + ":" + settings.USER_PASSWORD.get(); //$NON-NLS-1$ + String token = settings.OSM_USER_NAME.get() + ":" + settings.OSM_USER_PASSWORD.get(); //$NON-NLS-1$ connection.addRequestProperty("Authorization", "Basic " + Base64.encode(token.getBytes("UTF-8"))); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ connection.setDoInput(true); if (requestMethod.equals("PUT") || requestMethod.equals("POST") || requestMethod.equals("DELETE")) { //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ @@ -322,9 +322,9 @@ public class OpenstreetmapRemoteUtil implements OpenstreetmapUtil { ser.attribute(null, "version", "0.6"); //$NON-NLS-1$ //$NON-NLS-2$ ser.attribute(null, "generator", Version.getAppName(ctx)); //$NON-NLS-1$ if (n instanceof Node) { - writeNode((Node) n, info, ser, changeSetId, settings.USER_NAME.get()); + writeNode((Node) n, info, ser, changeSetId, settings.OSM_USER_NAME.get()); } else if (n instanceof Way) { - writeWay((Way) n, info, ser, changeSetId, settings.USER_NAME.get()); + writeWay((Way) n, info, ser, changeSetId, settings.OSM_USER_NAME.get()); } ser.endTag(null, OsmPoint.stringAction.get(action)); ser.endTag(null, "osmChange"); //$NON-NLS-1$ diff --git a/OsmAnd/src/net/osmand/plus/osmedit/OsmBugsRemoteUtil.java b/OsmAnd/src/net/osmand/plus/osmedit/OsmBugsRemoteUtil.java index 5d6c172738..30f9074a76 100644 --- a/OsmAnd/src/net/osmand/plus/osmedit/OsmBugsRemoteUtil.java +++ b/OsmAnd/src/net/osmand/plus/osmedit/OsmBugsRemoteUtil.java @@ -141,7 +141,7 @@ public class OsmBugsRemoteUtil implements OsmBugsUtil { connection.setRequestMethod(requestMethod); connection.setRequestProperty("User-Agent", Version.getFullVersion(app)); if (!anonymous) { - String token = settings.USER_NAME.get() + ":" + settings.USER_PASSWORD.get(); + String token = settings.OSM_USER_NAME.get() + ":" + settings.OSM_USER_PASSWORD.get(); connection.addRequestProperty("Authorization", "Basic " + Base64.encode(token.getBytes(StandardCharsets.UTF_8))); } connection.setDoInput(true); diff --git a/OsmAnd/src/net/osmand/plus/osmedit/OsmEditingFragment.java b/OsmAnd/src/net/osmand/plus/osmedit/OsmEditingFragment.java index 81cebe393d..153c730709 100644 --- a/OsmAnd/src/net/osmand/plus/osmedit/OsmEditingFragment.java +++ b/OsmAnd/src/net/osmand/plus/osmedit/OsmEditingFragment.java @@ -112,7 +112,7 @@ public class OsmEditingFragment extends BaseSettingsFragment implements OnPrefer boolean validToken = isValidToken(); Preference nameAndPasswordPref = findPreference(OSM_LOGOUT); if (validToken || isLoginExists()) { - String userName = validToken ? settings.USER_DISPLAY_NAME.get() : settings.USER_NAME.get(); + String userName = validToken ? settings.OSM_USER_DISPLAY_NAME.get() : settings.OSM_USER_NAME.get(); nameAndPasswordPref.setVisible(true); nameAndPasswordPref.setSummary(userName); nameAndPasswordPref.setIcon(getContentIcon(R.drawable.ic_action_user_account)); @@ -126,7 +126,7 @@ public class OsmEditingFragment extends BaseSettingsFragment implements OnPrefer } private boolean isLoginExists() { - return !Algorithms.isEmpty(settings.USER_NAME.get()) && !Algorithms.isEmpty(settings.USER_PASSWORD.get()); + return !Algorithms.isEmpty(settings.OSM_USER_NAME.get()) && !Algorithms.isEmpty(settings.OSM_USER_PASSWORD.get()); } private void setupOfflineEditingPref() { @@ -140,7 +140,7 @@ public class OsmEditingFragment extends BaseSettingsFragment implements OnPrefer } private void setupUseDevUrlPref() { - SwitchPreferenceEx useDevUrlPref = findPreference(settings.USE_DEV_URL.getId()); + SwitchPreferenceEx useDevUrlPref = findPreference(settings.OSM_USE_DEV_URL.getId()); if (OsmandPlugin.isDevelopment()) { Drawable icon = getPersistentPrefIcon(R.drawable.ic_action_laptop); useDevUrlPref.setDescription(getString(R.string.use_dev_url_descr)); @@ -176,8 +176,8 @@ public class OsmEditingFragment extends BaseSettingsFragment implements OnPrefer @Override public boolean onPreferenceChange(Preference preference, Object newValue) { String prefId = preference.getKey(); - if (settings.USE_DEV_URL.getId().equals(prefId) && newValue instanceof Boolean) { - settings.USE_DEV_URL.set((Boolean) newValue); + if (settings.OSM_USE_DEV_URL.getId().equals(prefId) && newValue instanceof Boolean) { + settings.OSM_USE_DEV_URL.set((Boolean) newValue); osmLogout(); return true; } @@ -220,7 +220,7 @@ public class OsmEditingFragment extends BaseSettingsFragment implements OnPrefer @Override public void onPreferenceChanged(String prefId) { - if (settings.USE_DEV_URL.getId().equals(prefId)) { + if (settings.OSM_USE_DEV_URL.getId().equals(prefId)) { osmLogout(); } updateAllSettings(); diff --git a/OsmAnd/src/net/osmand/plus/osmedit/OsmEditingPlugin.java b/OsmAnd/src/net/osmand/plus/osmedit/OsmEditingPlugin.java index f734b1c718..4f25b58761 100644 --- a/OsmAnd/src/net/osmand/plus/osmedit/OsmEditingPlugin.java +++ b/OsmAnd/src/net/osmand/plus/osmedit/OsmEditingPlugin.java @@ -457,9 +457,9 @@ public class OsmEditingPlugin extends OsmandPlugin { } public boolean sendGPXFiles(final FragmentActivity activity, Fragment fragment, final GpxInfo... info) { - String name = settings.USER_NAME.get(); - String pwd = settings.USER_PASSWORD.get(); - String authToken = settings.USER_ACCESS_TOKEN.get(); + String name = settings.OSM_USER_NAME.get(); + String pwd = settings.OSM_USER_PASSWORD.get(); + String authToken = settings.OSM_USER_ACCESS_TOKEN.get(); if ((Algorithms.isEmpty(name) || Algorithms.isEmpty(pwd)) && Algorithms.isEmpty(authToken)) { LoginBottomSheetFragment.showInstance(activity.getSupportFragmentManager(), fragment); return false; diff --git a/OsmAnd/src/net/osmand/plus/osmedit/ValidateOsmLoginDetailsTask.java b/OsmAnd/src/net/osmand/plus/osmedit/ValidateOsmLoginDetailsTask.java index 5dabe123b4..ec028e87fd 100644 --- a/OsmAnd/src/net/osmand/plus/osmedit/ValidateOsmLoginDetailsTask.java +++ b/OsmAnd/src/net/osmand/plus/osmedit/ValidateOsmLoginDetailsTask.java @@ -30,8 +30,8 @@ public class ValidateOsmLoginDetailsTask extends AsyncTask USER_NAME = new StringPreference(this, "user_name", "").makeGlobal().makeShared(); - public final OsmandPreference USER_DISPLAY_NAME = new StringPreference(this, "user_display_name", "").makeGlobal().makeShared(); + public final OsmandPreference OSM_USER_NAME = new StringPreference(this, "user_name", "").makeGlobal().makeShared(); + public final OsmandPreference OSM_USER_DISPLAY_NAME = new StringPreference(this, "user_display_name", "").makeGlobal().makeShared(); public static final String BILLING_USER_DONATION_WORLD_PARAMETER = ""; public static final String BILLING_USER_DONATION_NONE_PARAMETER = "none"; @@ -1156,13 +1156,13 @@ public class OsmandSettings { new StringPreference(this, "user_osm_bug_name", "NoName/OsmAnd").makeGlobal().makeShared(); // this value string is synchronized with settings_pref.xml preference name - public final OsmandPreference USER_PASSWORD = + public final OsmandPreference OSM_USER_PASSWORD = new StringPreference(this, "user_password", "").makeGlobal().makeShared(); - public final OsmandPreference USER_ACCESS_TOKEN = + public final OsmandPreference OSM_USER_ACCESS_TOKEN = new StringPreference(this, "user_access_token", "").makeGlobal(); - public final OsmandPreference USER_ACCESS_TOKEN_SECRET = + public final OsmandPreference OSM_USER_ACCESS_TOKEN_SECRET = new StringPreference(this, "user_access_token_secret", "").makeGlobal(); public final OsmandPreference OPR_ACCESS_TOKEN = @@ -1176,11 +1176,11 @@ public class OsmandSettings { // this value boolean is synchronized with settings_pref.xml preference offline POI/Bugs edition public final OsmandPreference OFFLINE_EDITION = new BooleanPreference(this, "offline_osm_editing", true).makeGlobal().makeShared(); - public final OsmandPreference USE_DEV_URL = new BooleanPreference(this, "use_dev_url", false).makeGlobal().makeShared(); + public final OsmandPreference OSM_USE_DEV_URL = new BooleanPreference(this, "use_dev_url", false).makeGlobal().makeShared(); public String getOsmUrl() { String osmUrl; - if (USE_DEV_URL.get()) { + if (OSM_USE_DEV_URL.get()) { osmUrl = "https://master.apis.dev.openstreetmap.org/"; } else { osmUrl = "https://api.openstreetmap.org/"; diff --git a/OsmAnd/src/net/osmand/plus/settings/bottomsheets/OsmLoginDataBottomSheet.java b/OsmAnd/src/net/osmand/plus/settings/bottomsheets/OsmLoginDataBottomSheet.java index 384f5457da..00d3c674f4 100644 --- a/OsmAnd/src/net/osmand/plus/settings/bottomsheets/OsmLoginDataBottomSheet.java +++ b/OsmAnd/src/net/osmand/plus/settings/bottomsheets/OsmLoginDataBottomSheet.java @@ -6,7 +6,6 @@ import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.widget.EditText; -import android.widget.ScrollView; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -49,8 +48,8 @@ public class OsmLoginDataBottomSheet extends BasePreferenceBottomSheet { userNameEditText = view.findViewById(R.id.name_edit_text); passwordEditText = view.findViewById(R.id.password_edit_text); - String name = app.getSettings().USER_NAME.get(); - String password = app.getSettings().USER_PASSWORD.get(); + String name = app.getSettings().OSM_USER_NAME.get(); + String password = app.getSettings().OSM_USER_PASSWORD.get(); if (savedInstanceState != null) { name = savedInstanceState.getString(USER_NAME_KEY, null); @@ -96,8 +95,8 @@ public class OsmLoginDataBottomSheet extends BasePreferenceBottomSheet { protected void onRightBottomButtonClick() { OsmandApplication app = requiredMyApplication(); - app.getSettings().USER_NAME.set(userNameEditText.getText().toString()); - app.getSettings().USER_PASSWORD.set(passwordEditText.getText().toString()); + app.getSettings().OSM_USER_NAME.set(userNameEditText.getText().toString()); + app.getSettings().OSM_USER_PASSWORD.set(passwordEditText.getText().toString()); Fragment targetFragment = getTargetFragment(); if (targetFragment instanceof ValidateOsmLoginListener) { From 43f326e320cba34dd1357187ba43eb60d07fc484 Mon Sep 17 00:00:00 2001 From: Vitaliy Date: Wed, 3 Feb 2021 13:22:20 +0200 Subject: [PATCH 37/65] Add OpenPlaceReviewsPlugin --- OsmAnd/res/xml/open_place_reviews.xml | 31 +++++ .../src/net/osmand/plus/AppInitializer.java | 4 +- .../net/osmand/plus/OsmandApplication.java | 6 + OsmAnd/src/net/osmand/plus/OsmandPlugin.java | 4 +- .../net/osmand/plus/helpers/IntentHelper.java | 18 ++- .../plus/mapcontextmenu/MenuBuilder.java | 17 ++- .../builders/cards/ImageCard.java | 6 +- .../OpenPlaceReviewsPlugin.java | 57 +++++++++ .../plus/openplacereviews/OprAuthHelper.java | 61 +++++++++ .../openplacereviews/OprSettingsFragment.java | 119 ++++++++++++++++++ .../openplacereviews/OprStartFragment.java | 23 ++-- .../fragments/BaseSettingsFragment.java | 2 + 12 files changed, 331 insertions(+), 17 deletions(-) create mode 100644 OsmAnd/res/xml/open_place_reviews.xml create mode 100644 OsmAnd/src/net/osmand/plus/openplacereviews/OpenPlaceReviewsPlugin.java create mode 100644 OsmAnd/src/net/osmand/plus/openplacereviews/OprAuthHelper.java create mode 100644 OsmAnd/src/net/osmand/plus/openplacereviews/OprSettingsFragment.java diff --git a/OsmAnd/res/xml/open_place_reviews.xml b/OsmAnd/res/xml/open_place_reviews.xml new file mode 100644 index 0000000000..f58c2be074 --- /dev/null +++ b/OsmAnd/res/xml/open_place_reviews.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/AppInitializer.java b/OsmAnd/src/net/osmand/plus/AppInitializer.java index 424855f2a0..065c7aba2e 100644 --- a/OsmAnd/src/net/osmand/plus/AppInitializer.java +++ b/OsmAnd/src/net/osmand/plus/AppInitializer.java @@ -28,7 +28,6 @@ import net.osmand.map.OsmandRegions.RegionTranslation; import net.osmand.map.WorldRegion; import net.osmand.osm.AbstractPoiType; import net.osmand.osm.MapPoiTypes; -import net.osmand.plus.helpers.DayNightHelper; import net.osmand.plus.activities.LocalIndexHelper; import net.osmand.plus.activities.LocalIndexInfo; import net.osmand.plus.activities.SavingTrackHelper; @@ -36,6 +35,7 @@ import net.osmand.plus.base.MapViewTrackingUtilities; import net.osmand.plus.download.DownloadActivity; import net.osmand.plus.download.ui.AbstractLoadLocalIndexTask; import net.osmand.plus.helpers.AvoidSpecificRoads; +import net.osmand.plus.helpers.DayNightHelper; import net.osmand.plus.helpers.LockHelper; import net.osmand.plus.helpers.WaypointHelper; import net.osmand.plus.inapp.InAppPurchaseHelperImpl; @@ -45,6 +45,7 @@ import net.osmand.plus.mapmarkers.MapMarkersHelper; import net.osmand.plus.monitoring.LiveMonitoringHelper; import net.osmand.plus.monitoring.OsmandMonitoringPlugin; import net.osmand.plus.onlinerouting.OnlineRoutingHelper; +import net.osmand.plus.openplacereviews.OprAuthHelper; import net.osmand.plus.osmedit.oauth.OsmOAuthHelper; import net.osmand.plus.poi.PoiFiltersHelper; import net.osmand.plus.quickaction.QuickActionRegistry; @@ -468,6 +469,7 @@ public class AppInitializer implements IProgress { app.settingsHelper = startupInit(new SettingsHelper(app), SettingsHelper.class); app.quickActionRegistry = startupInit(new QuickActionRegistry(app.getSettings()), QuickActionRegistry.class); app.osmOAuthHelper = startupInit(new OsmOAuthHelper(app), OsmOAuthHelper.class); + app.oprAuthHelper = startupInit(new OprAuthHelper(app), OprAuthHelper.class); app.onlineRoutingHelper = startupInit(new OnlineRoutingHelper(app), OnlineRoutingHelper.class); initOpeningHoursParser(); diff --git a/OsmAnd/src/net/osmand/plus/OsmandApplication.java b/OsmAnd/src/net/osmand/plus/OsmandApplication.java index 6b9aa4d0a4..90f34f580a 100644 --- a/OsmAnd/src/net/osmand/plus/OsmandApplication.java +++ b/OsmAnd/src/net/osmand/plus/OsmandApplication.java @@ -68,6 +68,7 @@ import net.osmand.plus.mapmarkers.MapMarkersHelper; import net.osmand.plus.measurementtool.MeasurementEditingContext; import net.osmand.plus.monitoring.LiveMonitoringHelper; import net.osmand.plus.onlinerouting.OnlineRoutingHelper; +import net.osmand.plus.openplacereviews.OprAuthHelper; import net.osmand.plus.osmedit.oauth.OsmOAuthHelper; import net.osmand.plus.poi.PoiFiltersHelper; import net.osmand.plus.quickaction.QuickActionRegistry; @@ -159,6 +160,7 @@ public class OsmandApplication extends MultiDexApplication { GpxDbHelper gpxDbHelper; QuickActionRegistry quickActionRegistry; OsmOAuthHelper osmOAuthHelper; + OprAuthHelper oprAuthHelper; MeasurementEditingContext measurementEditingContext; OnlineRoutingHelper onlineRoutingHelper; @@ -394,6 +396,10 @@ public class OsmandApplication extends MultiDexApplication { return osmOAuthHelper; } + public OprAuthHelper getOprAuthHelper() { + return oprAuthHelper; + } + public synchronized DownloadIndexesThread getDownloadThread() { if (downloadIndexesThread == null) { downloadIndexesThread = new DownloadIndexesThread(this); diff --git a/OsmAnd/src/net/osmand/plus/OsmandPlugin.java b/OsmAnd/src/net/osmand/plus/OsmandPlugin.java index e04f055b35..6df76e1f7e 100644 --- a/OsmAnd/src/net/osmand/plus/OsmandPlugin.java +++ b/OsmAnd/src/net/osmand/plus/OsmandPlugin.java @@ -38,6 +38,7 @@ import net.osmand.plus.mapcontextmenu.MenuController; import net.osmand.plus.mapillary.MapillaryPlugin; import net.osmand.plus.monitoring.OsmandMonitoringPlugin; import net.osmand.plus.myplaces.FavoritesActivity; +import net.osmand.plus.openplacereviews.OpenPlaceReviewsPlugin; import net.osmand.plus.openseamapsplugin.NauticalMapsPlugin; import net.osmand.plus.osmedit.OsmEditingPlugin; import net.osmand.plus.parkingpoint.ParkingPositionPlugin; @@ -133,7 +134,7 @@ public abstract class OsmandPlugin { public boolean init(@NonNull OsmandApplication app, @Nullable Activity activity) { if (activity != null) { // called from UI - for (ApplicationMode appMode: getAddedAppModes()) { + for (ApplicationMode appMode : getAddedAppModes()) { ApplicationMode.changeProfileAvailability(appMode, true, app); } } @@ -282,6 +283,7 @@ public abstract class OsmandPlugin { checkMarketPlugin(app, enabledPlugins, new ParkingPositionPlugin(app)); allPlugins.add(new AccessibilityPlugin(app)); allPlugins.add(new OsmEditingPlugin(app)); + allPlugins.add(new OpenPlaceReviewsPlugin(app)); allPlugins.add(new OsmandDevelopmentPlugin(app)); loadCustomPlugins(app); diff --git a/OsmAnd/src/net/osmand/plus/helpers/IntentHelper.java b/OsmAnd/src/net/osmand/plus/helpers/IntentHelper.java index 0d569ba880..1649e1ea1a 100644 --- a/OsmAnd/src/net/osmand/plus/helpers/IntentHelper.java +++ b/OsmAnd/src/net/osmand/plus/helpers/IntentHelper.java @@ -22,6 +22,7 @@ import net.osmand.plus.mapmarkers.MapMarkersDialogFragment; import net.osmand.plus.mapmarkers.MapMarkersGroup; import net.osmand.plus.mapsource.EditMapSourceDialogFragment; import net.osmand.plus.openplacereviews.OPRConstants; +import net.osmand.plus.openplacereviews.OprAuthHelper.OprAuthorizationListener; import net.osmand.plus.search.QuickSearchDialogFragment; import net.osmand.plus.settings.backend.ApplicationMode; import net.osmand.plus.settings.backend.OsmandSettings; @@ -326,8 +327,8 @@ public class IntentHelper { if (uri.toString().startsWith(OPRConstants.OPR_OAUTH_PREFIX)) { String token = uri.getQueryParameter("opr-token"); String username = uri.getQueryParameter("opr-nickname"); - app.getSettings().OPR_ACCESS_TOKEN.set(token); - app.getSettings().OPR_USERNAME.set(username); + app.getOprAuthHelper().addListener(getOprAuthorizationListener()); + app.getOprAuthHelper().authorize(token, username); mapActivity.setIntent(null); return true; } @@ -348,6 +349,19 @@ public class IntentHelper { }; } + private OprAuthorizationListener getOprAuthorizationListener() { + return new OprAuthorizationListener() { + @Override + public void authorizationCompleted() { + for (Fragment fragment : mapActivity.getSupportFragmentManager().getFragments()) { + if (fragment instanceof OprAuthorizationListener) { + ((OprAuthorizationListener) fragment).authorizationCompleted(); + } + } + } + }; + } + private boolean handleSendText(Intent intent) { String sharedText = intent.getStringExtra(Intent.EXTRA_TEXT); if (!Algorithms.isEmpty(sharedText)) { diff --git a/OsmAnd/src/net/osmand/plus/mapcontextmenu/MenuBuilder.java b/OsmAnd/src/net/osmand/plus/mapcontextmenu/MenuBuilder.java index 93f2bdf6b5..08c3994668 100644 --- a/OsmAnd/src/net/osmand/plus/mapcontextmenu/MenuBuilder.java +++ b/OsmAnd/src/net/osmand/plus/mapcontextmenu/MenuBuilder.java @@ -47,7 +47,6 @@ import net.osmand.plus.OsmandApplication; import net.osmand.plus.OsmandPlugin; import net.osmand.plus.R; import net.osmand.plus.UiUtilities; -import net.osmand.plus.Version; import net.osmand.plus.activities.ActivityResultListener; import net.osmand.plus.activities.ActivityResultListener.OnActivityResultListener; import net.osmand.plus.activities.MapActivity; @@ -61,6 +60,7 @@ import net.osmand.plus.mapcontextmenu.controllers.AmenityMenuController; import net.osmand.plus.mapcontextmenu.controllers.TransportStopController; import net.osmand.plus.openplacereviews.AddPhotosBottomSheetDialogFragment; import net.osmand.plus.openplacereviews.OPRConstants; +import net.osmand.plus.openplacereviews.OpenPlaceReviewsPlugin; import net.osmand.plus.openplacereviews.OprStartFragment; import net.osmand.plus.osmedit.opr.OpenDBAPI; import net.osmand.plus.poi.PoiFiltersHelper; @@ -133,7 +133,7 @@ public class MenuBuilder { @Override public void onPlaceIdAcquired(String[] placeId) { MenuBuilder.this.placeId = placeId; - if (placeId.length < 2) { + if (placeId.length < 2 || OsmandPlugin.getEnabledPlugin(OpenPlaceReviewsPlugin.class) == null) { app.runInUIThread(new Runnable() { @Override public void run() { @@ -158,6 +158,16 @@ public class MenuBuilder { } }; + public void addImageCard(ImageCard card) { + if (onlinePhotoCards.size() == 1 && onlinePhotoCards.get(0) instanceof NoImagesCard) { + onlinePhotoCards.clear(); + } + onlinePhotoCards.add(0, card); + if (onlinePhotoCardsRow != null) { + onlinePhotoCardsRow.setCards(onlinePhotoCards); + } + } + public interface CollapseExpandListener { void onCollapseExpand(boolean collapsed); } @@ -443,8 +453,7 @@ public class MenuBuilder { } } }); - //TODO This feature is under development - if (!Version.isDeveloperVersion(app)) { + if (OsmandPlugin.getEnabledPlugin(OpenPlaceReviewsPlugin.class) == null) { view.setVisibility(View.GONE); } photoButton = view; diff --git a/OsmAnd/src/net/osmand/plus/mapcontextmenu/builders/cards/ImageCard.java b/OsmAnd/src/net/osmand/plus/mapcontextmenu/builders/cards/ImageCard.java index 86fd8c2d81..a8eea711fa 100644 --- a/OsmAnd/src/net/osmand/plus/mapcontextmenu/builders/cards/ImageCard.java +++ b/OsmAnd/src/net/osmand/plus/mapcontextmenu/builders/cards/ImageCard.java @@ -22,6 +22,7 @@ import net.osmand.PlatformUtil; import net.osmand.data.Amenity; import net.osmand.data.LatLon; import net.osmand.plus.OsmandApplication; +import net.osmand.plus.OsmandPlugin; import net.osmand.plus.R; import net.osmand.plus.Version; import net.osmand.plus.activities.MapActivity; @@ -29,6 +30,7 @@ import net.osmand.plus.mapcontextmenu.MenuBuilder; import net.osmand.plus.mapillary.MapillaryContributeCard; import net.osmand.plus.mapillary.MapillaryImageCard; import net.osmand.plus.openplacereviews.OPRConstants; +import net.osmand.plus.openplacereviews.OpenPlaceReviewsPlugin; import net.osmand.plus.wikimedia.WikiImageHelper; import net.osmand.util.Algorithms; @@ -198,7 +200,7 @@ public abstract class ImageCard extends AbstractCard { return imageCard; } - private static ImageCard createCardOpr(MapActivity mapActivity, JSONObject imageObject) { + public static ImageCard createCardOpr(MapActivity mapActivity, JSONObject imageObject) { ImageCard imageCard = null; if (imageObject.has("cid")) { imageCard = new IPFSImageCard(mapActivity, imageObject); @@ -464,7 +466,7 @@ public abstract class ImageCard extends AbstractCard { TrafficStats.setThreadStatsTag(GET_IMAGE_CARD_THREAD_ID); List result = new ArrayList<>(); Object o = mapActivity.getMapLayers().getContextMenuLayer().getSelectedObject(); - if (o instanceof Amenity) { + if (o instanceof Amenity && OsmandPlugin.getEnabledPlugin(OpenPlaceReviewsPlugin.class) != null) { Amenity am = (Amenity) o; long amenityId = am.getId() >> 1; String baseUrl = OPRConstants.getBaseUrl(app); diff --git a/OsmAnd/src/net/osmand/plus/openplacereviews/OpenPlaceReviewsPlugin.java b/OsmAnd/src/net/osmand/plus/openplacereviews/OpenPlaceReviewsPlugin.java new file mode 100644 index 0000000000..263f62a570 --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/openplacereviews/OpenPlaceReviewsPlugin.java @@ -0,0 +1,57 @@ +package net.osmand.plus.openplacereviews; + +import android.graphics.drawable.Drawable; + +import net.osmand.plus.OsmandApplication; +import net.osmand.plus.OsmandPlugin; +import net.osmand.plus.R; +import net.osmand.plus.settings.fragments.BaseSettingsFragment.SettingsScreenType; + +public class OpenPlaceReviewsPlugin extends OsmandPlugin { + + private static final String ID = "osmand.openplacereviews"; + + public OpenPlaceReviewsPlugin(OsmandApplication app) { + super(app); + } + + @Override + public String getId() { + return ID; + } + + + @Override + public String getName() { + return app.getString(R.string.open_place_reviews); + } + + @Override + public CharSequence getDescription() { + return app.getString(R.string.open_place_reviews_plugin_description); + } + + @Override + public SettingsScreenType getSettingsScreenType() { + return SettingsScreenType.OPEN_PLACE_REVIEWS; + } + + @Override + public int getLogoResourceId() { + return R.drawable.ic_img_logo_openplacereview; + } + + @Override + public Drawable getAssetResourceImage() { + return app.getUIUtilities().getIcon(R.drawable.img_plugin_openplacereviews); + } + + @Override + public void disable(OsmandApplication app) { + if (app.getSettings().OPR_USE_DEV_URL.get()) { + app.getSettings().OPR_USE_DEV_URL.set(false); + app.getOprAuthHelper().resetAuthorization(); + } + super.disable(app); + } +} diff --git a/OsmAnd/src/net/osmand/plus/openplacereviews/OprAuthHelper.java b/OsmAnd/src/net/osmand/plus/openplacereviews/OprAuthHelper.java new file mode 100644 index 0000000000..f26a548e7e --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/openplacereviews/OprAuthHelper.java @@ -0,0 +1,61 @@ +package net.osmand.plus.openplacereviews; + +import androidx.annotation.NonNull; + +import net.osmand.plus.OsmandApplication; +import net.osmand.plus.osmedit.opr.OpenDBAPI; +import net.osmand.plus.settings.backend.OsmandSettings; +import net.osmand.util.Algorithms; + +import java.util.HashSet; +import java.util.Set; + +public class OprAuthHelper { + + private final OsmandApplication app; + private final OsmandSettings settings; + private final OpenDBAPI openDBAPI = new OpenDBAPI(); + private final Set listeners = new HashSet<>(); + + public OprAuthHelper(@NonNull OsmandApplication app) { + this.app = app; + settings = app.getSettings(); + } + + public void addListener(OprAuthorizationListener listener) { + listeners.add(listener); + } + + public void removeListener(OprAuthorizationListener listener) { + listeners.remove(listener); + } + + public void resetAuthorization() { + if (isLoginExists()) { + settings.OPR_USERNAME.resetToDefault(); + settings.OPR_ACCESS_TOKEN.resetToDefault(); + settings.OPR_BLOCKCHAIN_NAME.resetToDefault(); + } + } + + public boolean isLoginExists() { + return !Algorithms.isEmpty(settings.OPR_USERNAME.get()) + && !Algorithms.isEmpty(settings.OPR_BLOCKCHAIN_NAME.get()) + && !Algorithms.isEmpty(settings.OPR_ACCESS_TOKEN.get()); + } + + public void notifyAndRemoveListeners() { + for (OprAuthorizationListener listener : listeners) { + listener.authorizationCompleted(); + } + listeners.clear(); + } + + public void authorize(final String token, final String username) { + + } + + public interface OprAuthorizationListener { + void authorizationCompleted(); + } +} \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/openplacereviews/OprSettingsFragment.java b/OsmAnd/src/net/osmand/plus/openplacereviews/OprSettingsFragment.java new file mode 100644 index 0000000000..7ae0b5b825 --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/openplacereviews/OprSettingsFragment.java @@ -0,0 +1,119 @@ +package net.osmand.plus.openplacereviews; + +import android.os.Bundle; + +import androidx.activity.OnBackPressedCallback; +import androidx.fragment.app.FragmentActivity; +import androidx.fragment.app.FragmentManager; +import androidx.preference.Preference; + +import net.osmand.plus.OsmandPlugin; +import net.osmand.plus.R; +import net.osmand.plus.activities.MapActivity; +import net.osmand.plus.openplacereviews.OprAuthHelper.OprAuthorizationListener; +import net.osmand.plus.settings.fragments.BaseSettingsFragment; +import net.osmand.plus.settings.fragments.OnPreferenceChanged; +import net.osmand.plus.settings.preferences.SwitchPreferenceEx; + +public class OprSettingsFragment extends BaseSettingsFragment implements OnPreferenceChanged, OprAuthorizationListener { + + private static final String OPR_LOGOUT = "opr_logout"; + public static final String OPR_LOGIN_DATA = "opr_login_data"; + + private OprAuthHelper authHelper; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + authHelper = app.getOprAuthHelper(); + + FragmentActivity activity = requireMyActivity(); + activity.getOnBackPressedDispatcher().addCallback(this, new OnBackPressedCallback(true) { + public void handleOnBackPressed() { + MapActivity mapActivity = getMapActivity(); + if (mapActivity != null) { + mapActivity.launchPrevActivityIntent(); + } + dismiss(); + } + }); + } + + @Override + protected void setupPreferences() { + Preference oprSettingsInfo = findPreference("opr_settings_info"); + oprSettingsInfo.setIconSpaceReserved(false); + + setupLoginPref(); + setupLogoutPref(); + setupUseDevUrlPref(); + } + + private void setupLoginPref() { + Preference nameAndPasswordPref = findPreference(OPR_LOGIN_DATA); + nameAndPasswordPref.setVisible(!authHelper.isLoginExists()); + nameAndPasswordPref.setIcon(getContentIcon(R.drawable.ic_action_user_account)); + } + + private void setupLogoutPref() { + Preference nameAndPasswordPref = findPreference(OPR_LOGOUT); + nameAndPasswordPref.setVisible(authHelper.isLoginExists()); + nameAndPasswordPref.setSummary(settings.OPR_USERNAME.get()); + nameAndPasswordPref.setIcon(getContentIcon(R.drawable.ic_action_user_account)); + } + + private void setupUseDevUrlPref() { + SwitchPreferenceEx useDevUrlPref = findPreference(settings.OPR_USE_DEV_URL.getId()); + useDevUrlPref.setVisible(OsmandPlugin.isDevelopment()); + useDevUrlPref.setIcon(getPersistentPrefIcon(R.drawable.ic_plugin_developer)); + } + + @Override + public boolean onPreferenceClick(Preference preference) { + String prefId = preference.getKey(); + if (OPR_LOGIN_DATA.equals(prefId)) { + FragmentManager fragmentManager = getFragmentManager(); + if (fragmentManager != null) { + OprStartFragment.showInstance(fragmentManager); + return true; + } + } else if (OPR_LOGOUT.equals(prefId)) { + oprLogout(); + return true; + } + return super.onPreferenceClick(preference); + } + + @Override + public boolean onPreferenceChange(Preference preference, Object newValue) { + String prefId = preference.getKey(); + if (settings.OPR_USE_DEV_URL.getId().equals(prefId) && newValue instanceof Boolean) { + settings.OPR_USE_DEV_URL.set((Boolean) newValue); + oprLogout(); + return true; + } + return super.onPreferenceChange(preference, newValue); + } + + public void oprLogout() { + authHelper.resetAuthorization(); + app.showShortToastMessage(R.string.osm_edit_logout_success); + updateAllSettings(); + } + + @Override + public void onPreferenceChanged(String prefId) { + if (settings.OPR_USE_DEV_URL.getId().equals(prefId)) { + oprLogout(); + } + updateAllSettings(); + } + + @Override + public void authorizationCompleted() { + if (getContext() != null) { + updateAllSettings(); + } + } +} \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/openplacereviews/OprStartFragment.java b/OsmAnd/src/net/osmand/plus/openplacereviews/OprStartFragment.java index 1b435654ef..98517d0a70 100644 --- a/OsmAnd/src/net/osmand/plus/openplacereviews/OprStartFragment.java +++ b/OsmAnd/src/net/osmand/plus/openplacereviews/OprStartFragment.java @@ -24,10 +24,11 @@ import net.osmand.PlatformUtil; import net.osmand.plus.R; import net.osmand.plus.UiUtilities; import net.osmand.plus.base.BaseOsmAndFragment; +import net.osmand.plus.openplacereviews.OprAuthHelper.OprAuthorizationListener; import org.apache.commons.logging.Log; -public class OprStartFragment extends BaseOsmAndFragment { +public class OprStartFragment extends BaseOsmAndFragment implements OprAuthorizationListener { private static final String TAG = OprStartFragment.class.getSimpleName(); private static final Log LOG = PlatformUtil.getLog(OprStartFragment.class); private static final String openPlaceReviewsUrl = "OpenPlaceReviews.org"; @@ -42,10 +43,7 @@ public class OprStartFragment extends BaseOsmAndFragment { v.findViewById(R.id.back_button).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { - FragmentActivity activity = getActivity(); - if (activity != null) { - activity.getSupportFragmentManager().popBackStack(); - } + dismiss(); } }); UiUtilities.setupDialogButton(nightMode, createAccount, UiUtilities.DialogButtonType.PRIMARY, @@ -70,14 +68,14 @@ public class OprStartFragment extends BaseOsmAndFragment { } private void handleHaveAccount() { - String url = OPRConstants.getLoginUrl(requireContext()); + String url = OPRConstants.getLoginUrl(requireMyApplication()); CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder(); CustomTabsIntent customTabsIntent = builder.build(); customTabsIntent.launchUrl(requireContext(), Uri.parse(url)); } private void handleCreateAccount() { - String url = OPRConstants.getRegisterUrl(requireContext()); + String url = OPRConstants.getRegisterUrl(requireMyApplication()); CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder(); CustomTabsIntent customTabsIntent = builder.build(); customTabsIntent.launchUrl(requireContext(), Uri.parse(url)); @@ -114,6 +112,17 @@ public class OprStartFragment extends BaseOsmAndFragment { } } + @Override + public void authorizationCompleted() { + dismiss(); + } + + protected void dismiss() { + FragmentActivity activity = getActivity(); + if (activity != null) { + activity.getSupportFragmentManager().popBackStack(); + } + } public static void showInstance(@NonNull FragmentManager fm) { try { diff --git a/OsmAnd/src/net/osmand/plus/settings/fragments/BaseSettingsFragment.java b/OsmAnd/src/net/osmand/plus/settings/fragments/BaseSettingsFragment.java index 947a331290..63dab74fd4 100644 --- a/OsmAnd/src/net/osmand/plus/settings/fragments/BaseSettingsFragment.java +++ b/OsmAnd/src/net/osmand/plus/settings/fragments/BaseSettingsFragment.java @@ -61,6 +61,7 @@ import net.osmand.plus.activities.OsmandInAppPurchaseActivity; import net.osmand.plus.audionotes.MultimediaNotesFragment; import net.osmand.plus.development.DevelopmentSettingsFragment; import net.osmand.plus.monitoring.MonitoringSettingsFragment; +import net.osmand.plus.openplacereviews.OprSettingsFragment; import net.osmand.plus.osmedit.OsmEditingFragment; import net.osmand.plus.profiles.SelectAppModesBottomSheetDialogFragment; import net.osmand.plus.profiles.SelectAppModesBottomSheetDialogFragment.AppModeChangedListener; @@ -133,6 +134,7 @@ public abstract class BaseSettingsFragment extends PreferenceFragmentCompat impl MONITORING_SETTINGS(MonitoringSettingsFragment.class.getName(), true, ApplyQueryType.SNACK_BAR, R.xml.monitoring_settings, R.layout.profile_preference_toolbar), LIVE_MONITORING(LiveMonitoringFragment.class.getName(), false, ApplyQueryType.SNACK_BAR, R.xml.live_monitoring, R.layout.global_preferences_toolbar_with_switch), ACCESSIBILITY_SETTINGS(AccessibilitySettingsFragment.class.getName(), true, ApplyQueryType.SNACK_BAR, R.xml.accessibility_settings, R.layout.profile_preference_toolbar), + OPEN_PLACE_REVIEWS(OprSettingsFragment.class.getName(), false, null, R.xml.open_place_reviews, R.layout.global_preference_toolbar), DEVELOPMENT_SETTINGS(DevelopmentSettingsFragment.class.getName(), false, null, R.xml.development_settings, R.layout.global_preference_toolbar); public final String fragmentName; From fd8afa15b36287b49cd4b153a7cd0edbb8976cf7 Mon Sep 17 00:00:00 2001 From: Vitaliy Date: Wed, 3 Feb 2021 13:24:20 +0200 Subject: [PATCH 38/65] Add ability to switch to dev server --- .../builders/cards/IPFSImageCard.java | 6 ++++- .../plus/openplacereviews/OPRConstants.java | 25 +++++++++---------- .../plus/settings/backend/OsmandSettings.java | 6 +++++ 3 files changed, 23 insertions(+), 14 deletions(-) diff --git a/OsmAnd/src/net/osmand/plus/mapcontextmenu/builders/cards/IPFSImageCard.java b/OsmAnd/src/net/osmand/plus/mapcontextmenu/builders/cards/IPFSImageCard.java index 63f02d10fe..64bf146d56 100644 --- a/OsmAnd/src/net/osmand/plus/mapcontextmenu/builders/cards/IPFSImageCard.java +++ b/OsmAnd/src/net/osmand/plus/mapcontextmenu/builders/cards/IPFSImageCard.java @@ -2,11 +2,15 @@ package net.osmand.plus.mapcontextmenu.builders.cards; import android.view.View; + import androidx.core.content.ContextCompat; + import net.osmand.PlatformUtil; import net.osmand.plus.R; import net.osmand.plus.activities.MapActivity; +import net.osmand.plus.openplacereviews.OPRConstants; import net.osmand.util.Algorithms; + import org.apache.commons.logging.Log; import org.json.JSONException; import org.json.JSONObject; @@ -22,7 +26,7 @@ public class IPFSImageCard extends ImageCard { } catch (JSONException e) { LOG.error(e); } - String BASE_URL = mapActivity.getString(R.string.opr_base_url) + "api/ipfs/image-ipfs?cid="; + String BASE_URL = OPRConstants.getBaseUrl(mapActivity.getMyApplication()) + "api/ipfs/image-ipfs?cid="; url = BASE_URL + cid; imageHiresUrl = BASE_URL + cid; imageUrl = BASE_URL + cid; diff --git a/OsmAnd/src/net/osmand/plus/openplacereviews/OPRConstants.java b/OsmAnd/src/net/osmand/plus/openplacereviews/OPRConstants.java index a329e48235..a8901e2b0b 100644 --- a/OsmAnd/src/net/osmand/plus/openplacereviews/OPRConstants.java +++ b/OsmAnd/src/net/osmand/plus/openplacereviews/OPRConstants.java @@ -1,9 +1,9 @@ package net.osmand.plus.openplacereviews; -import android.content.Context; +import androidx.annotation.NonNull; -import net.osmand.plus.R; +import net.osmand.plus.OsmandApplication; import net.osmand.plus.osmedit.opr.OpenDBAPI; public class OPRConstants { @@ -11,28 +11,27 @@ public class OPRConstants { private static final String PURPOSE = OpenDBAPI.PURPOSE; private static final String CALLBACK_URL = OPR_OAUTH_PREFIX + "://osmand_opr_auth"; - public static String getBaseUrl(Context ctx) { - return ctx.getString(R.string.opr_base_url); + public static String getBaseUrl(@NonNull OsmandApplication app) { + return app.getSettings().getOprUrl(); } - - public static String getLoginUrl(Context ctx) { - return getBaseUrl(ctx) + "login" + getQueryString(ctx); + public static String getLoginUrl(@NonNull OsmandApplication app) { + return getBaseUrl(app) + "login" + getQueryString(); } - public static String getRegisterUrl(Context ctx) { - return getBaseUrl(ctx) + "signup" + getQueryString(ctx); + public static String getRegisterUrl(@NonNull OsmandApplication app) { + return getBaseUrl(app) + "signup" + getQueryString(); } - public static String getQueryString(Context ctx) { - return "?" + getPurposeParam(ctx) + "&" + getCallbackParam(ctx); + public static String getQueryString() { + return "?" + getPurposeParam() + "&" + getCallbackParam(); } - public static String getPurposeParam(Context ctx) { + public static String getPurposeParam() { return "purpose=" + PURPOSE; } - public static String getCallbackParam(Context ctx) { + public static String getCallbackParam() { return "callback=" + CALLBACK_URL; } } \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/settings/backend/OsmandSettings.java b/OsmAnd/src/net/osmand/plus/settings/backend/OsmandSettings.java index be347c4558..8ce068b2ae 100644 --- a/OsmAnd/src/net/osmand/plus/settings/backend/OsmandSettings.java +++ b/OsmAnd/src/net/osmand/plus/settings/backend/OsmandSettings.java @@ -1174,6 +1174,8 @@ public class OsmandSettings { public final OsmandPreference OPR_BLOCKCHAIN_NAME = new StringPreference(this, "opr_blockchain_name", "").makeGlobal(); + public final OsmandPreference OPR_USE_DEV_URL = new BooleanPreference(this, "opr_use_dev_url", false).makeGlobal().makeShared(); + // this value boolean is synchronized with settings_pref.xml preference offline POI/Bugs edition public final OsmandPreference OFFLINE_EDITION = new BooleanPreference(this, "offline_osm_editing", true).makeGlobal().makeShared(); public final OsmandPreference OSM_USE_DEV_URL = new BooleanPreference(this, "use_dev_url", false).makeGlobal().makeShared(); @@ -1188,6 +1190,10 @@ public class OsmandSettings { return osmUrl; } + public String getOprUrl() { + return ctx.getString(OPR_USE_DEV_URL.get() ? R.string.dev_opr_base_url : R.string.opr_base_url); + } + // this value string is synchronized with settings_pref.xml preference name public final CommonPreference DAYNIGHT_MODE = new EnumStringPreference(this, "daynight_mode", DayNightMode.DAY, DayNightMode.values()); From d6b1f24b55d59cd222a1a896099c7eba6db8312e Mon Sep 17 00:00:00 2001 From: Vitaliy Date: Wed, 3 Feb 2021 13:33:20 +0200 Subject: [PATCH 39/65] Add CheckOprAuthTask --- .../plus/openplacereviews/OprAuthHelper.java | 38 ++++++++++++++++++- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/OsmAnd/src/net/osmand/plus/openplacereviews/OprAuthHelper.java b/OsmAnd/src/net/osmand/plus/openplacereviews/OprAuthHelper.java index f26a548e7e..bc71900091 100644 --- a/OsmAnd/src/net/osmand/plus/openplacereviews/OprAuthHelper.java +++ b/OsmAnd/src/net/osmand/plus/openplacereviews/OprAuthHelper.java @@ -1,5 +1,7 @@ package net.osmand.plus.openplacereviews; +import android.os.AsyncTask; + import androidx.annotation.NonNull; import net.osmand.plus.OsmandApplication; @@ -14,7 +16,6 @@ public class OprAuthHelper { private final OsmandApplication app; private final OsmandSettings settings; - private final OpenDBAPI openDBAPI = new OpenDBAPI(); private final Set listeners = new HashSet<>(); public OprAuthHelper(@NonNull OsmandApplication app) { @@ -44,7 +45,7 @@ public class OprAuthHelper { && !Algorithms.isEmpty(settings.OPR_ACCESS_TOKEN.get()); } - public void notifyAndRemoveListeners() { + private void notifyAndRemoveListeners() { for (OprAuthorizationListener listener : listeners) { listener.authorizationCompleted(); } @@ -52,7 +53,40 @@ public class OprAuthHelper { } public void authorize(final String token, final String username) { + CheckOprAuthTask checkOprAuthTask = new CheckOprAuthTask(app, token, username); + checkOprAuthTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void) null); + } + private static class CheckOprAuthTask extends AsyncTask { + + private final OsmandApplication app; + private final OpenDBAPI openDBAPI = new OpenDBAPI(); + + private final String token; + private final String username; + + private CheckOprAuthTask(@NonNull OsmandApplication app, String token, String username) { + this.app = app; + this.token = token; + this.username = username; + } + + @Override + protected Boolean doInBackground(Void... params) { + String baseUrl = OPRConstants.getBaseUrl(app); + return openDBAPI.checkPrivateKeyValid(app, baseUrl, username, token); + } + + @Override + protected void onPostExecute(Boolean result) { + if (result) { + app.getSettings().OPR_ACCESS_TOKEN.set(token); + app.getSettings().OPR_USERNAME.set(username); + } else { + app.getOprAuthHelper().resetAuthorization(); + } + app.getOprAuthHelper().notifyAndRemoveListeners(); + } } public interface OprAuthorizationListener { From 0083b7d0e14b64d4fa908ead656ae2815783b8f3 Mon Sep 17 00:00:00 2001 From: Vitaliy Date: Wed, 3 Feb 2021 13:40:58 +0200 Subject: [PATCH 40/65] Fix possible npe with general router --- .../RouteOptionsBottomSheet.java | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/OsmAnd/src/net/osmand/plus/routepreparationmenu/RouteOptionsBottomSheet.java b/OsmAnd/src/net/osmand/plus/routepreparationmenu/RouteOptionsBottomSheet.java index 9916813c5e..8ba86dfe35 100644 --- a/OsmAnd/src/net/osmand/plus/routepreparationmenu/RouteOptionsBottomSheet.java +++ b/OsmAnd/src/net/osmand/plus/routepreparationmenu/RouteOptionsBottomSheet.java @@ -625,11 +625,14 @@ public class RouteOptionsBottomSheet extends MenuBottomSheetDialogFragment { private List getReliefParameters() { List reliefFactorParameters = new ArrayList<>(); - Map parameters = app.getRouter(applicationMode).getParameters(); - for (Map.Entry entry : parameters.entrySet()) { - RoutingParameter routingParameter = entry.getValue(); - if (RELIEF_SMOOTHNESS_FACTOR.equals(routingParameter.getGroup())) { - reliefFactorParameters.add(routingParameter); + GeneralRouter router = app.getRouter(applicationMode); + if (router != null) { + Map parameters = router.getParameters(); + for (Map.Entry entry : parameters.entrySet()) { + RoutingParameter routingParameter = entry.getValue(); + if (RELIEF_SMOOTHNESS_FACTOR.equals(routingParameter.getGroup())) { + reliefFactorParameters.add(routingParameter); + } } } return reliefFactorParameters; From 70e8472c6b9447e12c679b91e24675285e0d0fcc Mon Sep 17 00:00:00 2001 From: max-klaus Date: Wed, 3 Feb 2021 14:44:21 +0300 Subject: [PATCH 41/65] Added annotations --- OsmAnd/src/net/osmand/plus/OsmandApplication.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/OsmAnd/src/net/osmand/plus/OsmandApplication.java b/OsmAnd/src/net/osmand/plus/OsmandApplication.java index 6b9aa4d0a4..b794a5bc0a 100644 --- a/OsmAnd/src/net/osmand/plus/OsmandApplication.java +++ b/OsmAnd/src/net/osmand/plus/OsmandApplication.java @@ -24,6 +24,8 @@ import android.view.View; import android.view.accessibility.AccessibilityManager; import android.widget.Toast; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AppCompatDelegate; import androidx.multidex.MultiDex; @@ -910,6 +912,7 @@ public class OsmandApplication extends MultiDexApplication { return customRoutingConfigs.get(key); } + @NonNull public RoutingConfiguration.Builder getRoutingConfigForMode(ApplicationMode mode) { RoutingConfiguration.Builder builder = null; String routingProfileKey = mode.getRoutingProfile(); @@ -923,11 +926,13 @@ public class OsmandApplication extends MultiDexApplication { return builder != null ? builder : getDefaultRoutingConfig(); } + @Nullable public GeneralRouter getRouter(ApplicationMode mode) { Builder builder = getRoutingConfigForMode(mode); return getRouter(builder, mode); } + @Nullable public GeneralRouter getRouter(Builder builder, ApplicationMode am) { GeneralRouter router = builder.getRouter(am.getRoutingProfile()); if (router == null && am.getParent() != null) { From 52a2ba0ca31c15cb0b5fbe91889490cee0ab53e0 Mon Sep 17 00:00:00 2001 From: Vitaliy Date: Wed, 3 Feb 2021 13:56:27 +0200 Subject: [PATCH 42/65] Open overview tab in half screen --- OsmAnd/src/net/osmand/plus/track/TrackMenuFragment.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/OsmAnd/src/net/osmand/plus/track/TrackMenuFragment.java b/OsmAnd/src/net/osmand/plus/track/TrackMenuFragment.java index 4b58c0b9dc..6668996cf4 100644 --- a/OsmAnd/src/net/osmand/plus/track/TrackMenuFragment.java +++ b/OsmAnd/src/net/osmand/plus/track/TrackMenuFragment.java @@ -890,8 +890,6 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card private void updateMenuState() { if (menuType == TrackMenuType.OPTIONS) { openMenuFullScreen(); - } else if (menuType == TrackMenuType.OVERVIEW) { - openMenuHeaderOnly(); } else { openMenuHalfScreen(); } From 2df09406e1c3f48396f212fa54cbf4e1661d2b35 Mon Sep 17 00:00:00 2001 From: max-klaus Date: Wed, 3 Feb 2021 15:04:07 +0300 Subject: [PATCH 43/65] Fix npe --- OsmAnd/src/net/osmand/plus/track/TrackMenuFragment.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/OsmAnd/src/net/osmand/plus/track/TrackMenuFragment.java b/OsmAnd/src/net/osmand/plus/track/TrackMenuFragment.java index 4b58c0b9dc..260730c101 100644 --- a/OsmAnd/src/net/osmand/plus/track/TrackMenuFragment.java +++ b/OsmAnd/src/net/osmand/plus/track/TrackMenuFragment.java @@ -1130,7 +1130,9 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card if (mapActivity != null) { OsmandApplication app = mapActivity.getMyApplication(); SelectedGpxFile selectedGpxFile = app.getSelectedGpxHelper().selectGpxFile(result, true, false); - showInstance(mapActivity, selectedGpxFile, null); + if (selectedGpxFile != null) { + showInstance(mapActivity, selectedGpxFile, null); + } } if (progress != null && AndroidUtils.isActivityNotDestroyed(mapActivity)) { progress.dismiss(); @@ -1142,7 +1144,7 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card } } - public static boolean showInstance(@NonNull MapActivity mapActivity, SelectedGpxFile selectedGpxFile, @Nullable LatLon latLon) { + public static boolean showInstance(@NonNull MapActivity mapActivity, @NonNull SelectedGpxFile selectedGpxFile, @Nullable LatLon latLon) { try { Bundle args = new Bundle(); args.putInt(ContextMenuFragment.MENU_STATE_KEY, MenuState.HEADER_ONLY); From d63e21668f10e02a82e0799be220ce5680b3de73 Mon Sep 17 00:00:00 2001 From: Vitaliy Date: Wed, 3 Feb 2021 14:04:36 +0200 Subject: [PATCH 44/65] Show uploaded images in the context menu immediately after upload --- .../UploadPhotoProgressBottomSheet.java | 6 +-- .../plus/mapcontextmenu/MenuBuilder.java | 30 ++++++++++++- .../mapcontextmenu/UploadPhotosAsyncTask.java | 44 ++++++++----------- 3 files changed, 49 insertions(+), 31 deletions(-) diff --git a/OsmAnd/src/net/osmand/plus/dialogs/UploadPhotoProgressBottomSheet.java b/OsmAnd/src/net/osmand/plus/dialogs/UploadPhotoProgressBottomSheet.java index 05e4bcc468..cd06804f5e 100644 --- a/OsmAnd/src/net/osmand/plus/dialogs/UploadPhotoProgressBottomSheet.java +++ b/OsmAnd/src/net/osmand/plus/dialogs/UploadPhotoProgressBottomSheet.java @@ -19,9 +19,9 @@ import net.osmand.plus.base.MenuBottomSheetDialogFragment; import net.osmand.plus.base.bottomsheetmenu.BaseBottomSheetItem; import net.osmand.plus.base.bottomsheetmenu.BottomSheetItemWithDescription; import net.osmand.plus.base.bottomsheetmenu.simpleitems.DividerSpaceItem; -import net.osmand.plus.mapcontextmenu.UploadPhotosAsyncTask.UploadPhotosListener; +import net.osmand.plus.mapcontextmenu.UploadPhotosAsyncTask.UploadPhotosProgressListener; -public class UploadPhotoProgressBottomSheet extends MenuBottomSheetDialogFragment implements UploadPhotosListener { +public class UploadPhotoProgressBottomSheet extends MenuBottomSheetDialogFragment implements UploadPhotosProgressListener { public static final String TAG = UploadPhotoProgressBottomSheet.class.getSimpleName(); @@ -103,7 +103,7 @@ public class UploadPhotoProgressBottomSheet extends MenuBottomSheetDialogFragmen return uploadingFinished ? R.string.shared_string_close : R.string.shared_string_cancel; } - public static UploadPhotosListener showInstance(@NonNull FragmentManager fragmentManager, int maxProgress, OnDismissListener listener) { + public static UploadPhotosProgressListener showInstance(@NonNull FragmentManager fragmentManager, int maxProgress, OnDismissListener listener) { UploadPhotoProgressBottomSheet fragment = new UploadPhotoProgressBottomSheet(); fragment.setRetainInstance(true); fragment.setMaxProgress(maxProgress); diff --git a/OsmAnd/src/net/osmand/plus/mapcontextmenu/MenuBuilder.java b/OsmAnd/src/net/osmand/plus/mapcontextmenu/MenuBuilder.java index 08c3994668..5cfdd0a281 100644 --- a/OsmAnd/src/net/osmand/plus/mapcontextmenu/MenuBuilder.java +++ b/OsmAnd/src/net/osmand/plus/mapcontextmenu/MenuBuilder.java @@ -36,6 +36,7 @@ import androidx.core.content.ContextCompat; import androidx.core.graphics.drawable.DrawableCompat; import net.osmand.AndroidUtils; +import net.osmand.PlatformUtil; import net.osmand.data.Amenity; import net.osmand.data.LatLon; import net.osmand.data.PointDescription; @@ -51,6 +52,7 @@ import net.osmand.plus.activities.ActivityResultListener; import net.osmand.plus.activities.ActivityResultListener.OnActivityResultListener; import net.osmand.plus.activities.MapActivity; import net.osmand.plus.helpers.FontCache; +import net.osmand.plus.mapcontextmenu.UploadPhotosAsyncTask.UploadPhotosListener; import net.osmand.plus.mapcontextmenu.builders.cards.AbstractCard; import net.osmand.plus.mapcontextmenu.builders.cards.CardsRowBuilder; import net.osmand.plus.mapcontextmenu.builders.cards.ImageCard; @@ -75,6 +77,10 @@ import net.osmand.plus.widgets.tools.ClickableSpanTouchListener; import net.osmand.util.Algorithms; import net.osmand.util.MapUtils; +import org.apache.commons.logging.Log; +import org.json.JSONException; +import org.json.JSONObject; + import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; @@ -85,8 +91,9 @@ import java.util.Set; import static net.osmand.plus.mapcontextmenu.builders.cards.ImageCard.GetImageCardsTask.GetImageCardsListener; -public class MenuBuilder { +public class MenuBuilder implements UploadPhotosListener { + private static final Log LOG = PlatformUtil.getLog(MenuBuilder.class); private static final int PICK_IMAGE = 1231; public static final float SHADOW_HEIGHT_TOP_DP = 17f; public static final int TITLE_LIMIT = 60; @@ -168,6 +175,25 @@ public class MenuBuilder { } } + @Override + public void uploadPhotosSuccess(final String response) { + app.runInUIThread(new Runnable() { + @Override + public void run() { + if (AndroidUtils.isActivityNotDestroyed(mapActivity)) { + try { + ImageCard imageCard = ImageCard.createCardOpr(mapActivity, new JSONObject(response)); + if (imageCard != null) { + addImageCard(imageCard); + } + } catch (JSONException e) { + LOG.error(e); + } + } + } + }); + } + public interface CollapseExpandListener { void onCollapseExpand(boolean collapsed); } @@ -490,7 +516,7 @@ public class MenuBuilder { } } } - execute(new UploadPhotosAsyncTask(mapActivity, imagesUri, getLatLon(), placeId, getAdditionalCardParams(), imageCardListener)); + execute(new UploadPhotosAsyncTask(mapActivity, imagesUri, placeId, MenuBuilder.this)); } } })); diff --git a/OsmAnd/src/net/osmand/plus/mapcontextmenu/UploadPhotosAsyncTask.java b/OsmAnd/src/net/osmand/plus/mapcontextmenu/UploadPhotosAsyncTask.java index afe492af6f..cf0587e06f 100644 --- a/OsmAnd/src/net/osmand/plus/mapcontextmenu/UploadPhotosAsyncTask.java +++ b/OsmAnd/src/net/osmand/plus/mapcontextmenu/UploadPhotosAsyncTask.java @@ -13,14 +13,11 @@ import androidx.fragment.app.FragmentManager; import net.osmand.AndroidUtils; import net.osmand.PlatformUtil; -import net.osmand.data.LatLon; import net.osmand.osm.io.NetworkUtils; import net.osmand.plus.OsmandApplication; import net.osmand.plus.R; import net.osmand.plus.activities.MapActivity; import net.osmand.plus.dialogs.UploadPhotoProgressBottomSheet; -import net.osmand.plus.mapcontextmenu.builders.cards.ImageCard.GetImageCardsTask; -import net.osmand.plus.mapcontextmenu.builders.cards.ImageCard.GetImageCardsTask.GetImageCardsListener; import net.osmand.plus.openplacereviews.OPRConstants; import net.osmand.plus.openplacereviews.OprStartFragment; import net.osmand.plus.osmedit.opr.OpenDBAPI; @@ -36,7 +33,6 @@ import java.io.InputStream; import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.List; -import java.util.Map; public class UploadPhotosAsyncTask extends AsyncTask { @@ -47,22 +43,17 @@ public class UploadPhotosAsyncTask extends AsyncTask { private final OsmandApplication app; private final WeakReference activityRef; private final OpenDBAPI openDBAPI = new OpenDBAPI(); - private final LatLon latLon; private final List data; private final String[] placeId; - private final Map params; - private final GetImageCardsListener imageCardListener; - private UploadPhotosListener listener; + private final UploadPhotosListener listener; + private UploadPhotosProgressListener progressListener; - public UploadPhotosAsyncTask(MapActivity activity, List data, LatLon latLon, String[] placeId, - Map params, GetImageCardsListener imageCardListener) { + public UploadPhotosAsyncTask(MapActivity activity, List data, String[] placeId, UploadPhotosListener listener) { app = (OsmandApplication) activity.getApplicationContext(); activityRef = new WeakReference<>(activity); this.data = data; - this.latLon = latLon; - this.params = params; this.placeId = placeId; - this.imageCardListener = imageCardListener; + this.listener = listener; } @Override @@ -70,7 +61,7 @@ public class UploadPhotosAsyncTask extends AsyncTask { FragmentActivity activity = activityRef.get(); if (AndroidUtils.isActivityNotDestroyed(activity)) { FragmentManager manager = activity.getSupportFragmentManager(); - listener = UploadPhotoProgressBottomSheet.showInstance(manager, data.size(), new OnDismissListener() { + progressListener = UploadPhotoProgressBottomSheet.showInstance(manager, data.size(), new OnDismissListener() { @Override public void onDismiss(DialogInterface dialog) { cancel(false); @@ -81,8 +72,8 @@ public class UploadPhotosAsyncTask extends AsyncTask { @Override protected void onProgressUpdate(Integer... values) { - if (listener != null) { - listener.uploadPhotosProgressUpdate(values[0]); + if (progressListener != null) { + progressListener.uploadPhotosProgressUpdate(values[0]); } } @@ -103,8 +94,8 @@ public class UploadPhotosAsyncTask extends AsyncTask { @Override protected void onPostExecute(Void aVoid) { - if (listener != null) { - listener.uploadPhotosFinished(); + if (progressListener != null) { + progressListener.uploadPhotosFinished(); } } @@ -156,13 +147,9 @@ public class UploadPhotosAsyncTask extends AsyncTask { checkTokenAndShowScreen(); } else { success = true; - String str = app.getString(R.string.successfully_uploaded_pattern, 1, 1); - app.showToastMessage(str); //refresh the image - - MapActivity activity = activityRef.get(); - if (activity != null) { - MenuBuilder.execute(new GetImageCardsTask(activity, latLon, params, imageCardListener)); + if (listener != null) { + listener.uploadPhotosSuccess(response); } } } else { @@ -215,12 +202,17 @@ public class UploadPhotosAsyncTask extends AsyncTask { return os.toByteArray(); } - - public interface UploadPhotosListener { + public interface UploadPhotosProgressListener { void uploadPhotosProgressUpdate(int progress); void uploadPhotosFinished(); } + + public interface UploadPhotosListener { + + void uploadPhotosSuccess(String response); + + } } \ No newline at end of file From 5ea855ed618f3a90d14a06b9e3380b5f0a10dc71 Mon Sep 17 00:00:00 2001 From: Vitaliy Date: Wed, 3 Feb 2021 14:13:00 +0200 Subject: [PATCH 45/65] UI fixes --- OsmAnd/res/layout/fragment_opr_login.xml | 52 +++++++------------ .../openplacereviews/OprStartFragment.java | 19 +++++-- 2 files changed, 34 insertions(+), 37 deletions(-) diff --git a/OsmAnd/res/layout/fragment_opr_login.xml b/OsmAnd/res/layout/fragment_opr_login.xml index e941075f54..ee969b1a74 100644 --- a/OsmAnd/res/layout/fragment_opr_login.xml +++ b/OsmAnd/res/layout/fragment_opr_login.xml @@ -1,36 +1,22 @@ - + - + android:gravity="center_vertical" + android:padding="0dp" /> - - - - - + android:layout_height="0dp" + android:layout_weight="1"> + app:typeface="@string/font_roboto_regular" /> + - + + - \ No newline at end of file + \ No newline at end of file diff --git a/OsmAnd/src/net/osmand/plus/openplacereviews/OprStartFragment.java b/OsmAnd/src/net/osmand/plus/openplacereviews/OprStartFragment.java index 98517d0a70..e1f5b56e9d 100644 --- a/OsmAnd/src/net/osmand/plus/openplacereviews/OprStartFragment.java +++ b/OsmAnd/src/net/osmand/plus/openplacereviews/OprStartFragment.java @@ -16,10 +16,12 @@ import android.widget.TextView; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import androidx.appcompat.widget.Toolbar; import androidx.browser.customtabs.CustomTabsIntent; import androidx.fragment.app.FragmentActivity; import androidx.fragment.app.FragmentManager; +import net.osmand.AndroidUtils; import net.osmand.PlatformUtil; import net.osmand.plus.R; import net.osmand.plus.UiUtilities; @@ -37,15 +39,22 @@ public class OprStartFragment extends BaseOsmAndFragment implements OprAuthoriza @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { nightMode = getMyApplication().getDaynightHelper().isNightModeForMapControls(); - View v = UiUtilities.getInflater(requireMyActivity(), nightMode).inflate(R.layout.fragment_opr_login, container, - false); - View createAccount = v.findViewById(R.id.register_opr_create_account); - v.findViewById(R.id.back_button).setOnClickListener(new View.OnClickListener() { + + View v = UiUtilities.getInflater(requireMyActivity(), nightMode).inflate(R.layout.fragment_opr_login, container, false); + AndroidUtils.addStatusBarPadding21v(requireMyActivity(), v); + + Toolbar toolbar = (Toolbar) v.findViewById(R.id.toolbar); + int icBackResId = AndroidUtils.getNavigationIconResId(v.getContext()); + toolbar.setNavigationIcon(getContentIcon(icBackResId)); + toolbar.setNavigationContentDescription(R.string.access_shared_string_navigate_up); + toolbar.setNavigationOnClickListener(new View.OnClickListener() { @Override - public void onClick(View view) { + public void onClick(View v) { dismiss(); } }); + + View createAccount = v.findViewById(R.id.register_opr_create_account); UiUtilities.setupDialogButton(nightMode, createAccount, UiUtilities.DialogButtonType.PRIMARY, R.string.register_opr_create_new_account); createAccount.setOnClickListener(new View.OnClickListener() { From b8ae00f6c986c5e9ba469383c04f12dfcad6574e Mon Sep 17 00:00:00 2001 From: Vitaliy Date: Wed, 3 Feb 2021 14:46:33 +0200 Subject: [PATCH 46/65] Add populateImageCards to osmand plugins --- OsmAnd/src/net/osmand/plus/OsmandPlugin.java | 13 +- .../plus/mapcontextmenu/MenuBuilder.java | 22 ++-- .../builders/cards/ImageCard.java | 71 +---------- .../OpenPlaceReviewsPlugin.java | 113 ++++++++++++++++++ 4 files changed, 135 insertions(+), 84 deletions(-) diff --git a/OsmAnd/src/net/osmand/plus/OsmandPlugin.java b/OsmAnd/src/net/osmand/plus/OsmandPlugin.java index 6df76e1f7e..aadeed5671 100644 --- a/OsmAnd/src/net/osmand/plus/OsmandPlugin.java +++ b/OsmAnd/src/net/osmand/plus/OsmandPlugin.java @@ -35,6 +35,8 @@ import net.osmand.plus.dialogs.PluginInstalledBottomSheetDialog; import net.osmand.plus.download.IndexItem; import net.osmand.plus.mapcontextmenu.MenuBuilder; import net.osmand.plus.mapcontextmenu.MenuController; +import net.osmand.plus.mapcontextmenu.builders.cards.ImageCard; +import net.osmand.plus.mapcontextmenu.builders.cards.ImageCard.GetImageCardsTask.GetImageCardsListener; import net.osmand.plus.mapillary.MapillaryPlugin; import net.osmand.plus.monitoring.OsmandMonitoringPlugin; import net.osmand.plus.myplaces.FavoritesActivity; @@ -209,6 +211,10 @@ public abstract class OsmandPlugin { return Collections.emptyList(); } + protected List getImageCards(@Nullable GetImageCardsListener listener) { + return Collections.emptyList(); + } + /** * Plugin was installed */ @@ -736,7 +742,6 @@ public abstract class OsmandPlugin { return l; } - public static void onMapActivityCreate(MapActivity activity) { for (OsmandPlugin plugin : getEnabledPlugins()) { plugin.mapActivityCreate(activity); @@ -870,6 +875,12 @@ public abstract class OsmandPlugin { return collection; } + public static void populateImageCards(@NonNull List imageCards, @Nullable GetImageCardsListener listener) { + for (OsmandPlugin p : getEnabledPlugins()) { + imageCards.addAll(p.getImageCards(listener)); + } + } + public static boolean isPackageInstalled(String packageInfo, Context ctx) { if (packageInfo == null) { return false; diff --git a/OsmAnd/src/net/osmand/plus/mapcontextmenu/MenuBuilder.java b/OsmAnd/src/net/osmand/plus/mapcontextmenu/MenuBuilder.java index 5cfdd0a281..ca11b8a456 100644 --- a/OsmAnd/src/net/osmand/plus/mapcontextmenu/MenuBuilder.java +++ b/OsmAnd/src/net/osmand/plus/mapcontextmenu/MenuBuilder.java @@ -51,6 +51,7 @@ import net.osmand.plus.UiUtilities; import net.osmand.plus.activities.ActivityResultListener; import net.osmand.plus.activities.ActivityResultListener.OnActivityResultListener; import net.osmand.plus.activities.MapActivity; +import net.osmand.plus.helpers.AndroidUiHelper; import net.osmand.plus.helpers.FontCache; import net.osmand.plus.mapcontextmenu.UploadPhotosAsyncTask.UploadPhotosListener; import net.osmand.plus.mapcontextmenu.builders.cards.AbstractCard; @@ -62,7 +63,6 @@ import net.osmand.plus.mapcontextmenu.controllers.AmenityMenuController; import net.osmand.plus.mapcontextmenu.controllers.TransportStopController; import net.osmand.plus.openplacereviews.AddPhotosBottomSheetDialogFragment; import net.osmand.plus.openplacereviews.OPRConstants; -import net.osmand.plus.openplacereviews.OpenPlaceReviewsPlugin; import net.osmand.plus.openplacereviews.OprStartFragment; import net.osmand.plus.osmedit.opr.OpenDBAPI; import net.osmand.plus.poi.PoiFiltersHelper; @@ -138,16 +138,14 @@ public class MenuBuilder implements UploadPhotosListener { } @Override - public void onPlaceIdAcquired(String[] placeId) { + public void onPlaceIdAcquired(final String[] placeId) { MenuBuilder.this.placeId = placeId; - if (placeId.length < 2 || OsmandPlugin.getEnabledPlugin(OpenPlaceReviewsPlugin.class) == null) { - app.runInUIThread(new Runnable() { - @Override - public void run() { - photoButton.setVisibility(View.GONE); - } - }); - } + app.runInUIThread(new Runnable() { + @Override + public void run() { + AndroidUiHelper.updateVisibility(photoButton, placeId.length >= 2); + } + }); } @Override @@ -479,9 +477,7 @@ public class MenuBuilder implements UploadPhotosListener { } } }); - if (OsmandPlugin.getEnabledPlugin(OpenPlaceReviewsPlugin.class) == null) { - view.setVisibility(View.GONE); - } + AndroidUiHelper.updateVisibility(view, false); photoButton = view; return view; } diff --git a/OsmAnd/src/net/osmand/plus/mapcontextmenu/builders/cards/ImageCard.java b/OsmAnd/src/net/osmand/plus/mapcontextmenu/builders/cards/ImageCard.java index a8eea711fa..1c2339648e 100644 --- a/OsmAnd/src/net/osmand/plus/mapcontextmenu/builders/cards/ImageCard.java +++ b/OsmAnd/src/net/osmand/plus/mapcontextmenu/builders/cards/ImageCard.java @@ -29,8 +29,6 @@ import net.osmand.plus.activities.MapActivity; import net.osmand.plus.mapcontextmenu.MenuBuilder; import net.osmand.plus.mapillary.MapillaryContributeCard; import net.osmand.plus.mapillary.MapillaryImageCard; -import net.osmand.plus.openplacereviews.OPRConstants; -import net.osmand.plus.openplacereviews.OpenPlaceReviewsPlugin; import net.osmand.plus.wikimedia.WikiImageHelper; import net.osmand.util.Algorithms; @@ -43,9 +41,7 @@ import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; -import java.util.Collections; import java.util.Date; -import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.Locale; @@ -412,28 +408,6 @@ public abstract class ImageCard extends AbstractCard { } } - private static String[] getIdFromResponse(String response) { - try { - JSONArray obj = new JSONObject(response).getJSONArray("objects"); - JSONArray images = (JSONArray) ((JSONObject) obj.get(0)).get("id"); - return toStringArray(images); - } catch (JSONException e) { - e.printStackTrace(); - } - return new String[0]; - } - - private static String[] toStringArray(JSONArray array) { - if (array == null) - return null; - - String[] arr = new String[array.length()]; - for (int i = 0; i < arr.length; i++) { - arr[i] = array.optString(i); - } - return arr; - } - public static class GetImageCardsTask extends AsyncTask> { private MapActivity mapActivity; @@ -465,20 +439,7 @@ public abstract class ImageCard extends AbstractCard { protected List doInBackground(Void... params) { TrafficStats.setThreadStatsTag(GET_IMAGE_CARD_THREAD_ID); List result = new ArrayList<>(); - Object o = mapActivity.getMapLayers().getContextMenuLayer().getSelectedObject(); - if (o instanceof Amenity && OsmandPlugin.getEnabledPlugin(OpenPlaceReviewsPlugin.class) != null) { - Amenity am = (Amenity) o; - long amenityId = am.getId() >> 1; - String baseUrl = OPRConstants.getBaseUrl(app); - String url = baseUrl + "api/objects-by-index?type=opr.place&index=osmid&key=" + amenityId; - String response = AndroidNetworkUtils.sendRequest(app, url, Collections.emptyMap(), - "Requesting location images...", false, false); - if (response != null) { - getPicturesForPlace(result, response); - String[] id = getIdFromResponse(response); - listener.onPlaceIdAcquired(id); - } - } + OsmandPlugin.populateImageCards(result, listener); try { final Map pms = new LinkedHashMap<>(); pms.put("lat", "" + (float) latLon.getLatitude()); @@ -539,36 +500,6 @@ public abstract class ImageCard extends AbstractCard { return result; } - private void getPicturesForPlace(List result, String response) { - try { - if (!Algorithms.isEmpty(response)) { - JSONArray obj = new JSONObject(response).getJSONArray("objects"); - JSONObject imagesWrapper = ((JSONObject) ((JSONObject) obj.get(0)).get("images")); - Iterator it = imagesWrapper.keys(); - while (it.hasNext()) { - JSONArray images = imagesWrapper.getJSONArray(it.next()); - if (images.length() > 0) { - for (int i = 0; i < images.length(); i++) { - try { - JSONObject imageObject = (JSONObject) images.get(i); - if (imageObject != JSONObject.NULL) { - ImageCard imageCard = ImageCard.createCardOpr(mapActivity, imageObject); - if (imageCard != null) { - result.add(imageCard); - } - } - } catch (JSONException e) { - LOG.error(e); - } - } - } - } - } - } catch (Exception e) { - LOG.error(e); - } - } - @Override protected void onPostExecute(List cardList) { result = cardList; diff --git a/OsmAnd/src/net/osmand/plus/openplacereviews/OpenPlaceReviewsPlugin.java b/OsmAnd/src/net/osmand/plus/openplacereviews/OpenPlaceReviewsPlugin.java index 263f62a570..abf4d23b0e 100644 --- a/OsmAnd/src/net/osmand/plus/openplacereviews/OpenPlaceReviewsPlugin.java +++ b/OsmAnd/src/net/osmand/plus/openplacereviews/OpenPlaceReviewsPlugin.java @@ -2,15 +2,38 @@ package net.osmand.plus.openplacereviews; import android.graphics.drawable.Drawable; +import androidx.annotation.Nullable; + +import net.osmand.AndroidNetworkUtils; +import net.osmand.PlatformUtil; +import net.osmand.data.Amenity; import net.osmand.plus.OsmandApplication; import net.osmand.plus.OsmandPlugin; import net.osmand.plus.R; +import net.osmand.plus.activities.MapActivity; +import net.osmand.plus.mapcontextmenu.builders.cards.ImageCard; +import net.osmand.plus.mapcontextmenu.builders.cards.ImageCard.GetImageCardsTask.GetImageCardsListener; import net.osmand.plus.settings.fragments.BaseSettingsFragment.SettingsScreenType; +import net.osmand.util.Algorithms; + +import org.apache.commons.logging.Log; +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; public class OpenPlaceReviewsPlugin extends OsmandPlugin { + private static final Log LOG = PlatformUtil.getLog(OpenPlaceReviewsPlugin.class); + private static final String ID = "osmand.openplacereviews"; + private MapActivity mapActivity; + public OpenPlaceReviewsPlugin(OsmandApplication app) { super(app); } @@ -46,6 +69,96 @@ public class OpenPlaceReviewsPlugin extends OsmandPlugin { return app.getUIUtilities().getIcon(R.drawable.img_plugin_openplacereviews); } + @Override + public void mapActivityResume(MapActivity activity) { + this.mapActivity = activity; + } + + @Override + public void mapActivityResumeOnTop(MapActivity activity) { + this.mapActivity = activity; + } + + @Override + public void mapActivityPause(MapActivity activity) { + this.mapActivity = null; + } + + @Override + protected List getImageCards(@Nullable GetImageCardsListener listener) { + List imageCards = new ArrayList<>(); + if (mapActivity != null) { + Object object = mapActivity.getMapLayers().getContextMenuLayer().getSelectedObject(); + if (object instanceof Amenity) { + Amenity am = (Amenity) object; + long amenityId = am.getId() >> 1; + String baseUrl = OPRConstants.getBaseUrl(app); + String url = baseUrl + "api/objects-by-index?type=opr.place&index=osmid&key=" + amenityId; + String response = AndroidNetworkUtils.sendRequest(app, url, Collections.emptyMap(), + "Requesting location images...", false, false); + if (response != null) { + getPicturesForPlace(imageCards, response); + if (listener != null) { + listener.onPlaceIdAcquired(getIdFromResponse(response)); + } + } + } + } + return imageCards; + } + + private void getPicturesForPlace(List result, String response) { + try { + if (!Algorithms.isEmpty(response)) { + JSONArray obj = new JSONObject(response).getJSONArray("objects"); + JSONObject imagesWrapper = ((JSONObject) ((JSONObject) obj.get(0)).get("images")); + Iterator it = imagesWrapper.keys(); + while (it.hasNext()) { + JSONArray images = imagesWrapper.getJSONArray(it.next()); + if (images.length() > 0) { + for (int i = 0; i < images.length(); i++) { + try { + JSONObject imageObject = (JSONObject) images.get(i); + if (imageObject != JSONObject.NULL) { + ImageCard imageCard = ImageCard.createCardOpr(mapActivity, imageObject); + if (imageCard != null) { + result.add(imageCard); + } + } + } catch (JSONException e) { + LOG.error(e); + } + } + } + } + } + } catch (Exception e) { + LOG.error(e); + } + } + + private static String[] getIdFromResponse(String response) { + try { + JSONArray obj = new JSONObject(response).getJSONArray("objects"); + JSONArray images = (JSONArray) ((JSONObject) obj.get(0)).get("id"); + return toStringArray(images); + } catch (JSONException e) { + e.printStackTrace(); + } + return new String[0]; + } + + private static String[] toStringArray(JSONArray array) { + if (array == null) + return null; + + String[] arr = new String[array.length()]; + for (int i = 0; i < arr.length; i++) { + arr[i] = array.optString(i); + } + return arr; + } + @Override public void disable(OsmandApplication app) { if (app.getSettings().OPR_USE_DEV_URL.get()) { From 457c90f945c5c867b160dade4e755b9834bfcacc Mon Sep 17 00:00:00 2001 From: max-klaus Date: Wed, 3 Feb 2021 16:10:46 +0300 Subject: [PATCH 47/65] Fix kmz reading --- .../net/osmand/plus/importfiles/GpxOrFavouritesImportTask.java | 2 +- OsmAnd/src/net/osmand/plus/importfiles/KmzImportTask.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/OsmAnd/src/net/osmand/plus/importfiles/GpxOrFavouritesImportTask.java b/OsmAnd/src/net/osmand/plus/importfiles/GpxOrFavouritesImportTask.java index 9ae0e9b59b..7286c7ee19 100644 --- a/OsmAnd/src/net/osmand/plus/importfiles/GpxOrFavouritesImportTask.java +++ b/OsmAnd/src/net/osmand/plus/importfiles/GpxOrFavouritesImportTask.java @@ -63,7 +63,7 @@ class GpxOrFavouritesImportTask extends BaseLoadAsyncTask { ZipEntry entry; while ((entry = zis.getNextEntry()) != null) { if (entry.getName().endsWith(ImportHelper.KML_SUFFIX)) { - InputStream gpxStream = convertKmlToGpxStream(is); + InputStream gpxStream = convertKmlToGpxStream(zis); if (gpxStream != null) { fileSize = gpxStream.available(); return GPXUtilities.loadGPXFile(gpxStream); diff --git a/OsmAnd/src/net/osmand/plus/importfiles/KmzImportTask.java b/OsmAnd/src/net/osmand/plus/importfiles/KmzImportTask.java index 6a145a04f7..2ed67cc0e4 100644 --- a/OsmAnd/src/net/osmand/plus/importfiles/KmzImportTask.java +++ b/OsmAnd/src/net/osmand/plus/importfiles/KmzImportTask.java @@ -49,7 +49,7 @@ class KmzImportTask extends BaseLoadAsyncTask { ZipEntry entry; while ((entry = zis.getNextEntry()) != null) { if (entry.getName().endsWith(KML_SUFFIX)) { - InputStream gpxStream = convertKmlToGpxStream(is); + InputStream gpxStream = convertKmlToGpxStream(zis); if (gpxStream != null) { fileSize = gpxStream.available(); return GPXUtilities.loadGPXFile(gpxStream); From 27fe223dd014d9a3cf9e5c64185cbe0a6802af33 Mon Sep 17 00:00:00 2001 From: androiddevkotlin <64539346+androiddevkotlin@users.noreply.github.com> Date: Wed, 3 Feb 2021 15:29:00 +0200 Subject: [PATCH 48/65] Missed text in UI "Get" button in "Downloads. OsmAnd Live screen after purchase. --- OsmAnd/res/layout/subscription_fragment.xml | 143 +++++++++--------- .../layout/two_line_with_images_list_item.xml | 28 ++-- 2 files changed, 85 insertions(+), 86 deletions(-) diff --git a/OsmAnd/res/layout/subscription_fragment.xml b/OsmAnd/res/layout/subscription_fragment.xml index 59b6f9b1b8..2ab9967918 100644 --- a/OsmAnd/res/layout/subscription_fragment.xml +++ b/OsmAnd/res/layout/subscription_fragment.xml @@ -1,5 +1,4 @@ - @@ -19,19 +18,19 @@ android:layout_width="52dp" android:layout_height="52dp" android:contentDescription="@string/shared_string_close" - app:srcCompat="@drawable/ic_action_remove_dark"/> + app:srcCompat="@drawable/ic_action_remove_dark" /> + app:typeface="@string/font_roboto_regular" /> @@ -39,7 +38,7 @@ android:layout_width="match_parent" android:layout_height="match_parent"> - + @@ -76,54 +75,54 @@ android:layout_width="56dp" android:layout_height="48dp" android:scaleType="center" - app:srcCompat="@drawable/ic_action_osm_live" - android:tint="@color/osmand_orange"/> + android:tint="@color/osmand_orange" + app:srcCompat="@drawable/ic_action_osm_live" /> + android:textColor="?android:attr/textColorPrimary" /> + android:orientation="horizontal"> + android:text="@string/donation_to_osm" /> + android:layout_marginStart="@dimen/list_content_padding_large" + android:layout_marginLeft="@dimen/context_menu_progress_padding_left" + android:layout_marginEnd="@dimen/context_menu_progress_padding_left" + android:layout_marginRight="@dimen/context_menu_progress_padding_left" + android:paddingStart="@dimen/subHeaderPadding" + android:paddingLeft="@dimen/subHeaderPadding" + android:paddingEnd="@dimen/subHeaderPadding" + android:paddingRight="@dimen/subHeaderPadding" + android:text="@string/donation_to_osm_desc" /> @@ -140,13 +139,13 @@ android:layout_width="match_parent" android:layout_height="1dp" android:layout_marginBottom="6dp" - android:background="?attr/dashboard_divider"/> + android:background="?attr/dashboard_divider" /> @@ -155,47 +154,47 @@ android:layout_width="56dp" android:layout_height="48dp" android:scaleType="center" - app:srcCompat="@drawable/ic_world_globe_dark"/> + app:srcCompat="@drawable/ic_world_globe_dark" /> + android:layout_marginEnd="16dp" + android:layout_marginRight="16dp" + android:orientation="vertical"> + android:textColor="?android:attr/textColorSecondary" /> + app:drawableEndCompat="@drawable/ic_action_arrow_drop_down" + app:drawableRightCompat="@drawable/ic_action_arrow_drop_down" /> + android:textColor="?android:attr/textColorSecondary" /> @@ -213,21 +212,21 @@ android:layout_width="56dp" android:layout_height="48dp" android:scaleType="center" - app:srcCompat="@drawable/ic_action_message"/> + app:srcCompat="@drawable/ic_action_message" /> + android:paddingStart="2dp" + android:paddingLeft="2dp" /> @@ -235,14 +234,14 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="center_vertical" + android:layout_marginStart="72dp" android:layout_marginLeft="72dp" + android:layout_marginEnd="16dp" android:layout_marginRight="16dp" + android:paddingStart="2dp" android:paddingLeft="2dp" android:text="@string/osm_live_email_desc" - android:textColor="?android:attr/textColorSecondary" - android:paddingStart="2dp" - android:layout_marginStart="72dp" - android:layout_marginEnd="16dp" /> + android:textColor="?android:attr/textColorSecondary" /> + app:srcCompat="@drawable/ic_action_user" /> + android:paddingStart="2dp" + android:paddingLeft="2dp" /> @@ -284,16 +283,16 @@ android:id="@+id/hideUserNameCheckbox" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_marginBottom="12dp" + android:layout_marginStart="72dp" android:layout_marginLeft="72dp" - android:layout_marginRight="16dp" android:layout_marginTop="8dp" + android:layout_marginEnd="16dp" + android:layout_marginRight="16dp" + android:layout_marginBottom="12dp" + android:paddingStart="4dp" android:paddingLeft="4dp" android:text="@string/osm_live_hide_user_name" - android:textColor="?android:attr/textColorPrimary" - android:layout_marginEnd="16dp" - android:paddingStart="4dp" - android:layout_marginStart="72dp" /> + android:textColor="?android:attr/textColorPrimary" /> @@ -303,35 +302,35 @@ android:id="@+id/editModeBottomView" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_marginBottom="16dp" android:layout_marginTop="16dp" + android:layout_marginBottom="16dp" android:visibility="visible">