Merge pull request #10198 from osmandapp/export_ui
Export UI first screen
This commit is contained in:
commit
3f1458579e
20 changed files with 1333 additions and 662 deletions
62
OsmAnd/res/layout/enough_space_warning_card.xml
Normal file
62
OsmAnd/res/layout/enough_space_warning_card.xml
Normal file
|
@ -0,0 +1,62 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/warning_card"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/bg_color"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:id="@+id/warning_img"
|
||||
android:layout_width="@dimen/standard_icon_size"
|
||||
android:layout_height="@dimen/standard_icon_size"
|
||||
android:layout_marginLeft="@dimen/content_padding"
|
||||
android:layout_marginTop="@dimen/content_padding"
|
||||
android:layout_marginRight="@dimen/content_padding"
|
||||
android:src="@drawable/ic_action_sdcard_warning_colored" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="@dimen/content_padding"
|
||||
android:layout_marginTop="@dimen/measurement_tool_menu_title_padding_top"
|
||||
android:layout_marginRight="@dimen/content_padding"
|
||||
android:layout_marginBottom="@dimen/measurement_tool_menu_title_padding_top"
|
||||
android:orientation="vertical">
|
||||
|
||||
<net.osmand.plus.widgets.TextViewEx
|
||||
android:id="@+id/warning_title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:letterSpacing="@dimen/text_button_letter_spacing"
|
||||
android:text="@string/export_not_enough_space"
|
||||
android:textColor="?android:textColorPrimary"
|
||||
android:textSize="@dimen/default_list_text_size"
|
||||
app:lineHeight="@dimen/default_title_line_height"
|
||||
app:typeface="@string/font_roboto_medium" />
|
||||
|
||||
<net.osmand.plus.widgets.TextViewEx
|
||||
android:id="@+id/warning_descr"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:letterSpacing="@dimen/description_letter_spacing"
|
||||
android:textColor="?android:textColorSecondary"
|
||||
android:textSize="@dimen/default_desc_text_size"
|
||||
app:lineHeight="@dimen/default_desc_line_height"
|
||||
app:typeface="@string/font_roboto_regular"
|
||||
tools:text="@string/export_not_enough_space_descr" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<include layout="@layout/card_bottom_divider" />
|
||||
|
||||
</LinearLayout>
|
|
@ -21,73 +21,80 @@
|
|||
<LinearLayout
|
||||
android:id="@+id/buttons_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/dialog_button_ex_height"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom"
|
||||
android:background="?attr/bg_color"
|
||||
android:gravity="center"
|
||||
android:minHeight="@dimen/bottom_sheet_title_height"
|
||||
android:orientation="vertical">
|
||||
|
||||
<include layout="@layout/divider" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="horizontal"
|
||||
android:paddingLeft="@dimen/content_padding"
|
||||
android:paddingTop="@dimen/content_padding_small"
|
||||
android:paddingRight="@dimen/content_padding"
|
||||
android:paddingBottom="@dimen/content_padding_small">
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<FrameLayout
|
||||
<LinearLayout
|
||||
android:id="@+id/file_size_container"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1">
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical"
|
||||
android:paddingLeft="@dimen/content_padding"
|
||||
android:paddingTop="@dimen/bottom_sheet_title_padding_bottom"
|
||||
android:paddingRight="@dimen/content_padding"
|
||||
android:paddingBottom="@dimen/bottom_sheet_title_padding_bottom"
|
||||
android:visibility="invisible"
|
||||
tools:visibility="visible">
|
||||
|
||||
<net.osmand.plus.widgets.TextViewEx
|
||||
android:id="@+id/select_button"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:id="@+id/file_size"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="end"
|
||||
android:letterSpacing="@dimen/description_letter_spacing"
|
||||
android:maxLines="1"
|
||||
android:textColor="?android:textColorPrimary"
|
||||
android:textSize="@dimen/default_desc_text_size"
|
||||
osmand:lineHeight="@dimen/default_desc_line_height"
|
||||
osmand:typeface="@string/font_roboto_regular"
|
||||
tools:text="567 MB" />
|
||||
|
||||
<net.osmand.plus.widgets.TextViewEx
|
||||
android:id="@+id/file_size_descr"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="end"
|
||||
android:gravity="start|center_vertical"
|
||||
android:letterSpacing="@dimen/description_letter_spacing"
|
||||
android:maxLines="1"
|
||||
android:paddingLeft="@dimen/content_padding_small"
|
||||
android:paddingRight="@dimen/content_padding_small"
|
||||
android:text="@string/shared_string_select_all"
|
||||
android:textColor="?attr/active_color_basic"
|
||||
android:text="@string/approximate_file_size"
|
||||
android:textColor="?android:textColorSecondary"
|
||||
android:textSize="@dimen/default_desc_text_size"
|
||||
osmand:typeface="@string/font_roboto_medium"
|
||||
tools:text="Select all" />
|
||||
osmand:lineHeight="@dimen/default_desc_line_height"
|
||||
osmand:typeface="@string/font_roboto_regular" />
|
||||
|
||||
</FrameLayout>
|
||||
</LinearLayout>
|
||||
|
||||
<View
|
||||
android:layout_width="@dimen/content_padding"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:background="?attr/dlg_btn_primary">
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="@dimen/content_padding_half"
|
||||
android:layout_marginTop="@dimen/content_padding_half"
|
||||
android:layout_marginRight="@dimen/content_padding_half"
|
||||
android:layout_marginBottom="@dimen/content_padding_half">
|
||||
|
||||
<net.osmand.plus.widgets.TextViewEx
|
||||
<include
|
||||
android:id="@+id/continue_button"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:ellipsize="end"
|
||||
android:gravity="center"
|
||||
android:maxLines="1"
|
||||
android:paddingLeft="@dimen/content_padding_small"
|
||||
android:paddingRight="@dimen/content_padding_small"
|
||||
android:text="@string/shared_string_continue"
|
||||
android:textColor="?attr/dlg_btn_primary_text"
|
||||
android:textSize="@dimen/default_desc_text_size"
|
||||
osmand:typeface="@string/font_roboto_medium"
|
||||
tools:text="Continue" />
|
||||
layout="@layout/bottom_sheet_dialog_button"
|
||||
android:visibility="visible" />
|
||||
|
||||
</FrameLayout>
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
@ -95,8 +102,8 @@
|
|||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:id="@+id/appbar"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@android:color/transparent">
|
||||
|
||||
<com.google.android.material.appbar.CollapsingToolbarLayout
|
||||
|
@ -104,24 +111,24 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/toolbar_height_expanded"
|
||||
android:background="?attr/actionModeBackground"
|
||||
osmand:collapsedTitleTextAppearance="@style/AppBarTitle"
|
||||
osmand:expandedTitleGravity="start|bottom"
|
||||
osmand:expandedTitleMarginBottom="@dimen/content_padding_small"
|
||||
osmand:expandedTitleMarginEnd="@dimen/content_padding"
|
||||
osmand:expandedTitleMarginStart="@dimen/content_padding"
|
||||
osmand:collapsedTitleTextAppearance="@style/AppBarTitle"
|
||||
osmand:expandedTitleGravity="start|bottom"
|
||||
osmand:expandedTitleTextAppearance="@style/AppBarTitle"
|
||||
osmand:layout_scrollFlags="scroll|exitUntilCollapsed">
|
||||
|
||||
<androidx.appcompat.widget.Toolbar
|
||||
android:id="@+id/toolbar"
|
||||
osmand:titleMarginEnd="0dp"
|
||||
osmand:titleMarginStart="0dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/toolbar_height"
|
||||
android:minHeight="@dimen/toolbar_height"
|
||||
osmand:layout_collapseMode="pin"
|
||||
osmand:layout_scrollFlags="scroll|enterAlways|exitUntilCollapsed"
|
||||
osmand:title="@string/shared_string_import">
|
||||
osmand:title="@string/shared_string_import"
|
||||
osmand:titleMarginEnd="0dp"
|
||||
osmand:titleMarginStart="0dp">
|
||||
|
||||
</androidx.appcompat.widget.Toolbar>
|
||||
|
||||
|
@ -132,8 +139,8 @@
|
|||
style="@style/Widget.MaterialProgressBar.ProgressBar.Horizontal"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="5dp"
|
||||
android:visibility="gone"
|
||||
android:indeterminate="true"
|
||||
android:visibility="gone"
|
||||
osmand:mpb_progressStyle="horizontal"
|
||||
osmand:mpb_setBothDrawables="true"
|
||||
osmand:mpb_useIntrinsicPadding="false"
|
||||
|
|
|
@ -10,15 +10,25 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/bg_color"
|
||||
android:lineSpacingMultiplier="@dimen/line_spacing_multiplier_description"
|
||||
android:paddingStart="@dimen/content_padding"
|
||||
android:paddingTop="@dimen/list_header_settings_top_margin"
|
||||
android:paddingEnd="@dimen/content_padding"
|
||||
android:lineSpacingMultiplier="@dimen/line_spacing_multiplier_description"
|
||||
android:paddingBottom="@dimen/list_header_settings_top_margin"
|
||||
android:textColor="?android:textColorPrimary"
|
||||
android:textSize="@dimen/default_list_text_size"
|
||||
tools:text="@string/select_data_to_import" />
|
||||
|
||||
<include layout="@layout/card_bottom_divider" />
|
||||
<View
|
||||
android:id="@+id/divider"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="?attr/list_divider"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<include
|
||||
android:id="@+id/card_bottom_divider"
|
||||
layout="@layout/card_bottom_divider" />
|
||||
|
||||
</LinearLayout>
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:osmand="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:osmand="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
|
@ -14,32 +14,32 @@
|
|||
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/bg_color">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:gravity="center_vertical"
|
||||
android:minHeight="66dp"
|
||||
android:minHeight="@dimen/setting_list_item_large_height"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:id="@+id/explist_indicator"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/content_padding"
|
||||
android:layout_width="@dimen/standard_icon_size"
|
||||
android:layout_height="@dimen/standard_icon_size"
|
||||
android:layout_marginLeft="@dimen/content_padding"
|
||||
android:layout_marginTop="@dimen/content_padding"
|
||||
android:layout_marginEnd="@dimen/list_content_padding_large"
|
||||
android:layout_marginRight="@dimen/list_content_padding_large"
|
||||
android:layout_marginBottom="@dimen/content_padding"
|
||||
android:layout_marginTop="@dimen/bottom_sheet_icon_margin"
|
||||
android:layout_marginRight="@dimen/content_padding"
|
||||
android:layout_marginBottom="@dimen/bottom_sheet_icon_margin"
|
||||
osmand:srcCompat="@drawable/ic_action_arrow_down" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="@dimen/content_padding"
|
||||
android:layout_marginRight="@dimen/content_padding"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="vertical">
|
||||
|
@ -48,16 +48,20 @@
|
|||
android:id="@+id/title_tv"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:letterSpacing="@dimen/text_button_letter_spacing"
|
||||
android:textColor="?android:textColorPrimary"
|
||||
android:textSize="@dimen/default_list_text_size"
|
||||
osmand:lineHeight="@dimen/default_title_line_height"
|
||||
tools:text="Quick actions" />
|
||||
|
||||
<net.osmand.plus.widgets.TextViewEx
|
||||
android:id="@+id/sub_text_tv"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:letterSpacing="@dimen/description_letter_spacing"
|
||||
android:textColor="?android:textColorSecondary"
|
||||
android:textSize="@dimen/default_desc_text_size"
|
||||
osmand:lineHeight="@dimen/default_desc_line_height"
|
||||
tools:text="8 of 4" />
|
||||
|
||||
</LinearLayout>
|
||||
|
@ -66,22 +70,22 @@
|
|||
android:id="@+id/vertical_divider"
|
||||
android:layout_width="1dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginTop="@dimen/content_padding"
|
||||
android:layout_marginBottom="@dimen/content_padding"
|
||||
android:layout_marginTop="@dimen/setting_profile_item_switch_margin"
|
||||
android:layout_marginBottom="@dimen/setting_profile_item_switch_margin"
|
||||
android:background="?attr/list_divider" />
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/check_box_container"
|
||||
style="@style/Widget.AppCompat.Toolbar.Button.Navigation"
|
||||
android:layout_width="@dimen/acceptable_touch_radius"
|
||||
android:layout_height="@dimen/acceptable_touch_radius"
|
||||
android:layout_marginEnd="@dimen/text_margin_small"
|
||||
android:layout_marginRight="@dimen/text_margin_small"
|
||||
android:background="?attr/selectableItemBackgroundBorderless">
|
||||
android:layout_marginRight="@dimen/text_margin_small">
|
||||
|
||||
<net.osmand.view.ThreeStateCheckbox
|
||||
android:id="@+id/check_box"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="@dimen/standard_icon_size"
|
||||
android:layout_height="@dimen/standard_icon_size"
|
||||
android:layout_gravity="center"
|
||||
android:clickable="false"
|
||||
android:enabled="false"
|
||||
|
|
|
@ -210,6 +210,8 @@
|
|||
<dimen name="welcome_header_text_size">23sp</dimen>
|
||||
<dimen name="text_button_text_size">15sp</dimen>
|
||||
<dimen name="travel_card_primary_text_size">15sp</dimen>
|
||||
<dimen name="default_title_line_height">24sp</dimen>
|
||||
<dimen name="default_desc_line_height">20sp</dimen>
|
||||
|
||||
<dimen name="default_split_segments_overview">13sp</dimen>
|
||||
<dimen name="default_split_segments_data">13sp</dimen>
|
||||
|
|
|
@ -11,6 +11,12 @@
|
|||
Thx - Hardy
|
||||
|
||||
-->
|
||||
<string name="export_not_enough_space">There is not enough space</string>
|
||||
<string name="export_not_enough_space_descr">Your device only has %1$s free. Please free up some space or unselect some items to export.</string>
|
||||
<string name="file_size_needed_for_import">Needed for import</string>
|
||||
<string name="select_data_to_export">Select the data to be exported to the file.</string>
|
||||
<string name="approximate_file_size">Approximate file size</string>
|
||||
<string name="shared_string_resources">Resources</string>
|
||||
<string name="app_mode_motorboat">Motorboat</string>
|
||||
<string name="app_mode_kayak">Kayak</string>
|
||||
<string name="shared_string_search_history">Search history</string>
|
||||
|
|
|
@ -788,6 +788,14 @@ public class AndroidUtils {
|
|||
return result;
|
||||
}
|
||||
|
||||
public static long getAvailableSpace(@Nullable File dir) {
|
||||
if (dir != null && dir.canRead()) {
|
||||
StatFs fs = new StatFs(dir.getAbsolutePath());
|
||||
return fs.getAvailableBlocksLong() * fs.getBlockSize();
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public static float getFreeSpaceGb(File dir) {
|
||||
if (dir.canRead()) {
|
||||
StatFs fs = new StatFs(dir.getAbsolutePath());
|
||||
|
|
|
@ -2312,7 +2312,7 @@ public class OsmandAidlApi {
|
|||
File exportDir = app.getSettings().getExternalStorageDirectory();
|
||||
String fileName = appMode.toHumanString();
|
||||
SettingsHelper settingsHelper = app.getSettingsHelper();
|
||||
settingsItems.addAll(settingsHelper.getFilteredSettingsItems(settingsHelper.getAdditionalData(false), settingsTypes));
|
||||
settingsItems.addAll(settingsHelper.getFilteredSettingsItems(settingsTypes, false));
|
||||
settingsHelper.exportSettings(exportDir, fileName, null, settingsItems, true);
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -22,7 +22,6 @@ import android.widget.LinearLayout;
|
|||
import android.widget.ProgressBar;
|
||||
import android.widget.Space;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
@ -36,7 +35,6 @@ import androidx.fragment.app.FragmentActivity;
|
|||
import androidx.viewpager.widget.ViewPager;
|
||||
|
||||
import net.osmand.AndroidUtils;
|
||||
import net.osmand.IProgress;
|
||||
import net.osmand.IndexConstants;
|
||||
import net.osmand.PlatformUtil;
|
||||
import net.osmand.access.AccessibilityAssistant;
|
||||
|
@ -45,7 +43,6 @@ import net.osmand.data.PointDescription;
|
|||
import net.osmand.map.WorldRegion;
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.plus.OsmandPlugin;
|
||||
import net.osmand.plus.settings.backend.OsmandSettings;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.Version;
|
||||
import net.osmand.plus.activities.LocalIndexInfo;
|
||||
|
@ -64,6 +61,8 @@ import net.osmand.plus.helpers.FileNameTranslationHelper;
|
|||
import net.osmand.plus.inapp.InAppPurchaseHelper;
|
||||
import net.osmand.plus.inapp.InAppPurchaseHelper.InAppPurchaseTaskType;
|
||||
import net.osmand.plus.openseamapsplugin.NauticalMapsPlugin;
|
||||
import net.osmand.plus.settings.backend.OsmandSettings;
|
||||
import net.osmand.plus.download.ReloadIndexesTask.ReloadIndexesListener;
|
||||
import net.osmand.plus.srtmplugin.SRTMPlugin;
|
||||
import net.osmand.plus.views.controls.PagerSlidingTabStrip;
|
||||
import net.osmand.util.Algorithms;
|
||||
|
@ -389,8 +388,7 @@ public class DownloadActivity extends AbstractDownloadActivity implements Downlo
|
|||
return !Version.isPaidVersion(application)
|
||||
|| application.getSettings().SHOULD_SHOW_FREE_VERSION_BANNER.get();
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static class FreeVersionBanner {
|
||||
private final View freeVersionBanner;
|
||||
private final View freeVersionBannerTitle;
|
||||
|
@ -441,7 +439,7 @@ public class DownloadActivity extends AbstractDownloadActivity implements Downlo
|
|||
freeVersionBanner.setVisibility(View.VISIBLE);
|
||||
downloadsLeftProgressBar.setMax(DownloadValidationManager.MAXIMUM_AVAILABLE_FREE_DOWNLOADS);
|
||||
freeVersionDescriptionTextView.setText(ctx.getString(R.string.free_version_message,
|
||||
DownloadValidationManager.MAXIMUM_AVAILABLE_FREE_DOWNLOADS +"" ));
|
||||
DownloadValidationManager.MAXIMUM_AVAILABLE_FREE_DOWNLOADS + ""));
|
||||
|
||||
LinearLayout marksLinearLayout = (LinearLayout) freeVersionBanner.findViewById(R.id.marksLinearLayout);
|
||||
Space spaceView = new Space(ctx);
|
||||
|
@ -493,6 +491,7 @@ public class DownloadActivity extends AbstractDownloadActivity implements Downlo
|
|||
freeVersionBannerTitle.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateAvailableDownloads() {
|
||||
int activeTasks = ctx.getDownloadThread().getCountedDownloads();
|
||||
OsmandSettings settings = ctx.getMyApplication().getSettings();
|
||||
|
@ -570,36 +569,26 @@ public class DownloadActivity extends AbstractDownloadActivity implements Downlo
|
|||
}
|
||||
}
|
||||
|
||||
@SuppressLint("StaticFieldLeak")
|
||||
public void reloadLocalIndexes() {
|
||||
AsyncTask<Void, String, List<String>> task = new AsyncTask<Void, String, List<String>>() {
|
||||
final OsmandApplication app = (OsmandApplication) getApplication();
|
||||
ReloadIndexesTask reloadIndexesTask = new ReloadIndexesTask(app, new ReloadIndexesListener() {
|
||||
@Override
|
||||
protected void onPreExecute() {
|
||||
super.onPreExecute();
|
||||
public void reloadIndexesStarted() {
|
||||
setSupportProgressBarIndeterminateVisibility(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<String> doInBackground(Void... params) {
|
||||
return getMyApplication().getResourceManager().reloadIndexes(IProgress.EMPTY_PROGRESS,
|
||||
new ArrayList<String>()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(List<String> warnings) {
|
||||
public void reloadIndexesFinished(List<String> warnings) {
|
||||
setSupportProgressBarIndeterminateVisibility(false);
|
||||
if (!warnings.isEmpty()) {
|
||||
Toast.makeText(DownloadActivity.this, AndroidUtils.formatWarnings(warnings).toString(), Toast.LENGTH_LONG).show();
|
||||
if (!Algorithms.isEmpty(warnings)) {
|
||||
app.showToastMessage(AndroidUtils.formatWarnings(warnings).toString());
|
||||
}
|
||||
newDownloadIndexes();
|
||||
}
|
||||
};
|
||||
task.executeOnExecutor(singleThreadExecutor);
|
||||
});
|
||||
reloadIndexesTask.executeOnExecutor(singleThreadExecutor);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void setDownloadItem(WorldRegion region, String targetFileName) {
|
||||
if (downloadItem == null) {
|
||||
downloadItem = region;
|
||||
|
@ -666,8 +655,8 @@ public class DownloadActivity extends AbstractDownloadActivity implements Downlo
|
|||
int percent = 0;
|
||||
if (dir.canRead()) {
|
||||
StatFs fs = new StatFs(dir.getAbsolutePath());
|
||||
size = AndroidUtils.formatSize(activity, ((long)fs.getAvailableBlocks()) * fs.getBlockSize());
|
||||
percent = 100 - (int)((long)fs.getAvailableBlocks() * 100 / fs.getBlockCount());
|
||||
size = AndroidUtils.formatSize(activity, ((long) fs.getAvailableBlocks()) * fs.getBlockSize());
|
||||
percent = 100 - (int) ((long) fs.getAvailableBlocks() * 100 / fs.getBlockCount());
|
||||
}
|
||||
sizeProgress.setIndeterminate(false);
|
||||
sizeProgress.setProgress(percent);
|
||||
|
|
49
OsmAnd/src/net/osmand/plus/download/ReloadIndexesTask.java
Normal file
49
OsmAnd/src/net/osmand/plus/download/ReloadIndexesTask.java
Normal file
|
@ -0,0 +1,49 @@
|
|||
package net.osmand.plus.download;
|
||||
|
||||
import android.os.AsyncTask;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import net.osmand.IProgress;
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ReloadIndexesTask extends AsyncTask<Void, String, List<String>> {
|
||||
|
||||
private final OsmandApplication app;
|
||||
private final ReloadIndexesListener listener;
|
||||
|
||||
public ReloadIndexesTask(@NonNull OsmandApplication app, @Nullable ReloadIndexesListener listener) {
|
||||
this.app = app;
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPreExecute() {
|
||||
if (listener != null) {
|
||||
listener.reloadIndexesStarted();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<String> doInBackground(Void... params) {
|
||||
return app.getResourceManager().reloadIndexes(IProgress.EMPTY_PROGRESS, new ArrayList<String>());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(List<String> warnings) {
|
||||
if (listener != null) {
|
||||
listener.reloadIndexesFinished(warnings);
|
||||
}
|
||||
}
|
||||
|
||||
public interface ReloadIndexesListener {
|
||||
|
||||
void reloadIndexesStarted();
|
||||
|
||||
void reloadIndexesFinished(List<String> warnings);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
package net.osmand.plus.settings.backend;
|
||||
|
||||
import androidx.annotation.StringRes;
|
||||
|
||||
import net.osmand.plus.R;
|
||||
|
||||
public enum ExportSettingsCategory {
|
||||
SETTINGS(R.string.shared_string_settings),
|
||||
MY_PLACES(R.string.shared_string_my_places),
|
||||
RESOURCES(R.string.shared_string_resources);
|
||||
|
||||
@StringRes
|
||||
private final int titleId;
|
||||
|
||||
ExportSettingsCategory(@StringRes int titleId) {
|
||||
this.titleId = titleId;
|
||||
}
|
||||
|
||||
public int getTitleId() {
|
||||
return titleId;
|
||||
}
|
||||
}
|
|
@ -1,23 +1,63 @@
|
|||
package net.osmand.plus.settings.backend;
|
||||
|
||||
import androidx.annotation.DrawableRes;
|
||||
import androidx.annotation.StringRes;
|
||||
|
||||
import net.osmand.plus.R;
|
||||
|
||||
public enum ExportSettingsType {
|
||||
PROFILE,
|
||||
QUICK_ACTIONS,
|
||||
POI_TYPES,
|
||||
MAP_SOURCES,
|
||||
CUSTOM_RENDER_STYLE,
|
||||
CUSTOM_ROUTING,
|
||||
AVOID_ROADS,
|
||||
TRACKS,
|
||||
MULTIMEDIA_NOTES,
|
||||
GLOBAL,
|
||||
OSM_NOTES,
|
||||
OSM_EDITS,
|
||||
OFFLINE_MAPS,
|
||||
FAVORITES,
|
||||
TTS_VOICE,
|
||||
VOICE,
|
||||
ACTIVE_MARKERS,
|
||||
HISTORY_MARKERS,
|
||||
SEARCH_HISTORY
|
||||
}
|
||||
PROFILE(R.string.shared_string_profiles, R.drawable.ic_action_manage_profiles),
|
||||
GLOBAL(R.string.general_settings_2, R.drawable.ic_action_settings),
|
||||
QUICK_ACTIONS(R.string.configure_screen_quick_action, R.drawable.ic_quick_action),
|
||||
POI_TYPES(R.string.poi_dialog_poi_type, R.drawable.ic_action_info_dark),
|
||||
SEARCH_HISTORY(R.string.shared_string_search_history, R.drawable.ic_action_history),
|
||||
AVOID_ROADS(R.string.avoid_road, R.drawable.ic_action_alert),
|
||||
FAVORITES(R.string.shared_string_favorites, R.drawable.ic_action_favorite),
|
||||
TRACKS(R.string.shared_string_tracks, R.drawable.ic_action_route_distance),
|
||||
OSM_NOTES(R.string.osm_notes, R.drawable.ic_action_openstreetmap_logo),
|
||||
OSM_EDITS(R.string.osm_edits, R.drawable.ic_action_openstreetmap_logo),
|
||||
MULTIMEDIA_NOTES(R.string.audionotes_plugin_name, R.drawable.ic_grouped_by_type),
|
||||
ACTIVE_MARKERS(R.string.map_markers, R.drawable.ic_action_flag),
|
||||
HISTORY_MARKERS(R.string.markers_history, R.drawable.ic_action_flag),
|
||||
CUSTOM_RENDER_STYLE(R.string.shared_string_rendering_style, R.drawable.ic_action_map_style),
|
||||
CUSTOM_ROUTING(R.string.shared_string_routing, R.drawable.ic_action_route_distance),
|
||||
MAP_SOURCES(R.string.quick_action_map_source_title, R.drawable.ic_map),
|
||||
OFFLINE_MAPS(R.string.shared_string_maps, R.drawable.ic_map),
|
||||
TTS_VOICE(R.string.local_indexes_cat_tts, R.drawable.ic_action_volume_up),
|
||||
VOICE(R.string.local_indexes_cat_voice, R.drawable.ic_action_volume_up);
|
||||
|
||||
@StringRes
|
||||
private final int titleId;
|
||||
@DrawableRes
|
||||
private final int drawableRes;
|
||||
|
||||
ExportSettingsType(@StringRes int titleId, @DrawableRes int drawableRes) {
|
||||
this.titleId = titleId;
|
||||
this.drawableRes = drawableRes;
|
||||
}
|
||||
|
||||
@StringRes
|
||||
public int getTitleId() {
|
||||
return titleId;
|
||||
}
|
||||
|
||||
@DrawableRes
|
||||
public int getIconRes() {
|
||||
return drawableRes;
|
||||
}
|
||||
|
||||
public boolean isSettingsCategory() {
|
||||
return this == PROFILE || this == GLOBAL || this == QUICK_ACTIONS || this == POI_TYPES
|
||||
|| this == SEARCH_HISTORY || this == AVOID_ROADS;
|
||||
}
|
||||
|
||||
public boolean isMyPlacesCategory() {
|
||||
return this == FAVORITES || this == TRACKS || this == OSM_EDITS || this == OSM_NOTES
|
||||
|| this == MULTIMEDIA_NOTES || this == ACTIVE_MARKERS || this == HISTORY_MARKERS;
|
||||
}
|
||||
|
||||
public boolean isResourcesCategory() {
|
||||
return this == CUSTOM_RENDER_STYLE || this == CUSTOM_ROUTING || this == MAP_SOURCES
|
||||
|| this == OFFLINE_MAPS || this == VOICE || this == TTS_VOICE;
|
||||
}
|
||||
}
|
|
@ -29,10 +29,10 @@ import net.osmand.plus.helpers.AvoidSpecificRoads.AvoidRoadInfo;
|
|||
import net.osmand.plus.helpers.FileNameTranslationHelper;
|
||||
import net.osmand.plus.helpers.GpxUiHelper;
|
||||
import net.osmand.plus.helpers.GpxUiHelper.GPXInfo;
|
||||
import net.osmand.plus.mapmarkers.MapMarker;
|
||||
import net.osmand.plus.mapmarkers.MapMarkersGroup;
|
||||
import net.osmand.plus.helpers.SearchHistoryHelper;
|
||||
import net.osmand.plus.helpers.SearchHistoryHelper.HistoryEntry;
|
||||
import net.osmand.plus.mapmarkers.MapMarker;
|
||||
import net.osmand.plus.mapmarkers.MapMarkersGroup;
|
||||
import net.osmand.plus.osmedit.OpenstreetmapPoint;
|
||||
import net.osmand.plus.osmedit.OsmEditingPlugin;
|
||||
import net.osmand.plus.osmedit.OsmNotesPoint;
|
||||
|
@ -41,7 +41,9 @@ import net.osmand.plus.quickaction.QuickAction;
|
|||
import net.osmand.plus.quickaction.QuickActionRegistry;
|
||||
import net.osmand.plus.settings.backend.ApplicationMode;
|
||||
import net.osmand.plus.settings.backend.ApplicationMode.ApplicationModeBean;
|
||||
import net.osmand.plus.settings.backend.ExportSettingsCategory;
|
||||
import net.osmand.plus.settings.backend.ExportSettingsType;
|
||||
import net.osmand.plus.settings.fragments.ExportDataObject;
|
||||
import net.osmand.util.Algorithms;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
|
@ -54,6 +56,7 @@ import java.util.Arrays;
|
|||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
@ -467,6 +470,17 @@ public class SettingsHelper {
|
|||
exportSettings(fileDir, fileName, listener, new ArrayList<>(Arrays.asList(items)), exportItemsFiles);
|
||||
}
|
||||
|
||||
public List<SettingsItem> getFilteredSettingsItems(List<ExportSettingsType> settingsTypes, boolean globalExport) {
|
||||
Map<ExportSettingsCategory, List<ExportDataObject>> dataList = getAdditionalData(globalExport);
|
||||
Map<ExportSettingsType, List<?>> typesMap = new HashMap<>();
|
||||
for (List<ExportDataObject> objects : dataList.values()) {
|
||||
for (ExportDataObject exportObject : objects) {
|
||||
typesMap.put(exportObject.getType(), exportObject.getItems());
|
||||
}
|
||||
}
|
||||
return getFilteredSettingsItems(typesMap, settingsTypes);
|
||||
}
|
||||
|
||||
public List<SettingsItem> getFilteredSettingsItems(Map<ExportSettingsType, List<?>> additionalData,
|
||||
List<ExportSettingsType> settingsTypes) {
|
||||
List<SettingsItem> settingsItems = new ArrayList<>();
|
||||
|
@ -484,20 +498,139 @@ public class SettingsHelper {
|
|||
return settingsItems;
|
||||
}
|
||||
|
||||
public Map<ExportSettingsType, List<?>> getAdditionalData(boolean globalExport) {
|
||||
Map<ExportSettingsType, List<?>> dataList = new HashMap<>();
|
||||
public Map<ExportSettingsCategory, List<ExportDataObject>> getAdditionalData(boolean globalExport) {
|
||||
Map<ExportSettingsCategory, List<ExportDataObject>> dataList = new LinkedHashMap<>();
|
||||
|
||||
List<ExportDataObject> settingsItems = getSettingsItems(globalExport);
|
||||
List<ExportDataObject> myPlacesItems = getMyPlacesItems();
|
||||
List<ExportDataObject> resourcesItems = getResourcesItems();
|
||||
|
||||
if (!settingsItems.isEmpty()) {
|
||||
sortExportSettingsObjects(settingsItems);
|
||||
dataList.put(ExportSettingsCategory.SETTINGS, settingsItems);
|
||||
}
|
||||
if (!myPlacesItems.isEmpty()) {
|
||||
sortExportSettingsObjects(myPlacesItems);
|
||||
dataList.put(ExportSettingsCategory.MY_PLACES, myPlacesItems);
|
||||
}
|
||||
if (!resourcesItems.isEmpty()) {
|
||||
sortExportSettingsObjects(resourcesItems);
|
||||
dataList.put(ExportSettingsCategory.RESOURCES, resourcesItems);
|
||||
}
|
||||
|
||||
return dataList;
|
||||
}
|
||||
|
||||
private List<ExportDataObject> getSettingsItems(boolean globalExport) {
|
||||
List<ExportDataObject> settingsItems = new ArrayList<>();
|
||||
|
||||
if (globalExport) {
|
||||
List<ApplicationModeBean> appModeBeans = new ArrayList<>();
|
||||
for (ApplicationMode mode : ApplicationMode.allPossibleValues()) {
|
||||
appModeBeans.add(mode.toModeBean());
|
||||
}
|
||||
settingsItems.add(new ExportDataObject(ExportSettingsType.PROFILE, appModeBeans));
|
||||
}
|
||||
settingsItems.add(new ExportDataObject(ExportSettingsType.GLOBAL, Collections.singletonList(new GlobalSettingsItem(app.getSettings()))));
|
||||
|
||||
QuickActionRegistry registry = app.getQuickActionRegistry();
|
||||
List<QuickAction> actionsList = registry.getQuickActions();
|
||||
if (!actionsList.isEmpty()) {
|
||||
dataList.put(ExportSettingsType.QUICK_ACTIONS, actionsList);
|
||||
settingsItems.add(new ExportDataObject(ExportSettingsType.QUICK_ACTIONS, actionsList));
|
||||
}
|
||||
|
||||
List<PoiUIFilter> poiList = app.getPoiFilters().getUserDefinedPoiFilters(false);
|
||||
if (!poiList.isEmpty()) {
|
||||
dataList.put(ExportSettingsType.POI_TYPES, poiList);
|
||||
settingsItems.add(new ExportDataObject(ExportSettingsType.POI_TYPES, poiList));
|
||||
}
|
||||
List<HistoryEntry> historyEntries = SearchHistoryHelper.getInstance(app).getHistoryEntries(false);
|
||||
if (!historyEntries.isEmpty()) {
|
||||
settingsItems.add(new ExportDataObject(ExportSettingsType.SEARCH_HISTORY, historyEntries));
|
||||
}
|
||||
Map<LatLon, AvoidRoadInfo> impassableRoads = app.getAvoidSpecificRoads().getImpassableRoads();
|
||||
if (!impassableRoads.isEmpty()) {
|
||||
settingsItems.add(new ExportDataObject(ExportSettingsType.AVOID_ROADS, new ArrayList<>(impassableRoads.values())));
|
||||
}
|
||||
return settingsItems;
|
||||
}
|
||||
|
||||
private List<ExportDataObject> getMyPlacesItems() {
|
||||
List<ExportDataObject> myPlacesItems = new ArrayList<>();
|
||||
|
||||
List<FavoriteGroup> favoriteGroups = app.getFavorites().getFavoriteGroups();
|
||||
if (!favoriteGroups.isEmpty()) {
|
||||
myPlacesItems.add(new ExportDataObject(ExportSettingsType.FAVORITES, favoriteGroups));
|
||||
}
|
||||
File gpxDir = app.getAppPath(IndexConstants.GPX_INDEX_DIR);
|
||||
List<GPXInfo> gpxInfoList = GpxUiHelper.getSortedGPXFilesInfo(gpxDir, null, true);
|
||||
if (!gpxInfoList.isEmpty()) {
|
||||
List<File> files = new ArrayList<>();
|
||||
for (GPXInfo gpxInfo : gpxInfoList) {
|
||||
File file = new File(gpxInfo.getFileName());
|
||||
if (file.exists()) {
|
||||
files.add(file);
|
||||
}
|
||||
}
|
||||
if (!files.isEmpty()) {
|
||||
myPlacesItems.add(new ExportDataObject(ExportSettingsType.TRACKS, files));
|
||||
}
|
||||
}
|
||||
OsmEditingPlugin osmEditingPlugin = OsmandPlugin.getPlugin(OsmEditingPlugin.class);
|
||||
if (osmEditingPlugin != null) {
|
||||
List<OsmNotesPoint> notesPointList = osmEditingPlugin.getDBBug().getOsmbugsPoints();
|
||||
if (!notesPointList.isEmpty()) {
|
||||
myPlacesItems.add(new ExportDataObject(ExportSettingsType.OSM_NOTES, notesPointList));
|
||||
}
|
||||
List<OpenstreetmapPoint> editsPointList = osmEditingPlugin.getDBPOI().getOpenstreetmapPoints();
|
||||
if (!editsPointList.isEmpty()) {
|
||||
myPlacesItems.add(new ExportDataObject(ExportSettingsType.OSM_EDITS, editsPointList));
|
||||
}
|
||||
}
|
||||
AudioVideoNotesPlugin plugin = OsmandPlugin.getPlugin(AudioVideoNotesPlugin.class);
|
||||
if (plugin != null) {
|
||||
List<File> files = new ArrayList<>();
|
||||
for (Recording rec : plugin.getAllRecordings()) {
|
||||
File file = rec.getFile();
|
||||
if (file != null && file.exists()) {
|
||||
files.add(file);
|
||||
}
|
||||
}
|
||||
if (!files.isEmpty()) {
|
||||
myPlacesItems.add(new ExportDataObject(ExportSettingsType.MULTIMEDIA_NOTES, files));
|
||||
}
|
||||
}
|
||||
List<MapMarker> mapMarkers = app.getMapMarkersHelper().getMapMarkersFromDefaultGroups(false);
|
||||
if (!mapMarkers.isEmpty()) {
|
||||
String name = app.getString(R.string.map_markers);
|
||||
String groupId = ExportSettingsType.ACTIVE_MARKERS.name();
|
||||
MapMarkersGroup markersGroup = new MapMarkersGroup(groupId, name, MapMarkersGroup.ANY_TYPE);
|
||||
markersGroup.setMarkers(mapMarkers);
|
||||
myPlacesItems.add(new ExportDataObject(ExportSettingsType.ACTIVE_MARKERS, Collections.singletonList(markersGroup)));
|
||||
}
|
||||
List<MapMarker> markersHistory = app.getMapMarkersHelper().getMapMarkersFromDefaultGroups(true);
|
||||
if (!markersHistory.isEmpty()) {
|
||||
String name = app.getString(R.string.shared_string_history);
|
||||
String groupId = ExportSettingsType.HISTORY_MARKERS.name();
|
||||
MapMarkersGroup markersGroup = new MapMarkersGroup(groupId, name, MapMarkersGroup.ANY_TYPE);
|
||||
markersGroup.setMarkers(markersHistory);
|
||||
myPlacesItems.add(new ExportDataObject(ExportSettingsType.HISTORY_MARKERS, Collections.singletonList(markersGroup)));
|
||||
}
|
||||
return myPlacesItems;
|
||||
}
|
||||
|
||||
private List<ExportDataObject> getResourcesItems() {
|
||||
List<ExportDataObject> resourcesItems = new ArrayList<>();
|
||||
|
||||
Map<String, File> externalRenderers = app.getRendererRegistry().getExternalRenderers();
|
||||
if (!externalRenderers.isEmpty()) {
|
||||
resourcesItems.add(new ExportDataObject(ExportSettingsType.CUSTOM_RENDER_STYLE, new ArrayList<>(externalRenderers.values())));
|
||||
}
|
||||
File routingProfilesFolder = app.getAppPath(IndexConstants.ROUTING_PROFILES_DIR);
|
||||
if (routingProfilesFolder.exists() && routingProfilesFolder.isDirectory()) {
|
||||
File[] fl = routingProfilesFolder.listFiles();
|
||||
if (fl != null && fl.length > 0) {
|
||||
resourcesItems.add(new ExportDataObject(ExportSettingsType.CUSTOM_ROUTING, Arrays.asList(fl)));
|
||||
}
|
||||
}
|
||||
List<ITileSource> iTileSources = new ArrayList<>();
|
||||
Set<String> tileSourceNames = app.getSettings().getTileSourceEntries(true).keySet();
|
||||
for (String name : tileSourceNames) {
|
||||
|
@ -515,111 +648,25 @@ public class SettingsHelper {
|
|||
}
|
||||
}
|
||||
if (!iTileSources.isEmpty()) {
|
||||
dataList.put(ExportSettingsType.MAP_SOURCES, iTileSources);
|
||||
}
|
||||
|
||||
Map<String, File> externalRenderers = app.getRendererRegistry().getExternalRenderers();
|
||||
if (!externalRenderers.isEmpty()) {
|
||||
dataList.put(ExportSettingsType.CUSTOM_RENDER_STYLE, new ArrayList<>(externalRenderers.values()));
|
||||
}
|
||||
|
||||
File routingProfilesFolder = app.getAppPath(IndexConstants.ROUTING_PROFILES_DIR);
|
||||
if (routingProfilesFolder.exists() && routingProfilesFolder.isDirectory()) {
|
||||
File[] fl = routingProfilesFolder.listFiles();
|
||||
if (fl != null && fl.length > 0) {
|
||||
dataList.put(ExportSettingsType.CUSTOM_ROUTING, Arrays.asList(fl));
|
||||
}
|
||||
}
|
||||
|
||||
Map<LatLon, AvoidRoadInfo> impassableRoads = app.getAvoidSpecificRoads().getImpassableRoads();
|
||||
if (!impassableRoads.isEmpty()) {
|
||||
dataList.put(ExportSettingsType.AVOID_ROADS, new ArrayList<>(impassableRoads.values()));
|
||||
}
|
||||
AudioVideoNotesPlugin plugin = OsmandPlugin.getPlugin(AudioVideoNotesPlugin.class);
|
||||
if (plugin != null) {
|
||||
List<File> files = new ArrayList<>();
|
||||
for (Recording rec : plugin.getAllRecordings()) {
|
||||
File file = rec.getFile();
|
||||
if (file != null && file.exists()) {
|
||||
files.add(file);
|
||||
}
|
||||
}
|
||||
if (!files.isEmpty()) {
|
||||
dataList.put(ExportSettingsType.MULTIMEDIA_NOTES, files);
|
||||
}
|
||||
}
|
||||
File gpxDir = app.getAppPath(IndexConstants.GPX_INDEX_DIR);
|
||||
List<GPXInfo> gpxInfoList = GpxUiHelper.getSortedGPXFilesInfo(gpxDir, null, true);
|
||||
if (!gpxInfoList.isEmpty()) {
|
||||
List<File> files = new ArrayList<>();
|
||||
for (GPXInfo gpxInfo : gpxInfoList) {
|
||||
File file = new File(gpxInfo.getFileName());
|
||||
if (file.exists()) {
|
||||
files.add(file);
|
||||
}
|
||||
}
|
||||
if (!files.isEmpty()) {
|
||||
dataList.put(ExportSettingsType.TRACKS, files);
|
||||
}
|
||||
}
|
||||
if (globalExport) {
|
||||
List<ApplicationModeBean> appModeBeans = new ArrayList<>();
|
||||
for (ApplicationMode mode : ApplicationMode.allPossibleValues()) {
|
||||
appModeBeans.add(mode.toModeBean());
|
||||
}
|
||||
dataList.put(ExportSettingsType.PROFILE, appModeBeans);
|
||||
}
|
||||
OsmEditingPlugin osmEditingPlugin = OsmandPlugin.getPlugin(OsmEditingPlugin.class);
|
||||
if (osmEditingPlugin != null) {
|
||||
List<OsmNotesPoint> notesPointList = osmEditingPlugin.getDBBug().getOsmbugsPoints();
|
||||
if (!notesPointList.isEmpty()) {
|
||||
dataList.put(ExportSettingsType.OSM_NOTES, notesPointList);
|
||||
}
|
||||
List<OpenstreetmapPoint> editsPointList = osmEditingPlugin.getDBPOI().getOpenstreetmapPoints();
|
||||
if (!editsPointList.isEmpty()) {
|
||||
dataList.put(ExportSettingsType.OSM_EDITS, editsPointList);
|
||||
}
|
||||
}
|
||||
List<FavoriteGroup> favoriteGroups = app.getFavorites().getFavoriteGroups();
|
||||
if (!favoriteGroups.isEmpty()) {
|
||||
dataList.put(ExportSettingsType.FAVORITES, favoriteGroups);
|
||||
resourcesItems.add(new ExportDataObject(ExportSettingsType.MAP_SOURCES, iTileSources));
|
||||
}
|
||||
List<LocalIndexInfo> localIndexInfoList = getLocalIndexData();
|
||||
List<File> files = getFilesByType(localIndexInfoList, LocalIndexType.MAP_DATA, LocalIndexType.TILES_DATA,
|
||||
LocalIndexType.SRTM_DATA, LocalIndexType.WIKI_DATA);
|
||||
if (!files.isEmpty()) {
|
||||
sortLocalFiles(files);
|
||||
dataList.put(ExportSettingsType.OFFLINE_MAPS, files);
|
||||
resourcesItems.add(new ExportDataObject(ExportSettingsType.OFFLINE_MAPS, files));
|
||||
}
|
||||
files = getFilesByType(localIndexInfoList, LocalIndexType.TTS_VOICE_DATA);
|
||||
if (!files.isEmpty()) {
|
||||
dataList.put(ExportSettingsType.TTS_VOICE, files);
|
||||
resourcesItems.add(new ExportDataObject(ExportSettingsType.TTS_VOICE, files));
|
||||
}
|
||||
files = getFilesByType(localIndexInfoList, LocalIndexType.VOICE_DATA);
|
||||
if (!files.isEmpty()) {
|
||||
dataList.put(ExportSettingsType.VOICE, files);
|
||||
resourcesItems.add(new ExportDataObject(ExportSettingsType.VOICE, files));
|
||||
}
|
||||
List<MapMarker> mapMarkers = app.getMapMarkersHelper().getMapMarkersFromDefaultGroups(false);
|
||||
if (!mapMarkers.isEmpty()) {
|
||||
String name = app.getString(R.string.map_markers);
|
||||
String groupId = ExportSettingsType.ACTIVE_MARKERS.name();
|
||||
MapMarkersGroup markersGroup = new MapMarkersGroup(groupId, name, MapMarkersGroup.ANY_TYPE);
|
||||
markersGroup.setMarkers(mapMarkers);
|
||||
dataList.put(ExportSettingsType.ACTIVE_MARKERS, Collections.singletonList(markersGroup));
|
||||
}
|
||||
List<MapMarker> markersHistory = app.getMapMarkersHelper().getMapMarkersFromDefaultGroups(true);
|
||||
if (!markersHistory.isEmpty()) {
|
||||
String name = app.getString(R.string.shared_string_history);
|
||||
String groupId = ExportSettingsType.HISTORY_MARKERS.name();
|
||||
MapMarkersGroup markersGroup = new MapMarkersGroup(groupId, name, MapMarkersGroup.ANY_TYPE);
|
||||
markersGroup.setMarkers(markersHistory);
|
||||
dataList.put(ExportSettingsType.HISTORY_MARKERS, Collections.singletonList(markersGroup));
|
||||
}
|
||||
List<HistoryEntry> historyEntries = SearchHistoryHelper.getInstance(app).getHistoryEntries(false);
|
||||
if (!historyEntries.isEmpty()) {
|
||||
dataList.put(ExportSettingsType.SEARCH_HISTORY, historyEntries);
|
||||
}
|
||||
return dataList;
|
||||
|
||||
return resourcesItems;
|
||||
}
|
||||
|
||||
private List<LocalIndexInfo> getLocalIndexData() {
|
||||
|
@ -745,6 +792,40 @@ public class SettingsHelper {
|
|||
return settingsItems;
|
||||
}
|
||||
|
||||
public static Map<ExportSettingsCategory, List<ExportDataObject>> getSettingsToOperateByCategory(List<SettingsItem> items, boolean importComplete) {
|
||||
Map<ExportSettingsCategory, List<ExportDataObject>> exportMap = new LinkedHashMap<>();
|
||||
Map<ExportSettingsType, List<?>> settingsToOperate = getSettingsToOperate(items, importComplete);
|
||||
|
||||
List<ExportDataObject> settingsItems = new ArrayList<>();
|
||||
List<ExportDataObject> myPlacesItems = new ArrayList<>();
|
||||
List<ExportDataObject> resourcesItems = new ArrayList<>();
|
||||
|
||||
for (Map.Entry<ExportSettingsType, List<?>> entry : settingsToOperate.entrySet()) {
|
||||
ExportSettingsType type = entry.getKey();
|
||||
if (type.isSettingsCategory()) {
|
||||
settingsItems.add(new ExportDataObject(type, entry.getValue()));
|
||||
} else if (type.isMyPlacesCategory()) {
|
||||
myPlacesItems.add(new ExportDataObject(type, entry.getValue()));
|
||||
} else if (type.isResourcesCategory()) {
|
||||
resourcesItems.add(new ExportDataObject(type, entry.getValue()));
|
||||
}
|
||||
}
|
||||
if (!settingsItems.isEmpty()) {
|
||||
sortExportSettingsObjects(settingsItems);
|
||||
exportMap.put(ExportSettingsCategory.SETTINGS, settingsItems);
|
||||
}
|
||||
if (!myPlacesItems.isEmpty()) {
|
||||
sortExportSettingsObjects(myPlacesItems);
|
||||
exportMap.put(ExportSettingsCategory.MY_PLACES, myPlacesItems);
|
||||
}
|
||||
if (!resourcesItems.isEmpty()) {
|
||||
sortExportSettingsObjects(resourcesItems);
|
||||
exportMap.put(ExportSettingsCategory.RESOURCES, resourcesItems);
|
||||
}
|
||||
|
||||
return exportMap;
|
||||
}
|
||||
|
||||
public static Map<ExportSettingsType, List<?>> getSettingsToOperate(List<SettingsItem> settingsItems, boolean importComplete) {
|
||||
Map<ExportSettingsType, List<?>> settingsToOperate = new HashMap<>();
|
||||
List<ApplicationModeBean> profiles = new ArrayList<>();
|
||||
|
@ -913,7 +994,7 @@ public class SettingsHelper {
|
|||
if (!markersGroups.isEmpty()) {
|
||||
settingsToOperate.put(ExportSettingsType.ACTIVE_MARKERS, markersGroups);
|
||||
}
|
||||
if (!markersGroups.isEmpty()) {
|
||||
if (!markersHistoryGroups.isEmpty()) {
|
||||
settingsToOperate.put(ExportSettingsType.HISTORY_MARKERS, markersHistoryGroups);
|
||||
}
|
||||
if (!historyEntries.isEmpty()) {
|
||||
|
@ -935,4 +1016,15 @@ public class SettingsHelper {
|
|||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static void sortExportSettingsObjects(List<ExportDataObject> items) {
|
||||
Collections.sort(items, new Comparator<ExportDataObject>() {
|
||||
@Override
|
||||
public int compare(ExportDataObject lhs, ExportDataObject rhs) {
|
||||
int order1 = lhs.getType().ordinal();
|
||||
int order2 = rhs.getType().ordinal();
|
||||
return (order1 < order2) ? -1 : ((order1 == order2) ? 0 : 1);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
|
@ -31,12 +31,9 @@ import androidx.recyclerview.widget.RecyclerView;
|
|||
import net.osmand.AndroidUtils;
|
||||
import net.osmand.IndexConstants;
|
||||
import net.osmand.PlatformUtil;
|
||||
import net.osmand.plus.settings.backend.ApplicationMode;
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.plus.OsmandPlugin;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.settings.backend.backup.SettingsHelper;
|
||||
import net.osmand.plus.settings.backend.backup.SettingsHelper.SettingsCollectListener;
|
||||
import net.osmand.plus.UiUtilities;
|
||||
import net.osmand.plus.activities.MapActivity;
|
||||
import net.osmand.plus.helpers.AndroidUiHelper;
|
||||
|
@ -44,6 +41,9 @@ import net.osmand.plus.helpers.FontCache;
|
|||
import net.osmand.plus.openseamapsplugin.NauticalMapsPlugin;
|
||||
import net.osmand.plus.profiles.SelectCopyAppModeBottomSheet;
|
||||
import net.osmand.plus.profiles.SelectCopyAppModeBottomSheet.CopyAppModePrefsListener;
|
||||
import net.osmand.plus.settings.backend.ApplicationMode;
|
||||
import net.osmand.plus.settings.backend.backup.SettingsHelper;
|
||||
import net.osmand.plus.settings.backend.backup.SettingsHelper.SettingsCollectListener;
|
||||
import net.osmand.plus.settings.backend.backup.SettingsItem;
|
||||
import net.osmand.plus.settings.bottomsheets.ResetProfilePrefsBottomSheet;
|
||||
import net.osmand.plus.settings.bottomsheets.ResetProfilePrefsBottomSheet.ResetAppModePrefsListener;
|
||||
|
@ -433,10 +433,7 @@ public class ConfigureProfileFragment extends BaseSettingsFragment implements Co
|
|||
} else if (EXPORT_PROFILE.equals(prefId)) {
|
||||
FragmentManager fragmentManager = getFragmentManager();
|
||||
if (fragmentManager != null) {
|
||||
ExportProfileBottomSheet.showInstance(
|
||||
fragmentManager,
|
||||
this,
|
||||
getSelectedAppMode(), false);
|
||||
ExportSettingsFragment.showInstance(fragmentManager, getSelectedAppMode(), false);
|
||||
}
|
||||
} else if (DELETE_PROFILE.equals(prefId)) {
|
||||
onDeleteProfileClick();
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
package net.osmand.plus.settings.fragments;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import net.osmand.plus.settings.backend.ExportSettingsType;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class ExportDataObject {
|
||||
|
||||
private ExportSettingsType type;
|
||||
private List<?> items;
|
||||
|
||||
public ExportDataObject(@NonNull ExportSettingsType type, @NonNull List<?> items) {
|
||||
this.type = type;
|
||||
this.items = items;
|
||||
}
|
||||
|
||||
public ExportSettingsType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public List<?> getItems() {
|
||||
return items;
|
||||
}
|
||||
}
|
|
@ -1,429 +0,0 @@
|
|||
package net.osmand.plus.settings.fragments;
|
||||
|
||||
import android.app.ProgressDialog;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.res.ColorStateList;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.graphics.drawable.LayerDrawable;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.ExpandableListView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.widget.SwitchCompat;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
|
||||
import net.osmand.AndroidUtils;
|
||||
import net.osmand.FileUtils;
|
||||
import net.osmand.IndexConstants;
|
||||
import net.osmand.PlatformUtil;
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.UiUtilities;
|
||||
import net.osmand.plus.base.bottomsheetmenu.BaseBottomSheetItem;
|
||||
import net.osmand.plus.base.bottomsheetmenu.BottomSheetItemWithCompoundButton;
|
||||
import net.osmand.plus.base.bottomsheetmenu.SimpleBottomSheetItem;
|
||||
import net.osmand.plus.base.bottomsheetmenu.simpleitems.TitleItem;
|
||||
import net.osmand.plus.settings.backend.ApplicationMode;
|
||||
import net.osmand.plus.settings.backend.ExportSettingsType;
|
||||
import net.osmand.plus.settings.backend.backup.FileSettingsItem;
|
||||
import net.osmand.plus.settings.backend.backup.GlobalSettingsItem;
|
||||
import net.osmand.plus.settings.backend.backup.ProfileSettingsItem;
|
||||
import net.osmand.plus.settings.backend.backup.SettingsHelper.SettingsExportListener;
|
||||
import net.osmand.plus.settings.backend.backup.SettingsItem;
|
||||
import net.osmand.plus.settings.bottomsheets.BasePreferenceBottomSheet;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
|
||||
import java.io.File;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
public class ExportProfileBottomSheet extends BasePreferenceBottomSheet {
|
||||
|
||||
public static final String TAG = ExportProfileBottomSheet.class.getSimpleName();
|
||||
|
||||
private static final Log LOG = PlatformUtil.getLog(ExportProfileBottomSheet.class);
|
||||
|
||||
private static final String GLOBAL_EXPORT_KEY = "global_export_key";
|
||||
private static final String EXPORT_START_TIME_KEY = "export_start_time_key";
|
||||
private static final String EXPORTING_PROFILE_KEY = "exporting_profile_key";
|
||||
private static final String INCLUDE_ADDITIONAL_DATA_KEY = "include_additional_data_key";
|
||||
private static final String INCLUDE_GLOBAL_SETTINGS_KEY = "include_global_settings_key";
|
||||
private static final String PROGRESS_MAX_KEY = "progress_max_key";
|
||||
private static final String PROGRESS_VALUE_KEY = "progress_value_key";
|
||||
|
||||
private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("dd-MM-yy", Locale.US);
|
||||
|
||||
private OsmandApplication app;
|
||||
private Map<ExportSettingsType, List<?>> dataList = new HashMap<>();
|
||||
private ExportImportSettingsAdapter adapter;
|
||||
|
||||
private SettingsExportListener exportListener;
|
||||
private ProgressDialog progress;
|
||||
private int progressMax;
|
||||
private int progressValue;
|
||||
|
||||
private long exportStartTime;
|
||||
|
||||
private boolean globalExport = false;
|
||||
private boolean exportingProfile = false;
|
||||
private boolean includeAdditionalData = false;
|
||||
private boolean includeGlobalSettings = false;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
app = requiredMyApplication();
|
||||
if (savedInstanceState != null) {
|
||||
globalExport = savedInstanceState.getBoolean(GLOBAL_EXPORT_KEY);
|
||||
exportingProfile = savedInstanceState.getBoolean(EXPORTING_PROFILE_KEY);
|
||||
includeAdditionalData = savedInstanceState.getBoolean(INCLUDE_ADDITIONAL_DATA_KEY);
|
||||
includeGlobalSettings = savedInstanceState.getBoolean(INCLUDE_GLOBAL_SETTINGS_KEY);
|
||||
exportStartTime = savedInstanceState.getLong(EXPORT_START_TIME_KEY);
|
||||
progressMax = savedInstanceState.getInt(PROGRESS_MAX_KEY);
|
||||
progressValue = savedInstanceState.getInt(PROGRESS_VALUE_KEY);
|
||||
}
|
||||
dataList = app.getSettingsHelper().getAdditionalData(globalExport);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
outState.putBoolean(GLOBAL_EXPORT_KEY, globalExport);
|
||||
outState.putBoolean(EXPORTING_PROFILE_KEY, exportingProfile);
|
||||
outState.putBoolean(INCLUDE_ADDITIONAL_DATA_KEY, includeAdditionalData);
|
||||
outState.putBoolean(INCLUDE_GLOBAL_SETTINGS_KEY, includeGlobalSettings);
|
||||
outState.putLong(EXPORT_START_TIME_KEY, exportStartTime);
|
||||
outState.putInt(PROGRESS_MAX_KEY, progress.getMax());
|
||||
outState.putInt(PROGRESS_VALUE_KEY, progress.getProgress());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createMenuItems(Bundle savedInstanceState) {
|
||||
final Context context = getContext();
|
||||
if (context == null) {
|
||||
return;
|
||||
}
|
||||
if (globalExport) {
|
||||
items.add(new TitleItem(getString(R.string.shared_string_export)));
|
||||
|
||||
final BottomSheetItemWithCompoundButton[] globalSettingsItem = new BottomSheetItemWithCompoundButton[1];
|
||||
globalSettingsItem[0] = (BottomSheetItemWithCompoundButton) new BottomSheetItemWithCompoundButton.Builder()
|
||||
.setChecked(includeGlobalSettings)
|
||||
.setTitle(getString(R.string.general_settings_2))
|
||||
.setLayoutId(R.layout.bottom_sheet_item_with_switch_no_icon)
|
||||
.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
boolean checked = !globalSettingsItem[0].isChecked();
|
||||
globalSettingsItem[0].setChecked(checked);
|
||||
includeGlobalSettings = checked;
|
||||
}
|
||||
})
|
||||
.create();
|
||||
items.add(globalSettingsItem[0]);
|
||||
} else {
|
||||
items.add(new TitleItem(getString(R.string.export_profile)));
|
||||
ApplicationMode profile = getAppMode();
|
||||
int profileColor = profile.getIconColorInfo().getColor(nightMode);
|
||||
int colorNoAlpha = ContextCompat.getColor(context, profileColor);
|
||||
|
||||
Drawable backgroundIcon = UiUtilities.getColoredSelectableDrawable(context, colorNoAlpha, 0.3f);
|
||||
Drawable[] layers = {new ColorDrawable(UiUtilities.getColorWithAlpha(colorNoAlpha, 0.10f)), backgroundIcon};
|
||||
|
||||
BaseBottomSheetItem profileItem = new BottomSheetItemWithCompoundButton.Builder()
|
||||
.setChecked(true)
|
||||
.setCompoundButtonColorId(profileColor)
|
||||
.setButtonTintList(ColorStateList.valueOf(getResolvedColor(profileColor)))
|
||||
.setDescription(BaseSettingsFragment.getAppModeDescription(context, profile))
|
||||
.setIcon(getIcon(profile.getIconRes(), profileColor))
|
||||
.setTitle(profile.toHumanString())
|
||||
.setBackground(new LayerDrawable(layers))
|
||||
.setLayoutId(R.layout.preference_profile_item_with_radio_btn)
|
||||
.create();
|
||||
items.add(profileItem);
|
||||
}
|
||||
setupAdditionalItems();
|
||||
}
|
||||
|
||||
private void setupAdditionalItems() {
|
||||
if (!dataList.isEmpty()) {
|
||||
LayoutInflater inflater = UiUtilities.getInflater(app, nightMode);
|
||||
View additionalDataView = inflater.inflate(R.layout.bottom_sheet_item_additional_data, null);
|
||||
ExpandableListView listView = additionalDataView.findViewById(R.id.list);
|
||||
adapter = new ExportImportSettingsAdapter(app, nightMode, false);
|
||||
|
||||
View listHeader = inflater.inflate(R.layout.item_header_export_expand_list, null);
|
||||
final View topSwitchDivider = listHeader.findViewById(R.id.topSwitchDivider);
|
||||
final View bottomSwitchDivider = listHeader.findViewById(R.id.bottomSwitchDivider);
|
||||
final SwitchCompat switchItem = listHeader.findViewById(R.id.switchItem);
|
||||
switchItem.setTextColor(getResources().getColor(nightMode ? R.color.active_color_primary_dark : R.color.active_color_primary_light));
|
||||
switchItem.setChecked(includeAdditionalData);
|
||||
switchItem.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
includeAdditionalData = !includeAdditionalData;
|
||||
topSwitchDivider.setVisibility(includeAdditionalData ? View.VISIBLE : View.GONE);
|
||||
bottomSwitchDivider.setVisibility(includeAdditionalData ? View.VISIBLE : View.GONE);
|
||||
if (includeAdditionalData) {
|
||||
adapter.updateSettingsList(app.getSettingsHelper().getAdditionalData(globalExport));
|
||||
adapter.selectAll(true);
|
||||
} else {
|
||||
adapter.selectAll(false);
|
||||
adapter.clearSettingsList();
|
||||
}
|
||||
updateSwitch(switchItem);
|
||||
setupHeightAndBackground(getView());
|
||||
}
|
||||
});
|
||||
listView.setOnGroupExpandListener(new ExpandableListView.OnGroupExpandListener() {
|
||||
@Override
|
||||
public void onGroupExpand(int i) {
|
||||
setupHeightAndBackground(getView());
|
||||
}
|
||||
});
|
||||
|
||||
updateSwitch(switchItem);
|
||||
listView.addHeaderView(listHeader);
|
||||
listView.setAdapter(adapter);
|
||||
final SimpleBottomSheetItem titleItem = (SimpleBottomSheetItem) new SimpleBottomSheetItem.Builder()
|
||||
.setCustomView(additionalDataView)
|
||||
.create();
|
||||
items.add(titleItem);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateSwitch(View view) {
|
||||
if (includeAdditionalData) {
|
||||
UiUtilities.setMargins(view, 0, 0, 0, 0);
|
||||
view.setPadding(AndroidUtils.dpToPx(app, 32), 0, AndroidUtils.dpToPx(app, 32), 0);
|
||||
} else {
|
||||
UiUtilities.setMargins(view, AndroidUtils.dpToPx(app, 16), 0, AndroidUtils.dpToPx(app, 16), 0);
|
||||
view.setPadding(AndroidUtils.dpToPx(app, 16), 0, AndroidUtils.dpToPx(app, 16), 0);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getRightBottomButtonTextId() {
|
||||
return R.string.shared_string_export;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onRightBottomButtonClick() {
|
||||
prepareFile();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getDismissButtonTextId() {
|
||||
return R.string.shared_string_cancel;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean useScrollableItemsContainer() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean useExpandableList() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
checkExportingFile();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
if (exportingProfile) {
|
||||
File file = getExportFile();
|
||||
app.getSettingsHelper().updateExportListener(file, null);
|
||||
}
|
||||
}
|
||||
|
||||
private void setGlobalExport(boolean globalExport) {
|
||||
this.globalExport = globalExport;
|
||||
}
|
||||
|
||||
private List<SettingsItem> prepareSettingsItemsForExport() {
|
||||
List<SettingsItem> settingsItems = new ArrayList<>();
|
||||
if (!globalExport) {
|
||||
settingsItems.add(new ProfileSettingsItem(app, getAppMode()));
|
||||
}
|
||||
if (includeGlobalSettings) {
|
||||
settingsItems.add(new GlobalSettingsItem(app.getSettings()));
|
||||
}
|
||||
if (includeAdditionalData) {
|
||||
settingsItems.addAll(app.getSettingsHelper().prepareAdditionalSettingsItems(adapter.getData()));
|
||||
}
|
||||
return settingsItems;
|
||||
}
|
||||
|
||||
private void prepareFile() {
|
||||
if (app != null) {
|
||||
exportingProfile = true;
|
||||
exportStartTime = System.currentTimeMillis();
|
||||
showExportProgressDialog();
|
||||
File tempDir = FileUtils.getTempDir(app);
|
||||
String fileName = getFileName();
|
||||
List<SettingsItem> items = prepareSettingsItemsForExport();
|
||||
progress.setMax(getMaxProgress(items));
|
||||
app.getSettingsHelper().exportSettings(tempDir, fileName, getSettingsExportListener(), items, true);
|
||||
}
|
||||
}
|
||||
|
||||
private int getMaxProgress(List<SettingsItem> items) {
|
||||
long maxProgress = 0;
|
||||
for (SettingsItem item : items) {
|
||||
if (item instanceof FileSettingsItem) {
|
||||
maxProgress += ((FileSettingsItem) item).getSize();
|
||||
}
|
||||
}
|
||||
return (int) maxProgress / (1 << 20);
|
||||
}
|
||||
|
||||
private String getFileName() {
|
||||
if (globalExport) {
|
||||
if (exportStartTime == 0) {
|
||||
exportStartTime = System.currentTimeMillis();
|
||||
}
|
||||
return "Export_" + DATE_FORMAT.format(new Date(exportStartTime));
|
||||
} else {
|
||||
return getAppMode().toHumanString();
|
||||
}
|
||||
}
|
||||
|
||||
private void showExportProgressDialog() {
|
||||
Context context = getContext();
|
||||
if (context == null) {
|
||||
return;
|
||||
}
|
||||
if (progress != null) {
|
||||
progress.dismiss();
|
||||
}
|
||||
progress = new ProgressDialog(context);
|
||||
progress.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
|
||||
progress.setCancelable(true);
|
||||
progress.setTitle(app.getString(R.string.shared_string_export));
|
||||
progress.setMessage(app.getString(R.string.shared_string_preparing));
|
||||
progress.setButton(DialogInterface.BUTTON_NEGATIVE, app.getString(R.string.shared_string_cancel), new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
cancelExport();
|
||||
}
|
||||
});
|
||||
progress.setOnCancelListener(new DialogInterface.OnCancelListener() {
|
||||
@Override
|
||||
public void onCancel(DialogInterface dialog) {
|
||||
cancelExport();
|
||||
}
|
||||
});
|
||||
progress.show();
|
||||
}
|
||||
|
||||
private void cancelExport() {
|
||||
app.getSettingsHelper().cancelExportForFile(getExportFile());
|
||||
progress.dismiss();
|
||||
dismiss();
|
||||
}
|
||||
|
||||
private SettingsExportListener getSettingsExportListener() {
|
||||
if (exportListener == null) {
|
||||
exportListener = new SettingsExportListener() {
|
||||
|
||||
@Override
|
||||
public void onSettingsExportFinished(@NonNull File file, boolean succeed) {
|
||||
dismissExportProgressDialog();
|
||||
exportingProfile = false;
|
||||
if (succeed) {
|
||||
shareProfile(file);
|
||||
} else {
|
||||
app.showToastMessage(R.string.export_profile_failed);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSettingsExportProgressUpdate(int value) {
|
||||
progress.setProgress(value);
|
||||
}
|
||||
};
|
||||
}
|
||||
return exportListener;
|
||||
}
|
||||
|
||||
private void checkExportingFile() {
|
||||
if (exportingProfile) {
|
||||
File file = getExportFile();
|
||||
boolean fileExporting = app.getSettingsHelper().isFileExporting(file);
|
||||
if (fileExporting) {
|
||||
showExportProgressDialog();
|
||||
progress.setMax(progressMax);
|
||||
progress.setProgress(progressValue);
|
||||
app.getSettingsHelper().updateExportListener(file, getSettingsExportListener());
|
||||
} else if (file.exists()) {
|
||||
dismissExportProgressDialog();
|
||||
shareProfile(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void dismissExportProgressDialog() {
|
||||
FragmentActivity activity = getActivity();
|
||||
if (progress != null && activity != null && AndroidUtils.isActivityNotDestroyed(activity)) {
|
||||
progress.dismiss();
|
||||
}
|
||||
}
|
||||
|
||||
private File getExportFile() {
|
||||
File tempDir = FileUtils.getTempDir(app);
|
||||
String fileName = getFileName();
|
||||
return new File(tempDir, fileName + IndexConstants.OSMAND_SETTINGS_FILE_EXT);
|
||||
}
|
||||
|
||||
private void shareProfile(@NonNull File file) {
|
||||
try {
|
||||
final Intent sendIntent = new Intent();
|
||||
sendIntent.setAction(Intent.ACTION_SEND);
|
||||
sendIntent.putExtra(Intent.EXTRA_SUBJECT, file.getName());
|
||||
sendIntent.putExtra(Intent.EXTRA_STREAM, AndroidUtils.getUriForFile(getMyApplication(), file));
|
||||
sendIntent.setType("*/*");
|
||||
sendIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||
startActivity(sendIntent);
|
||||
dismiss();
|
||||
} catch (Exception e) {
|
||||
Toast.makeText(requireContext(), R.string.export_profile_failed, Toast.LENGTH_SHORT).show();
|
||||
LOG.error("Share profile error", e);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean showInstance(@NonNull FragmentManager fragmentManager,
|
||||
Fragment target, @NonNull ApplicationMode appMode,
|
||||
boolean globalExport) {
|
||||
try {
|
||||
ExportProfileBottomSheet fragment = new ExportProfileBottomSheet();
|
||||
fragment.setAppMode(appMode);
|
||||
fragment.setGlobalExport(globalExport);
|
||||
fragment.setTargetFragment(target, 0);
|
||||
fragment.show(fragmentManager, TAG);
|
||||
return true;
|
||||
} catch (RuntimeException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,341 @@
|
|||
package net.osmand.plus.settings.fragments;
|
||||
|
||||
import android.content.res.ColorStateList;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.core.widget.CompoundButtonCompat;
|
||||
|
||||
import net.osmand.AndroidUtils;
|
||||
import net.osmand.PlatformUtil;
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.UiUtilities;
|
||||
import net.osmand.plus.activities.OsmandBaseExpandableListAdapter;
|
||||
import net.osmand.plus.helpers.AndroidUiHelper;
|
||||
import net.osmand.plus.helpers.FontCache;
|
||||
import net.osmand.plus.settings.backend.ExportSettingsCategory;
|
||||
import net.osmand.plus.settings.backend.ExportSettingsType;
|
||||
import net.osmand.plus.settings.backend.backup.FileSettingsItem;
|
||||
import net.osmand.view.ThreeStateCheckbox;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static net.osmand.view.ThreeStateCheckbox.State.CHECKED;
|
||||
import static net.osmand.view.ThreeStateCheckbox.State.MISC;
|
||||
import static net.osmand.view.ThreeStateCheckbox.State.UNCHECKED;
|
||||
|
||||
public class ExportSettingsAdapter extends OsmandBaseExpandableListAdapter {
|
||||
|
||||
private static final Log LOG = PlatformUtil.getLog(ExportImportSettingsAdapter.class.getName());
|
||||
|
||||
private final OsmandApplication app;
|
||||
private final UiUtilities uiUtilities;
|
||||
|
||||
private List<ExportSettingsCategory> itemsTypes = new ArrayList<>();
|
||||
private Map<ExportSettingsType, List<?>> selectedItemsMap = new HashMap<>();
|
||||
private Map<ExportSettingsCategory, List<ExportDataObject>> itemsMap = new LinkedHashMap<>();
|
||||
|
||||
private final OnItemSelectedListener listener;
|
||||
|
||||
private final LayoutInflater themedInflater;
|
||||
|
||||
private final boolean nightMode;
|
||||
private final int activeColorRes;
|
||||
private final int secondaryColorRes;
|
||||
|
||||
ExportSettingsAdapter(OsmandApplication app, OnItemSelectedListener listener, boolean nightMode) {
|
||||
this.app = app;
|
||||
this.listener = listener;
|
||||
this.nightMode = nightMode;
|
||||
uiUtilities = app.getUIUtilities();
|
||||
themedInflater = UiUtilities.getInflater(app, nightMode);
|
||||
activeColorRes = nightMode ? R.color.icon_color_active_dark : R.color.icon_color_active_light;
|
||||
secondaryColorRes = nightMode ? R.color.icon_color_secondary_dark : R.color.icon_color_secondary_light;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
|
||||
View group = convertView;
|
||||
if (group == null) {
|
||||
group = themedInflater.inflate(R.layout.profile_data_list_item_group, parent, false);
|
||||
}
|
||||
final ExportSettingsCategory category = itemsTypes.get(groupPosition);
|
||||
final List<ExportDataObject> items = itemsMap.get(category);
|
||||
|
||||
String title = app.getString(category.getTitleId());
|
||||
TextView titleTv = group.findViewById(R.id.title_tv);
|
||||
titleTv.setText(UiUtilities.createCustomFontSpannable(FontCache.getRobotoMedium(app), title, title));
|
||||
|
||||
TextView subTextTv = group.findViewById(R.id.sub_text_tv);
|
||||
subTextTv.setText(getCategoryDescr(category));
|
||||
|
||||
int selectedTypes = 0;
|
||||
for (int i = 0; i < items.size(); i++) {
|
||||
ExportDataObject object = items.get(i);
|
||||
if (selectedItemsMap.containsKey(object.getType())) {
|
||||
selectedTypes++;
|
||||
}
|
||||
}
|
||||
final ThreeStateCheckbox checkBox = group.findViewById(R.id.check_box);
|
||||
if (selectedTypes == 0) {
|
||||
checkBox.setState(UNCHECKED);
|
||||
} else {
|
||||
checkBox.setState(selectedTypes == items.size() ? CHECKED : MISC);
|
||||
}
|
||||
int checkBoxColor = checkBox.getState() == UNCHECKED ? secondaryColorRes : activeColorRes;
|
||||
CompoundButtonCompat.setButtonTintList(checkBox, ColorStateList.valueOf(ContextCompat.getColor(app, checkBoxColor)));
|
||||
|
||||
group.findViewById(R.id.check_box_container).setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
checkBox.performClick();
|
||||
boolean selected = checkBox.getState() == CHECKED;
|
||||
if (selected) {
|
||||
for (ExportDataObject object : items) {
|
||||
if (!selectedItemsMap.containsKey(object.getType())) {
|
||||
selectedItemsMap.put(object.getType(), object.getItems());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (ExportDataObject object : items) {
|
||||
selectedItemsMap.remove(object.getType());
|
||||
}
|
||||
}
|
||||
if (listener != null) {
|
||||
listener.onCategorySelected(category, selected);
|
||||
}
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
});
|
||||
|
||||
adjustIndicator(app, groupPosition, isExpanded, group, nightMode);
|
||||
AndroidUiHelper.updateVisibility(group.findViewById(R.id.divider), isExpanded);
|
||||
AndroidUiHelper.updateVisibility(group.findViewById(R.id.card_top_divider), true);
|
||||
AndroidUiHelper.updateVisibility(group.findViewById(R.id.vertical_divider), false);
|
||||
AndroidUiHelper.updateVisibility(group.findViewById(R.id.card_bottom_divider), !isExpanded);
|
||||
|
||||
return group;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getChildView(int groupPosition, final int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
|
||||
View child = convertView;
|
||||
if (child == null) {
|
||||
child = themedInflater.inflate(R.layout.profile_data_list_item_group, parent, false);
|
||||
}
|
||||
final ExportDataObject currentItem = itemsMap.get(itemsTypes.get(groupPosition)).get(childPosition);
|
||||
List<?> selectedItems = selectedItemsMap.get(currentItem.getType());
|
||||
|
||||
TextView titleTv = child.findViewById(R.id.title_tv);
|
||||
titleTv.setText(currentItem.getType().getTitleId());
|
||||
|
||||
TextView subTextTv = child.findViewById(R.id.sub_text_tv);
|
||||
subTextTv.setText(getSelectedTypeDescr(currentItem));
|
||||
|
||||
ImageView icon = child.findViewById(R.id.explist_indicator);
|
||||
setupIcon(icon, currentItem.getType().getIconRes(), selectedItems != null);
|
||||
|
||||
final ThreeStateCheckbox checkBox = child.findViewById(R.id.check_box);
|
||||
if (selectedItems == null) {
|
||||
checkBox.setState(UNCHECKED);
|
||||
} else if (selectedItems.containsAll(currentItem.getItems())) {
|
||||
checkBox.setState(CHECKED);
|
||||
} else {
|
||||
boolean contains = false;
|
||||
for (Object object : currentItem.getItems()) {
|
||||
if (selectedItems.contains(object)) {
|
||||
contains = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
checkBox.setState(contains ? MISC : UNCHECKED);
|
||||
}
|
||||
|
||||
int checkBoxColor = checkBox.getState() == UNCHECKED ? secondaryColorRes : activeColorRes;
|
||||
CompoundButtonCompat.setButtonTintList(checkBox, ColorStateList.valueOf(ContextCompat.getColor(app, checkBoxColor)));
|
||||
child.findViewById(R.id.check_box_container).setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
checkBox.performClick();
|
||||
boolean selected = checkBox.getState() == CHECKED;
|
||||
if (selected) {
|
||||
selectedItemsMap.put(currentItem.getType(), currentItem.getItems());
|
||||
} else {
|
||||
selectedItemsMap.remove(currentItem.getType());
|
||||
}
|
||||
if (listener != null) {
|
||||
listener.onTypeSelected(currentItem.getType(), selected);
|
||||
}
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
});
|
||||
|
||||
AndroidUiHelper.updateVisibility(child.findViewById(R.id.card_bottom_divider), isLastChild);
|
||||
|
||||
return child;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getGroupCount() {
|
||||
return itemsTypes.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getChildrenCount(int i) {
|
||||
return itemsMap.get(itemsTypes.get(i)).size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getGroup(int i) {
|
||||
return itemsMap.get(itemsTypes.get(i));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getChild(int groupPosition, int childPosition) {
|
||||
return itemsMap.get(itemsTypes.get(groupPosition)).get(childPosition);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getGroupId(int i) {
|
||||
return i;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getChildId(int groupPosition, int childPosition) {
|
||||
return groupPosition * 10000 + childPosition;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasStableIds() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isChildSelectable(int i, int i1) {
|
||||
return true;
|
||||
}
|
||||
|
||||
private void setupIcon(ImageView icon, int iconRes, boolean itemSelected) {
|
||||
if (itemSelected) {
|
||||
int colorRes = nightMode ? R.color.icon_color_active_dark : R.color.icon_color_osmand_light;
|
||||
icon.setImageDrawable(uiUtilities.getIcon(iconRes, colorRes));
|
||||
} else {
|
||||
icon.setImageDrawable(uiUtilities.getIcon(iconRes, secondaryColorRes));
|
||||
}
|
||||
}
|
||||
|
||||
public void updateSettingsList(Map<ExportSettingsCategory, List<ExportDataObject>> itemsMap) {
|
||||
this.itemsMap = itemsMap;
|
||||
this.itemsTypes = new ArrayList<>(itemsMap.keySet());
|
||||
Collections.sort(itemsTypes);
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
public void clearSettingsList() {
|
||||
this.itemsMap.clear();
|
||||
this.itemsTypes.clear();
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
public boolean hasSelectedData() {
|
||||
return !selectedItemsMap.isEmpty();
|
||||
}
|
||||
|
||||
public List<? super Object> getData() {
|
||||
List<Object> selectedItems = new ArrayList<>();
|
||||
for (List<?> items : selectedItemsMap.values()) {
|
||||
selectedItems.addAll(items);
|
||||
}
|
||||
return selectedItems;
|
||||
}
|
||||
|
||||
private String getCategoryDescr(ExportSettingsCategory category) {
|
||||
long itemsSize = 0;
|
||||
int selectedTypes = 0;
|
||||
List<ExportDataObject> items = itemsMap.get(category);
|
||||
for (int i = 0; i < items.size(); i++) {
|
||||
ExportDataObject object = items.get(i);
|
||||
if (selectedItemsMap.containsKey(object.getType())) {
|
||||
selectedTypes++;
|
||||
itemsSize += calculateItemsSize(object.getItems());
|
||||
}
|
||||
}
|
||||
String description;
|
||||
if (selectedTypes == 0) {
|
||||
description = app.getString(R.string.shared_string_none);
|
||||
} else if (selectedTypes == items.size()) {
|
||||
description = app.getString(R.string.shared_string_all);
|
||||
} else {
|
||||
description = app.getString(R.string.ltr_or_rtl_combine_via_slash, String.valueOf(selectedTypes), String.valueOf(items.size()));
|
||||
}
|
||||
String formattedSize = AndroidUtils.formatSize(app, itemsSize);
|
||||
return itemsSize == 0 ? description : app.getString(R.string.ltr_or_rtl_combine_via_comma, description, formattedSize);
|
||||
}
|
||||
|
||||
public static long calculateItemsSize(List<?> items) {
|
||||
long itemsSize = 0;
|
||||
for (Object item : items) {
|
||||
if (item instanceof FileSettingsItem) {
|
||||
itemsSize += ((FileSettingsItem) item).getSize();
|
||||
} else if (item instanceof File) {
|
||||
itemsSize += ((File) item).length();
|
||||
}
|
||||
}
|
||||
return itemsSize;
|
||||
}
|
||||
|
||||
private String getSelectedTypeDescr(ExportDataObject dataObject) {
|
||||
long itemsSize = 0;
|
||||
int selectedTypes = 0;
|
||||
|
||||
List<?> items = dataObject.getItems();
|
||||
List<?> selectedItems = selectedItemsMap.get(dataObject.getType());
|
||||
if (selectedItems != null) {
|
||||
for (int i = 0; i < items.size(); i++) {
|
||||
Object object = items.get(i);
|
||||
if (selectedItems.contains(object)) {
|
||||
selectedTypes++;
|
||||
if (object instanceof FileSettingsItem) {
|
||||
itemsSize += ((FileSettingsItem) object).getSize();
|
||||
} else if (object instanceof File) {
|
||||
itemsSize += ((File) object).length();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
String description;
|
||||
if (selectedTypes == 0) {
|
||||
description = app.getString(R.string.shared_string_none);
|
||||
} else if (selectedTypes == items.size()) {
|
||||
description = app.getString(R.string.shared_string_all);
|
||||
if (itemsSize == 0) {
|
||||
description = app.getString(R.string.ltr_or_rtl_combine_via_comma, description, String.valueOf(items.size()));
|
||||
}
|
||||
} else {
|
||||
description = app.getString(R.string.ltr_or_rtl_combine_via_slash, String.valueOf(selectedTypes), String.valueOf(items.size()));
|
||||
}
|
||||
String formattedSize = AndroidUtils.formatSize(app, itemsSize);
|
||||
return itemsSize == 0 ? description : app.getString(R.string.ltr_or_rtl_combine_via_comma, description, formattedSize);
|
||||
}
|
||||
|
||||
interface OnItemSelectedListener {
|
||||
|
||||
void onCategorySelected(ExportSettingsCategory type, boolean selected);
|
||||
|
||||
void onTypeSelected(ExportSettingsType type, boolean selected);
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,455 @@
|
|||
package net.osmand.plus.settings.fragments;
|
||||
|
||||
import android.app.ProgressDialog;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewTreeObserver;
|
||||
import android.widget.ExpandableListView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.activity.OnBackPressedCallback;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.core.view.ViewCompat;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
|
||||
import com.google.android.material.appbar.CollapsingToolbarLayout;
|
||||
|
||||
import net.osmand.AndroidUtils;
|
||||
import net.osmand.FileUtils;
|
||||
import net.osmand.IndexConstants;
|
||||
import net.osmand.PlatformUtil;
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.UiUtilities;
|
||||
import net.osmand.plus.UiUtilities.DialogButtonType;
|
||||
import net.osmand.plus.base.BaseOsmAndFragment;
|
||||
import net.osmand.plus.helpers.AndroidUiHelper;
|
||||
import net.osmand.plus.settings.backend.ApplicationMode;
|
||||
import net.osmand.plus.settings.backend.ExportSettingsCategory;
|
||||
import net.osmand.plus.settings.backend.ExportSettingsType;
|
||||
import net.osmand.plus.settings.backend.backup.FileSettingsItem;
|
||||
import net.osmand.plus.settings.backend.backup.SettingsHelper.SettingsExportListener;
|
||||
import net.osmand.plus.settings.backend.backup.SettingsItem;
|
||||
import net.osmand.plus.settings.fragments.ExportSettingsAdapter.OnItemSelectedListener;
|
||||
import net.osmand.plus.widgets.TextViewEx;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
|
||||
import java.io.File;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
import static net.osmand.plus.settings.fragments.BaseSettingsFragment.APP_MODE_KEY;
|
||||
|
||||
public class ExportSettingsFragment extends BaseOsmAndFragment implements OnItemSelectedListener {
|
||||
|
||||
public static final String TAG = ImportSettingsFragment.class.getSimpleName();
|
||||
public static final Log LOG = PlatformUtil.getLog(ImportSettingsFragment.class.getSimpleName());
|
||||
|
||||
private static final String EXPORT_SETTINGS_TAG = "import_settings_tag";
|
||||
private static final String GLOBAL_EXPORT_KEY = "global_export_key";
|
||||
private static final String EXPORT_START_TIME_KEY = "export_start_time_key";
|
||||
private static final String EXPORTING_STARTED_KEY = "exporting_started_key";
|
||||
private static final String INCLUDE_ADDITIONAL_DATA_KEY = "include_additional_data_key";
|
||||
private static final String INCLUDE_GLOBAL_SETTINGS_KEY = "include_global_settings_key";
|
||||
private static final String PROGRESS_MAX_KEY = "progress_max_key";
|
||||
private static final String PROGRESS_VALUE_KEY = "progress_value_key";
|
||||
|
||||
private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("dd-MM-yy", Locale.US);
|
||||
|
||||
private OsmandApplication app;
|
||||
private Map<ExportSettingsCategory, List<ExportDataObject>> dataList;
|
||||
|
||||
private ProgressDialog progress;
|
||||
private ApplicationMode appMode;
|
||||
private SettingsExportListener exportListener;
|
||||
|
||||
private View continueBtn;
|
||||
private View headerShadow;
|
||||
private View headerDivider;
|
||||
private View itemsSizeContainer;
|
||||
private View availableSpaceContainer;
|
||||
private TextViewEx selectedItemsSize;
|
||||
private TextViewEx availableSpaceDescr;
|
||||
private LinearLayout buttonsContainer;
|
||||
private ExpandableListView expandableList;
|
||||
private ExportSettingsAdapter adapter;
|
||||
|
||||
private int progressMax;
|
||||
private int progressValue;
|
||||
|
||||
private long exportStartTime;
|
||||
|
||||
private boolean nightMode;
|
||||
private boolean globalExport;
|
||||
private boolean exportingStarted;
|
||||
|
||||
@Override
|
||||
public int getStatusBarColorId() {
|
||||
return nightMode ? R.color.status_bar_color_dark : R.color.status_bar_color_light;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
app = requireMyApplication();
|
||||
nightMode = !app.getSettings().isLightContent();
|
||||
if (savedInstanceState != null) {
|
||||
appMode = ApplicationMode.valueOfStringKey(savedInstanceState.getString(APP_MODE_KEY), null);
|
||||
globalExport = savedInstanceState.getBoolean(GLOBAL_EXPORT_KEY);
|
||||
exportingStarted = savedInstanceState.getBoolean(EXPORTING_STARTED_KEY);
|
||||
exportStartTime = savedInstanceState.getLong(EXPORT_START_TIME_KEY);
|
||||
progressMax = savedInstanceState.getInt(PROGRESS_MAX_KEY);
|
||||
progressValue = savedInstanceState.getInt(PROGRESS_VALUE_KEY);
|
||||
}
|
||||
dataList = app.getSettingsHelper().getAdditionalData(globalExport);
|
||||
|
||||
requireActivity().getOnBackPressedDispatcher().addCallback(this, new OnBackPressedCallback(true) {
|
||||
@Override
|
||||
public void handleOnBackPressed() {
|
||||
showExitDialog();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||
LayoutInflater themedInflater = UiUtilities.getInflater(app, nightMode);
|
||||
View root = themedInflater.inflate(R.layout.fragment_import, container, false);
|
||||
AndroidUtils.addStatusBarPadding21v(app, root);
|
||||
|
||||
selectedItemsSize = root.findViewById(R.id.file_size);
|
||||
itemsSizeContainer = root.findViewById(R.id.file_size_container);
|
||||
expandableList = root.findViewById(R.id.list);
|
||||
buttonsContainer = root.findViewById(R.id.buttons_container);
|
||||
|
||||
Toolbar toolbar = root.findViewById(R.id.toolbar);
|
||||
setupToolbar(toolbar);
|
||||
ViewCompat.setNestedScrollingEnabled(expandableList, true);
|
||||
|
||||
View header = themedInflater.inflate(R.layout.list_item_description_header, null);
|
||||
headerDivider = header.findViewById(R.id.divider);
|
||||
headerShadow = header.findViewById(R.id.card_bottom_divider);
|
||||
expandableList.addHeaderView(header);
|
||||
|
||||
availableSpaceContainer = inflater.inflate(R.layout.enough_space_warning_card, null);
|
||||
availableSpaceDescr = availableSpaceContainer.findViewById(R.id.warning_descr);
|
||||
|
||||
continueBtn = root.findViewById(R.id.continue_button);
|
||||
UiUtilities.setupDialogButton(nightMode, continueBtn, DialogButtonType.PRIMARY, getString(R.string.shared_string_continue));
|
||||
continueBtn.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
prepareFile();
|
||||
}
|
||||
});
|
||||
|
||||
ViewTreeObserver treeObserver = buttonsContainer.getViewTreeObserver();
|
||||
treeObserver.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
|
||||
@Override
|
||||
public void onGlobalLayout() {
|
||||
if (buttonsContainer != null) {
|
||||
ViewTreeObserver vts = buttonsContainer.getViewTreeObserver();
|
||||
int height = buttonsContainer.getMeasuredHeight();
|
||||
expandableList.setPadding(0, 0, 0, height);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
|
||||
vts.removeOnGlobalLayoutListener(this);
|
||||
} else {
|
||||
vts.removeGlobalOnLayoutListener(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
adapter = new ExportSettingsAdapter(app, this, nightMode);
|
||||
adapter.updateSettingsList(dataList);
|
||||
expandableList.setAdapter(adapter);
|
||||
|
||||
CollapsingToolbarLayout toolbarLayout = root.findViewById(R.id.toolbar_layout);
|
||||
toolbarLayout.setTitle(getString(R.string.shared_string_export));
|
||||
TextView description = header.findViewById(R.id.description);
|
||||
description.setText(R.string.select_data_to_export);
|
||||
updateAvailableSpace();
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(@NonNull Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
outState.putBoolean(GLOBAL_EXPORT_KEY, globalExport);
|
||||
outState.putBoolean(EXPORTING_STARTED_KEY, exportingStarted);
|
||||
outState.putLong(EXPORT_START_TIME_KEY, exportStartTime);
|
||||
outState.putString(APP_MODE_KEY, appMode.getStringKey());
|
||||
if (progress != null) {
|
||||
outState.putInt(PROGRESS_MAX_KEY, progress.getMax());
|
||||
outState.putInt(PROGRESS_VALUE_KEY, progress.getProgress());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
checkExportingFile();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
if (exportingStarted) {
|
||||
File file = getExportFile();
|
||||
app.getSettingsHelper().updateExportListener(file, null);
|
||||
}
|
||||
}
|
||||
|
||||
private void dismissFragment() {
|
||||
FragmentManager fm = getFragmentManager();
|
||||
if (fm != null && !fm.isStateSaved()) {
|
||||
getFragmentManager().popBackStack(EXPORT_SETTINGS_TAG, FragmentManager.POP_BACK_STACK_INCLUSIVE);
|
||||
}
|
||||
}
|
||||
|
||||
public void showExitDialog() {
|
||||
Context themedContext = UiUtilities.getThemedContext(getActivity(), nightMode);
|
||||
AlertDialog.Builder dismissDialog = new AlertDialog.Builder(themedContext);
|
||||
dismissDialog.setTitle(getString(R.string.shared_string_dismiss));
|
||||
dismissDialog.setMessage(getString(R.string.exit_without_saving));
|
||||
dismissDialog.setNegativeButton(R.string.shared_string_cancel, null);
|
||||
dismissDialog.setPositiveButton(R.string.shared_string_exit, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
dismissFragment();
|
||||
}
|
||||
});
|
||||
dismissDialog.show();
|
||||
}
|
||||
|
||||
private void setupToolbar(Toolbar toolbar) {
|
||||
int color = ContextCompat.getColor(app, nightMode ? R.color.active_buttons_and_links_text_dark : R.color.active_buttons_and_links_text_light);
|
||||
toolbar.setNavigationIcon(getPaintedContentIcon(R.drawable.ic_action_close, color));
|
||||
toolbar.setNavigationContentDescription(R.string.shared_string_close);
|
||||
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
showExitDialog();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void updateAvailableSpace() {
|
||||
long calculatedSize = ExportSettingsAdapter.calculateItemsSize(adapter.getData());
|
||||
if (calculatedSize != 0) {
|
||||
selectedItemsSize.setText(AndroidUtils.formatSize(app, calculatedSize));
|
||||
|
||||
File dir = app.getAppPath("").getParentFile();
|
||||
long availableSizeBytes = AndroidUtils.getAvailableSpace(dir);
|
||||
if (calculatedSize > availableSizeBytes) {
|
||||
String availableSize = AndroidUtils.formatSize(app, availableSizeBytes);
|
||||
availableSpaceDescr.setText(getString(R.string.export_not_enough_space_descr, availableSize));
|
||||
updateWarningHeaderVisibility(true);
|
||||
continueBtn.setEnabled(false);
|
||||
} else {
|
||||
updateWarningHeaderVisibility(false);
|
||||
continueBtn.setEnabled(adapter.hasSelectedData());
|
||||
}
|
||||
itemsSizeContainer.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
updateWarningHeaderVisibility(false);
|
||||
itemsSizeContainer.setVisibility(View.INVISIBLE);
|
||||
continueBtn.setEnabled(adapter.hasSelectedData());
|
||||
}
|
||||
}
|
||||
|
||||
private void updateWarningHeaderVisibility(boolean visible) {
|
||||
if (visible) {
|
||||
if (expandableList.getHeaderViewsCount() < 2) {
|
||||
expandableList.addHeaderView(availableSpaceContainer);
|
||||
}
|
||||
AndroidUiHelper.updateVisibility(headerShadow, false);
|
||||
AndroidUiHelper.updateVisibility(headerDivider, true);
|
||||
} else {
|
||||
expandableList.removeHeaderView(availableSpaceContainer);
|
||||
AndroidUiHelper.updateVisibility(headerShadow, true);
|
||||
AndroidUiHelper.updateVisibility(headerDivider, false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCategorySelected(ExportSettingsCategory type, boolean selected) {
|
||||
updateAvailableSpace();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTypeSelected(ExportSettingsType type, boolean selected) {
|
||||
updateAvailableSpace();
|
||||
}
|
||||
|
||||
private void prepareFile() {
|
||||
if (app != null) {
|
||||
exportingStarted = true;
|
||||
exportStartTime = System.currentTimeMillis();
|
||||
showExportProgressDialog();
|
||||
File tempDir = FileUtils.getTempDir(app);
|
||||
String fileName = getFileName();
|
||||
List<SettingsItem> items = app.getSettingsHelper().prepareAdditionalSettingsItems(adapter.getData());
|
||||
progress.setMax(getMaxProgress(items));
|
||||
app.getSettingsHelper().exportSettings(tempDir, fileName, getSettingsExportListener(), items, true);
|
||||
}
|
||||
}
|
||||
|
||||
private int getMaxProgress(List<SettingsItem> items) {
|
||||
long maxProgress = 0;
|
||||
for (SettingsItem item : items) {
|
||||
if (item instanceof FileSettingsItem) {
|
||||
maxProgress += ((FileSettingsItem) item).getSize();
|
||||
}
|
||||
}
|
||||
return (int) maxProgress / (1 << 20);
|
||||
}
|
||||
|
||||
private String getFileName() {
|
||||
if (globalExport) {
|
||||
if (exportStartTime == 0) {
|
||||
exportStartTime = System.currentTimeMillis();
|
||||
}
|
||||
return "Export_" + DATE_FORMAT.format(new Date(exportStartTime));
|
||||
} else {
|
||||
return appMode.toHumanString();
|
||||
}
|
||||
}
|
||||
|
||||
private void showExportProgressDialog() {
|
||||
Context context = getContext();
|
||||
if (context == null) {
|
||||
return;
|
||||
}
|
||||
if (progress != null) {
|
||||
progress.dismiss();
|
||||
}
|
||||
progress = new ProgressDialog(context);
|
||||
progress.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
|
||||
progress.setCancelable(true);
|
||||
progress.setTitle(app.getString(R.string.shared_string_export));
|
||||
progress.setMessage(app.getString(R.string.shared_string_preparing));
|
||||
progress.setButton(DialogInterface.BUTTON_NEGATIVE, app.getString(R.string.shared_string_cancel), new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
cancelExport();
|
||||
}
|
||||
});
|
||||
progress.setOnCancelListener(new DialogInterface.OnCancelListener() {
|
||||
@Override
|
||||
public void onCancel(DialogInterface dialog) {
|
||||
cancelExport();
|
||||
}
|
||||
});
|
||||
progress.show();
|
||||
}
|
||||
|
||||
private void cancelExport() {
|
||||
app.getSettingsHelper().cancelExportForFile(getExportFile());
|
||||
progress.dismiss();
|
||||
dismissFragment();
|
||||
}
|
||||
|
||||
private SettingsExportListener getSettingsExportListener() {
|
||||
if (exportListener == null) {
|
||||
exportListener = new SettingsExportListener() {
|
||||
|
||||
@Override
|
||||
public void onSettingsExportFinished(@NonNull File file, boolean succeed) {
|
||||
dismissExportProgressDialog();
|
||||
exportingStarted = false;
|
||||
if (succeed) {
|
||||
shareProfile(file);
|
||||
} else {
|
||||
app.showToastMessage(R.string.export_profile_failed);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSettingsExportProgressUpdate(int value) {
|
||||
progress.setProgress(value);
|
||||
}
|
||||
};
|
||||
}
|
||||
return exportListener;
|
||||
}
|
||||
|
||||
private void checkExportingFile() {
|
||||
if (exportingStarted) {
|
||||
File file = getExportFile();
|
||||
boolean fileExporting = app.getSettingsHelper().isFileExporting(file);
|
||||
if (fileExporting) {
|
||||
showExportProgressDialog();
|
||||
progress.setMax(progressMax);
|
||||
progress.setProgress(progressValue);
|
||||
app.getSettingsHelper().updateExportListener(file, getSettingsExportListener());
|
||||
} else if (file.exists()) {
|
||||
dismissExportProgressDialog();
|
||||
shareProfile(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void dismissExportProgressDialog() {
|
||||
FragmentActivity activity = getActivity();
|
||||
if (progress != null && activity != null && AndroidUtils.isActivityNotDestroyed(activity)) {
|
||||
progress.dismiss();
|
||||
}
|
||||
}
|
||||
|
||||
private File getExportFile() {
|
||||
File tempDir = FileUtils.getTempDir(app);
|
||||
String fileName = getFileName();
|
||||
return new File(tempDir, fileName + IndexConstants.OSMAND_SETTINGS_FILE_EXT);
|
||||
}
|
||||
|
||||
private void shareProfile(@NonNull File file) {
|
||||
try {
|
||||
final Intent sendIntent = new Intent();
|
||||
sendIntent.setAction(Intent.ACTION_SEND);
|
||||
sendIntent.putExtra(Intent.EXTRA_SUBJECT, file.getName());
|
||||
sendIntent.putExtra(Intent.EXTRA_STREAM, AndroidUtils.getUriForFile(getMyApplication(), file));
|
||||
sendIntent.setType("*/*");
|
||||
sendIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||
startActivity(sendIntent);
|
||||
dismissFragment();
|
||||
} catch (Exception e) {
|
||||
Toast.makeText(requireContext(), R.string.export_profile_failed, Toast.LENGTH_SHORT).show();
|
||||
LOG.error("Share profile error", e);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean showInstance(@NonNull FragmentManager fragmentManager, @NonNull ApplicationMode appMode, boolean globalExport) {
|
||||
try {
|
||||
ExportSettingsFragment fragment = new ExportSettingsFragment();
|
||||
fragment.appMode = appMode;
|
||||
fragment.globalExport = globalExport;
|
||||
fragmentManager.beginTransaction().
|
||||
replace(R.id.fragmentContainer, fragment, TAG)
|
||||
.addToBackStack(EXPORT_SETTINGS_TAG)
|
||||
.commitAllowingStateLoss();
|
||||
return true;
|
||||
} catch (RuntimeException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -90,7 +90,6 @@ public class ImportSettingsFragment extends BaseOsmAndFragment {
|
|||
private OsmandApplication app;
|
||||
private ExportImportSettingsAdapter adapter;
|
||||
private ExpandableListView expandableList;
|
||||
private TextViewEx selectBtn;
|
||||
private TextView description;
|
||||
private List<SettingsItem> settingsItems;
|
||||
private File file;
|
||||
|
@ -137,7 +136,6 @@ public class ImportSettingsFragment extends BaseOsmAndFragment {
|
|||
Toolbar toolbar = root.findViewById(R.id.toolbar);
|
||||
TextViewEx continueBtn = root.findViewById(R.id.continue_button);
|
||||
toolbarLayout = root.findViewById(R.id.toolbar_layout);
|
||||
selectBtn = root.findViewById(R.id.select_button);
|
||||
expandableList = root.findViewById(R.id.list);
|
||||
buttonsContainer = root.findViewById(R.id.buttons_container);
|
||||
progressBar = root.findViewById(R.id.progress_bar);
|
||||
|
@ -157,14 +155,6 @@ public class ImportSettingsFragment extends BaseOsmAndFragment {
|
|||
}
|
||||
}
|
||||
});
|
||||
selectBtn.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
allSelected = !allSelected;
|
||||
selectBtn.setText(allSelected ? R.string.shared_string_deselect_all : R.string.shared_string_select_all);
|
||||
adapter.selectAll(allSelected);
|
||||
}
|
||||
});
|
||||
if (Build.VERSION.SDK_INT >= 21) {
|
||||
AndroidUtils.addStatusBarPadding21v(app, root);
|
||||
}
|
||||
|
|
|
@ -153,7 +153,7 @@ public class MainSettingsFragment extends BaseSettingsFragment {
|
|||
if (mapActivity != null) {
|
||||
ApplicationMode mode = getSelectedAppMode();
|
||||
FragmentManager fragmentManager = mapActivity.getSupportFragmentManager();
|
||||
ExportProfileBottomSheet.showInstance(fragmentManager, this, mode, true);
|
||||
ExportSettingsFragment.showInstance(fragmentManager, mode, true);
|
||||
}
|
||||
}
|
||||
return super.onPreferenceClick(preference);
|
||||
|
|
Loading…
Reference in a new issue