Merge pull request #10832 from osmandapp/master

update test branch
This commit is contained in:
Hardy 2021-02-10 22:41:28 +01:00 committed by GitHub
commit 76c65130fa
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
32 changed files with 990 additions and 947 deletions

View file

@ -4,7 +4,7 @@
<application
android:icon="@mipmap/icon_free"
android:label="@string/app_name_free"
android:label="@string/app_name"
tools:replace="android:icon, android:label">
<meta-data

View file

@ -24,6 +24,7 @@ android {
// Build that doesn't include 3D OpenGL
legacy {
dimension "coreversion"
resValue "string", "app_edition", ""
}
}
}

View file

@ -37,6 +37,7 @@
android:layout_marginRight="@dimen/dialog_content_margin"
android:layout_marginEnd="@dimen/dialog_content_margin"
android:clickable="false"
android:scrollbars="none"
android:focusableInTouchMode="false" />
<androidx.appcompat.widget.AppCompatImageView

View file

@ -1,198 +0,0 @@
<?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:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/text_margin_small"
android:layout_marginRight="@dimen/text_margin_small"
android:background="?attr/wikivoyage_travel_card_bg"
android:orientation="vertical"
android:layout_marginEnd="@dimen/text_margin_small"
android:layout_marginStart="@dimen/text_margin_small">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="@dimen/content_padding"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/bottom_sheet_content_padding_small">
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/content_padding"
android:layout_marginRight="@dimen/content_padding"
android:layout_marginTop="4dp"
android:layout_weight="1"
android:ellipsize="end"
android:maxLines="1"
android:textColor="?attr/wikivoyage_primary_text_color"
android:textSize="@dimen/travel_card_primary_text_size"
osmand:typeface="@string/font_roboto_medium"
tools:text="Download file"/>
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:ignore="ContentDescription"
tools:src="@drawable/travel_card_download_icon"/>
</LinearLayout>
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/description"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:lineSpacingMultiplier="@dimen/text_button_line_spacing_multiplier"
android:textColor="@color/wikivoyage_secondary_text"
android:textSize="@dimen/travel_card_primary_text_size"
osmand:typeface="@string/font_roboto_regular"
tools:text="Download this Wikivoyage travel guides file to view articles about places around the world without an internet connection."/>
</LinearLayout>
<LinearLayout
android:id="@+id/file_data_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/content_padding"
android:layout_marginLeft="@dimen/bottom_sheet_content_margin_small"
android:layout_marginRight="@dimen/bottom_sheet_content_margin_small"
android:background="?attr/wikivoyage_travel_card_stroke_bg"
android:minHeight="@dimen/bottom_sheet_selected_item_title_height"
android:paddingLeft="@dimen/content_padding"
android:paddingRight="@dimen/content_padding"
android:layout_marginStart="@dimen/bottom_sheet_content_margin_small"
android:paddingEnd="@dimen/content_padding"
android:paddingStart="@dimen/content_padding"
android:layout_marginEnd="@dimen/bottom_sheet_content_margin_small">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/file_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginEnd="@dimen/content_padding"
android:layout_marginRight="@dimen/content_padding"
tools:ignore="ContentDescription"
tools:src="@drawable/ic_action_read_article"
tools:tint="?attr/wikivoyage_active_color"/>
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_weight="1"
android:orientation="vertical">
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/file_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:maxLines="1"
android:textColor="?attr/wikivoyage_primary_text_color"
android:textSize="@dimen/default_list_text_size"
osmand:typeface="@string/font_roboto_regular"
tools:text="Wikivoyage"/>
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/file_description"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:maxLines="1"
android:textColor="@color/wikivoyage_secondary_text"
android:textSize="@dimen/default_sub_text_size"
osmand:typeface="@string/font_roboto_regular"
tools:text="255 Mb • Update 11 April"/>
<ProgressBar
android:id="@+id/progress_bar"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="2dp"
android:minHeight="0dp"
android:visibility="gone"
tools:visibility="visible"/>
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/bottom_sheet_content_margin_small"
android:layout_marginLeft="@dimen/bottom_sheet_content_margin_small"
android:layout_marginRight="@dimen/bottom_sheet_content_margin_small"
android:layout_marginEnd="@dimen/bottom_sheet_content_margin_small"
android:layout_marginStart="@dimen/bottom_sheet_content_margin_small">
<FrameLayout
android:id="@+id/secondary_btn_container"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="?attr/wikivoyage_secondary_btn_bg">
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/secondary_button"
android:layout_width="match_parent"
android:layout_height="@dimen/wikivoyage_card_button_height"
android:layout_gravity="center"
android:background="?attr/selectableItemBackgroundBorderless"
android:ellipsize="end"
android:gravity="center"
android:letterSpacing="@dimen/text_button_letter_spacing"
android:maxLines="1"
android:textColor="?attr/wikivoyage_active_color"
android:textSize="@dimen/text_button_text_size"
osmand:typeface="@string/font_roboto_medium"
tools:ignore="UnusedAttribute"
tools:text="Later"/>
</FrameLayout>
<View
android:id="@+id/buttons_divider"
android:layout_width="@dimen/bottom_sheet_content_margin_small"
android:layout_height="match_parent"/>
<FrameLayout
android:id="@+id/primary_btn_container"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="?attr/wikivoyage_primary_btn_bg">
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/primary_button"
android:layout_width="match_parent"
android:layout_height="@dimen/wikivoyage_card_button_height"
android:layout_gravity="center"
android:background="?attr/selectableItemBackgroundBorderless"
android:ellipsize="end"
android:gravity="center"
android:letterSpacing="@dimen/text_button_letter_spacing"
android:maxLines="1"
android:textColor="?attr/wikivoyage_primary_btn_text_color"
android:textSize="@dimen/text_button_text_size"
osmand:typeface="@string/font_roboto_medium"
tools:ignore="UnusedAttribute"
tools:text="Update"/>
</FrameLayout>
</LinearLayout>
</LinearLayout>

View file

@ -18,16 +18,34 @@
android:layout_margin="@dimen/content_padding"
android:orientation="vertical">
<net.osmand.plus.widgets.TextViewEx
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/content_padding"
android:ellipsize="end"
android:maxLines="1"
android:text="@string/maps_you_need"
android:textColor="?attr/wikivoyage_primary_text_color"
android:textSize="@dimen/travel_card_primary_text_size"
osmand:typeface="@string/font_roboto_medium"/>
android:layout_marginBottom="@dimen/bottom_sheet_content_padding_small">
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/content_padding"
android:layout_marginRight="@dimen/content_padding"
android:layout_marginTop="4dp"
android:layout_weight="1"
android:ellipsize="end"
android:maxLines="1"
android:textColor="?attr/wikivoyage_primary_text_color"
android:textSize="@dimen/travel_card_primary_text_size"
osmand:typeface="@string/font_roboto_medium"
tools:text="Download file" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:ignore="ContentDescription"
tools:src="@drawable/travel_card_download_icon" />
</LinearLayout>
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/description"

View file

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
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:padding="@dimen/content_padding"
android:background="?attr/wikivoyage_card_bg_color"
android:gravity="center_vertical">
<include
android:id="@+id/button"
android:layout_width="match_parent"
android:layout_height="@dimen/dialog_button_height"
layout="@layout/bottom_sheet_dialog_button" />
</LinearLayout>
<include
android:id="@+id/shadow"
layout="@layout/card_bottom_divider"
android:visibility="visible" />
</LinearLayout>

View file

@ -103,6 +103,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:maxLines="2"
android:scrollbars="none"
android:textColor="@color/wikivoyage_secondary_text"
android:textSize="@dimen/default_sub_text_size"
osmand:typeface="@string/font_roboto_regular"

View file

