Merge branch 'master' into Fix-UI-bottomsheet
This commit is contained in:
commit
9fccd0b2ea
71 changed files with 1437 additions and 728 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"
|
||||
|
|
|
@ -436,7 +436,7 @@
|
|||
<string name="poi_pump">مضخة</string>
|
||||
<string name="poi_telescope_type">النوع</string>
|
||||
<string name="poi_animal_training_type">النوع</string>
|
||||
<string name="poi_embassy_type">النوع</string>
|
||||
<string name="poi_diplomatic_filter">النوع</string>
|
||||
<string name="poi_healthcare_alternative_types">التخصص</string>
|
||||
<string name="poi_archaeological_site_type">النوع</string>
|
||||
<string name="poi_religion_type">الدين</string>
|
||||
|
|
|
@ -1469,7 +1469,7 @@
|
|||
<string name="rendering_attr_currentTrackColor_description">لون جي بي إكس</string>
|
||||
<string name="city_type_district">منطقة</string>
|
||||
<string name="city_type_neighbourhood">حي</string>
|
||||
<string name="file_name_containes_illegal_char">يحتوي اسم الملف على حرف غير قانوني</string>
|
||||
<string name="file_name_containes_illegal_char">حرف غير قانوني في اسم الملف</string>
|
||||
<string name="reports_for">تقرير عن</string>
|
||||
<string name="world_maps">خرائط العالم</string>
|
||||
<string name="move_marker_bottom_sheet_title">حرك الخريطة لتغيير مكان التوجيه المباشر</string>
|
||||
|
@ -2454,7 +2454,7 @@
|
|||
<string name="measurement_tool_action_bar">تصفح الخريطة وإضافة نقاط</string>
|
||||
<string name="measurement_tool">قياس المسافة</string>
|
||||
<string name="none_point_error">الرجاء إضافة نقطة واحدة على الأقل.</string>
|
||||
<string name="enter_gpx_name">اسم المسار :</string>
|
||||
<string name="enter_gpx_name">اسم مسار الـGPX :</string>
|
||||
<string name="show_on_map_after_saving">عرض على الخريطة بعد الحفظ</string>
|
||||
<string name="add_waypoint">إضافة نقطة</string>
|
||||
<string name="save_gpx_waypoint">حفظ نقطة GPX</string>
|
||||
|
@ -2623,7 +2623,7 @@
|
|||
<string name="map_imported_successfully">تمت عملية استيراد الخريطة</string>
|
||||
<string name="make_as_start_point">وضعها نقطة البداية</string>
|
||||
<string name="show_closed_notes">إظهار الملاحظات المغلقة</string>
|
||||
<string name="switch_osm_notes_visibility_desc">عرض ملاحظات OSM على الخريطة.</string>
|
||||
<string name="switch_osm_notes_visibility_desc">عرض أو اخفاء ملاحظات OSM على الخريطة.</string>
|
||||
<string name="shared_string_gpx_file">ملف GPX</string>
|
||||
<string name="osc_file">ملف OSC</string>
|
||||
<string name="choose_file_type">قم باختيار نسق الملف</string>
|
||||
|
@ -3087,7 +3087,7 @@
|
|||
<string name="swap_two_places">تبديل %1$s و %2$s</string>
|
||||
<string name="route_start_point">نقطة البداية</string>
|
||||
<string name="track_saved">تم حفظ المسار</string>
|
||||
<string name="empty_filename">اسم الملف فارغ</string>
|
||||
<string name="empty_filename">اسم ملف فارغ</string>
|
||||
<string name="shared_string_revert">استرجاع</string>
|
||||
<string name="clear_confirmation_msg">مسح %1$s\?</string>
|
||||
<string name="turn_on_profile_desc">يرجى تشغيل وضع واحد على الأقل لاستخدام هذا الإعداد.</string>
|
||||
|
@ -3322,9 +3322,9 @@
|
|||
<string name="application_profiles_descr">حدد الأوضاع لتكون مرئية في التطبيق.</string>
|
||||
<string name="application_profiles">أوضاع التطبيق</string>
|
||||
<string name="quick_action_need_to_add_item_to_list">أضف عنصراً واحداً على الأقل إلى القائمة في إعدادات \"الاختصار السريع\"</string>
|
||||
<string name="routing_attr_piste_type_downhill_name">جبال الألب/التزلج علي المنحدرات</string>
|
||||
<string name="routing_attr_piste_type_downhill_name">جبال الألب والتزلج علي المنحدرات</string>
|
||||
<string name="routing_attr_piste_type_downhill_description">التزلج على جبال الألب أو الانحدار.</string>
|
||||
<string name="routing_attr_piste_type_nordic_name">التزلج عبر البلاد / الشمال</string>
|
||||
<string name="routing_attr_piste_type_nordic_name">التزلج عبر الريف والشمال</string>
|
||||
<string name="routing_attr_piste_type_nordic_description">مسارات للتزلج الشمالي أو الريفي علي الثلج.</string>
|
||||
<string name="routing_attr_piste_type_skitour_name">جولة تزلج</string>
|
||||
<string name="routing_attr_piste_type_skitour_description">طرق لجولات التزلج.</string>
|
||||
|
@ -3558,7 +3558,7 @@
|
|||
<string name="quick_action_terrain_descr">زر لإظهار طبقة التضاريس أو إخفائها على الخريطة.</string>
|
||||
<string name="quick_action_terrain_show">إظهار التضاريس</string>
|
||||
<string name="quick_action_terrain_hide">إخفاء التضاريس</string>
|
||||
<string name="quick_action_show_hide_terrain">إظهار/إخفاء التضاريس</string>
|
||||
<string name="quick_action_show_hide_terrain">إظهارأو إخفاء التضاريس</string>
|
||||
<string name="download_slope_maps">المنحدرات</string>
|
||||
<string name="shared_string_hillshade">التضاريس</string>
|
||||
<string name="terrain_empty_state_text">تمكين لعرض المنحدرات أو خريطة التضاريس. يمكنك قراءة المزيد عن أنواع الخرائط هذه على موقعنا.</string>
|
||||
|
@ -3681,11 +3681,11 @@
|
|||
<string name="additional_actions_descr">يمكنك الوصول إلى هذه الإجراءات عن طريق النقر على زر \"%1$s\".</string>
|
||||
<string name="quick_action_transport_hide">إخفاء وسائل النقل العام</string>
|
||||
<string name="quick_action_transport_show">إظهار وسائل النقل العام</string>
|
||||
<string name="quick_action_show_hide_transport">إظهار/إخفاء وسائل النقل العام</string>
|
||||
<string name="quick_action_show_hide_transport">إظهارأو إخفاء وسائل النقل العام</string>
|
||||
<string name="quick_action_transport_descr">زر لإظهار أو إخفاء وسائل النقل العام على الخريطة.</string>
|
||||
<string name="create_edit_poi">إنشاء /تحرير موضع مكان</string>
|
||||
<string name="create_edit_poi">إنشاء أو تعديل نقطة الأهتمام POI</string>
|
||||
<string name="parking_positions">مكان الموقف</string>
|
||||
<string name="add_edit_favorite">إضافة / تحرير المفضلة</string>
|
||||
<string name="add_edit_favorite">إضافة أو تعديل المفضلة</string>
|
||||
<string name="reset_deafult_order">استعادة ترتيب العناصر الافتراضية</string>
|
||||
<string name="back_to_editing">عودة إلى التحرير</string>
|
||||
<string name="quick_action_switch_profile_descr">سيتم تبديل زر الإجراء التسجيل بين التشكيلات الجانبية المحددة.</string>
|
||||
|
@ -3856,7 +3856,7 @@
|
|||
<string name="plan_route_change_route_type_after">تغيير نوع المسار بعد</string>
|
||||
<string name="number_of_gpx_files_selected_pattern">%s ملفات مسارات محددة</string>
|
||||
<string name="disable_recording_once_app_killed_descrp">سيتم إيقاف تسجيل المسار مؤقتًا عند غلق التطبيق (عبر نافذة التطبيقات المستخدمة مؤخرا). (إشارة تشغيل التطبيق في الخلفية ستختفي من الشريط العلوي.)</string>
|
||||
<string name="save_global_track_interval_descr">حدد الفاصل الزمني للادخال الخاص بالتسجيل العام للمسار (مفعل من خلال ودجت تسجيل الرحلة على الخريطة).</string>
|
||||
<string name="save_global_track_interval_descr">حدد الفاصل الزمني للادخال الخاص بالتسجيل العام للمسار (مفعل من خلال ودجت \"تسجيل الرحلة\" على الخريطة).</string>
|
||||
<string name="gpx_monitoring_stop">إيقاف تسجيل الرحلة مؤقتًا</string>
|
||||
<string name="gpx_monitoring_start">استئناف تسجيل الرحلة</string>
|
||||
<string name="system_default_theme">النظام الافتراضي</string>
|
||||
|
@ -3891,7 +3891,7 @@
|
|||
<string name="sort_last_modified">آخر تعديل</string>
|
||||
<string name="sort_name_descending">الاسم: أ – ي</string>
|
||||
<string name="sort_name_ascending">الاسم: أ – ي</string>
|
||||
<string name="start_finish_icons">رموز البدء/الانتهاء</string>
|
||||
<string name="start_finish_icons">أيقونات البدء والانتهاء</string>
|
||||
<string name="contour_lines_thanks">شكرا لشرائك \"خطوط الكنتور\"</string>
|
||||
<string name="osm_live_payment_desc_hw">رسوم الاشتراك ستفرض كل شهر. يمكنك إلغاء اشتراكك متى أردت عبر Google play.</string>
|
||||
<string name="osm_live_payment_subscription_management_hw">سيتم تحصيل المبلغ على حساب AppGallery الخاص بك عند تأكيد الشراء.
|
||||
|
@ -3948,7 +3948,7 @@
|
|||
<string name="use_login_password">استخدام تسجيل الدخول وكلمة المرور</string>
|
||||
<string name="login_account">الحساب</string>
|
||||
<string name="user_login">تسجيل الدخول</string>
|
||||
<string name="gpx_upload_trackable_visibility_descr">إمكانية التتبع تعني أن التتبع لن يظهر في أي قوائم عامة ولكن ستظل نقاط التتبع الصادرة عنه متاحة من خلال واجهة برمجة تطبيقات GPS API العامة مع طوابع زمنية. سيتمكن المستخدمون الآخرون فقط من تنزيل نقاط التتبع المعالجة من التتبع الخاص بك والتي لا يمكن ربطها بك مباشرةً.</string>
|
||||
<string name="gpx_upload_trackable_visibility_descr">\"إمكانية التتبع\" تعني أن التتبع لا يظهر في أي قوائم عامة ولكن نقاط التتبع المعالجة مع طوابع زمنية صادرة عنها(التي لا يمكن أن تكون مرتبطة بك مباشرة) ستظهر خلال التنزيلات من واجهة برمجة التطبيقات GPS API العامة.</string>
|
||||
<string name="markers_history">سجل تاريخ العلامات</string>
|
||||
<string name="send_files_to_openstreetmap">أرسل ملف GPX إلى OpenStreetMap</string>
|
||||
<string name="enter_text_separated">أدخل العلامات مفصولة بفاصلة.</string>
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
<string name="poi_observatory_designation">Categoría</string>
|
||||
<string name="poi_telescope_type">Tipu</string>
|
||||
<string name="poi_animal_training_type">Tipu</string>
|
||||
<string name="poi_embassy_type">Tipu</string>
|
||||
<string name="poi_diplomatic_filter">Tipu</string>
|
||||
<string name="poi_city_capital">Capital</string>
|
||||
<string name="poi_pharmacy_dispensing">Dispensa recetes</string>
|
||||
<string name="poi_healthcare_alternative_types">Especialidá</string>
|
||||
|
|
|
@ -39,7 +39,7 @@
|
|||
<string name="poi_pump">Nasos</string>
|
||||
<string name="poi_telescope_type">Növ</string>
|
||||
<string name="poi_animal_training_type">Növ</string>
|
||||
<string name="poi_embassy_type">Növ</string>
|
||||
<string name="poi_diplomatic_filter">Növ</string>
|
||||
<string name="poi_city_capital">Paytaxt</string>
|
||||
<string name="poi_archaeological_site_type">Növ</string>
|
||||
<string name="poi_religion_type">Din</string>
|
||||
|
|
|
@ -415,7 +415,7 @@
|
|||
<string name="poi_bicycle_parking_type">typ</string>
|
||||
<string name="poi_telescope_type">typ</string>
|
||||
<string name="poi_animal_training_type">typ</string>
|
||||
<string name="poi_embassy_type">typ</string>
|
||||
<string name="poi_diplomatic_filter">typ</string>
|
||||
<string name="poi_archaeological_site_type">typ</string>
|
||||
<string name="poi_information_type">typ</string>
|
||||
<string name="poi_resort_type">typ</string>
|
||||
|
|
|
@ -509,7 +509,7 @@
|
|||
<string name="poi_information_type">Anaw</string>
|
||||
<string name="poi_wheelchair_yes">Ih</string>
|
||||
<string name="poi_archaeological_site_type">Anaw</string>
|
||||
<string name="poi_embassy_type">Anaw</string>
|
||||
<string name="poi_diplomatic_filter">Anaw</string>
|
||||
<string name="poi_animal_training_type">Anaw</string>
|
||||
<string name="poi_telescope_type">Anaw</string>
|
||||
<string name="poi_observatory_designation">Isem</string>
|
||||
|
|
|
@ -2790,7 +2790,7 @@
|
|||
<string name="poi_observatory_designation">Прызначэнне</string>
|
||||
<string name="poi_telescope_type">Тып</string>
|
||||
<string name="poi_animal_training_type">Тып</string>
|
||||
<string name="poi_embassy_type">Тып</string>
|
||||
<string name="poi_diplomatic_filter">Тып</string>
|
||||
<string name="poi_city_capital">Сталіца</string>
|
||||
<string name="poi_pharmacy_dispensing">Продаж лекаў па рэцэптам</string>
|
||||
<string name="poi_healthcare_alternative_types">Спецыялізацыя</string>
|
||||
|
|
|
@ -80,7 +80,7 @@
|
|||
<string name="poi_city_capital">রাজধানী</string>
|
||||
<string name="poi_service_general">পরিসেবা</string>
|
||||
<string name="poi_cash_withdrawal_bank_card">নগদ উত্তোলন</string>
|
||||
<string name="poi_embassy_type">ধরণ</string>
|
||||
<string name="poi_diplomatic_filter">ধরণ</string>
|
||||
<string name="poi_animal_training_type">ধরণ</string>
|
||||
<string name="poi_telescope_type">ধরণ</string>
|
||||
<string name="poi_vending_type">ভেন্ডিং টাইপ</string>
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
<string name="poi_observatory_designation">Anv</string>
|
||||
<string name="poi_telescope_type">Seurt</string>
|
||||
<string name="poi_animal_training_type">Seurt</string>
|
||||
<string name="poi_embassy_type">Seurt</string>
|
||||
<string name="poi_diplomatic_filter">Seurt</string>
|
||||
<string name="poi_city_capital">Kêrbenn</string>
|
||||
<string name="poi_pharmacy_dispensing">Ordrenañs</string>
|
||||
<string name="poi_healthcare_alternative_types">Arbennigiezh</string>
|
||||
|
|
|
@ -2118,7 +2118,7 @@
|
|||
<string name="poi_aerialway_heating">Calefacció</string>
|
||||
<string name="poi_telescope_type">Tipus</string>
|
||||
<string name="poi_animal_training_type">Tipus</string>
|
||||
<string name="poi_embassy_type">Tipus</string>
|
||||
<string name="poi_diplomatic_filter">Tipus</string>
|
||||
<string name="poi_city_capital">Capital</string>
|
||||
<string name="poi_healthcare_alternative_types">Especialitat</string>
|
||||
<string name="poi_free_flying_characteristics">Característica</string>
|
||||
|
|
|
@ -2692,7 +2692,7 @@
|
|||
<string name="poi_bicycle_parking_type">Typ</string>
|
||||
<string name="poi_telescope_type">Typ</string>
|
||||
<string name="poi_animal_training_type">Typ</string>
|
||||
<string name="poi_embassy_type">Typ</string>
|
||||
<string name="poi_diplomatic_filter">Typ</string>
|
||||
<string name="poi_archaeological_site_type">Typ</string>
|
||||
<string name="poi_information_type">Typ</string>
|
||||
<string name="poi_resort_type">Typ</string>
|
||||
|
|
|
@ -2805,7 +2805,7 @@
|
|||
<string name="poi_observatory_designation">Betegnelse</string>
|
||||
<string name="poi_telescope_type">Type</string>
|
||||
<string name="poi_animal_training_type">Type</string>
|
||||
<string name="poi_embassy_type">Type</string>
|
||||
<string name="poi_diplomatic_filter">Type</string>
|
||||
<string name="poi_city_capital">Hovedstad</string>
|
||||
<string name="poi_pharmacy_dispensing">Udlevering</string>
|
||||
<string name="poi_healthcare_alternative_types">Speciale</string>
|
||||
|
|
|
@ -2795,7 +2795,7 @@
|
|||
<string name="poi_observatory_designation">Bezeichnung</string>
|
||||
<string name="poi_telescope_type">Art</string>
|
||||
<string name="poi_animal_training_type">Art</string>
|
||||
<string name="poi_embassy_type">Art</string>
|
||||
<string name="poi_diplomatic_filter">Art</string>
|
||||
<string name="poi_city_capital">Hauptstadt</string>
|
||||
<string name="poi_traffic_signals_sound">Signalton</string>
|
||||
<string name="poi_subway_station_filter">U-Bahnstation</string>
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
<string name="poi_observatory_designation">Περιγραφή</string>
|
||||
<string name="poi_telescope_type">Τύπος</string>
|
||||
<string name="poi_animal_training_type">Τύπος</string>
|
||||
<string name="poi_embassy_type">Τύπος</string>
|
||||
<string name="poi_diplomatic_filter">Τύπος</string>
|
||||
<string name="poi_city_capital">Πρωτεύουσα</string>
|
||||
<string name="poi_pharmacy_dispensing">Διανομή</string>
|
||||
<string name="poi_healthcare_alternative_types">Ειδικότητα</string>
|
||||
|
|
|
@ -2786,7 +2786,7 @@
|
|||
<string name="poi_observatory_designation">Apliko</string>
|
||||
<string name="poi_telescope_type">Speco de teleskopo</string>
|
||||
<string name="poi_animal_training_type">Dresado de</string>
|
||||
<string name="poi_embassy_type">Speco de diplomata oficejo</string>
|
||||
<string name="poi_diplomatic_filter">Speco de diplomata oficejo</string>
|
||||
<string name="poi_city_capital">Ĉefurbo</string>
|
||||
<string name="poi_pharmacy_dispensing">Medikamentoj je preskribo</string>
|
||||
<string name="poi_healthcare_alternative_types">Kontraŭmedicino</string>
|
||||
|
|
|
@ -2804,7 +2804,7 @@
|
|||
<string name="poi_observatory_designation">Designación</string>
|
||||
<string name="poi_telescope_type">Tipo de telescopio</string>
|
||||
<string name="poi_animal_training_type">Tipo de amaestramiento</string>
|
||||
<string name="poi_embassy_type">Tipo de embajada</string>
|
||||
<string name="poi_diplomatic_filter">Tipo de embajada</string>
|
||||
<string name="poi_city_capital">Ciudad capital</string>
|
||||
<string name="poi_pharmacy_dispensing">Receta médica</string>
|
||||
<string name="poi_healthcare_alternative_types">Especialidad</string>
|
||||
|
|
|
@ -2805,7 +2805,7 @@
|
|||
<string name="poi_observatory_designation">Designación</string>
|
||||
<string name="poi_telescope_type">Tipo de telescopio</string>
|
||||
<string name="poi_animal_training_type">Tipo de amaestramiento</string>
|
||||
<string name="poi_embassy_type">Tipo de embajada</string>
|
||||
<string name="poi_diplomatic_filter">Tipo de embajada</string>
|
||||
<string name="poi_city_capital">Ciudad capital</string>
|
||||
<string name="poi_pharmacy_dispensing">Receta médica</string>
|
||||
<string name="poi_healthcare_alternative_types">Especialidad</string>
|
||||
|
|
|
@ -2794,7 +2794,7 @@
|
|||
<string name="poi_observatory_designation">Designación</string>
|
||||
<string name="poi_telescope_type">Tipo</string>
|
||||
<string name="poi_animal_training_type">Tipo</string>
|
||||
<string name="poi_embassy_type">Tipo</string>
|
||||
<string name="poi_diplomatic_filter">Tipo</string>
|
||||
<string name="poi_city_capital">Capital</string>
|
||||
<string name="poi_healthcare_alternative_types">Especialidad</string>
|
||||
<string name="poi_free_flying_characteristics">Característica</string>
|
||||
|
|
|
@ -212,7 +212,7 @@
|
|||
<string name="poi_observatory_designation">Määramine</string>
|
||||
<string name="poi_telescope_type">Liik</string>
|
||||
<string name="poi_animal_training_type">Liik</string>
|
||||
<string name="poi_embassy_type">Liik</string>
|
||||
<string name="poi_diplomatic_filter">Liik</string>
|
||||
<string name="poi_city_capital">Pealinn</string>
|
||||
<string name="poi_pharmacy_dispensing">Väljastamine</string>
|
||||
<string name="poi_healthcare_alternative_types">Eriala</string>
|
||||
|
|
|
@ -1208,7 +1208,7 @@
|
|||
<string name="poi_observatory_designation">Izendapena</string>
|
||||
<string name="poi_telescope_type">Mota</string>
|
||||
<string name="poi_animal_training_type">Mota</string>
|
||||
<string name="poi_embassy_type">Mota</string>
|
||||
<string name="poi_diplomatic_filter">Mota</string>
|
||||
<string name="poi_city_capital">Hiriburua</string>
|
||||
<string name="poi_pharmacy_dispensing">Farmazia</string>
|
||||
<string name="poi_healthcare_alternative_types">Espezialitatea</string>
|
||||
|
|
|
@ -646,7 +646,7 @@
|
|||
<string name="poi_ferry_terminal_cargo">ترمینال باربری</string>
|
||||
<string name="poi_telescope_type">نوع تلسکوپ</string>
|
||||
<string name="poi_animal_training_type">نوع</string>
|
||||
<string name="poi_embassy_type">نوع سفارت</string>
|
||||
<string name="poi_diplomatic_filter">نوع سفارت</string>
|
||||
<string name="poi_city_capital">پایتخت</string>
|
||||
<string name="poi_healthcare_alternative_types">تخصص</string>
|
||||
<string name="poi_free_flying_characteristics">مشخصات</string>
|
||||
|
|
|
@ -60,7 +60,7 @@
|
|||
<string name="poi_pump">Pumppu</string>
|
||||
<string name="poi_telescope_type">Tyyppi</string>
|
||||
<string name="poi_animal_training_type">Tyyppi</string>
|
||||
<string name="poi_embassy_type">Tyyppi</string>
|
||||
<string name="poi_diplomatic_filter">Tyyppi</string>
|
||||
<string name="poi_city_capital">Pääkaupunki</string>
|
||||
<string name="poi_healthcare_alternative_types">Erikoisuus</string>
|
||||
<string name="poi_free_flying_characteristics">Ominainen</string>
|
||||
|
|
|
@ -1975,7 +1975,7 @@
|
|||
<string name="poi_ferry_terminal_cargo">Cargo</string>
|
||||
<string name="poi_telescope_type">Type</string>
|
||||
<string name="poi_animal_training_type">Type</string>
|
||||
<string name="poi_embassy_type">Type</string>
|
||||
<string name="poi_diplomatic_filter">Type</string>
|
||||
<string name="poi_city_capital">Capitale</string>
|
||||
<string name="poi_healthcare_alternative_types">Spécialité</string>
|
||||
<string name="poi_free_flying_characteristics">Caractéristiques</string>
|
||||
|
|
|
@ -1029,7 +1029,7 @@
|
|||
<string name="poi_observatory_designation">Designación</string>
|
||||
<string name="poi_telescope_type">Tipo</string>
|
||||
<string name="poi_animal_training_type">Tipo</string>
|
||||
<string name="poi_embassy_type">Tipo</string>
|
||||
<string name="poi_diplomatic_filter">Tipo</string>
|
||||
<string name="poi_city_capital">Capital</string>
|
||||
<string name="poi_healthcare_alternative_types">Especialidade</string>
|
||||
<string name="poi_free_flying_characteristics">Característica</string>
|
||||
|
|
|
@ -1849,7 +1849,7 @@
|
|||
<string name="poi_pump">Szivattyú</string>
|
||||
<string name="poi_telescope_type">Típus</string>
|
||||
<string name="poi_animal_training_type">Típus</string>
|
||||
<string name="poi_embassy_type">Típus</string>
|
||||
<string name="poi_diplomatic_filter">Típus</string>
|
||||
<string name="poi_city_capital">Főváros</string>
|
||||
<string name="poi_healthcare_alternative_types">Szakosodás</string>
|
||||
<string name="poi_free_flying_characteristics">Jellemző</string>
|
||||
|
|
|
@ -183,7 +183,7 @@
|
|||
<string name="poi_observatory_designation">Tilgangur</string>
|
||||
<string name="poi_telescope_type">Tegund</string>
|
||||
<string name="poi_animal_training_type">Tegund</string>
|
||||
<string name="poi_embassy_type">Tegund</string>
|
||||
<string name="poi_diplomatic_filter">Tegund</string>
|
||||
<string name="poi_archaeological_site_type">Tegund</string>
|
||||
<string name="poi_star_rating">Stjörnugjöf</string>
|
||||
<string name="poi_religion_type">Trúarbrögð</string>
|
||||
|
|
|
@ -729,7 +729,7 @@
|
|||
<string name="poi_observatory_designation">Designazione</string>
|
||||
<string name="poi_telescope_type">Tipo</string>
|
||||
<string name="poi_animal_training_type">Tipo</string>
|
||||
<string name="poi_embassy_type">Tipo</string>
|
||||
<string name="poi_diplomatic_filter">Tipo</string>
|
||||
<string name="poi_city_capital">Capitale</string>
|
||||
<string name="poi_pharmacy_dispensing">Ricette</string>
|
||||
<string name="poi_healthcare_alternative_types">Specialità</string>
|
||||
|
|
|
@ -166,7 +166,7 @@
|
|||
<string name="poi_bicycle_parking_type">סוג</string>
|
||||
<string name="poi_telescope_type">סוג</string>
|
||||
<string name="poi_animal_training_type">סוג</string>
|
||||
<string name="poi_embassy_type">סוג</string>
|
||||
<string name="poi_diplomatic_filter">סוג</string>
|
||||
<string name="poi_city_capital">בירה</string>
|
||||
<string name="poi_healthcare_alternative_types">מומחיות</string>
|
||||
<string name="poi_free_flying_characteristics">מאפיינים</string>
|
||||
|
|
|
@ -1989,7 +1989,7 @@
|
|||
<string name="poi_telescope">望遠鏡</string>
|
||||
<string name="poi_observatory_designation">観測ドーム</string>
|
||||
<string name="poi_animal_training_type">動物訓練施設の種類</string>
|
||||
<string name="poi_embassy_type">外交関連施設(領事館、大使住居等)の種類</string>
|
||||
<string name="poi_diplomatic_filter">外交関連施設(領事館、大使住居等)の種類</string>
|
||||
<string name="poi_service_parts">部品</string>
|
||||
<string name="poi_service_dealer">販売</string>
|
||||
<string name="poi_service_repair">修理</string>
|
||||
|
|
|
@ -133,7 +133,7 @@
|
|||
<string name="poi_pump">Siurblys</string>
|
||||
<string name="poi_telescope_type">Tipas</string>
|
||||
<string name="poi_animal_training_type">Tipas</string>
|
||||
<string name="poi_embassy_type">Tipas</string>
|
||||
<string name="poi_diplomatic_filter">Tipas</string>
|
||||
<string name="poi_city_capital">Sostinė</string>
|
||||
<string name="poi_healthcare_alternative_types">Specializacija</string>
|
||||
<string name="poi_archaeological_site_type">Tipas</string>
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
<string name="poi_observatory_designation">Nozīmēšana</string>
|
||||
<string name="poi_telescope_type">Veids</string>
|
||||
<string name="poi_animal_training_type">Veids</string>
|
||||
<string name="poi_embassy_type">Veids</string>
|
||||
<string name="poi_diplomatic_filter">Veids</string>
|
||||
<string name="poi_city_capital">Galvaspilsēta</string>
|
||||
<string name="poi_pharmacy_dispensing">Zāles pret receptēm</string>
|
||||
<string name="poi_healthcare_alternative_types">Specializācija</string>
|
||||
|
|
|
@ -875,7 +875,7 @@
|
|||
<string name="poi_observatory_designation">പദവി</string>
|
||||
<string name="poi_telescope_type">തരം</string>
|
||||
<string name="poi_animal_training_type">തരം</string>
|
||||
<string name="poi_embassy_type">തരം</string>
|
||||
<string name="poi_diplomatic_filter">തരം</string>
|
||||
<string name="poi_city_capital">തലസ്ഥാനം</string>
|
||||
<string name="poi_pharmacy_dispensing">വിതരണം</string>
|
||||
<string name="poi_healthcare_alternative_types">സ്പെഷ്യാലിറ്റി</string>
|
||||
|
|
|
@ -630,7 +630,7 @@
|
|||
<string name="poi_pump">Pumpe</string>
|
||||
<string name="poi_telescope_type">Type</string>
|
||||
<string name="poi_animal_training_type">Type</string>
|
||||
<string name="poi_embassy_type">Type</string>
|
||||
<string name="poi_diplomatic_filter">Type</string>
|
||||
<string name="poi_healthcare_alternative_types">Spesialitet</string>
|
||||
<string name="poi_free_flying_characteristics">Kjennetegn</string>
|
||||
<string name="poi_archaeological_site_type">Type</string>
|
||||
|
|
|
@ -1692,8 +1692,8 @@
|
|||
\n
|
||||
\n OsmAnd utvikles aktivt, og prosjektet vårt og dets videre framdrift avhenger av finansielle bidrag for å drive utviklingen og testingen av nye funksjoner. Overvei å kjøpe OsmAnd+ eller støtte spesifikke nye funksjoner eller bidra med en generell donasjon på https://osmand.net.</string>
|
||||
<string name="upload_osm_note_description">Last opp ditt OSM-notat anonymt eller ved å bruke din profil hos OpenStreetMap.org.</string>
|
||||
<string name="gpx_no_tracks_title">Du har ingen GPX-filer enda</string>
|
||||
<string name="gpx_no_tracks_title_folder">Du kan også legge til GPX-filer i mappen</string>
|
||||
<string name="gpx_no_tracks_title">Du har ingen sporfiler ennå</string>
|
||||
<string name="gpx_no_tracks_title_folder">Du kan også legge til sporfiler i mappen</string>
|
||||
<string name="gpx_add_track">Legg til flere…</string>
|
||||
<string name="trip_rec_notification_settings">Skru på hurtigopptak</string>
|
||||
<string name="trip_rec_notification_settings_desc">Vis et systemvarsel som kan starte turopptak.</string>
|
||||
|
@ -1792,7 +1792,7 @@
|
|||
<string name="live_monitoring_start">Start nettbasert sporing</string>
|
||||
<string name="live_monitoring_stop">Stopp nettbasert sporing</string>
|
||||
<string name="select_index_file_to_download">Fant ikke noe. Hvis du ikke finner din region, kan du lage den selv (se https://osmand.net).</string>
|
||||
<string name="none_selected_gpx">Ingen GPX-filer valgt. Velg en ved lang-trykking.</string>
|
||||
<string name="none_selected_gpx">Spesifiser først en GPX-fil med et langt trykk.</string>
|
||||
<string name="gpx_split_interval">Oppdelingsintervall</string>
|
||||
<string name="gpx_info_asc_altitude">Nedstigning/stigning: %1$s</string>
|
||||
<string name="gpx_timespan">Tidsrom: %1$s</string>
|
||||
|
@ -2020,7 +2020,7 @@
|
|||
<string name="routing_attr_relief_smoothness_factor_more_plains_name">Flatt</string>
|
||||
<string name="relief_smoothness_factor_descr">Foretrukket terreng: flatt eller kupert.</string>
|
||||
<string name="add_new_folder">Legg til ny mappe</string>
|
||||
<string name="shared_string_gpx_track">GPX-spor</string>
|
||||
<string name="shared_string_gpx_track">Spor</string>
|
||||
<string name="routing_attr_height_obstacles_name">Bruk høydedata</string>
|
||||
<string name="routing_attr_height_obstacles_description">Ta hensyn til terrenghøyde (data fra SRTM, ASTER og EU-DEM).</string>
|
||||
<string name="quick_action_bug_message">Melding</string>
|
||||
|
@ -2708,7 +2708,7 @@
|
|||
<string name="plugin_ski_descr">Dette programtillegget for OsmAnd gir deg detaljer om skibakker, langrennsløyper, alpine skiruter, taubaner og skiheiser. Ruter og løyper blir fargekodet etter vanskelighetsgrad, og vises i en spesiell \'Vinterkartstil\' som ligner et snødekt landskap.
|
||||
\n
|
||||
\nAktivering av denne visningen endrer kartstilen til \'Vinter og ski\', med alle kjennemerker for et landskap under vinterlige forhold. Denne visningen kan tilbakestilles enten ved å deaktivere tillegget igjen her, eller endre \'Kartstil\' under \'Kartinnstilling\'.</string>
|
||||
<string name="osmand_distance_planning_plugin_description">Dette programtillegget tilbyr et miniprogram på kartet der du kan opprette stier ved å trykke på kartet, eller ved å endre eksisterende GPX-filer, for å planlegge en tur og måle avstanden mellom punkter. Resultatet kan lagres som en GPX-fil, som senere kan brukes for veiledning.</string>
|
||||
<string name="osmand_distance_planning_plugin_description">Opprett stier ved å trykke på kartet, eller ved å bruke eller endre eksisterende GPX-filer, for å planlegge en tur og måle avstanden mellom punkter. Resultatet kan lagres som en GPX-fil, som senere kan brukes for veiledning.</string>
|
||||
<string name="osm_editing_plugin_description">Via dette programtillegget kan OsmAnd brukes til å sende inn OSM-bidrag, som opprettelse eller endring av OSM-POI-objekter, åpning eller kommentering av OSM-notater, og bidrag til GPX-spor. OSM er et verdensomspennende kartprosjekt i offentlig eiendom. For detaljer, se https://openstreetmap.org. Aktiv deltagelse verdsettes, og bidrag kan gjøres direkte fra OsmAnd, hvis du angir din personlige OSM-innloggingsinfo i programmet.</string>
|
||||
<string name="osmand_extended_description_part3">Kart
|
||||
\n • Viser interessepunkter rundt deg
|
||||
|
@ -3916,4 +3916,7 @@
|
|||
<string name="open_street_map_login_mode">Du må logge inn for å laste opp nye ting eller endringer.
|
||||
\n
|
||||
\nDu kan logge inn med den sikre OAuth-metoden eller benytte ditt brukernavn og passord.</string>
|
||||
<string name="shared_string_search_history">Søkehistorikk</string>
|
||||
<string name="app_mode_kayak">Kajakk</string>
|
||||
<string name="app_mode_motorboat">Motorbåt</string>
|
||||
</resources>
|
|
@ -1418,7 +1418,7 @@
|
|||
<string name="poi_observatory_designation">Aanduiding</string>
|
||||
<string name="poi_telescope_type">Type</string>
|
||||
<string name="poi_animal_training_type">Type</string>
|
||||
<string name="poi_embassy_type">Type</string>
|
||||
<string name="poi_diplomatic_filter">Type</string>
|
||||
<string name="poi_city_capital">Hoofdstad</string>
|
||||
<string name="poi_pharmacy_dispensing">Apotheek</string>
|
||||
<string name="poi_healthcare_alternative_types">Gespecialiseerd</string>
|
||||
|
|
|
@ -64,7 +64,7 @@
|
|||
<string name="poi_beauty_salon_service">Servici</string>
|
||||
<string name="poi_aerialway_heating">Caufatge</string>
|
||||
<string name="poi_animal_training_type">Tipe</string>
|
||||
<string name="poi_embassy_type">Tipe</string>
|
||||
<string name="poi_diplomatic_filter">Tipe</string>
|
||||
<string name="poi_archaeological_site_type">Tipe</string>
|
||||
<string name="poi_star_rating">Valor en estèlas</string>
|
||||
<string name="poi_information_type">Tipe</string>
|
||||
|
|
|
@ -2795,7 +2795,7 @@
|
|||
<string name="poi_observatory_designation">Zastosowanie</string>
|
||||
<string name="poi_telescope_type">Rodzaj</string>
|
||||
<string name="poi_animal_training_type">Tresura</string>
|
||||
<string name="poi_embassy_type">Rodzaj</string>
|
||||
<string name="poi_diplomatic_filter">Rodzaj</string>
|
||||
<string name="poi_city_capital">Stolica</string>
|
||||
<string name="poi_pharmacy_dispensing">Recepty</string>
|
||||
<string name="poi_healthcare_alternative_types">Specjalizacja</string>
|
||||
|
|
|
@ -2476,7 +2476,7 @@
|
|||
<string name="poi_observatory_designation">Designação</string>
|
||||
<string name="poi_telescope_type">Tipo</string>
|
||||
<string name="poi_animal_training_type">Tipo</string>
|
||||
<string name="poi_embassy_type">Tipo</string>
|
||||
<string name="poi_diplomatic_filter">Tipo</string>
|
||||
<string name="poi_city_capital">Capital</string>
|
||||
<string name="poi_pharmacy_dispensing">Dispensa</string>
|
||||
<string name="poi_healthcare_alternative_types">Especialidade</string>
|
||||
|
|
|
@ -269,7 +269,7 @@
|
|||
<string name="poi_observatory_designation">Designação</string>
|
||||
<string name="poi_telescope_type">Tipo</string>
|
||||
<string name="poi_animal_training_type">Tipo</string>
|
||||
<string name="poi_embassy_type">Tipo</string>
|
||||
<string name="poi_diplomatic_filter">Tipo</string>
|
||||
<string name="poi_healthcare_alternative_types">Especialidade</string>
|
||||
<string name="poi_free_flying_characteristics">Característica</string>
|
||||
<string name="poi_archaeological_site_type">Tipo</string>
|
||||
|
|
|
@ -2793,7 +2793,7 @@
|
|||
<string name="poi_organic_no">Отсутствуют</string>
|
||||
<string name="poi_organic_only">Исключительно</string>
|
||||
<string name="poi_traffic_mirror">Дорожное зеркало</string>
|
||||
<string name="poi_embassy_type">Вид</string>
|
||||
<string name="poi_diplomatic_filter">Вид</string>
|
||||
<string name="poi_diplomatic_consulate">Консульство</string>
|
||||
<string name="poi_diplomatic_consulate_general">Генеральное консульство</string>
|
||||
<string name="poi_diplomatic_honorary_consulate">Почётное консульство</string>
|
||||
|
|
|
@ -1782,7 +1782,7 @@
|
|||
<string name="poi_pump">Pompa</string>
|
||||
<string name="poi_telescope_type">Casta</string>
|
||||
<string name="poi_animal_training_type">Casta</string>
|
||||
<string name="poi_embassy_type">Casta</string>
|
||||
<string name="poi_diplomatic_filter">Casta</string>
|
||||
<string name="poi_city_capital">Capitale</string>
|
||||
<string name="poi_healthcare_alternative_types">Ispetzialidade</string>
|
||||
<string name="poi_free_flying_characteristics">Caraterìstica</string>
|
||||
|
|
|
@ -1933,7 +1933,7 @@
|
|||
<string name="poi_pump">Pumpa</string>
|
||||
<string name="poi_telescope_type">Typ</string>
|
||||
<string name="poi_animal_training_type">Typ</string>
|
||||
<string name="poi_embassy_type">Typ</string>
|
||||
<string name="poi_diplomatic_filter">Typ</string>
|
||||
<string name="poi_city_capital">Hlavné mesto</string>
|
||||
<string name="poi_pharmacy_dispensing">Výdaj na predpis</string>
|
||||
<string name="poi_healthcare_alternative_types">Špecializácia</string>
|
||||
|
|
|
@ -422,7 +422,7 @@
|
|||
<string name="poi_pump">Črpalka</string>
|
||||
<string name="poi_telescope_type">Vrsta</string>
|
||||
<string name="poi_animal_training_type">Vrsta</string>
|
||||
<string name="poi_embassy_type">Vrsta</string>
|
||||
<string name="poi_diplomatic_filter">Vrsta</string>
|
||||
<string name="poi_city_capital">Glavno mesto</string>
|
||||
<string name="poi_healthcare_alternative_types">Specializacija</string>
|
||||
<string name="poi_archaeological_site_type">Vrsta</string>
|
||||
|
|
|
@ -61,7 +61,7 @@
|
|||
<string name="poi_pump">Пумпа</string>
|
||||
<string name="poi_telescope_type">Врста</string>
|
||||
<string name="poi_animal_training_type">Врста</string>
|
||||
<string name="poi_embassy_type">ТипВрста</string>
|
||||
<string name="poi_diplomatic_filter">ТипВрста</string>
|
||||
<string name="poi_city_capital">Главни град</string>
|
||||
<string name="poi_healthcare_alternative_types">Специјализација</string>
|
||||
<string name="poi_free_flying_characteristics">Особина</string>
|
||||
|
|
|
@ -48,7 +48,7 @@
|
|||
<string name="poi_observatory_designation">Beteckning</string>
|
||||
<string name="poi_telescope_type">Typ</string>
|
||||
<string name="poi_animal_training_type">Typ</string>
|
||||
<string name="poi_embassy_type">Typ</string>
|
||||
<string name="poi_diplomatic_filter">Typ</string>
|
||||
<string name="poi_city_capital">Huvudstad</string>
|
||||
<string name="poi_pharmacy_dispensing">Utskrivning</string>
|
||||
<string name="poi_healthcare_alternative_types">Specialitet</string>
|
||||
|
|
|
@ -1023,7 +1023,7 @@
|
|||
<string name="poi_bicycle_parking_type">Tür</string>
|
||||
<string name="poi_telescope_type">Tür</string>
|
||||
<string name="poi_animal_training_type">Tür</string>
|
||||
<string name="poi_embassy_type">Tür</string>
|
||||
<string name="poi_diplomatic_filter">Tür</string>
|
||||
<string name="poi_archaeological_site_type">Tür</string>
|
||||
<string name="poi_information_type">Tür</string>
|
||||
<string name="poi_resort_type">Tür</string>
|
||||
|
|
|
@ -548,7 +548,7 @@
|
|||
<string name="poi_observatory_designation">Призначення</string>
|
||||
<string name="poi_telescope_type">Вид</string>
|
||||
<string name="poi_animal_training_type">Вид</string>
|
||||
<string name="poi_embassy_type">Вид</string>
|
||||
<string name="poi_diplomatic_filter">Вид</string>
|
||||
<string name="poi_city_capital">Столиця</string>
|
||||
<string name="poi_pharmacy_dispensing">Продаж ліків за рецептами</string>
|
||||
<string name="poi_healthcare_alternative_types">Спеціалізація</string>
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
<string name="poi_service_general">服务</string>
|
||||
<string name="poi_brushless">无刷</string>
|
||||
<string name="poi_animal_training_type">类型</string>
|
||||
<string name="poi_embassy_type">类型</string>
|
||||
<string name="poi_diplomatic_filter">类型</string>
|
||||
<string name="poi_clock_option">额外的</string>
|
||||
<string name="poi_osmwiki">维基百科</string>
|
||||
<string name="poi_user_defined_other">用户自定义</string>
|
||||
|
|
|
@ -2256,7 +2256,7 @@
|
|||
<string name="poi_observatory_designation">指示</string>
|
||||
<string name="poi_telescope_type">類型</string>
|
||||
<string name="poi_animal_training_type">類型</string>
|
||||
<string name="poi_embassy_type">類型</string>
|
||||
<string name="poi_diplomatic_filter">類型</string>
|
||||
<string name="poi_archaeological_site_type">類型</string>
|
||||
<string name="poi_information_type">類型</string>
|
||||
<string name="poi_resort_type">類型</string>
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
<string name="poi_observatory_designation">Designation</string>
|
||||
<string name="poi_telescope_type">Type</string>
|
||||
<string name="poi_animal_training_type">Type</string>
|
||||
<string name="poi_embassy_type">Type</string>
|
||||
<string name="poi_diplomatic_filter">Diplomatic institution</string>
|
||||
<string name="poi_city_capital">Capital</string>
|
||||
<string name="poi_pharmacy_dispensing">Dispensing</string>
|
||||
<string name="poi_healthcare_alternative_types">Specialty</string>
|
||||
|
@ -138,6 +138,12 @@
|
|||
<string name="poi_traffic_signals_arrow">Arrow</string>
|
||||
<string name="poi_drinking_water_refill">Drinking water refill</string>
|
||||
<string name="poi_departures_board">Departures board</string>
|
||||
<string name="poi_embassy_filter">Embassy</string>
|
||||
<string name="poi_consulate_filter">Consulate</string>
|
||||
<string name="poi_liaison_filter">Liaison</string>
|
||||
<string name="poi_diplomatic_services_non_immigrant_visas_filter">Non-immigrant visas</string>
|
||||
<string name="poi_diplomatic_services_immigrant_visas_filter">Immigrant visas</string>
|
||||
<string name="poi_diplomatic_services_citizen_services_filter">Citizen services</string>
|
||||
|
||||
<!-- categories -->
|
||||
<string name="poi_shop">Store</string>
|
||||
|
@ -4267,4 +4273,31 @@
|
|||
|
||||
<string name="poi_radar_tower">Radar tower</string>
|
||||
|
||||
<string name="poi_diplomatic_embassy">Embassy</string>
|
||||
<string name="poi_diplomatic_liaison">Liaison</string>
|
||||
|
||||
<string name="poi_embassy_yes">Headed by an ambassador</string>
|
||||
<string name="poi_embassy_branch_embassy">Branch</string>
|
||||
<string name="poi_embassy_delegation">Delegation</string>
|
||||
<string name="poi_embassy_high_commission">High commission</string>
|
||||
<string name="poi_embassy_interests_section">Interests section</string>
|
||||
<string name="poi_embassy_mission">Mission</string>
|
||||
<string name="poi_embassy_nunciature">Nunciature</string>
|
||||
<string name="poi_embassy_residence">Residence</string>
|
||||
<string name="poi_consulate_yes">Headed by a consul</string>
|
||||
<string name="poi_consulate_consular_agency">Consular agency</string>
|
||||
<string name="poi_consulate_consular_office">Consular office</string>
|
||||
<string name="poi_consulate_consulate_general">Consulate general</string>
|
||||
<string name="poi_consulate_honorary_consul">Honorary consul</string>
|
||||
<string name="poi_liaison_liaison_office">Office</string>
|
||||
<string name="poi_liaison_representative_office">Representative office</string>
|
||||
<string name="poi_liaison_subnational">Subnational</string>
|
||||
|
||||
<string name="poi_diplomatic_services_non_immigrant_visas_yes">Yes</string>
|
||||
<string name="poi_diplomatic_services_non_immigrant_visas_no">No</string>
|
||||
<string name="poi_diplomatic_services_immigrant_visas_yes">Yes</string>
|
||||
<string name="poi_diplomatic_services_immigrant_visas_no">No</string>
|
||||
<string name="poi_diplomatic_services_citizen_services_yes">Yes</string>
|
||||
<string name="poi_diplomatic_services_citizen_services_no">No</string>
|
||||
|
||||
</resources>
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -336,6 +336,8 @@ public class MenuBuilder {
|
|||
b.setTypeface(null, Typeface.BOLD);
|
||||
b.setText(context.getResources().getString(R.string.shared_string_add_photo));
|
||||
b.setBackgroundResource(R.drawable.btn_border_light);
|
||||
//TODO This feature is under development
|
||||
b.setVisibility(View.GONE);
|
||||
b.setTextColor(ContextCompat.getColor(context, R.color.preference_category_title));
|
||||
return b;
|
||||
}
|
||||
|
|
|
@ -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 = themedInflater.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