Merge branch 'master' into Fix-UI-bottomsheet

This commit is contained in:
androiddevkkotlin 2020-11-18 12:47:10 +02:00
commit 9fccd0b2ea
71 changed files with 1437 additions and 728 deletions

View 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>

View file

@ -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"

View file

@ -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>

View file

@ -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"

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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());

View file

@ -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;
}

View file

@ -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);

View 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);
}
}

View file

@ -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;
}

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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);
}
});
}
}

View file

@ -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();

View file

@ -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;
}
}

View file

@ -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;
}
}
}

View file

@ -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);
}
}

View file

@ -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;
}
}
}

View file

@ -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);
}

View file

@ -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);