@ -329,7 +329,7 @@
<string name="local_osm_changes_backup">نسخ الاحتياطي كتعديل OSM</string>
<string name="files_limit">%1$d ملف بقى</string>
<string name="osmand_background_plugin_description">يظهر الإعدادات لتمكين التتبع والملاحة في وضعية السكون ( الشاشة مغلقة ) عبر إيقاظ دوري لجهاز GPS.</string>
<string name="precise_routing_mode_descr">حساب الطرق بدقة دون أخطاء. لا يزال محدود المسافة وبطيء.</string>
<string name="precise_routing_mode_descr">تمكين لحساب المسارات بدقة دون أخطاء. لا يزال محدود المسافة وبطيء.</string>
<string name="recording_photo_description">صورة %1$s %2$s</string>
<string name="dropbox_plugin_description">مزامنة المسارات والملاحظات الصوتية / الفيديو مع حساب Dropbox الخاص بك.</string>
<string name="av_video_format_descr">تنسيق الفيديو الناتج:</string>
@ -359,7 +359,7 @@
<string name="osmand_short_description_80_chars">برنامج عرض الخرائط العالمية والملاحة باستخدام خرائط الشوارع المفتوحة OSM أثناء الاتصال بالإنترنت أو من دونه</string>
<string name="osmand_plus_play_title_30_chars">أوسماند+ للخرائط و الملاحة</string>
<string name="osmand_plus_short_description_80_chars">برنامج عرض الخرائط العالمية والملاحة باستخدام خرائط الشوارع المفتوحة OSM أثناء الاتصال بالإنترنت أو من دونه</string>
<string name="filterpoi_activity">أنشئ مُرشِّح نقاط مهمة</string>
<string name="filterpoi_activity">إنشاء فلتر نقاط الاهتمام</string>
<string name="recalculate_route_to_your_location">نمط المواصلات:</string>
<string name="select_navigation_mode">وسائل النقل:</string>
<string name="day_night_info_description">الشروق: %1$s
@ -471,7 +471,7 @@
<string name="index_name_africa">إفريقيا</string>
<string name="index_name_asia">آسيا</string>
<string name="index_name_oceania">أستراليا و أوقيانوسيا</string>
<string name="routing_settings">التوجيه</string>
<string name="routing_settings">التوجيه مع الطرق</string>
<string name="routing_settings_descr">ضبط خاص لكل وضع من أوضاع الملاحة.</string>
<string name="index_settings">إدارة بيانات الخرائط</string>
<string name="general_settings">إعدادات عامة</string>
@ -977,7 +977,7 @@
<string name="map_source">مصدر الخريطة</string>
<string name="layer_amenity_label">عرض أسماء المفضلة</string>
<string name="map_locale">لغة الخريطة</string>
<string name="rendering_category_details">التفاصيل</string>
<string name="rendering_category_details">تفاصيل إضافية</string>
<string name="map_widget_plain_time">الوقت الحالي</string>
<string name="rotate_map_to_bearing">اتجاه الخريطة</string>
<string name="rotate_map_bearing_opt">اتجاه الحركة في الأعلى</string>
@ -992,7 +992,7 @@
<string name="record_plugin_name">تسجيل المسار</string>
<string name="save_track_interval_descr">اختر الفاصل الزمني لتسجيل المسار أثناء الملاحة</string>
<string name="voice">صوت مسج</string>
<string name="get_directions">الاتجاهات</string>
<string name="get_directions">التوجيه مع الطرق</string>
<string name="show_point_options">استخدام الموقع…</string>
<string name="favorite">مفضلة</string>
<string name="speak_favorites">نقاط مفضلة مجاورة</string>
@ -1071,7 +1071,7 @@
<string name="impassable_road">تجنب الطرق…</string>
<string name="rendering_attr_trainLightrailRoutes_name">طرق السكك الحديدية</string>
<string name="rendering_attr_tramRoutes_name">خطوط الترام</string>
<string name="rendering_category_routes">الطرق</string>
<string name="rendering_category_routes">المسارات الرياضية</string>
<string name="rendering_category_transport">وسائل المواصلات</string>
<string name="rendering_category_others">سمات أخرى للخريطة</string>
<string name="map_widget_appearance_rem">العناصر الأخرى</string>
@ -1170,7 +1170,7 @@
<string name="rendering_attr_trolleybusRoutes_name">طرق الحافلات الكهربائية</string>
<string name="rendering_attr_busRoutes_name">طرق الحافلات</string>
<string name="rendering_attr_subwayMode_name">سكك قطار الأنفاق</string>
<string name="rendering_attr_shareTaxiRoutes_name">تاكسي مشاركة الطرق</string>
<string name="rendering_attr_shareTaxiRoutes_name">شارك طرق التاكسي</string>
<string name="speed_limit_exceed_message">حدد حد السرعة المسموح به لتلقي تنبيه صوتي إذا ما تجاوزته.</string>
<string name="traffic_warning_border_control">مراقبة الحدود</string>
<string name="traffic_warning_payment">كشك الرسوم</string>
@ -1184,7 +1184,7 @@
<string name="rendering_attr_hideAccess_name">قيود الدخول</string>
<string name="rendering_attr_showAccess_name">عرض قيود الدخول</string>
<string name="rendering_attr_showSurfaces_name">عرض سطح الطريق</string>
<string name="rendering_attr_showCycleRoutes_name">إظهار طرق الدراجات</string>
<string name="rendering_attr_showCycleRoutes_name">إظهار مسارات الدراجات</string>
<string name="delay_navigation_start">بدء التوجيه المفصل تلقائياً</string>
<string name="gpx_info_subtracks">مسارات فرعية: %1$s</string>
<string name="gpx_info_waypoints">نقاط الطريق: %1$s</string>
@ -1390,7 +1390,7 @@
<string name="app_mode_train">قطار</string>
<string name="current_track">المسار الحالي</string>
<string name="map_widget_battery">مستوى البطارية</string>
<string name="change_markers_position">تغيير موقع العلامة</string>
<string name="change_markers_position">تغيير موقع التوجيه المباشر</string>
<string name="follow_us">تابعنا</string>
<string name="access_direction_audio_feedback">اتجاه صدى الصوت</string>
<string name="use_osm_live_routing">الملاحة عبر أوسماند لايف</string>
@ -1411,7 +1411,7 @@
<string name="map_mode">مظهرالخريطة</string>
<string name="rendering_value_thin_name">رقيقة</string>
<string name="rendering_value_medium_name">متوسط</string>
<string name="no_map_markers_found">أضف علامات عبر الخريطة</string>
<string name="no_map_markers_found">لم تضف توجيه مباشر على الخريطة</string>
<string name="no_waypoints_found">لم يتم العثور على نقاط الطريق</string>
<string name="report">التقرير</string>
<string name="storage_permission_restart_is_required">سمح الآن للتطبيق بالكتابة على وحدة التخزين الخارجية. الرجاء إعادة تشغيله يدويا.</string>
@ -1436,7 +1436,7 @@
<string name="upload_anonymously">رفع كمستخدم مجهول</string>
<string name="upload_osm_note">رفع ملاحظة OSM</string>
<string name="shared_string_toolbar">شريط الأدوات</string>
<string name="select_map_markers">حدد علامات الخريطة</string>
<string name="select_map_markers">حدد توجيه مباشرعلى الخريطة</string>
<string name="shared_string_reverse_order">ترتيب عكسي</string>
<string name="show_map_markers_description">تفعيل ميزة العلامات.</string>
<string name="lang_ast">الأسترية</string>
@ -1472,7 +1472,7 @@
<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>
<string name="move_marker_bottom_sheet_title">حرك الخريطة لتغيير مكان التوجيه المباشر</string>
<!-- string name="lat_lon_pattern">خط العرض: %1$.5f خط الطول: %2$.5f</string -->
<string name="access_direction_audio_feedback_descr">إشارة صوتية عند اتجاه نقطة الوصول.</string>
<string name="access_direction_haptic_feedback_descr">حدد اتجاه النقطة المستهدفة بالاهتزاز.</string>
@ -1590,7 +1590,7 @@
<string name="shared_string_move_down">حرك للاسفل</string>
<string name="open_street_map_login_and_pass">اسم مستخدم و كلمة سر OSM</string>
<string name="osm_live_email_desc">نحن بحاجة اليه لكي نوفر لك معلومات حول المساهمات.</string>
<string name="select_map_marker">اختر علامة</string>
<string name="select_map_marker">حدد توجيه مباشر</string>
<string name="show_transparency_seekbar">عرض شريط الشفافية</string>
<string name="download_files_error_not_enough_space">لا توجد مساحة كافية!
\n {3} MB مطلوب مؤقتا ، {1} ميجا بايت بشكل دائم.
@ -1611,7 +1611,7 @@
\nللعودة إلى واحدة من أنماط الخريطة التقليدية، ببساطة إما عطل هذا الملحق مرة أخرى أو غير \'نمط الخريطة\' في \'ضبط الخريطة\' حسب الرغبة.</string>
<string name="search_near_map">البحث قرب مركز الخريطة الحالية</string>
<string name="active_markers">عدد خطوط التوجيه</string>
<string name="map_markers">علامات الخريطة</string>
<string name="map_markers">التوجيه المباشر</string>
<string name="routing_attr_avoid_borders_name">تخطي الحدود</string>
<string name="impassable_road_desc">حدد الطرق التي تريد تجنبها أثناء التنقل.</string>
<string name="search_categories">الفئات</string>
@ -1629,11 +1629,11 @@
<string name="available_maps">الخرائط الموجودة</string>
<string name="access_shared_string_navigate_up">انتقال للأعلى</string>
<string name="osm_user_stat">التعديلات %1$s ، الرتبة %2$s ، مجموع التعديلات %3$s</string>
<string name="map_marker_1st">أول علامة</string>
<string name="map_marker_2nd">ثاني علامة</string>
<string name="shared_string_add_to_map_markers">إضافة إلى علامات الخريطة</string>
<string name="clear_active_markers_q">حذف كافة العلامات النشطة على الخريطة؟</string>
<string name="map_marker">علامة خريطة</string>
<string name="map_marker_1st">التوجيه المباشرالأول للخريطة</string>
<string name="map_marker_2nd">التوجيه المباشرالثاني للخريطة</string>
<string name="shared_string_add_to_map_markers">إضافة إلى التوجيه المباشر</string>
<string name="clear_active_markers_q">حذف كافة التوجيه المباشرالنشط على الخريطة؟</string>
<string name="map_marker">توجيه مباشر على الخريطة</string>
<string name="show_polygons">عرض المضلعات</string>
<string name="shared_string_status">الحالة</string>
<string name="shared_string_save_changes">حفظ التعديلات</string>
@ -1655,7 +1655,7 @@
<string name="select_voice_provider">اختر التوجيه الصوتي</string>
<string name="select_voice_provider_descr">اختر أو قم بتحميل التوجيه الصوتي الخاص بلغتك.</string>
<string name="no_location_permission">منح الوصول إلى بيانات الموقع.</string>
<string name="rendering_attr_horseRoutes_name">طرق الخيول</string>
<string name="rendering_attr_horseRoutes_name">مسارات الخيول</string>
<string name="shared_string_hide">إخفاء</string>
<string name="av_video_quality_low">جودة أقل</string>
<string name="av_video_quality_high">أعلى جودة</string>
@ -1749,7 +1749,7 @@
<string name="update_poi_error_local">خطأ تحيين القائمة المحلية لPOI.</string>
<string name="context_menu_item_update_poi">تحيين الPOI</string>
<string name="upload_osm_note_description">قم بتحميل مذكرة OSM الخاصة بك دون الكشف عن هويتك أو باستخدام ملف تعريف OpenStreetMap.org .</string>
<string name="add_points_to_map_markers_q">إضافة جميع النقاط إلى علامات الخريطة؟</string>
<string name="add_points_to_map_markers_q">إضافة جميع النقاط إلى التوجيه المباشر؟</string>
<string name="clear_markers_history_q">مسح السجلات ؟</string>
<string name="rendering_attr_showMtbRoutes_name">إظهار مسارات الدراجة الجبلية</string>
<string name="clear_updates_proposition_message">يمكنك إزالة التحديثات المحملة والرجوع إلى الإصدار الأصلي للخريطة</string>
@ -1868,7 +1868,7 @@
<string name="rendering_value_walkingRoutesScopeOSMC_name">تلوين وفق الانتماء للشبكة</string>
<string name="rendering_value_walkingRoutesOSMC_name">تلوين وفق رمز تنزه OSMC</string>
<string name="shared_string_logoff">خروج</string>
<string name="local_recordings_delete_all_confirm">حذف الملاحظات %1$d؟</string>
<string name="local_recordings_delete_all_confirm">هل أنت متأكد من أنك تريد حذف الملاحظات %1$d؟</string>
<string name="nautical_maps_missing">لعرض الخرائط البحرية، يجب تحميل خريطة خاصة محلياً.</string>
<string name="save_track_to_gpx_globally_descr">تسجيل الموقع العام إلى ملف GPX يمكن تشغيله أو إيقافه باستخدام نافذة تسجيل GPX على الشاشة خريطة.</string>
<string name="proxy_host_descr">ضبط اسم مضيف البروكسي (مثال 127.0.0.1).</string>
@ -1962,8 +1962,7 @@
\nليست هناك حاجة لتحميل خريطة خاصة،الرؤية يتم إنشاؤها من خلال خرائطنا المحلية.
\n
\nهذه الرؤية يمكن التراجع عنها إما عن طريق تعطيلها هنا، أو تغيير \'نمط الخريطة\' في \'ضبط الخريطة\' حسب الرغبة.</string>
<string name="create_poi_link_to_osm_doc">
<u>Online OSM</u> تصنيف الخريطة مع الصور.</string>
<string name="create_poi_link_to_osm_doc"><u>Online OSM</u> تصنيف الخريطة مع الصور.</string>
<string name="background_service_wait_int_descr">تعيين الحد الأقصى لوقت الانتظار لكل إصلاح موقع في الخلفية.</string>
<string name="background_service_wait_int">الانتظار الأقصى للإصلاح</string>
<string name="voice_data_not_supported">إصدار غير معتمد من البيانات الصوتية</string>
@ -2072,7 +2071,7 @@
<string name="rendering_value_fine_name">اللون والسمك</string>
<string name="route_roundabout_short">خذ المخرج %1$d ثم واصل</string>
<string name="search_map_hint">المدينة أو المنطقة</string>
<string name="wiki_around">مقالات ويكيبيديا قريبة</string>
<string name="wiki_around">مقالات ويكيبيديا القريبة</string>
<string name="routing_attr_allow_motorway_name">استخدام الطرق السريعة</string>
<string name="routing_attr_allow_motorway_description">السماح للطرق السريعة.</string>
<string name="lang_sr_latn">الصربية (اللاتينية)</string>
@ -2089,7 +2088,7 @@
<string name="configure_screen_quick_action">إجراءات سريعة</string>
<string name="quick_action_item_action">إجراء %d</string>
<string name="quick_action_item_screen">شاشة %d</string>
<string name="quick_action_add_marker">إضافة علامة خريطة</string>
<string name="quick_action_add_marker">إضافة توجيه مباشر للخريطة</string>
<string name="quick_action_add_poi">إضافة POI</string>
<string name="quick_action_map_style">نمط الخريطة</string>
<string name="quick_action_map_style_switch">نمط الخرائط تغير ل \"%s\".</string>
@ -2219,18 +2218,19 @@
<string name="select_gpx_folder">حدد مجلد المسار</string>
<string name="shared_string_gpx_tracks">المسارات</string>
<string name="shared_string_time">الوقت</string>
<string name="osmand_plus_extended_description_part8">التغطية التقريبية للخريطة و جودتها :
\n• أوروبا الغربية : ****
\n• أوروبا الشرقية : ***
\n• روسيا : ***
\n• أمريكا الشمالية : ***
\n• امريكا الجنوبية : **
\n• آسيا : **
\n• اليابان وكوريا : ***
\n• الشرق الأوسط : **
\n• إفريقيا : **
\n• أنتاركتيكا : *
\n معظم البلدان في جميع أنحاء العالم متاحة للتنزيل ! من أفغانستان إلى زيمبابوي، من أستراليا إلى الولايات المتحدة الأمريكية. الأرجنتين، البرازيل، كندا، فرنسا، ألمانيا، المكسيك، المملكة المتحدة، إسبانيا
<string name="osmand_plus_extended_description_part8">التغطية التقريبية للخريطة و جودتها:
\n • أوروبا الغربية: ****
\n • أوروبا الشرقية: ***
\n • روسيا: ***
\n • أمريكا الشمالية: ***
\n • امريكا الجنوبية: **
\n • آسيا: **
\n • اليابان وكوريا: ***
\n • الشرق الأوسط : **
\n • إفريقيا: **
\n • أنتاركتيكا: *
\n معظم البلدان في جميع أنحاء العالم متاحة للتنزيل
\n من أفغانستان إلى زيمبابوي، من أستراليا إلى الولايات المتحدة الأمريكية. الأرجنتين، البرازيل، كندا، فرنسا، ألمانيا، المكسيك، المملكة المتحدة، أسبانيا , …
\n</string>
<string name="restart_search">إعادة البحث</string>
<string name="osmand_extended_description_part7">المساهمة في OSM
@ -2372,12 +2372,13 @@
\n
\n بعض الميزات الرئيسية:</string>
<string name="osmand_plus_extended_description_part2">الملاحة
\n• يعمل على الإنترنت (سريع) أو في وضع غير متصل (لا رسوم تجوال خارج الوطن)
\n• توجيه صوتي بالتفصيل (الأصوات المسجلة أو مدرجة)
\n• موجه مسار اختياري، عرض اسم الشارع، والوقت المقدر للوصول
\n• يدعم نقاط وسيطة خلال مسارك
\n• إعادة تلقائية للتوجيه كلما انحرفت عن الطريق
\n• البحث عن الأماكن حسب العنوان، النوع (مثل: مطعم، فندق، محطة وقود، متحف)،أو حسب الإحداثيات الجغرافية</string>
\n • يعمل على الإنترنت (سريع) أو في وضع غير متصل (لا رسوم تجوال خارج الوطن)
\n • توجيه صوتي بالتفصيل (الأصوات المسجلة أو مدرجة)
\n • موجه مسار اختياري، عرض اسم الشارع، والوقت المقدر للوصول
\n • يدعم نقاط وسيطة خلال مسارك
\n • إعادة تلقائية للتوجيه كلما انحرفت عن الطريق
\n • البحث عن الأماكن حسب العنوان، النوع (مثل: مطعم، فندق، محطة وقود، متحف)،أو حسب الإحداثيات الجغرافية
\n</string>
<string name="osmand_plus_extended_description_part3">عرض الخريطة
\n• عرض موقعك والتوجيه
\n• محاذاة اختيارية للصورة وفق البوصلة أو توجيه الحركة
@ -2418,7 +2419,8 @@
<string name="quick_action_duplicates">اسم الاختصار السريع المحدد قيد الاستخدام، لقد تم تغييره إلى %1$s لتجنب التكرار.</string>
<string name="quick_action_page_list_descr">الضغط على زر الإجراء سيطبق أحد الأنماط من القائمة أدناه.</string>
<string name="route_points_category_name">تنقلاتك على هذا الطريق</string>
<string name="navigate_point_olc_info_area">OLC الصالحة بالكامل\nتمثل المنطقة: %1$s x %2$s</string>
<string name="navigate_point_olc_info_area">الصالحة بالكامل OLC
\nيمثل المنطقة: %1$s x %2$s</string>
<string name="wrong_user_name">اسم المستخدم خاطئ</string>
<string name="shared_string_to">إلى</string>
<string name="mapillary_menu_date_from">مِن</string>
@ -2468,7 +2470,7 @@
<string name="add_point_before">إضافة نقطة قبل</string>
<string name="add_point_after">إضافة نقطة بعد</string>
<string name="shared_string_options">خيارات</string>
<string name="measurement_tool_snap_to_road_descr">سيتم توصيل النقاط بطرق الوضع المحدد.</string>
<string name="measurement_tool_snap_to_road_descr">سيتم توصيل النقاط بمسارات الوضع المحدد.</string>
<string name="measurement_tool_save_as_new_track_descr">يمكنك حفظ النقاط إما كنقاط طريق أو كخط.</string>
<string name="choose_navigation_type">اختر وضع الملاحة</string>
<string name="add_route_points">إضافة نقاط مسار</string>
@ -2481,12 +2483,12 @@
<string name="map_orientation_change_in_accordance_with_speed">عتبة توجيه الخريطة</string>
<string name="map_orientation_change_in_accordance_with_speed_descr">حدد أدناه على أي سرعة يتغير توجيه الخريطة من \'اتجاه الحركة\' إلى \'البوصلة\'.</string>
<string name="all_markers_moved_to_history">تم نقل جميع العلامات إلى السجل</string>
<string name="marker_moved_to_history">تم نقل العلامة إلى السجل</string>
<string name="marker_moved_to_active">العلامة أصبحت نشطة</string>
<string name="marker_moved_to_history">تم نقل التوجيه المباشر إلى السجل</string>
<string name="marker_moved_to_active">التوجيه المباشر انتقل كنشط</string>
<string name="shared_string_list">قائمة</string>
<string name="shared_string_groups">مجموعات</string>
<string name="passed">آخر استخدام : %1$s</string>
<string name="make_active">تنشيط العلامة</string>
<string name="make_active">تنشيط التوجيه المباشر</string>
<string name="today">اليوم</string>
<string name="yesterday">أمس</string>
<string name="last_seven_days">آخر ٧ أيام</string>
@ -2502,12 +2504,12 @@
<string name="show_arrows_on_the_map">سهم متجه للهدف</string>
<string name="show_passed">عرض المتجاوز</string>
<string name="hide_passed">إخفاء المتجاوز</string>
<string name="remove_from_map_markers">إزالة من \"علامات الخريطة\"</string>
<string name="remove_from_map_markers">إزالة من \"التوجيه المباشر\"</string>
<string name="descendingly">تنازلي</string>
<string name="ascendingly">تصاعدي</string>
<string name="date_added">تاريخ الإضافة</string>
<string name="order_by">ترتيب حسب:</string>
<string name="marker_show_distance_descr">حدد كيفية الإشارة إلى مسافة واتجاه العلامة على شاشة الخريطة:</string>
<string name="marker_show_distance_descr">حدد كيفية الإشارة إلى المسافة والاتجاه للتوجيه المباشر على شاشة الخريطة:</string>
<string name="use_location">استخدم الموقع</string>
<string name="add_location_as_first_point_descr">أضف موقعك كنقطة أولى لتخطيط طريق مثالي.</string>
<string name="my_location">موقعي</string>
@ -2518,7 +2520,7 @@
<string name="marker_save_as_track_descr">تصدير علاماتك إلى ملف يمكنك تحديده هنا:</string>
<string name="move_to_history">نقل إلى السجل</string>
<string name="group_will_be_removed_after_restart">سيتم إزالة المجموعة بعد إعادة تشغيل التطبيق.</string>
<string name="shared_string_markers">العلامات</string>
<string name="shared_string_markers">التوجيه المباشر</string>
<string name="coordinates_format">نمط الإحداثيات</string>
<string name="use_system_keyboard">لوحة مفاتيح النظام</string>
<string name="fast_coordinates_input_descr">اختر نسق إدخال الأحداثيات. يمكنك دائماً تغييره بالنقر على خيارات.</string>
@ -2535,12 +2537,12 @@
<string name="show_map">أظهر الخريطة</string>
<string name="route_is_calculated">تم حساب المسار</string>
<string name="round_trip">رحلة ذهاب وإياب</string>
<string name="plan_route_no_markers_toast">يجب عليك إضافة علامة واحدة على الأقل لاستخدام هذه الوظيفة.</string>
<string name="plan_route_no_markers_toast">يجب عليك إضافة توجيه مباشر واحد على الأقل لاستخدام هذه الوظيفة.</string>
<string name="wrong_format">تنسيق خاطئ</string>
<string name="enter_new_name">أدخل اسم جديد</string>
<string name="shared_string_back">عودة</string>
<string name="shared_string_view">عرض</string>
<string name="waypoints_added_to_map_markers">تمت إضافة نقاط الطريق إلى علامات الخريطة</string>
<string name="waypoints_added_to_map_markers">تمت إضافة نقاط الطريق إلى التوجيه المباشر للخريطة</string>
<string name="wrong_input">إدخال خاطئ</string>
<string name="import_gpx_file_description">يمكن استيرادها كنقاط مفضلة، أو كملف GPX.</string>
<string name="import_as_gpx">استيراد كملف GPX</string>
@ -2548,15 +2550,15 @@
<string name="import_file">استيراد ملف</string>
<string name="tap_on_map_to_hide_interface_descr">نقرة على الخريطة ستفعل أزرار التحكم والويدجت.</string>
<string name="tap_on_map_to_hide_interface">شاشة كاملة</string>
<string name="mark_passed">علامة مُجتازة</string>
<string name="mark_passed">توجيه مباشر مجتاز</string>
<string name="empty_state_osm_edits">إنشاء أو تعديل عناصر OSM</string>
<string name="empty_state_osm_edits_descr">قم بإنشاء أو تعديل نقاط الاهتمام OSM ، وفتح ملاحظات OSM أو التعليق عليها ، والمساهمة في ملفات GPX المسجلة.</string>
<string name="shared_string_deleted">حذف</string>
<string name="shared_string_edited">مُعدلة</string>
<string name="shared_string_added">تمت الإضافة</string>
<string name="modify_the_search_query">تعديل طلب البحث.</string>
<string name="marker_activated">تم تنشيط العلامة %s.</string>
<string name="one_tap_active_descr">انقر على العلامة في الخريطة لجعلها بالاعلى بدون فتح القائمة.</string>
<string name="marker_activated">تم تنشيط التوجيه المباشر %s.</string>
<string name="one_tap_active_descr">انقر على التوجيه المباشر في الخريطة لجعله الاعلى بدون فتح القائمة.</string>
<string name="empty_state_av_notes">تدوين ملاحظات!</string>
<string name="without_time_limit">بدون حد زمني</string>
<string name="context_menu_read_full_article">اقرأ المقال كاملا</string>
@ -2564,27 +2566,27 @@
<string name="context_menu_points_of_group">جميع نقاط هذه المجموعة</string>
<string name="open_from">افتح من</string>
<string name="open_till">مفتوح حتى</string>
<string name="will_close_at">يغلق عند</string>
<string name="will_open_at">يفتح عند</string>
<string name="will_open_on">يفتح عند</string>
<string name="will_close_at">يغلق أبوابه على</string>
<string name="will_open_at">سيفتح الأبواب على</string>
<string name="will_open_on">يفتح أبوابه على</string>
<string name="additional_actions">إجراءات إضافية</string>
<string name="shared_string_actions">إجراءات</string>
<string name="shared_string_marker">العلامات</string>
<string name="shared_string_marker">توجيه مباشر</string>
<string name="notes_by_date">الملاحظات حسب التاريخ</string>
<string name="by_date">حسب التاريخ</string>
<string name="by_type">حسب النوع</string>
<string name="shared_string_more_without_dots">المزيد</string>
<string name="appearance_on_the_map">المظهر على الخريطة</string>
<string name="appearance_on_the_map">التوجيه المباشر</string>
<string name="shared_string_gpx_waypoints">نقاط المسار</string>
<string name="add_group">إضافة مجموعة</string>
<string name="empty_state_markers_active">قم بإنشاء علامات على الخريطة !</string>
<string name="empty_state_markers_active">قم بإنشاء التوجيه المباشر على الخريطة !</string>
<string name="empty_state_markers_groups">استيراد مجموعات</string>
<string name="digits_quantity">عدد الأرقام</string>
<string name="shared_string_right">اليمين</string>
<string name="shared_string_left">اليسار</string>
<string name="shared_string_paste">لصق</string>
<string name="go_to_next_field">الانتقال إلى الحقل التالي</string>
<string name="rename_marker">إعادة تسمية العلامة</string>
<string name="rename_marker">إعادة تسمية التوجيه المباشر</string>
<string name="total_donations">مجموع التبرعات</string>
<string name="rendering_attr_hidePOILabels_name">تسميات POI</string>
<string name="shared_string_without_name">بدون اسم</string>
@ -2616,7 +2618,7 @@
<string name="south_abbreviation">ج</string>
<string name="north_abbreviation">ش</string>
<string name="optional_point_name">اسم النقطة</string>
<string name="transport_nearby_routes_within">الطرق القريبة في الداخل</string>
<string name="transport_nearby_routes_within">الطرق الداخلية المجاورة</string>
<string name="enter_the_file_name">أدخل اسم الملف.</string>
<string name="map_import_error">خطأ أثناء استرجاع الخريطة</string>
<string name="map_imported_successfully">تمت عملية استيراد الخريطة</string>
@ -2628,7 +2630,7 @@
<string name="choose_file_type">قم باختيار نسق الملف</string>
<string name="all_data">جميع البيانات</string>
<string name="osm_notes">ملاحظات OSM</string>
<string name="will_open_tomorrow_at">سيفتح غداً عند</string>
<string name="will_open_tomorrow_at">سيفتح أبوابه غداً على</string>
<string name="what_is_here">ماذا هنا:</string>
<string name="lang_lo">اللاوسية</string>
<string name="touring_view_renderer">عرض خريطة السياحة</string>
@ -2692,7 +2694,7 @@
<string name="download_all">تنزيل الكل</string>
<string name="shared_string_restart">إعادة تشغيل التطبيق</string>
<string name="shared_string_bookmark">إشارة مرجعية</string>
<string name="waypoints_removed_from_map_markers">نقاط بالطريق تم إزالتها من علامات الخريطة</string>
<string name="waypoints_removed_from_map_markers">نقاط بالطريق تم إزالتها من التوجيه المباشر للخريطة</string>
<string name="powered_by_osmand">بواسطة أوسماند</string>
<string name="osm_live_plan_pricing">الأسعار والاشتراك</string>
<string name="osm_live_payment_monthly_title">شهري</string>
@ -2707,14 +2709,14 @@
<string name="osm_live_payment_renews_annually">يجدد سنويا</string>
<string name="osm_live_payment_header">حدد فترة الدفع المناسبة لك:</string>
<string name="osm_live_payment_contribute_descr">تبرعات مساعدة صندوق رسم الخرائط OSM.</string>
<string name="markers_remove_dialog_msg">حذف العلامة \'%s\'؟</string>
<string name="edit_map_marker">تعديل العلامة</string>
<string name="markers_remove_dialog_msg">حذف التوجيه المباشر \'%s\'؟</string>
<string name="edit_map_marker">تعديل التوجيه المباشر</string>
<string name="search_street">بحث عن شارع</string>
<string name="start_search_from_city">اختر المدينة أولاً</string>
<string name="shared_string_restore">استعادة</string>
<string name="third_party_application">تطبيق من طرف ثالث</string>
<string name="keep_passed_markers_descr">ستبقى العلامات المضافة من مجموعة إحداثيات أو من نقاط طريق على الخريطة عند اختيار \"تجاوز العلامة\". إذا كانت المجموعة غير نشطة ستختفي العلامات من الخريطة.</string>
<string name="keep_passed_markers">إبقاء العلامة المتجاوز</string>
<string name="keep_passed_markers_descr">عند التفعيل سيبقى التوجيه المباشر المضاف من مجموعة إحداثيات أو من نقاط طريق على الخريطة عند اختيار \"تجاوز التوجيه المباشر\". إذا كانت المجموعة غير نشطة ستختفي الوجهات المباشرة من الخريطة.</string>
<string name="keep_passed_markers">إبقاء التوجيه المباشر المتجاوز</string>
<string name="more_transport_on_stop_hint">هناك المزيد من وسائل النقل في هذا الموقف.</string>
<string name="ask_for_location_permission">يرجى إعطاء إذن تحديد الموقع للتطبيق لكي يواصل.</string>
<string name="thank_you_for_feedback">شكرا على الرد</string>
@ -2842,7 +2844,7 @@
<string name="empty_state_av_notes_desc">إضافة ملاحظة صوتية أو فيديو أو صورة لكل نقطة على الخريطة، باستخدام قائمة السياق أو القطعة.</string>
<string name="looking_for_tracks_with_waypoints">ابحث عن المسارات مع نقاط الطريق</string>
<string name="add_track_to_markers_descr">حدد مسار لإضافة نقاط الطريق إلى العلامات(يتم سرد المسارات فقط مع نقاط الطريق).</string>
<string name="empty_state_markers_active_desc">نقرة طويلة أو قصيرة على الأماكن ثم اضغط على زر علامة.</string>
<string name="empty_state_markers_active_desc">نقرة طويلة أو قصيرة على الأماكن ثم اضغط على زر التوجيه المباشر.</string>
<string name="empty_state_markers_groups_desc">يمكنك استيراد المجموعات المفضلة أو نقاط المسار كتوجيه.</string>
<string name="empty_state_markers_history_desc">ستظهر العلامات التي تم تجاوزها على هذه الشاشة.</string>
<string name="show_guide_line_descr">خط مباشر من موقعك إلى الهدف.</string>
@ -2992,7 +2994,7 @@
<string name="years_5">سنوات</string>
<string name="months_3">ثلاثة أشهر</string>
<string name="price_free">مجاناً</string>
<string name="rendering_attr_showCycleNodeNetworkRoutes_name">إظهار شبكة طرق الدارجات الهوائية</string>
<string name="rendering_attr_showCycleNodeNetworkRoutes_name">إظهار شبكة مسارات الدارجات الهوائية</string>
<string name="download_map_dialog">نافذة تحميل الخريطة</string>
<string name="dialogs_and_notifications_title">النوافذ والإشعارات</string>
<string name="dialogs_and_notifications_descr">التحكم في النوافذ المنبثقة ، ومربعات الحوار والإشعارات.</string>
@ -3017,7 +3019,7 @@
<string name="paste_Osmand_data_folder_path">لصق مسار مجلد بيانات أوسماند</string>
<string name="change_osmand_data_folder_question">تغيير مجلد التخزين ؟</string>
<string name="move_maps_to_new_destination">نقل للموقع الجديد</string>
<string name="avoid_in_routing_descr_">تجنب بعض أنواع الطرق</string>
<string name="avoid_in_routing_descr_">تجنب بعض الطرق</string>
<string name="app_mode_utv">جنبًا إلى جنب</string>
<string name="rendering_attr_piste_difficulty_aerialway_name">طريق تلفريك</string>
<string name="rendering_attr_piste_difficulty_connection_name">اتصال</string>
@ -3042,7 +3044,7 @@
<string name="routing_attr_prefer_unpaved_name">تفضيل الطرق الغير معبدة</string>
<string name="routing_attr_prefer_unpaved_description">تفضيل الطرق الغير معبدة.</string>
<string name="update_all_maps">تحديث كل الخرائط</string>
<string name="update_all_maps_q">تحديث (%1$d) خريطة؟</string>
<string name="update_all_maps_q">هل أنت متأكد من رغبتك بتحديث (%1$d) خريطة؟</string>
<string name="release_3_5">• تحديث التطبيق وإعدادات الأوضاع: يتم ترتيب الإعدادات الآن حسب النوع. يمكن تخصيص كل وضع بشكل منفصل.
\n
\n • نافذة جديدة لتنزيل الخريطة المقترحة أثناء تصفح الخرائط
@ -3328,8 +3330,8 @@
<string name="routing_attr_piste_type_skitour_description">طرق لجولات التزلج.</string>
<string name="routing_attr_piste_type_sled_name">تزلج</string>
<string name="routing_attr_piste_type_sled_description">منحدرات لاستخدام الزلاجات.</string>
<string name="routing_attr_allow_intermediate_name">السماح بالطرق المتوسطة</string>
<string name="routing_attr_allow_intermediate_description">طرق أكثر صعوبة مع أقسام أكثر حدة. بعض العقبات ينبغي تجنبها.</string>
<string name="routing_attr_allow_intermediate_name">السماح بالمسارات المتوسطة</string>
<string name="routing_attr_allow_intermediate_description">طرق أكثر صعوبة مع أقسام أكثر حدة. بعض العقبات التي ينبغي تجنبها.</string>
<string name="routing_attr_allow_advanced_name">السماح للطرق المتقدمة</string>
<string name="routing_attr_allow_advanced_description">طرق صعبة ، مع عقبات خطيرة وأقسام شديدة الانحدار.</string>
<string name="routing_attr_allow_expert_name">السماح بطرق المتخصصين</string>
@ -3355,8 +3357,8 @@
<string name="sett_generic_ext_input">لوحة المفاتيح</string>
<string name="sett_wunderlinq_ext_input">وندرلينك</string>
<string name="sett_parrot_ext_input">ببغاء</string>
<string name="new_route_calculated_dist_dbg">المسار: المسافة%1$s، الوقت %2$s.
\nالحساب: %3$.1f ث، %4$d طريق، %5$d تجانب</string>
<string name="new_route_calculated_dist_dbg">المسار: المسافة%2$s، وقت التوجيه %1$s.
\nالحساب: %3$.1f ث، %4$d طريق، %5$d تجانب)</string>
<string name="lang_oc">الأوكيتانية</string>
<string name="get_discount_second_part">ثم %1$s</string>
<string name="apply_to_current_profile">تطبيق فقط على \"%1$s\"</string>
@ -3378,7 +3380,7 @@
<string name="select_color">اختر اللون</string>
<string name="edit_profiles_descr">لا يمكنك حذف أوضاع أوسماند الافتراضية ، ولكن يمكنك تعطيلها في الشاشة السابقة ، أو نقلها إلى الأسفل.</string>
<string name="edit_profiles">تحرير الأوضاع</string>
<string name="select_nav_profile_dialog_message">يؤثر نوع التنقل على قواعد حساب الطرق.</string>
<string name="select_nav_profile_dialog_message">يؤثر نوع التنقل على قواعد حسابات المسار.</string>
<string name="profile_appearance">مظهر الوضع</string>
<string name="choose_icon_color_name">اختر الايقونة واللون والاسم</string>
<string name="reorder_profiles">تحرير قائمة الأوضاع</string>
@ -3534,7 +3536,7 @@
<string name="restore_all_profile_settings">استعادة جميع إعدادات الوضع؟</string>
<string name="saving_new_profile">حفظ الوضع الجديد</string>
<string name="profile_backup_failed">لا يمكن عمل نسخة احتياطية لهذا الوضع.</string>
<string name="clear_recorded_data_warning">مسح البيانات المسجلة؟</string>
<string name="clear_recorded_data_warning">هل أنت متأكد من أنك تريد مسح البيانات المسجلة؟</string>
<string name="importing_from">استيراد البيانات من %1$s</string>
<string name="shared_string_importing">استيراد</string>
<string name="checking_for_duplicate_description">OsmAnd تحقق %1$s للتكرارات مع العناصر الموجودة في التطبيق.
@ -3730,7 +3732,7 @@
<string name="default_screen_timeout">مهلة الشاشة الافتراضية</string>
<string name="export_import_quick_actions_with_profiles_promo">يمكنك تصدير أو استيراد إجراءات سريعة باستخدام أوضاع التطبيق .</string>
<string name="shared_string_delete_all_q">حذف الكل؟</string>
<string name="delete_all_actions_message_q">حذف الاختصارات السريعة %d نهائيًا؟</string>
<string name="delete_all_actions_message_q">هل أنت متأكد من رغبتك في حذف الاختصارات السريعة %d نهائيًا؟</string>
<string name="screen_timeout">مهلة الشاشة</string>
<string name="shared_string_tones">نغمات</string>
<string name="width_limit_description">أدل بعرض مركبتك، قد يتم تطبيق بعض القيود على المركبات العريضة.</string>
@ -3787,7 +3789,7 @@
<string name="osm_edit_closed_note">أغلق ملاحظة OSM</string>
<string name="set_working_days_to_continue">تحتاج إلى تعيين أيام العمل للمتابعة</string>
<string name="route_between_points">المسار بين النقاط</string>
<string name="plan_a_route">تخطيط طريق</string>
<string name="plan_a_route">قياس المسافة</string>
<string name="add_to_a_track">إضافة إلى مسار</string>
<string name="add_hidden_group_info">لن تكون النقطة المضافة مرئية على الخريطة، نظرًا لأن المجموعة المحددة مخفية، يمكنك العثور عليها في \"%s\".</string>
<string name="track_show_start_finish_icons">إظهار رموز البدء والانتهاء</string>
@ -3800,7 +3802,7 @@
<string name="plan_route_last_edited">التعديل الأخير</string>
<string name="plan_route_import_track">استيراد المسار</string>
<string name="plan_route_open_existing_track">فتح مسار موجود</string>
<string name="plan_route_create_new_route">إنشاء طريق جديد</string>
<string name="plan_route_create_new_route">إنشاء مسار جديد</string>
<string name="plan_route_select_track_file_for_open">حدد المسار للفتح.</string>
<string name="shared_string_done">تم</string>
<string name="overwrite_track">الكتابة فوق المسار</string>
@ -3816,7 +3818,7 @@
<string name="route_between_points_warning_desc">بعد ذلك ، ألقط مسارك بأقرب طريق مسموح به باستخدام أحد أوضاع التنقل الخاصة بك لاستخدام هذا الخيار.</string>
<string name="threshold_distance">بداية المسافة</string>
<string name="street_level_imagery">صور للشارع</string>
<string name="plan_route_exit_dialog_descr">إغلاق مسار الرحلة دون حفظ؟ ستفقد كل التغييرات؟</string>
<string name="plan_route_exit_dialog_descr">هل أنت متأكد أنك تريد إغلاق مسار الرحلة دون حفظ؟ سوف تفقد كل التغييرات؟</string>
<string name="in_case_of_reverse_direction">في حالة الاتجاه المعاكس</string>
<string name="save_track_to_gpx">تسجيل المسار أثناء الملاحة</string>
<string name="shared_string_save_as_gpx">حفظ كملف مسار جديد</string>
@ -3833,10 +3835,10 @@
<string name="quick_action_add_gpx">أضف إحداثية مسار</string>
<string name="map_widget_monitoring">تسجيل الرحلة</string>
<string name="marker_save_as_track">حفظ كمسار</string>
<string name="follow_track">اتبع المسار</string>
<string name="follow_track">تتبع المسار</string>
<string name="follow_track_descr">اختر مسار للمتابعة</string>
<string name="import_track_descr">اختر ملف المسار للمتابعة أو قم باستيراده من الجهاز.</string>
<string name="select_another_track">حدد مساراً آخر</string>
<string name="select_another_track">حدد مسارا آخر</string>
<string name="navigate_to_track_descr">انتقل من موقعي إلى المسار</string>
<string name="pass_whole_track_descr">نقطة المسار للتنقل</string>
<string name="start_of_the_track">بداية المسار</string>
@ -3997,8 +3999,8 @@
\n • دعم ألوان مخصصة للمفضلة ونقاط لمسار الطريق
\n
\n</string>
<string name="profile_type_osmand_string">وضع التطبيق</string>
<string name="profile_type_user_string">حساب المستخدم</string>
<string name="profile_type_osmand_string">وضع الاستعراض</string>
<string name="profile_type_user_string">ملف تعريف المستخدم</string>
<string name="reverse_all_points">عكس جميع النقاط</string>
<string name="profile_by_default_description">حدد الوضع الذي سيتم استخدامه في بدء التطبيق.</string>
<string name="shared_string_last_used">آخر استخدام</string>
@ -4030,7 +4032,7 @@
<string name="select_folder">تحديد مجلد</string>
<string name="select_folder_descr">تحديد مجلد أو إضافة واحد جديد</string>
<string name="shared_string_empty">فارغ</string>
<string name="analyze_by_intervals">تحليل حسب الفاصل الزمني</string>
<string name="analyze_by_intervals">التحليل حسب الفواصل الزمنية (الفاصل الزمني)</string>
<string name="upload_to_openstreetmap">رفع إلى خريطة الشارع المفتوح</string>
<string name="edit_track">تحرير المسار</string>
<string name="rename_track">تسمية المسار</string>
@ -4080,7 +4082,20 @@
\nجميع بيانات OpenPlaceReview مفتوحة ومتاحة للجميع: http://openplacereviews.org/data.
\n
\nيمكنك قراءة المزيد على: http://openplacereviews.org</string>
<string name="open_place_reviews">مراجعات الأمكنة</string>
<string name="open_place_reviews">OpenPlaceReviews</string>
<string name="opr_use_dev_url">استخدام test.openplacereviews.org</string>
<string name="login_open_place_reviews">الدخول إلى OpenPlaceReviews</string>
<string name="activity_type_water_name">ماء</string>
<string name="activity_type_winter_name">شتاء</string>
<string name="activity_type_snowmobile_name">الثلج</string>
<string name="activity_type_riding_name">ركوب</string>
<string name="activity_type_racing_name">سباق</string>
<string name="activity_type_mountainbike_name">دراجة جبلية</string>
<string name="activity_type_cycling_name">دراجة</string>
<string name="activity_type_hiking_name">مشي</string>
<string name="activity_type_running_name">الجري</string>
<string name="activity_type_walking_name">مشي</string>
<string name="activity_type_offroad_name">الطرق الوعرة</string>
<string name="activity_type_motorbike_name">دراجة نارية</string>
<string name="activity_type_car_name">سيارة</string>
</resources>

View file

@ -3881,4 +3881,14 @@
<string name="poi_wildlife_crossing_bat_bridge">Ponto por vespertoj</string>
<string name="poi_wildlife_crossing">Trairejo por sovaĝaj bestoj</string>
<string name="poi_swimming_area">Naĝejo natura</string>
<string name="poi_piste_status_closed">Stato de skivojo: fermita</string>
<string name="poi_piste_status_open">Stato de skivojo: malfermita</string>
<string name="poi_patrolled_no">Kontrolata: ne</string>
<string name="poi_patrolled_yes">Kontrolata: jes</string>
<string name="poi_gladed_yes">Senarbigita: jes</string>
<string name="poi_piste_name">Nomo de skivojo</string>
<string name="poi_piste_ski_jump">Skisaltejo</string>
<string name="poi_mobile_library">Movebla biblioteko (haltloko)</string>
<string name="poi_summit_register_no">Pinttaglibro: ne</string>
<string name="poi_summit_register_yes">Pinttaglibro: jes</string>
</resources>

View file

@ -4020,4 +4020,17 @@
<string name="open_place_reviews">OpenPlaceReviews</string>
<string name="opr_use_dev_url">Uzi test.openplacereviews.org</string>
<string name="login_open_place_reviews">Ensaluti al OpenPlaceReviews</string>
<string name="activity_type_water_name">Akvo</string>
<string name="activity_type_winter_name">Vintro</string>
<string name="activity_type_snowmobile_name">Motorsledo</string>
<string name="activity_type_riding_name">Rajdado</string>
<string name="activity_type_racing_name">Kurkonkurso</string>
<string name="activity_type_mountainbike_name">Montbiciklo</string>
<string name="activity_type_cycling_name">Biciklado</string>
<string name="activity_type_hiking_name">Marŝado</string>
<string name="activity_type_running_name">Kurado</string>
<string name="activity_type_walking_name">Piedirado</string>
<string name="activity_type_offroad_name">Ekstervoje</string>
<string name="activity_type_motorbike_name">Motorciklo</string>
<string name="activity_type_car_name">Aŭto</string>
</resources>

View file

@ -4005,4 +4005,13 @@
<string name="open_place_reviews">OpenPlaceReviews</string>
<string name="opr_use_dev_url">Utilisez test.openplacereviews.org</string>
<string name="login_open_place_reviews">Se connecter à OpenPlaceReviews</string>
<string name="activity_type_water_name">Eau</string>
<string name="activity_type_winter_name">Hiver</string>
<string name="activity_type_snowmobile_name">Motoneige</string>
<string name="activity_type_cycling_name">Vélo</string>
<string name="activity_type_mountainbike_name">VTT</string>
<string name="activity_type_hiking_name">Randonnée</string>
<string name="activity_type_running_name">Course à pied</string>
<string name="activity_type_walking_name">Marche</string>
<string name="activity_type_car_name">Voiture</string>
</resources>

View file

@ -54,7 +54,7 @@
<string name="poi_service_tyres">Autógumi-szerelő</string>
<string name="poi_car_wash">Autómosó</string>
<string name="poi_fuel">Benzinkút;Töltőállomás;Gázolajtöltő-állomás</string>
<string name="poi_electricity_combined_charging">Elektromos töltőállomás</string>
<string name="poi_electricity_combined_charging">Elektromos töltőállomás;Elektromos autó töltése;Villanyautó töltése;Elektromos töltőpont</string>
<string name="poi_compressed_air">Sűrített levegő</string>
<string name="poi_parking">Parkoló</string>
<string name="poi_motorcycle_parking">Motorkerékpár-parkoló</string>
@ -3879,4 +3879,14 @@
<string name="poi_wildlife_crossing_bat_tunnel">Denevéralagút</string>
<string name="poi_wildlife_crossing_bat_bridge">Denevérhíd</string>
<string name="poi_wildlife_crossing">Vadátjáró</string>
<string name="poi_summit_register_no">Csúcsnapló nincs</string>
<string name="poi_summit_register_yes">Csúcsnapló van</string>
<string name="poi_patrolled_no">Hegyi mentő nincs</string>
<string name="poi_patrolled_yes">Hegyi mentő van</string>
<string name="poi_gladed_yes">Erdei pálya</string>
<string name="poi_mobile_library">Mozgó könyvtár tartózkodási helye</string>
<string name="poi_piste_status_closed">Pálya állapota: zárva</string>
<string name="poi_piste_status_open">Pálya állapota: nyitva</string>
<string name="poi_piste_name">Pálya neve</string>
<string name="poi_piste_ski_jump">Síugrósánc</string>
</resources>

View file

@ -3881,4 +3881,14 @@
<string name="poi_wildlife_crossing_bat_bridge">Brú fyrir leðurblökur</string>
<string name="poi_wildlife_crossing">Þverun villtra dýra</string>
<string name="poi_swimming_area">Sundsvæði</string>
<string name="poi_mobile_library">Stæði fyrir bókabíl</string>
<string name="poi_summit_register_no">Skráning á tind: nei</string>
<string name="poi_summit_register_yes">Skráning á tind: já</string>
<string name="poi_piste_status_closed">Staða brautar: lokuð</string>
<string name="poi_piste_status_open">Staða brautar: opin</string>
<string name="poi_patrolled_no">Eftirlit: nei</string>
<string name="poi_patrolled_yes">Eftirlit: já</string>
<string name="poi_gladed_yes">Skafið: já</string>
<string name="poi_piste_name">Heiti brautar</string>
<string name="poi_piste_ski_jump">Skíðastökk</string>
</resources>

View file

@ -3972,7 +3972,7 @@
<string name="select_folder">Veldu möppu</string>
<string name="select_folder_descr">Veldu möppu eða bættu við nýrri</string>
<string name="shared_string_empty">Tómt</string>
<string name="analyze_by_intervals">Greina eftir millibilum (uppskipting millibila)</string>
<string name="analyze_by_intervals">Greina eftir uppskiptingu millibila</string>
<string name="upload_to_openstreetmap">Senda inn í OpenStreetMap</string>
<string name="edit_track">Breyta ferli</string>
<string name="rename_track">Endurnefna feril</string>
@ -4005,4 +4005,32 @@
<string name="routing_engine_vehicle_type_mtb">Fjallahjól</string>
<string name="message_server_error">Villa í netþjóni: %1$s</string>
<string name="message_name_is_already_exists">Nafnið er þegar til staðar</string>
<string name="delete_online_routing_engine">Eyða þessari leiðagerð á netinu\?</string>
<string name="context_menu_read_full">Lesa óstytt</string>
<string name="context_menu_edit_descr">Breyta lýsingu</string>
<string name="delete_waypoints">Eyða ferilpunktum</string>
<string name="copy_to_map_markers">Afrita í kortamerki</string>
<string name="copy_to_map_favorites">Afrita í eftirlæti</string>
<string name="upload_photo">Sendi inn</string>
<string name="upload_photo_completed">Innsendingu er lokið</string>
<string name="uploading_count">Sendi inn %1$d af %2$d</string>
<string name="uploaded_count">Sent inn %1$d af %2$d</string>
<string name="toast_select_edits_for_upload">Veldu breytingar til að senda inn</string>
<string name="hillshade_slope_contour_lines">Hæðaskygging / Halli / Hæðarlínur</string>
<string name="open_place_reviews">OpenPlaceReviews</string>
<string name="opr_use_dev_url">Nota test.openplacereviews.org</string>
<string name="login_open_place_reviews">Skrá inn á OpenPlaceReviews</string>
<string name="activity_type_water_name">Vatn</string>
<string name="activity_type_winter_name">Vetur</string>
<string name="activity_type_snowmobile_name">Vélsleðar</string>
<string name="activity_type_riding_name">Útreiðar</string>
<string name="activity_type_racing_name">Kappakstur</string>
<string name="activity_type_mountainbike_name">Fjallahjól</string>
<string name="activity_type_cycling_name">Hjólreiðar</string>
<string name="activity_type_hiking_name">Gönguferðir</string>
<string name="activity_type_running_name">Hlaup</string>
<string name="activity_type_walking_name">Gangandi</string>
<string name="activity_type_offroad_name">Utanvegaakstur</string>
<string name="activity_type_motorbike_name">Vélhjól</string>
<string name="activity_type_car_name">Akandi</string>
</resources>

View file

@ -3970,7 +3970,7 @@
<string name="select_folder">בחירת תקינה</string>
<string name="select_folder_descr">נא לבחור תיקייה או להוסיף אחת חדשה</string>
<string name="shared_string_empty">ריק</string>
<string name="analyze_by_intervals">ניתוח לפי מרווחים (פיצול מרווחים)</string>
<string name="analyze_by_intervals">ניתוח מרווחי פיצול</string>
<string name="upload_to_openstreetmap">העלאה ל־OpenStreetMap</string>
<string name="edit_track">עריכת מסלול</string>
<string name="rename_track">שינוי שם מסלול</string>
@ -4016,4 +4016,11 @@
<string name="open_place_reviews">OpenPlaceReviews</string>
<string name="opr_use_dev_url">להשתמש ב־test.openplacereviews.org</string>
<string name="login_open_place_reviews">כניסה ל־OpenPlaceReviews</string>
<string name="announcement_time_descr">זמן ההכרזה של ההנחיות הקוליות השונות תלוי בסוג ההכרזה, במהירות הניווט הנוכחית ובמהירות הניווט כבררת מחדל.</string>
<string name="hillshade_slope_contour_lines">הצללה / מדרון / קווי מתאר</string>
<string name="open_place_reviews_plugin_description">OpenPlaceReviews הוא מיזם בהובלת הקהילה בנוגע למקומות ציבוריים כגון מסעדות, מלונות, מוזיאונים ונקודות דרך. הוא אוסף מידע ציבורי עליהם כגון תמונות, סקירות, קישורים למערכות אחרות שמקושרות ל־OpenStreetMap, ויקיפדיה.
\n
\nכל הנתונים של OpenPlaceReview הם פתוחים וזמינים לציבור הרחב: http://openplacereviews.org/data.
\n
\nניתן לקרוא עוד באתר: http://openplacereviews.org</string>
</resources>

View file

@ -502,7 +502,7 @@
<string name="poi_climbing">Tırmanma</string>
<string name="poi_cricket">Kriket</string>
<string name="poi_croquet">Kroket</string>
<string name="poi_cycling">Bisiklete binme</string>
<string name="poi_cycling">Bisiklet sürme</string>
<string name="poi_diving">Dalış</string>
<string name="poi_scuba_diving">Tüplü dalış</string>
<string name="poi_dog_racing">Köpek yarışı</string>

View file

@ -2227,7 +2227,7 @@
<string name="marker_save_as_track_descr">İşaretleyicilerinizi şu GPX dosyasına aktarın:</string>
<string name="show_arrows_on_the_map">Haritada yön gösterici okları göster</string>
<string name="measurement_tool_snap_to_road_descr">OsmAnd seçilmiş profil için rotalı noktalara bağlanacak.</string>
<string name="none_point_error">Lütfen en az bir nokta ekleyiniz.</string>
<string name="none_point_error">Lütfen en az bir nokta ekleyin.</string>
<string name="measurement_tool_action_bar">Haritayı görüntüle ve nokta ekle</string>
<string name="store_tracks_in_monthly_directories">Kaydedilmiş izlenen yolları aylık klasörlerde depola</string>
<string name="mapillary_menu_filter_description">Resimleri göndericiye, tarihe ya da türüne göre filtreleyin. Sadece yakın mesafe yakınlaştırmasında etkin.</string>
@ -3738,7 +3738,7 @@
<string name="track_coloring_solid">Koyu</string>
<string name="plan_route_last_edited">Son düzenleme</string>
<string name="plan_route_import_track">Yolu içe aktar</string>
<string name="plan_route_open_existing_track">Mevcut yolu aç</string>
<string name="plan_route_open_existing_track">Var olan yolu aç</string>
<string name="plan_route_create_new_route">Yeni güzergah oluştur</string>
<string name="plan_route_select_track_file_for_open">Açmak için bir yol dosyası seçin.</string>
<string name="shared_string_done">Bitti</string>
@ -3968,7 +3968,7 @@
<string name="select_folder">Klasör seç</string>
<string name="select_folder_descr">Klasör seçin veya yeni bir tane ekleyin</string>
<string name="shared_string_empty">Boş</string>
<string name="analyze_by_intervals">Aralıklara göre analiz et (bölme aralığı)</string>
<string name="analyze_by_intervals">Bölünmüş aralıkları analiz et</string>
<string name="upload_to_openstreetmap">OpenStreetMap\'e yükle</string>
<string name="edit_track">Yolu düzenle</string>
<string name="rename_track">Yolu yeniden adlandır</string>
@ -4012,4 +4012,26 @@
<string name="uploading_count">%1$d / %2$d karşıya yükleniyor</string>
<string name="uploaded_count">%1$d / %2$d karşıya yüklendi</string>
<string name="toast_select_edits_for_upload">Karşıya yüklenecek düzenlemeleri seçin</string>
<string name="hillshade_slope_contour_lines">tepe gölgesi / yamaç / eş yükselti eğrileri</string>
<string name="open_place_reviews_plugin_description">OpenPlaceReviews, restoranlar, oteller, müzeler, ara noktalar gibi halka açık yerler hakkında topluluk tarafından yürütülen bir projedir. Fotoğraflar, yorumlar, OpenStreetMap, Wikipedia gibi diğer sistemlere bağlantılar gibi onlar hakkındaki tüm halka açık bilgileri toplar.
\n
\nTüm OpenPlaceReview verileri açık ve herkes tarafından kullanılabilir: http://openplacereviews.org/data
\n
\nDaha fazlasını şu adresten okuyabilirsiniz: http://openplacereviews.org</string>
<string name="open_place_reviews">OpenPlaceReviews</string>
<string name="opr_use_dev_url">test.openplacereviews.org adresini kullan</string>
<string name="login_open_place_reviews">OpenPlaceReviews\'te oturum aç</string>
<string name="activity_type_water_name">Su</string>
<string name="activity_type_winter_name">Kış</string>
<string name="activity_type_snowmobile_name">Kar arabası</string>
<string name="activity_type_riding_name">Binme</string>
<string name="activity_type_racing_name">Yarış</string>
<string name="activity_type_mountainbike_name">Dağ bisikleti</string>
<string name="activity_type_cycling_name">Bisiklet sürme</string>
<string name="activity_type_hiking_name">Yürüyüş</string>
<string name="activity_type_running_name">Koşma</string>
<string name="activity_type_walking_name">Yürüme</string>
<string name="activity_type_offroad_name">Arazi</string>
<string name="activity_type_motorbike_name">Motosiklet</string>
<string name="activity_type_car_name">Araba</string>
</resources>

View file

@ -2663,7 +2663,7 @@
<string name="shared_string_travel_book">旅游书</string>
<string name="download_images">下载图片</string>
<string name="rendering_value_black_name">黑色</string>
<string name="rendering_attr_surface_wood_name"></string>
<string name="rendering_attr_surface_wood_name"></string>
<string name="app_mode_subway">地铁</string>
<string name="app_mode_horse">骑马</string>
<string name="shared_string_color_magenta">品红色</string>
@ -2674,7 +2674,7 @@
<string name="points_of_interests">兴趣点POI</string>
<string name="shared_string_capacity">容量</string>
<string name="rendering_attr_surface_metal_name">金属</string>
<string name="rendering_attr_highway_class_path_name">路径</string>
<string name="rendering_attr_highway_class_path_name">走道</string>
<string name="app_mode_helicopter">直升机</string>
<string name="app_mode_skiing">滑雪</string>
<string name="base_profile_descr_ski">滑雪</string>
@ -2839,7 +2839,7 @@
<string name="show_closed_notes">显示关闭的注记</string>
<string name="osm_edit_closed_note">关闭的OSM注记</string>
<string name="add_online_source">添加在线资源</string>
<string name="rendering_attr_highway_class_bridleway_name"/>
<string name="rendering_attr_highway_class_bridleway_name">驮道</string>
<string name="rendering_attr_surface_gravel_name">砾石</string>
<string name="rendering_attr_surface_sett_name">比利时石砌路</string>
<string name="routing_attr_allow_expert_name">允许专家路线</string>
@ -3124,4 +3124,79 @@
<string name="context_menu_item_add_waypoint">添加轨迹航点</string>
<string name="save_track_to_gpx_globally">将轨迹记录到GPX文件</string>
<string name="disable_recording_once_app_killed_descrp">当应用程序被杀死时跟踪日志将被暂停通过最近的应用程序OsmAnd背景指示会从Android通知栏中消失</string>
<string name="add_online_routing_engine">添加在线路线引擎</string>
<string name="edit_online_routing_engine">编辑在线路线引擎</string>
<string name="shared_string_subtype">子类型</string>
<string name="shared_string_vehicle">车辆</string>
<string name="shared_string_api_key">API 密钥</string>
<string name="shared_string_server_url">服务器 URL</string>
<string name="shared_string_enter_param">输入参数</string>
<string name="keep_it_empty_if_not">否则请保持空白</string>
<string name="test_route_calculation">测试路线计算</string>
<string name="routing_engine_vehicle_type_driving">驾驶</string>
<string name="routing_engine_vehicle_type_car">汽车</string>
<string name="copy_address">复制地址</string>
<string name="online_routing_engine">在线路线引擎</string>
<string name="online_routing_engines">在线路线引擎</string>
<string name="shared_string_folders">文件夹</string>
<string name="select_folder">选择文件夹</string>
<string name="select_folder_descr">选择文件夹或添加新文件夹</string>
<string name="upload_to_openstreetmap">上传到 OpenStreetMap</string>
<string name="edit_track">编辑轨迹</string>
<string name="rename_track">重命名轨迹</string>
<string name="change_folder">更改文件夹</string>
<string name="shared_string_sec"></string>
<string name="announcement_time_passing">通过</string>
<string name="announcement_time_prepare_long">长时间准备</string>
<string name="announcement_time_prepare">准备</string>
<string name="announcement_time_off_route">偏离路线</string>
<string name="announcement_time_arrive">到达目的地</string>
<string name="shared_string_turn">转弯</string>
<string name="announcement_time_intervals">时间和距离间隔</string>
<string name="announcement_time_descr">不同语音提示的公告时间取决于提示类型、当前导航速度和默认导航速度。</string>
<string name="announcement_time_title">公告时间</string>
<string name="start_recording">开始录制</string>
<string name="show_track_on_map">在地图上显示轨迹</string>
<string name="routing_engine_vehicle_type_wheelchair">轮椅</string>
<string name="routing_engine_vehicle_type_hiking">徒步</string>
<string name="routing_engine_vehicle_type_walking">步行</string>
<string name="routing_engine_vehicle_type_cycling_electric">电动自行车</string>
<string name="routing_engine_vehicle_type_cycling_mountain">山地自行车</string>
<string name="routing_engine_vehicle_type_cycling_road">公路自行车</string>
<string name="routing_engine_vehicle_type_hgv">重型货车</string>
<string name="routing_engine_vehicle_type_small_truck">小型卡车</string>
<string name="routing_engine_vehicle_type_truck">卡车</string>
<string name="routing_engine_vehicle_type_scooter">踏板车</string>
<string name="routing_engine_vehicle_type_racingbike">竞速自行车</string>
<string name="routing_engine_vehicle_type_mtb">山地车</string>
<string name="message_server_error">服务器错误:%1$s</string>
<string name="delete_online_routing_engine">删除这个在线路线引擎?</string>
<string name="message_name_is_already_exists">名字已经存在</string>
<string name="context_menu_read_full">阅读全文</string>
<string name="context_menu_edit_descr">编辑描述</string>
<string name="delete_waypoints">删除航点</string>
<string name="copy_to_map_markers">复制到地图标记</string>
<string name="copy_to_map_favorites">复制到收藏</string>
<string name="upload_photo">上传中</string>
<string name="upload_photo_completed">上传完成</string>
<string name="uploading_count">正在上传 %1$d共 %2$d</string>
<string name="toast_select_edits_for_upload">选择要上传的编辑</string>
<string name="uploaded_count">已上传 %1$d共 %2$d</string>
<string name="hillshade_slope_contour_lines">山体阴影/斜坡/等高线</string>
<string name="open_place_reviews_plugin_description">OpenPlaceReviews 是一个社区驱动的项目,关于公共场所,如餐馆,酒店,博物馆,航点。它收集了所有关于它们的公共信息,如照片、评论、链接到其他系统的 OpenStreetMap、维基百科。
\n
\n所有 OpenPlaceReview 的数据都是开放的所有人都可以使用http://openplacereviews.org/data。
\n
\n你可以在以下网站阅读更多信息http://openplacereviews.org</string>
<string name="open_place_reviews">OpenPlaceReviews</string>
<string name="opr_use_dev_url">使用 test.openplacereviews.org</string>
<string name="login_open_place_reviews">登录 OpenPlaceReviews</string>
<string name="activity_type_winter_name">冬季</string>
<string name="activity_type_snowmobile_name">雪地摩托</string>
<string name="activity_type_riding_name">骑行</string>
<string name="activity_type_cycling_name">骑车</string>
<string name="activity_type_hiking_name">健行</string>
<string name="activity_type_running_name">跑步</string>
<string name="activity_type_walking_name">步行</string>
<string name="activity_type_motorbike_name">摩托车</string>
</resources>

View file

@ -36,6 +36,7 @@ import net.osmand.data.LatLon;
import net.osmand.data.QuadRect;
import net.osmand.data.RotatedTileBox;
import net.osmand.plus.GpxSelectionHelper.GpxDisplayItem;
import net.osmand.plus.GpxSelectionHelper.SelectedGpxFile;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import net.osmand.plus.UiUtilities;
@ -66,6 +67,8 @@ public class TrackDetailsMenu {
@Nullable
private GpxDisplayItem gpxItem;
@Nullable
private SelectedGpxFile selectedGpxFile;
@Nullable
private TrackDetailsBarController toolbarController;
@Nullable
private TrkSegment segment;
@ -101,6 +104,15 @@ public class TrackDetailsMenu {
this.gpxItem = gpxItem;
}
@Nullable
public SelectedGpxFile getSelectedGpxFile() {
return selectedGpxFile;
}
public void setSelectedGpxFile(@NonNull SelectedGpxFile selectedGpxFile) {
this.selectedGpxFile = selectedGpxFile;
}
public boolean isVisible() {
return visible;
}
@ -539,7 +551,7 @@ public class TrackDetailsMenu {
}
}
public boolean shouldShowXAxisPoints () {
public boolean shouldShowXAxisPoints() {
return true;
}
@ -707,18 +719,19 @@ public class TrackDetailsMenu {
if (gpxItem.chartTypes != null && gpxItem.chartTypes.length > 0) {
for (int i = 0; i < gpxItem.chartTypes.length; i++) {
OrderedLineDataSet dataSet = null;
boolean withoutGaps = selectedGpxFile != null && (!selectedGpxFile.isJoinSegments() && gpxItem.isGeneralTrack());
switch (gpxItem.chartTypes[i]) {
case ALTITUDE:
dataSet = GpxUiHelper.createGPXElevationDataSet(app, chart, analysis,
gpxItem.chartAxisType, false, true, false);
gpxItem.chartAxisType, false, true, withoutGaps);
break;
case SPEED:
dataSet = GpxUiHelper.createGPXSpeedDataSet(app, chart, analysis,
gpxItem.chartAxisType, gpxItem.chartTypes.length > 1, true, false);
gpxItem.chartAxisType, gpxItem.chartTypes.length > 1, true, withoutGaps);
break;
case SLOPE:
dataSet = GpxUiHelper.createGPXSlopeDataSet(app, chart, analysis,
gpxItem.chartAxisType, null, gpxItem.chartTypes.length > 1, true, false);
gpxItem.chartAxisType, null, gpxItem.chartTypes.length > 1, true, withoutGaps);
break;
}
if (dataSet != null) {

View file

@ -1,10 +1,10 @@
package net.osmand.plus.track;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.ColorInt;
@ -12,21 +12,19 @@ import androidx.annotation.ColorRes;
import androidx.annotation.DrawableRes;
import androidx.annotation.NonNull;
import androidx.appcompat.widget.AppCompatImageView;
import androidx.core.content.ContextCompat;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import net.osmand.AndroidUtils;
import net.osmand.GPXUtilities.GPXFile;
import net.osmand.GPXUtilities.GPXTrackAnalysis;
import net.osmand.plus.GpxSelectionHelper.GpxDisplayGroup;
import net.osmand.plus.GpxSelectionHelper.GpxDisplayItem;
import net.osmand.plus.GpxSelectionHelper.GpxDisplayItemType;
import net.osmand.plus.GpxSelectionHelper.SelectedGpxFile;
import net.osmand.plus.OsmAndFormatter;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import net.osmand.plus.UiUtilities;
import net.osmand.plus.helpers.AndroidUiHelper;
import net.osmand.plus.helpers.GpxUiHelper;
import net.osmand.plus.helpers.GpxUiHelper.GPXDataSetType;
import net.osmand.plus.myplaces.SegmentActionsListener;
import net.osmand.plus.widgets.TextViewEx;
@ -40,101 +38,134 @@ public class GpxBlockStatisticsBuilder {
private final OsmandApplication app;
private RecyclerView blocksView;
private final SelectedGpxFile selectedGpxFile;
private final TrackDisplayHelper displayHelper;
private final GpxDisplayItemType[] filterTypes = {GpxDisplayItemType.TRACK_SEGMENT};
public GpxBlockStatisticsBuilder(OsmandApplication app, SelectedGpxFile selectedGpxFile, TrackDisplayHelper displayHelper) {
private BlockStatisticsAdapter adapter;
private final List<StatBlock> items = new ArrayList<>();
private final Handler handler = new Handler();
private Runnable updatingItems;
private boolean updateRunning = false;
public GpxBlockStatisticsBuilder(OsmandApplication app, SelectedGpxFile selectedGpxFile) {
this.app = app;
this.selectedGpxFile = selectedGpxFile;
this.displayHelper = displayHelper;
}
public void setBlocksView(RecyclerView blocksView) {
this.blocksView = blocksView;
}
private GPXTrackAnalysis getAnalysis() {
return selectedGpxFile.getTrackAnalysis(app);
private GpxDisplayItem getDisplayItem(GPXFile gpxFile) {
return GpxUiHelper.makeGpxDisplayItem(app, gpxFile);
}
private GPXFile getGPXFile() {
return selectedGpxFile.getGpxFile();
}
public void initStatBlocks(SegmentActionsListener actionsListener, @ColorInt int activeColor, boolean nightMode) {
GPXTrackAnalysis analysis = getAnalysis();
float totalDistance = analysis.totalDistance;
float timeSpan = analysis.timeSpan;
String asc = OsmAndFormatter.getFormattedAlt(analysis.diffElevationUp, app);
String desc = OsmAndFormatter.getFormattedAlt(analysis.diffElevationDown, app);
String avg = OsmAndFormatter.getFormattedSpeed(analysis.avgSpeed, app);
String max = OsmAndFormatter.getFormattedSpeed(analysis.maxSpeed, app);
List<StatBlock> items = new ArrayList<>();
prepareData(analysis, items, app.getString(R.string.distance), OsmAndFormatter.getFormattedDistance(totalDistance, app),
R.drawable.ic_action_track_16, R.color.icon_color_default_light, GPXDataSetType.ALTITUDE, GPXDataSetType.SPEED, ItemType.ITEM_DISTANCE);
prepareData(analysis, items, app.getString(R.string.altitude_ascent), asc,
R.drawable.ic_action_arrow_up_16, R.color.gpx_chart_red, GPXDataSetType.SLOPE, null, ItemType.ITEM_ALTITUDE);
prepareData(analysis, items, app.getString(R.string.altitude_descent), desc,
R.drawable.ic_action_arrow_down_16, R.color.gpx_pale_green, GPXDataSetType.ALTITUDE, GPXDataSetType.SLOPE, ItemType.ITEM_ALTITUDE);
prepareData(analysis, items, app.getString(R.string.average_speed), avg,
R.drawable.ic_action_speed_16, R.color.icon_color_default_light, GPXDataSetType.SPEED, null, ItemType.ITEM_SPEED);
prepareData(analysis, items, app.getString(R.string.max_speed), max,
R.drawable.ic_action_max_speed_16, R.color.icon_color_default_light, GPXDataSetType.SPEED, null, ItemType.ITEM_SPEED);
prepareData(analysis, items, app.getString(R.string.shared_string_time_span),
Algorithms.formatDuration((int) (timeSpan / 1000), app.accessibilityEnabled()),
R.drawable.ic_action_time_span_16, R.color.icon_color_default_light, GPXDataSetType.SPEED, null, ItemType.ITEM_TIME);
if (Algorithms.isEmpty(items)) {
AndroidUiHelper.updateVisibility(blocksView, false);
} else {
final BlockStatisticsAdapter sbAdapter = new BlockStatisticsAdapter(items, actionsListener, activeColor, nightMode);
initItems();
boolean isNotEmpty = !Algorithms.isEmpty(items);
AndroidUiHelper.updateVisibility(blocksView, isNotEmpty);
if (isNotEmpty) {
adapter = new BlockStatisticsAdapter(getDisplayItem(getGPXFile()), actionsListener, activeColor, nightMode);
adapter.setItems(items);
blocksView.setLayoutManager(new LinearLayoutManager(app, LinearLayoutManager.HORIZONTAL, false));
blocksView.setAdapter(sbAdapter);
blocksView.setAdapter(adapter);
}
}
public void prepareData(GPXTrackAnalysis analysis, List<StatBlock> listItems, String title,
String value, @DrawableRes int imageResId, @ColorRes int imageColorId,
public void stopUpdatingStatBlocks() {
handler.removeCallbacks(updatingItems);
updateRunning = false;
}
public void runUpdatingStatBlocks() {
updatingItems = new Runnable() {
@Override
public void run() {
if (adapter != null) {
initItems();
adapter.setItems(items);
AndroidUiHelper.updateVisibility(blocksView, !Algorithms.isEmpty(items));
}
int interval = app.getSettings().SAVE_GLOBAL_TRACK_INTERVAL.get();
handler.postDelayed(this, Math.max(1000, interval));
}
};
updateRunning = handler.post(updatingItems);
}
public void initItems() {
GPXFile gpxFile = getGPXFile();
GpxDisplayItem gpxDisplayItem = null;
GPXTrackAnalysis analysis = null;
boolean withoutGaps = true;
if (gpxFile.tracks.size() > 0) {
gpxDisplayItem = getDisplayItem(gpxFile);
}
if (gpxDisplayItem != null) {
analysis = gpxDisplayItem.analysis;
withoutGaps = !selectedGpxFile.isJoinSegments() && gpxDisplayItem.isGeneralTrack();
}
if (analysis != null) {
float totalDistance = withoutGaps ? analysis.totalDistanceWithoutGaps : analysis.totalDistance;
float timeSpan = withoutGaps ? analysis.timeSpanWithoutGaps : analysis.timeSpan;
String asc = OsmAndFormatter.getFormattedAlt(analysis.diffElevationUp, app);
String desc = OsmAndFormatter.getFormattedAlt(analysis.diffElevationDown, app);
String avg = OsmAndFormatter.getFormattedSpeed(analysis.avgSpeed, app);
String max = OsmAndFormatter.getFormattedSpeed(analysis.maxSpeed, app);
items.clear();
prepareData(analysis, app.getString(R.string.distance), OsmAndFormatter.getFormattedDistance(totalDistance, app),
R.drawable.ic_action_track_16, R.color.icon_color_default_light, GPXDataSetType.ALTITUDE, GPXDataSetType.SPEED, ItemType.ITEM_DISTANCE);
prepareData(analysis, app.getString(R.string.altitude_ascent), asc,
R.drawable.ic_action_arrow_up_16, R.color.gpx_chart_red, GPXDataSetType.SLOPE, null, ItemType.ITEM_ALTITUDE);
prepareData(analysis, app.getString(R.string.altitude_descent), desc,
R.drawable.ic_action_arrow_down_16, R.color.gpx_pale_green, GPXDataSetType.ALTITUDE, GPXDataSetType.SLOPE, ItemType.ITEM_ALTITUDE);
prepareData(analysis, app.getString(R.string.average_speed), avg,
R.drawable.ic_action_speed_16, R.color.icon_color_default_light, GPXDataSetType.SPEED, null, ItemType.ITEM_SPEED);
prepareData(analysis, app.getString(R.string.max_speed), max,
R.drawable.ic_action_max_speed_16, R.color.icon_color_default_light, GPXDataSetType.SPEED, null, ItemType.ITEM_SPEED);
prepareData(analysis, app.getString(R.string.shared_string_time_span),
Algorithms.formatDuration((int) (timeSpan / 1000), app.accessibilityEnabled()),
R.drawable.ic_action_time_span_16, R.color.icon_color_default_light, GPXDataSetType.SPEED, null, ItemType.ITEM_TIME);
}
}
public void prepareData(GPXTrackAnalysis analysis, String title, String value,
@DrawableRes int imageResId, @ColorRes int imageColorId,
GPXDataSetType firstType, GPXDataSetType secondType, ItemType itemType) {
StatBlock statBlock = new StatBlock(title, value, imageResId, imageColorId, firstType, secondType, itemType);
switch (statBlock.itemType) {
case ITEM_DISTANCE: {
if (analysis.totalDistance != 0f) {
listItems.add(statBlock);
items.add(statBlock);
}
break;
}
case ITEM_ALTITUDE: {
if (analysis.hasElevationData) {
listItems.add(statBlock);
items.add(statBlock);
}
break;
}
case ITEM_SPEED: {
if (analysis.isSpeedSpecified()) {
listItems.add(statBlock);
items.add(statBlock);
}
break;
}
case ITEM_TIME: {
if (analysis.hasSpeedData) {
listItems.add(statBlock);
items.add(statBlock);
}
break;
}
}
}
private void setImageDrawable(ImageView iv, @DrawableRes Integer resId, @ColorRes int color) {
Drawable icon = resId != null ? app.getUIUtilities().getIcon(resId, color)
: UiUtilities.tintDrawable(iv.getDrawable(), getResolvedColor(color));
iv.setImageDrawable(icon);
}
@ColorInt
protected int getResolvedColor(@ColorRes int colorId) {
return ContextCompat.getColor(app, colorId);
}
public class StatBlock {
private final String title;
private final String value;
private final int imageResId;
@ -164,14 +195,16 @@ public class GpxBlockStatisticsBuilder {
private class BlockStatisticsAdapter extends RecyclerView.Adapter<BlockStatisticsViewHolder> {
private final List<StatBlock> items = new ArrayList<>();
private final GpxDisplayItem displayItem;
private final SegmentActionsListener actionsListener;
@ColorInt
private final int activeColor;
private final List<StatBlock> statBlocks;
private final boolean nightMode;
private final SegmentActionsListener actionsListener;
public BlockStatisticsAdapter(List<StatBlock> statBlocks, SegmentActionsListener actionsListener, @ColorInt int activeColor, boolean nightMode) {
this.statBlocks = statBlocks;
public BlockStatisticsAdapter(GpxDisplayItem displayItem, SegmentActionsListener actionsListener,
@ColorInt int activeColor, boolean nightMode) {
this.displayItem = displayItem;
this.actionsListener = actionsListener;
this.activeColor = activeColor;
this.nightMode = nightMode;
@ -179,7 +212,7 @@ public class GpxBlockStatisticsBuilder {
@Override
public int getItemCount() {
return statBlocks.size();
return items.size();
}
@NonNull
@ -192,46 +225,44 @@ public class GpxBlockStatisticsBuilder {
@Override
public void onBindViewHolder(BlockStatisticsViewHolder holder, int position) {
final StatBlock item = statBlocks.get(position);
final StatBlock item = items.get(position);
holder.valueText.setText(item.value);
holder.titleText.setText(item.title);
if (updateRunning) {
holder.titleText.setWidth(app.getResources().getDimensionPixelSize(R.dimen.map_route_buttons_width));
}
holder.valueText.setTextColor(activeColor);
holder.titleText.setTextColor(app.getResources().getColor(R.color.text_color_secondary_light));
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
List<GpxDisplayGroup> groups = displayHelper.getDisplayGroups(filterTypes);
GpxDisplayGroup group = null;
for (GpxDisplayGroup g : groups) {
if (g.isGeneralTrack()) {
group = g;
}
}
if (group == null && !groups.isEmpty()) {
group = groups.get(0);
}
if (group != null) {
GpxDisplayItem displayItem = group.getModifiableList().get(0);
if (displayItem != null && displayItem.analysis != null) {
ArrayList<GPXDataSetType> list = new ArrayList<>();
if (displayItem.analysis.hasElevationData || displayItem.analysis.isSpeedSpecified() || displayItem.analysis.hasSpeedData) {
if (item.firstType != null) {
list.add(item.firstType);
}
if (item.secondType != null) {
list.add(item.secondType);
}
GPXTrackAnalysis analysis = displayItem != null ? displayItem.analysis : null;
if (analysis != null) {
ArrayList<GPXDataSetType> list = new ArrayList<>();
if (analysis.hasElevationData || analysis.isSpeedSpecified() || analysis.hasSpeedData) {
if (item.firstType != null) {
list.add(item.firstType);
}
if (item.secondType != null) {
list.add(item.secondType);
}
displayItem.chartTypes = list.size() > 0 ? list.toArray(new GPXDataSetType[0]) : null;
displayItem.locationOnMap = displayItem.locationStart;
actionsListener.openAnalyzeOnMap(displayItem);
}
displayItem.chartTypes = list.size() > 0 ? list.toArray(new GPXDataSetType[0]) : null;
displayItem.locationOnMap = displayItem.locationStart;
actionsListener.openAnalyzeOnMap(displayItem);
}
}
});
setImageDrawable(holder.imageView, item.imageResId, item.imageColorId);
Drawable icon = app.getUIUtilities().getIcon(item.imageResId, item.imageColorId);
holder.imageView.setImageDrawable(icon);
AndroidUtils.setBackgroundColor(app, holder.divider, nightMode, R.color.divider_color_light, R.color.divider_color_dark);
AndroidUiHelper.updateVisibility(holder.divider, position != statBlocks.size() - 1);
AndroidUiHelper.updateVisibility(holder.divider, position != items.size() - 1);
}
public void setItems(List<StatBlock> items) {
this.items.clear();
this.items.addAll(items);
notifyDataSetChanged();
}
}

View file

@ -43,12 +43,11 @@ public class OverviewCard extends BaseCard {
private final SelectedGpxFile selectedGpxFile;
private final GpxBlockStatisticsBuilder blockStatisticsBuilder;
public OverviewCard(@NonNull MapActivity mapActivity, @NonNull TrackDisplayHelper displayHelper,
@NonNull SegmentActionsListener actionsListener, SelectedGpxFile selectedGpxFile) {
public OverviewCard(@NonNull MapActivity mapActivity, @NonNull SegmentActionsListener actionsListener, SelectedGpxFile selectedGpxFile) {
super(mapActivity);
this.actionsListener = actionsListener;
this.selectedGpxFile = selectedGpxFile;
blockStatisticsBuilder = new GpxBlockStatisticsBuilder(app, selectedGpxFile, displayHelper);
blockStatisticsBuilder = new GpxBlockStatisticsBuilder(app, selectedGpxFile);
}
@Override

View file

@ -326,7 +326,7 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
}
headerContainer.addView(overviewCard.getView());
} else {
overviewCard = new OverviewCard(getMapActivity(), displayHelper, this, selectedGpxFile);
overviewCard = new OverviewCard(getMapActivity(), this, selectedGpxFile);
overviewCard.setListener(this);
headerContainer.addView(overviewCard.build(getMapActivity()));
}
@ -760,7 +760,7 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
segment = segments.get(0);
}
}
GpxDisplayItemType[] filterTypes = new GpxDisplayItemType[] {GpxDisplayItemType.TRACK_SEGMENT};
GpxDisplayItemType[] filterTypes = new GpxDisplayItemType[]{GpxDisplayItemType.TRACK_SEGMENT};
List<GpxDisplayItem> items = TrackDisplayHelper.flatten(displayHelper.getOriginalGroups(filterTypes));
if (segment != null && !Algorithms.isEmpty(items)) {
SplitSegmentDialogFragment.showInstance(fragmentManager, displayHelper, items.get(0), segment);
@ -1013,6 +1013,7 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
public void openAnalyzeOnMap(GpxDisplayItem gpxItem) {
TrackDetailsMenu trackDetailsMenu = getMapActivity().getTrackDetailsMenu();
trackDetailsMenu.setGpxItem(gpxItem);
trackDetailsMenu.setSelectedGpxFile(selectedGpxFile);
trackDetailsMenu.show();
hide();
}
@ -1110,7 +1111,7 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
@Override
public void gpxSavingFinished(Exception errorMessage) {
if (selectedGpxFile != null) {
List<GpxDisplayGroup> groups = displayHelper.getDisplayGroups(new GpxDisplayItemType[] {GpxDisplayItemType.TRACK_SEGMENT});
List<GpxDisplayGroup> groups = displayHelper.getDisplayGroups(new GpxDisplayItemType[]{GpxDisplayItemType.TRACK_SEGMENT});
selectedGpxFile.setDisplayGroups(groups, app);
selectedGpxFile.processPoints(app);
}

View file

@ -169,6 +169,26 @@ public class TravelArticle {
return new String[]{md5.substring(0, 1), md5.substring(0, 2)};
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
TravelArticle that = (TravelArticle) o;
return TravelArticleIdentifier.areLatLonEqual(that.lat, that.lon, lat, lon) &&
Algorithms.objectEquals(file, that.file) &&
Algorithms.stringsEqual(routeId, that.routeId) &&
Algorithms.stringsEqual(routeSource, that.routeSource);
}
@Override
public int hashCode() {
return Algorithms.hash(file, lat, lon, routeId, routeSource);
}
public static class TravelArticleIdentifier implements Parcelable {
@Nullable File file;
double lat;
@ -249,7 +269,7 @@ public class TravelArticle {
return Algorithms.hash(file, lat, lon, routeId, routeSource);
}
private static boolean areLatLonEqual(double lat1, double lon1, double lat2, double lon2) {
public static boolean areLatLonEqual(double lat1, double lon1, double lat2, double lon2) {
boolean latEqual = (Double.isNaN(lat1) && Double.isNaN(lat2)) || Math.abs(lat1 - lat2) < 0.00001;
boolean lonEqual = (Double.isNaN(lon1) && Double.isNaN(lon2)) || Math.abs(lon1 - lon2) < 0.00001;
return latEqual && lonEqual;

View file

@ -174,7 +174,7 @@ public class TravelDbHelper implements TravelHelper {
}
@Override
public void initializeDataToDisplay() {
public void initializeDataToDisplay(boolean resetData) {
localDataHelper.refreshCachedData();
loadPopularArticles();
}
@ -292,7 +292,7 @@ public class TravelDbHelper implements TravelHelper {
}
String LANG_WHERE = " WHERE " + ARTICLES_COL_LANG + " = '" + language + "'";
SQLiteCursor cursor = conn.rawQuery(POP_ARTICLES_TABLE_SELECT + LANG_WHERE, null);
if(cursor == null) {
if (cursor == null) {
return popularArticles;
}
// read popular articles
@ -549,13 +549,13 @@ public class TravelDbHelper implements TravelHelper {
@Override
@Nullable
public TravelArticle getArticleById(@NonNull TravelArticleIdentifier articleId, @NonNull String lang, boolean readGpx, @Nullable GpxReadCallback callback) {
public TravelArticle getArticleById(@NonNull TravelArticleIdentifier articleId, @Nullable String lang, boolean readGpx, @Nullable GpxReadCallback callback) {
TravelArticle res = null;
SQLiteConnection conn = openConnection();
String routeId = articleId.routeId;
if (conn != null && !Algorithms.isEmpty(routeId)) {
if (conn != null && !Algorithms.isEmpty(routeId) && lang != null) {
SQLiteCursor cursor = conn.rawQuery(ARTICLES_TABLE_SELECT + " WHERE " + ARTICLES_COL_TRIP_ID + " = ? AND "
+ ARTICLES_COL_LANG + " = ?", new String[] { routeId, lang });
+ ARTICLES_COL_LANG + " = ?", new String[]{routeId, lang});
if (cursor != null) {
if (cursor.moveToFirst()) {
res = readArticle(cursor);

View file

@ -3,7 +3,6 @@ package net.osmand.plus.wikivoyage.data;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import net.osmand.GPXUtilities;
import net.osmand.GPXUtilities.GPXFile;
import net.osmand.data.LatLon;
import net.osmand.data.QuadRect;
@ -18,6 +17,7 @@ public interface TravelHelper {
interface GpxReadCallback {
void onGpxFileReading();
void onGpxFileRead(@Nullable GPXFile gpxFile);
}
@ -25,7 +25,7 @@ public interface TravelHelper {
void initializeDataOnAppStartup();
void initializeDataToDisplay();
void initializeDataToDisplay(boolean resetData);
boolean isAnyTravelBookPresent();
@ -39,7 +39,7 @@ public interface TravelHelper {
Map<WikivoyageSearchResult, List<WikivoyageSearchResult>> getNavigationMap(@NonNull TravelArticle article);
@Nullable
TravelArticle getArticleById(@NonNull TravelArticleIdentifier articleId, @NonNull String lang, boolean readGpx, @Nullable GpxReadCallback callback);
TravelArticle getArticleById(@NonNull TravelArticleIdentifier articleId, @Nullable String lang, boolean readGpx, @Nullable GpxReadCallback callback);
@Nullable
TravelArticle getArticleByTitle(@NonNull String title, @NonNull String lang, boolean readGpx, @Nullable GpxReadCallback callback);

View file

@ -69,9 +69,7 @@ public class TravelObfHelper implements TravelHelper {
public static final String ROUTE_ARTICLE = "route_article";
public static final String ROUTE_ARTICLE_POINT = "route_article_point";
public static final String ROUTE_TRACK = "route_track";
public static final int POPULAR_ARTICLES_SEARCH_RADIUS = 100000;
public static final int ARTICLE_SEARCH_RADIUS = 50000;
public static final int GPX_TRACKS_SEARCH_RADIUS = 10000;
public static final int MAX_POPULAR_ARTICLES_COUNT = 30;
public static final String REF_TAG = "ref";
public static final String NAME_TAG = "name";
@ -82,6 +80,9 @@ public class TravelObfHelper implements TravelHelper {
private List<TravelArticle> popularArticles = new ArrayList<>();
private final Map<TravelArticleIdentifier, Map<String, TravelArticle>> cachedArticles = new ConcurrentHashMap<>();
private final TravelLocalDataHelper localDataHelper;
private int searchRadius = ARTICLE_SEARCH_RADIUS;
private int foundAmenitiesIndex = 0;
private final List<Pair<File, Amenity>> foundAmenities = new ArrayList<>();
public TravelObfHelper(OsmandApplication app) {
this.app = app;
@ -99,7 +100,13 @@ public class TravelObfHelper implements TravelHelper {
}
@Override
public void initializeDataToDisplay() {
public void initializeDataToDisplay(boolean resetData) {
if (resetData) {
foundAmenities.clear();
foundAmenitiesIndex = 0;
popularArticles.clear();
searchRadius = ARTICLE_SEARCH_RADIUS;
}
localDataHelper.refreshCachedData();
loadPopularArticles();
}
@ -107,38 +114,47 @@ public class TravelObfHelper implements TravelHelper {
@NonNull
public synchronized List<TravelArticle> loadPopularArticles() {
String lang = app.getLanguage();
List<TravelArticle> popularArticles = new ArrayList<>();
final List<Pair<File, Amenity>> amenities = new ArrayList<>();
final LatLon location = app.getMapViewTrackingUtilities().getMapLocation();
for (final BinaryMapIndexReader reader : getReaders()) {
try {
searchAmenity(amenities, location, reader, POPULAR_ARTICLES_SEARCH_RADIUS, -1, ROUTE_ARTICLE);
searchAmenity(amenities, location, reader, GPX_TRACKS_SEARCH_RADIUS, 15, ROUTE_TRACK);
} catch (Exception e) {
LOG.error(e.getMessage(), e);
List<TravelArticle> popularArticles = new ArrayList<>(this.popularArticles);
if (foundAmenities.size() - foundAmenitiesIndex < MAX_POPULAR_ARTICLES_COUNT) {
final LatLon location = app.getMapViewTrackingUtilities().getMapLocation();
for (final BinaryMapIndexReader reader : getReaders()) {
try {
searchAmenity(foundAmenities, location, reader, searchRadius, -1, ROUTE_ARTICLE);
searchAmenity(foundAmenities, location, reader, searchRadius / 5, 15, ROUTE_TRACK);
} catch (Exception e) {
LOG.error(e.getMessage(), e);
}
}
if (foundAmenities.size() > 0) {
Collections.sort(foundAmenities, new Comparator<Pair<File, Amenity>>() {
@Override
public int compare(Pair article1, Pair article2) {
Amenity amenity1 = (Amenity) article1.second;
double d1 = MapUtils.getDistance(amenity1.getLocation(), location)
/ (ROUTE_ARTICLE.equals(amenity1.getSubType()) ? 5 : 1);
Amenity amenity2 = (Amenity) article2.second;
double d2 = MapUtils.getDistance(amenity2.getLocation(), location)
/ (ROUTE_ARTICLE.equals(amenity2.getSubType()) ? 5 : 1);
return Double.compare(d1, d2);
}
});
}
searchRadius *= 2;
}
if (amenities.size() > 0) {
Collections.sort(amenities, new Comparator<Pair<File, Amenity>>() {
@Override
public int compare(Pair article1, Pair article2) {
int d1 = (int) (MapUtils.getDistance(((Amenity) article1.second).getLocation(), location));
int d2 = (int) (MapUtils.getDistance(((Amenity) article2.second).getLocation(), location));
return d1 < d2 ? -1 : (d1 == d2 ? 0 : 1);
}
});
for (Pair<File, Amenity> amenity : amenities) {
if (!Algorithms.isEmpty(amenity.second.getName(lang))) {
TravelArticle article = cacheTravelArticles(amenity.first, amenity.second, lang, false, null);
if (article != null) {
popularArticles.add(article);
if (popularArticles.size() >= MAX_POPULAR_ARTICLES_COUNT) {
break;
}
int pagesCount = popularArticles.size() / MAX_POPULAR_ARTICLES_COUNT;
while (foundAmenitiesIndex < foundAmenities.size() - 1) {
Pair<File, Amenity> amenity = foundAmenities.get(foundAmenitiesIndex);
if (!Algorithms.isEmpty(amenity.second.getName(lang))) {
TravelArticle article = cacheTravelArticles(amenity.first, amenity.second, lang, false, null);
if (article != null && !popularArticles.contains(article)) {
popularArticles.add(article);
if (popularArticles.size() >= (pagesCount + 1) * MAX_POPULAR_ARTICLES_COUNT) {
break;
}
}
}
foundAmenitiesIndex++;
}
this.popularArticles = popularArticles;
return popularArticles;
@ -616,8 +632,8 @@ public class TravelObfHelper implements TravelHelper {
}
@Override
public TravelArticle getArticleById(@NonNull TravelArticleIdentifier articleId, @NonNull String lang,
boolean readGpx, @Nullable GpxReadCallback callback) {
public TravelArticle getArticleById(@NonNull TravelArticleIdentifier articleId, @Nullable String lang,
boolean readGpx, @Nullable GpxReadCallback callback) {
TravelArticle article = getCachedArticle(articleId, lang, readGpx, callback);
if (article == null) {
article = localDataHelper.getSavedArticle(articleId.file, articleId.routeId, lang);
@ -629,8 +645,8 @@ public class TravelObfHelper implements TravelHelper {
}
@Nullable
private TravelArticle getCachedArticle(@NonNull TravelArticleIdentifier articleId, @NonNull String lang,
boolean readGpx, @Nullable GpxReadCallback callback) {
private TravelArticle getCachedArticle(@NonNull TravelArticleIdentifier articleId, @Nullable String lang,
boolean readGpx, @Nullable GpxReadCallback callback) {
TravelArticle article = null;
Map<String, TravelArticle> articles = cachedArticles.get(articleId);
if (articles != null) {

View file

@ -18,8 +18,9 @@ import net.osmand.plus.wikivoyage.explore.travelcards.OpenBetaTravelCard;
import net.osmand.plus.wikivoyage.explore.travelcards.OpenBetaTravelCard.OpenBetaTravelVH;
import net.osmand.plus.wikivoyage.explore.travelcards.StartEditingTravelCard;
import net.osmand.plus.wikivoyage.explore.travelcards.StartEditingTravelCard.StartEditingTravelVH;
import net.osmand.plus.wikivoyage.explore.travelcards.TravelButtonCard;
import net.osmand.plus.wikivoyage.explore.travelcards.TravelButtonCard.TravelButtonVH;
import net.osmand.plus.wikivoyage.explore.travelcards.TravelDownloadUpdateCard;
import net.osmand.plus.wikivoyage.explore.travelcards.TravelDownloadUpdateCard.DownloadUpdateVH;
import net.osmand.plus.wikivoyage.explore.travelcards.TravelGpxCard;
import net.osmand.plus.wikivoyage.explore.travelcards.TravelGpxCard.TravelGpxVH;
import net.osmand.plus.wikivoyage.explore.travelcards.TravelNeededMapsCard;
@ -53,12 +54,13 @@ public class ExploreRvAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
case TravelGpxCard.TYPE:
return new TravelGpxVH(inflate(parent, R.layout.wikivoyage_travel_gpx_card));
case TravelDownloadUpdateCard.TYPE:
return new DownloadUpdateVH(inflate(parent, R.layout.travel_download_update_card));
case HeaderTravelCard.TYPE:
return new HeaderTravelVH(inflate(parent, R.layout.wikivoyage_list_header));
case TravelButtonCard.TYPE:
return new TravelButtonVH(inflate(parent, R.layout.wikivoyage_button_card));
case TravelDownloadUpdateCard.TYPE:
case TravelNeededMapsCard.TYPE:
return new NeededMapsVH(inflate(parent, R.layout.travel_needed_maps_card));
@ -115,6 +117,9 @@ public class ExploreRvAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
private int getLastArticleItemIndex() {
for (int i = items.size() - 1; i > 0; i--) {
BaseTravelCard o = items.get(i);
if (o instanceof TravelButtonCard) {
return 0;
}
if (o instanceof ArticleTravelCard || o instanceof TravelGpxCard) {
return i;
}
@ -205,7 +210,7 @@ public class ExploreRvAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
if(onlyProgress) {
TravelDownloadUpdateCard dc = this.downloadCard;
if(dc != null) {
dc.updateProgresBar();
dc.updateView();
}
return;
}

View file

@ -1,7 +1,6 @@
package net.osmand.plus.wikivoyage.explore;
import android.app.Activity;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Pair;
@ -37,6 +36,7 @@ import net.osmand.plus.wikivoyage.explore.travelcards.BaseTravelCard;
import net.osmand.plus.wikivoyage.explore.travelcards.HeaderTravelCard;
import net.osmand.plus.wikivoyage.explore.travelcards.OpenBetaTravelCard;
import net.osmand.plus.wikivoyage.explore.travelcards.StartEditingTravelCard;
import net.osmand.plus.wikivoyage.explore.travelcards.TravelButtonCard;
import net.osmand.plus.wikivoyage.explore.travelcards.TravelDownloadUpdateCard;
import net.osmand.plus.wikivoyage.explore.travelcards.TravelGpxCard;
import net.osmand.plus.wikivoyage.explore.travelcards.TravelNeededMapsCard;
@ -46,6 +46,8 @@ import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
import static net.osmand.plus.wikivoyage.explore.WikivoyageExploreActivity.*;
public class ExploreTabFragment extends BaseOsmAndFragment implements DownloadEvents, TravelLocalDataHelper.Listener {
private static boolean SHOW_TRAVEL_UPDATE_CARD = true;
@ -63,9 +65,7 @@ public class ExploreTabFragment extends BaseOsmAndFragment implements DownloadEv
private DownloadValidationManager downloadManager;
@Nullable
private IndexItem currentDownloadingIndexItem;
@Nullable
private IndexItem mainIndexItem;
private final List<IndexItem> mainIndexItems = new ArrayList<>();
private final List<IndexItem> neededIndexItems = new ArrayList<>();
private boolean waitForIndexes;
@ -175,17 +175,39 @@ public class ExploreTabFragment extends BaseOsmAndFragment implements DownloadEv
if (!Version.isPaidVersion(app) && !OpenBetaTravelCard.isClosed()) {
items.add(new OpenBetaTravelCard(activity, nightMode));
}
List<TravelArticle> popularArticles = app.getTravelHelper().getPopularArticles();
final List<TravelArticle> popularArticles = app.getTravelHelper().getPopularArticles();
if (!popularArticles.isEmpty()) {
items.add(new HeaderTravelCard(app, nightMode, getString(R.string.popular_destinations)));
for (TravelArticle article : popularArticles) {
if (article instanceof TravelGpx) {
items.add(new TravelGpxCard(app, nightMode, (TravelGpx) article, getActivity()));
items.add(new TravelGpxCard(app, nightMode, (TravelGpx) article, activity));
} else {
items.add(new ArticleTravelCard(app, nightMode, article, activity.getSupportFragmentManager()));
}
}
}
TravelButtonCard travelButtonCard = new TravelButtonCard(app, nightMode);
travelButtonCard.setListener(new TravelNeededMapsCard.CardListener() {
@Override
public void onPrimaryButtonClick() {
if (activity instanceof WikivoyageExploreActivity) {
new LoadWikivoyageData((WikivoyageExploreActivity) activity,false).execute();
}
}
@Override
public void onSecondaryButtonClick() {
}
@Override
public void onIndexItemClick(IndexItem item) {
}
});
items.add(travelButtonCard);
items.add(new StartEditingTravelCard(activity, nightMode));
adapter.setItems(items);
final DownloadIndexesThread downloadThread = app.getDownloadThread();
@ -199,17 +221,24 @@ public class ExploreTabFragment extends BaseOsmAndFragment implements DownloadEv
}
private void removeRedundantCards() {
if (mainIndexItem != null && mainIndexItem.isDownloaded() && !mainIndexItem.isOutdated()) {
removeDownloadUpdateCard();
}
boolean allMapsDownloaded = true;
for (IndexItem item : neededIndexItems) {
boolean allTravelGuideDownloaded = true;
for (IndexItem item : mainIndexItems) {
if (!item.isDownloaded()) {
allMapsDownloaded = false;
allTravelGuideDownloaded = false;
break;
}
}
if (allMapsDownloaded) {
if (allTravelGuideDownloaded) {
removeDownloadUpdateCard();
}
boolean neededMapsDownloaded = true;
for (IndexItem item : neededIndexItems) {
if (!item.isDownloaded()) {
neededMapsDownloaded = false;
break;
}
}
if (neededMapsDownloaded) {
removeNeededMapsCard();
}
}
@ -218,8 +247,9 @@ public class ExploreTabFragment extends BaseOsmAndFragment implements DownloadEv
new ProcessIndexItemsTask(this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
private void addIndexItemCards(IndexItem mainIndexItem, List<IndexItem> neededIndexItems) {
this.mainIndexItem = mainIndexItem;
private void addIndexItemCards(List<IndexItem> mainIndexItem, List<IndexItem> neededIndexItems) {
this.mainIndexItems.clear();
this.mainIndexItems.addAll(mainIndexItem);
this.neededIndexItems.clear();
this.neededIndexItems.addAll(neededIndexItems);
addDownloadUpdateCard();
@ -228,53 +258,58 @@ public class ExploreTabFragment extends BaseOsmAndFragment implements DownloadEv
private void addDownloadUpdateCard() {
final OsmandApplication app = getMyApplication();
if (app != null) {
final DownloadIndexesThread downloadThread = app.getDownloadThread();
boolean outdated = mainIndexItem != null && mainIndexItem.isOutdated();
boolean needsDownloading = mainIndexItem != null && !mainIndexItem.isDownloaded();
if (!app.getTravelHelper().isAnyTravelBookPresent() || needsDownloading || (outdated && SHOW_TRAVEL_UPDATE_CARD)) {
boolean showOtherMaps = false;
if (needsDownloading) {
List<IndexItem> items = downloadThread.getIndexes().getWikivoyageItems();
showOtherMaps = items != null && items.size() > 1;
if (app != null && !mainIndexItems.isEmpty() && SHOW_TRAVEL_UPDATE_CARD) {
boolean outdated = isMapsOutdated();
downloadUpdateCard = new TravelDownloadUpdateCard(app, nightMode, mainIndexItems, !outdated);
downloadUpdateCard.setListener(new TravelDownloadUpdateCard.CardListener() {
@Override
public void onPrimaryButtonClick() {
if (downloadManager != null) {
downloadManager.startDownload(getMyActivity(), getAllItemsForDownload(mainIndexItems));
adapter.updateDownloadUpdateCard(false);
}
}
downloadUpdateCard = new TravelDownloadUpdateCard(app, nightMode, !outdated);
downloadUpdateCard.setShowOtherMapsBtn(showOtherMaps);
downloadUpdateCard.setListener(new TravelDownloadUpdateCard.ClickListener() {
@Override
public void onPrimaryButtonClick() {
if (mainIndexItem != null && downloadManager != null) {
downloadManager.startDownload(getMyActivity(), mainIndexItem);
adapter.updateDownloadUpdateCard(false);
}
@Override
public void onSecondaryButtonClick() {
if (downloadUpdateCard.isDownloading()) {
app.getDownloadThread().cancelDownload(mainIndexItems);
adapter.updateDownloadUpdateCard(false);
} else {
SHOW_TRAVEL_UPDATE_CARD = false;
removeDownloadUpdateCard();
}
}
@Override
public void onSecondaryButtonClick() {
if (downloadUpdateCard.isLoading()) {
downloadThread.cancelDownload(mainIndexItem);
adapter.updateDownloadUpdateCard(false);
} else if (!downloadUpdateCard.isDownload()) {
SHOW_TRAVEL_UPDATE_CARD = false;
removeDownloadUpdateCard();
} else if (downloadUpdateCard.isShowOtherMapsBtn()) {
Activity activity = getActivity();
if (activity != null) {
Intent newIntent = new Intent(activity,
((OsmandApplication) activity.getApplication()).getAppCustomization().getDownloadActivity());
newIntent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
activity.startActivity(newIntent);
}
@Override
public void onIndexItemClick(IndexItem item) {
if (item.getType() == DownloadActivityType.WIKIPEDIA_FILE && !Version.isPaidVersion(app)) {
FragmentManager fm = getFragmentManager();
if (fm != null) {
ChoosePlanDialogFragment.showWikipediaInstance(fm);
}
} else {
DownloadIndexesThread downloadThread = app.getDownloadThread();
if (downloadThread.isDownloading(item)) {
downloadThread.cancelDownload(item);
} else if (!item.isDownloaded() && downloadManager != null) {
downloadManager.startDownload(getMyActivity(), item);
}
adapter.updateDownloadUpdateCard(false);
}
});
downloadUpdateCard.setIndexItem(mainIndexItem);
adapter.addDownloadUpdateCard(downloadUpdateCard);
}
});
adapter.addDownloadUpdateCard(downloadUpdateCard);
}
}
private boolean isMapsOutdated() {
for (IndexItem indexItem : mainIndexItems) {
if (indexItem.isOutdated()) {
return true;
}
}
return false;
}
private void addNeededMapsCard() {
@ -285,7 +320,7 @@ public class ExploreTabFragment extends BaseOsmAndFragment implements DownloadEv
@Override
public void onPrimaryButtonClick() {
if (downloadManager != null) {
downloadManager.startDownload(getMyActivity(), getAllItemsForDownload());
downloadManager.startDownload(getMyActivity(), getAllItemsForDownload(neededIndexItems));
adapter.updateNeededMapsCard(false);
}
}
@ -323,10 +358,10 @@ public class ExploreTabFragment extends BaseOsmAndFragment implements DownloadEv
}
}
private IndexItem[] getAllItemsForDownload() {
private IndexItem[] getAllItemsForDownload(List<IndexItem> indexItems) {
boolean paidVersion = Version.isPaidVersion(getMyApplication());
ArrayList<IndexItem> res = new ArrayList<>();
for (IndexItem item : neededIndexItems) {
for (IndexItem item : indexItems) {
if (!item.isDownloaded() && (paidVersion || item.getType() != DownloadActivityType.WIKIPEDIA_FILE)) {
res.add(item);
}
@ -344,7 +379,7 @@ public class ExploreTabFragment extends BaseOsmAndFragment implements DownloadEv
neededMapsCard = null;
}
private static class ProcessIndexItemsTask extends AsyncTask<Void, Void, Pair<IndexItem, List<IndexItem>>> {
private static class ProcessIndexItemsTask extends AsyncTask<Void, Void, Pair<List<IndexItem>, List<IndexItem>>> {
private static final DownloadActivityType[] types = new DownloadActivityType[]{
DownloadActivityType.NORMAL_FILE,
@ -354,40 +389,41 @@ public class ExploreTabFragment extends BaseOsmAndFragment implements DownloadEv
private final OsmandApplication app;
private final WeakReference<ExploreTabFragment> weakFragment;
private final String fileName;
ProcessIndexItemsTask(ExploreTabFragment fragment) {
app = fragment.getMyApplication();
weakFragment = new WeakReference<>(fragment);
fileName = app != null ? app.getTravelHelper().getWikivoyageFileName() : null;
}
@Override
protected Pair<IndexItem, List<IndexItem>> doInBackground(Void... voids) {
if (fileName != null) {
IndexItem mainItem = app.getDownloadThread().getIndexes().getWikivoyageItem(fileName);
List<IndexItem> neededItems = new ArrayList<>();
for (TravelArticle article : app.getTravelHelper().getBookmarksHelper().getSavedArticles()) {
LatLon latLon = new LatLon(article.getLat(), article.getLon());
try {
for (DownloadActivityType type : types) {
IndexItem item = DownloadResources.findSmallestIndexItemAt(app, latLon, type);
if (item != null && !item.isDownloaded() && !neededItems.contains(item)) {
neededItems.add(item);
}
}
} catch (IOException e) {
// ignore
protected Pair<List<IndexItem>, List<IndexItem>> doInBackground(Void... voids) {
List<IndexItem> mainItems = new ArrayList<>();
List<IndexItem> allWikivoyageItems = app.getDownloadThread().getIndexes().getWikivoyageItems();
if (allWikivoyageItems != null) {
for (IndexItem item : allWikivoyageItems) {
if (!item.isDownloaded() && !mainItems.contains(item)) {
mainItems.add(item);
}
}
return new Pair<>(mainItem, neededItems);
}
return null;
List<IndexItem> neededItems = new ArrayList<>();
for (TravelArticle article : app.getTravelHelper().getBookmarksHelper().getSavedArticles()) {
LatLon latLon = new LatLon(article.getLat(), article.getLon());
try {
for (DownloadActivityType type : types) {
IndexItem item = DownloadResources.findSmallestIndexItemAt(app, latLon, type);
if (item != null && !item.isDownloaded() && !neededItems.contains(item)) {
neededItems.add(item);
}
}
} catch (IOException e) {
// ignore
}
}
return new Pair<>(mainItems, neededItems);
}
@Override
protected void onPostExecute(Pair<IndexItem, List<IndexItem>> res) {
protected void onPostExecute(Pair<List<IndexItem>, List<IndexItem>> res) {
ExploreTabFragment fragment = weakFragment.get();
if (res != null && fragment != null && fragment.isResumed()) {
fragment.addIndexItemCards(res.first, res.second);

View file

@ -326,12 +326,12 @@ public class WikivoyageExploreActivity extends TabActivity implements DownloadEv
public void onFinish(AppInitializer init) {
WikivoyageExploreActivity activity = activityRef.get();
if (AndroidUtils.isActivityNotDestroyed(activity)) {
new LoadWikivoyageData(activity).execute();
new LoadWikivoyageData(activity,true).execute();
}
}
});
} else {
new LoadWikivoyageData(this).execute();
new LoadWikivoyageData(this,true).execute();
}
}
@ -380,19 +380,21 @@ public class WikivoyageExploreActivity extends TabActivity implements DownloadEv
updateFragments();
}
private static class LoadWikivoyageData extends AsyncTask<Void, Void, Void> {
public static class LoadWikivoyageData extends AsyncTask<Void, Void, Void> {
private final WeakReference<WikivoyageExploreActivity> activityRef;
private final TravelHelper travelHelper;
private final boolean resetData;
LoadWikivoyageData(WikivoyageExploreActivity activity) {
LoadWikivoyageData(WikivoyageExploreActivity activity, boolean resetData) {
travelHelper = activity.getMyApplication().getTravelHelper();
activityRef = new WeakReference<>(activity);
this.resetData = resetData;
}
@Override
protected Void doInBackground(Void... params) {
travelHelper.initializeDataToDisplay();
travelHelper.initializeDataToDisplay(resetData);
return null;
}

View file

@ -0,0 +1,56 @@
package net.osmand.plus.wikivoyage.explore.travelcards;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import net.osmand.plus.UiUtilities;
import net.osmand.plus.wikivoyage.explore.travelcards.TravelNeededMapsCard.CardListener;
public class TravelButtonCard extends BaseTravelCard {
public static final int TYPE = 5;
private CardListener listener;
public TravelButtonCard(OsmandApplication app, boolean nightMode) {
super(app, nightMode);
}
public void setListener(CardListener listener) {
this.listener = listener;
}
@Override
public void bindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder) {
if (viewHolder instanceof TravelButtonVH) {
final TravelButtonVH holder = (TravelButtonVH) viewHolder;
UiUtilities.setupDialogButton(nightMode, holder.button, UiUtilities.DialogButtonType.SECONDARY, R.string.show_more);
holder.button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (listener != null) {
listener.onPrimaryButtonClick();
}
}
});
}
}
public static class TravelButtonVH extends RecyclerView.ViewHolder {
final View button;
public TravelButtonVH(View itemView) {
super(itemView);
button = itemView.findViewById(R.id.button);
}
}
@Override
public int getCardType() {
return TYPE;
}
}

View file

@ -1,257 +1,47 @@
package net.osmand.plus.wikivoyage.explore.travelcards;
import android.graphics.drawable.Drawable;
import android.view.View;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.StringRes;
import androidx.recyclerview.widget.RecyclerView;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import net.osmand.plus.download.IndexItem;
import java.lang.ref.WeakReference;
import java.text.DateFormat;
import java.util.List;
public class TravelDownloadUpdateCard extends BaseTravelCard {
public class TravelDownloadUpdateCard extends TravelNeededMapsCard {
public static final int TYPE = 50;
private boolean download;
private boolean showOtherMapsBtn;
private WeakReference<DownloadUpdateVH> ref;
private final boolean download;
private ClickListener listener;
@Nullable
private IndexItem indexItem;
private DateFormat dateFormat;
public boolean isDownload() {
return download;
}
public boolean isShowOtherMapsBtn() {
return showOtherMapsBtn;
}
public void setShowOtherMapsBtn(boolean showOtherMapsBtn) {
this.showOtherMapsBtn = showOtherMapsBtn;
}
public void setListener(ClickListener listener) {
this.listener = listener;
}
public void setIndexItem(@Nullable IndexItem indexItem) {
this.indexItem = indexItem;
}
public TravelDownloadUpdateCard(OsmandApplication app, boolean nightMode, boolean download) {
super(app, nightMode);
public TravelDownloadUpdateCard(@NonNull OsmandApplication app, boolean nightMode, @NonNull List<IndexItem> items,
boolean download) {
super(app, nightMode, items);
this.download = download;
dateFormat = android.text.format.DateFormat.getMediumDateFormat(app);
}
public int getTitle() {
if (isDownloading()) {
return R.string.shared_string_downloading;
}
return download ? R.string.download_file : R.string.update_is_available;
}
@Override
public void bindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder) {
if (viewHolder instanceof DownloadUpdateVH) {
boolean loading = isLoading();
DownloadUpdateVH holder = (DownloadUpdateVH) viewHolder;
this.ref = new WeakReference<TravelDownloadUpdateCard.DownloadUpdateVH>(holder);
holder.title.setText(getTitle(loading));
holder.icon.setImageResource(getIconRes());
holder.description.setText(getDescription());
if (indexItem == null) {
holder.fileDataContainer.setVisibility(View.GONE);
} else {
holder.fileDataContainer.setVisibility(View.VISIBLE);
holder.fileIcon.setImageDrawable(getFileIcon());
holder.fileTitle.setText(getFileTitle());
holder.fileDescription.setText(getFileDescription());
holder.progressBar.setVisibility(loading ? View.VISIBLE : View.GONE);
updateProgressBar(holder);
}
boolean primaryBtnVisible = updatePrimaryButton(holder, loading);
boolean secondaryBtnVisible = updateSecondaryButton(holder, loading);
holder.buttonsDivider.setVisibility(primaryBtnVisible && secondaryBtnVisible ? View.VISIBLE : View.GONE);
public int getDescription() {
if (!isInternetAvailable()) {
return R.string.no_index_file_to_download;
}
return download ? R.string.travel_card_download_descr : R.string.travel_card_update_descr;
}
public void updateProgresBar() {
if(ref != null) {
DownloadUpdateVH holder = ref.get();
if (holder != null && holder.itemView.isShown()) {
updateProgressBar(holder);
}
}
}
private void updateProgressBar(DownloadUpdateVH holder) {
if (isLoadingInProgress()) {
int progress = app.getDownloadThread().getCurrentDownloadingItemProgress();
holder.progressBar.setProgress(progress < 0 ? 0 : progress);
} else {
holder.progressBar.setProgress(0);
}
@Override
public int getIconRes() {
return download ? R.drawable.travel_card_download_icon : R.drawable.travel_card_update_icon;
}
@Override
public int getCardType() {
return TYPE;
}
@NonNull
private String getTitle(boolean loading) {
if (loading) {
return app.getString(R.string.shared_string_downloading);
}
return app.getString(download ? R.string.download_file : R.string.update_is_available);
}
private int getIconRes() {
return download ? R.drawable.travel_card_download_icon : R.drawable.travel_card_update_icon;
}
@NonNull
private String getDescription() {
if (!isInternetAvailable()) {
return app.getString(R.string.no_index_file_to_download);
}
return app.getString(download ? R.string.travel_card_download_descr : R.string.travel_card_update_descr);
}
@NonNull
private String getFileTitle() {
return indexItem == null ? "" : indexItem.getVisibleName(app, app.getRegions(), false);
}
@NonNull
private String getFileDescription() {
StringBuilder sb = new StringBuilder();
if (indexItem != null) {
sb.append(app.getString(R.string.file_size_in_mb, indexItem.getArchiveSizeMB()));
sb.append("");
sb.append(indexItem.getRemoteDate(dateFormat));
}
return sb.toString();
}
private Drawable getFileIcon() {
return getActiveIcon(R.drawable.ic_action_read_article);
}
/**
* @return true if button is visible, false otherwise.
*/
private boolean updateSecondaryButton(DownloadUpdateVH vh, boolean loading) {
if (loading || !download || showOtherMapsBtn) {
vh.secondaryBtnContainer.setVisibility(View.VISIBLE);
vh.secondaryBtn.setText(getSecondaryBtnTextId(loading));
vh.secondaryBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (listener != null) {
listener.onSecondaryButtonClick();
}
}
});
return true;
}
vh.secondaryBtnContainer.setVisibility(View.GONE);
return false;
}
@StringRes
private int getSecondaryBtnTextId(boolean loading) {
if (loading) {
return R.string.shared_string_cancel;
}
if (!download) {
return R.string.later;
}
return R.string.download_select_map_types;
}
/**
* @return true if button is visible, false otherwise.
*/
private boolean updatePrimaryButton(DownloadUpdateVH vh, boolean loading) {
if (!loading) {
boolean enabled = isInternetAvailable();
vh.primaryBtnContainer.setVisibility(View.VISIBLE);
vh.primaryBtnContainer.setBackgroundResource(getPrimaryBtnBgRes(enabled));
vh.primaryButton.setTextColor(getResolvedColor(getPrimaryBtnTextColorRes(enabled)));
vh.primaryButton.setEnabled(enabled);
vh.primaryButton.setText(download ? R.string.shared_string_download : R.string.shared_string_update);
vh.primaryButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (listener != null) {
listener.onPrimaryButtonClick();
}
}
});
return true;
}
vh.primaryBtnContainer.setVisibility(View.GONE);
return false;
}
public boolean isLoading() {
return indexItem != null && app.getDownloadThread().isDownloading(indexItem);
}
private boolean isLoadingInProgress() {
IndexItem current = app.getDownloadThread().getCurrentDownloadingItem();
return indexItem != null && current != null && indexItem == current;
}
public interface ClickListener {
void onPrimaryButtonClick();
void onSecondaryButtonClick();
}
public static class DownloadUpdateVH extends RecyclerView.ViewHolder {
final TextView title;
final ImageView icon;
final TextView description;
final View fileDataContainer;
final ImageView fileIcon;
final TextView fileTitle;
final TextView fileDescription;
final ProgressBar progressBar;
final View secondaryBtnContainer;
final TextView secondaryBtn;
final View buttonsDivider;
final View primaryBtnContainer;
final TextView primaryButton;
@SuppressWarnings("RedundantCast")
public DownloadUpdateVH(View itemView) {
super(itemView);
title = (TextView) itemView.findViewById(R.id.title);
icon = (ImageView) itemView.findViewById(R.id.icon);
description = (TextView) itemView.findViewById(R.id.description);
fileDataContainer = itemView.findViewById(R.id.file_data_container);
fileIcon = (ImageView) itemView.findViewById(R.id.file_icon);
fileTitle = (TextView) itemView.findViewById(R.id.file_title);
fileDescription = (TextView) itemView.findViewById(R.id.file_description);
progressBar = (ProgressBar) itemView.findViewById(R.id.progress_bar);
secondaryBtnContainer = itemView.findViewById(R.id.secondary_btn_container);
secondaryBtn = (TextView) itemView.findViewById(R.id.secondary_button);
buttonsDivider = itemView.findViewById(R.id.buttons_divider);
primaryBtnContainer = itemView.findViewById(R.id.primary_btn_container);
primaryButton = (TextView) itemView.findViewById(R.id.primary_button);
}
}
}

View file

@ -9,7 +9,9 @@ import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
import androidx.annotation.DrawableRes;
import androidx.annotation.NonNull;
import androidx.annotation.StringRes;
import androidx.recyclerview.widget.RecyclerView;
import net.osmand.plus.OsmandApplication;
@ -60,8 +62,12 @@ public class TravelNeededMapsCard extends BaseTravelCard {
if (viewHolder instanceof NeededMapsVH) {
NeededMapsVH holder = (NeededMapsVH) viewHolder;
ref = new WeakReference<NeededMapsVH>(holder);
holder.description.setText(isInternetAvailable()
? R.string.maps_you_need_descr : R.string.no_index_file_to_download);
holder.title.setText(getTitle());
holder.description.setText(getDescription());
int iconRes = getIconRes();
if (iconRes > 0) {
holder.icon.setImageResource(iconRes);
}
adjustChildCount(holder.itemsContainer);
updateView(holder);
@ -72,6 +78,22 @@ public class TravelNeededMapsCard extends BaseTravelCard {
}
}
@StringRes
public int getTitle() {
return R.string.maps_you_need;
}
@StringRes
public int getDescription() {
return isInternetAvailable()
? R.string.maps_you_need_descr : R.string.no_index_file_to_download;
}
@DrawableRes
public int getIconRes() {
return 0;
}
public void updateView() {
if (ref != null) {
NeededMapsVH holder = ref.get();
@ -227,7 +249,9 @@ public class TravelNeededMapsCard extends BaseTravelCard {
public static class NeededMapsVH extends RecyclerView.ViewHolder {
final TextView title;
final TextView description;
final ImageView icon;
final LinearLayout itemsContainer;
final View secondaryBtnContainer;
final TextView secondaryBtn;
@ -238,7 +262,9 @@ public class TravelNeededMapsCard extends BaseTravelCard {
@SuppressWarnings("RedundantCast")
public NeededMapsVH(View itemView) {
super(itemView);
title = (TextView) itemView.findViewById(R.id.title);
description = (TextView) itemView.findViewById(R.id.description);
icon = (ImageView) itemView.findViewById(R.id.icon);
itemsContainer = (LinearLayout) itemView.findViewById(R.id.items_container);
secondaryBtnContainer = itemView.findViewById(R.id.secondary_btn_container);
secondaryBtn = (TextView) itemView.findViewById(R.id.secondary_button);