Merge pull request #10687 from osmandapp/master

update test branch
This commit is contained in:
Hardy 2021-01-27 21:54:07 +01:00 committed by GitHub
commit 2ae835e817
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
85 changed files with 2025 additions and 1135 deletions

View file

@ -93,9 +93,9 @@
<string name="shared_string_share">Поділитися</string>
<string name="shared_string_back">Назад</string>
<string name="set_time">Оберіть час</string>
<string name="location_sharing_description">Оберіть контакти та групи, з якими ви бажаєте поділитися своїм місцезнаходженням.</string>
<string name="location_sharing_description">Виберіть контакти та групи, з якими ви бажаєте поділитися своїм місцеперебуванням.</string>
<string name="my_location_search_hint">Пошук: Група або контакт</string>
<string name="start_location_sharing">Поділитися місцезнаходженням</string>
<string name="start_location_sharing">Поділитися розташуванням</string>
<string name="show_on_map">Показати на карті</string>
<string name="app_name">OsmAnd онлайн GPS Tracker</string>
<string name="phone_number_title">Номер телефону</string>
@ -111,7 +111,7 @@
<string name="initialization">Запуск</string>
<string name="logging_out">Вихід із системи</string>
<string name="closing">Закриття</string>
<string name="gps_network_not_enabled">Служба визначення місцезнаходження вимкнена. Увімкнути\?</string>
<string name="gps_network_not_enabled">Служба визначення розташування вимкнена. Увімкнути\?</string>
<string name="not_logged_in">Ви не увійшли до системи</string>
<string name="shared_string_continue">Продовжити</string>
<string name="shared_string_cancel">Скасувати</string>
@ -225,8 +225,8 @@
<string name="start_end_date">Дата початку - кінця</string>
<string name="gpx_settings">Налаштування GPX</string>
<string name="timeline_no_data_descr">Ми не збирали дані за вибраний день</string>
<string name="send_location_as">Надіслати місцезнаходження як</string>
<string name="send_location_as_descr">Виберіть, як виглядатимуть повідомлення з вашим місцезнаходженням.</string>
<string name="send_location_as">Надіслати місцеперебування як</string>
<string name="send_location_as_descr">Виберіть, як виглядатимуть повідомлення з вашим місцеперебуванням.</string>
<string name="time_on_the_move">Час руху</string>
<string name="show_gps_points_descr">Показати кількість зібраних та відправлених GPS-точок.</string>
<string name="set_time_timeline_descr">Виберіть час для відображення</string>
@ -234,7 +234,7 @@
<string name="stale_location">Не рухається</string>
<string name="set_visible_time_for_all">Встановити денний час для всіх</string>
<string name="visible_time_for_all">Видимий час для всіх</string>
<string name="set_time_description">Встановіть час, коли вибрані контакти та групи будуть бачити ваше місцезнаходження в режимі реального часу.</string>
<string name="set_time_description">Встановіть час, коли вибрані контакти та групи бачитимуть ваше місцеперебування в режимі реального часу.</string>
<string name="location_service_no_gps_available">Виберіть одного з локальних постачальників, щоб поділитися своїм місцеположенням.</string>
<string name="search_contacts">Пошук контактів</string>
<string name="search_contacts_descr">Пошук у всіх своїх групах та контактах.</string>

View file

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<ProgressBar xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/progress"
android:layout_width="match_parent"
android:layout_height="@dimen/context_menu_progress_min_height"
android:gravity="center"
android:paddingLeft="@dimen/content_padding"
android:paddingRight="@dimen/content_padding"
android:paddingTop="@dimen/content_padding_small"
android:paddingBottom="@dimen/content_padding_small" />

View file

@ -0,0 +1,48 @@
<?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:minHeight="@dimen/bottom_sheet_selected_item_title_height"
android:orientation="vertical"
android:paddingStart="@dimen/content_padding"
android:paddingLeft="@dimen/content_padding"
android:paddingTop="@dimen/measurement_tool_menu_title_padding_top"
android:paddingEnd="@dimen/content_padding"
android:paddingRight="@dimen/content_padding"
android:paddingBottom="@dimen/content_padding_small">
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="end"
android:gravity="center_vertical"
android:maxLines="1"
android:textColor="?android:textColorPrimary"
android:textSize="@dimen/default_list_text_size"
osmand:typeface="@string/font_roboto_medium"
tools:text="Some title" />
<ProgressBar
android:id="@+id/progress_bar"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/route_info_buttons_padding_left_right"
android:layout_marginBottom="@dimen/route_info_buttons_padding_left_right"
android:minHeight="0dp"
android:visibility="visible" />
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/description"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:lineSpacingMultiplier="@dimen/bottom_sheet_text_spacing_multiplier"
android:textColor="?android:textColorPrimary"
android:textSize="@dimen/default_list_text_size"
osmand:typeface="@string/font_roboto_regular"
tools:text="Some description" />
</LinearLayout>

View file

@ -1,80 +1,83 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:baselineAligned="false"
android:gravity="center_vertical"
android:minHeight="@dimen/bottom_sheet_selected_item_title_height"
android:paddingStart="@dimen/content_padding"
android:paddingEnd="@dimen/content_padding"
android:paddingRight="@dimen/content_padding"
android:paddingLeft="@dimen/content_padding">
xmlns:app="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:baselineAligned="false"
android:gravity="center_vertical"
android:minHeight="@dimen/bottom_sheet_selected_item_title_height">
<LinearLayout
android:id="@+id/basic_item_body"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="?attr/selectableItemBackground">
<LinearLayout
android:id="@+id/basic_item_body"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="?attr/selectableItemBackground"
android:paddingStart="@dimen/content_padding"
android:paddingLeft="@dimen/content_padding"
android:paddingEnd="@dimen/content_padding"
android:paddingRight="@dimen/content_padding">
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_weight="1"
android:orientation="vertical">
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_weight="1"
android:orientation="vertical">
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:maxLines="1"
android:paddingTop="@dimen/content_padding_small"
android:paddingBottom="@dimen/content_padding"
android:textAppearance="@style/TextAppearance.ListItemTitle"
tools:text="Some title" />
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:maxLines="1"
android:paddingTop="@dimen/content_padding_small"
android:paddingBottom="@dimen/content_padding"
android:textAppearance="@style/TextAppearance.ListItemTitle"
tools:text="Some title" />
</LinearLayout>
</LinearLayout>
<com.google.android.material.switchmaterial.SwitchMaterial
android:id="@+id/switch_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="@dimen/bottom_sheet_content_margin"
android:layout_marginLeft="@dimen/bottom_sheet_content_margin"
android:layout_marginEnd="@dimen/bottom_sheet_content_margin"
android:layout_marginRight="@dimen/bottom_sheet_content_margin"
tools:checked="true" />
<com.google.android.material.switchmaterial.SwitchMaterial
android:id="@+id/switch_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="@dimen/bottom_sheet_content_margin"
android:layout_marginLeft="@dimen/bottom_sheet_content_margin"
android:clickable="false"
android:focusable="false"
android:focusableInTouchMode="false"
tools:checked="true" />
</LinearLayout>
</LinearLayout>
<LinearLayout
android:id="@+id/additional_button"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:orientation="horizontal">
<LinearLayout
android:id="@+id/additional_button"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:orientation="horizontal">
<View
android:layout_width="1dp"
android:layout_height="match_parent"
android:layout_marginTop="@dimen/content_padding_half"
android:layout_marginBottom="@dimen/content_padding_half"
android:background="?attr/divider_color_basic" />
<View
android:layout_width="1dp"
android:layout_height="match_parent"
android:layout_marginTop="@dimen/content_padding_half"
android:layout_marginBottom="@dimen/content_padding_half"
android:background="?attr/divider_color_basic" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/icon_after_divider"
style="@style/Widget.AppCompat.Toolbar.Button.Navigation"
android:layout_width="@dimen/favorites_icon_right_margin"
android:layout_height="@dimen/favorites_icon_right_margin"
android:layout_gravity="center"
android:layout_marginStart="@dimen/content_padding"
android:layout_marginLeft="@dimen/content_padding"
app:srcCompat="@drawable/ic_action_track_line_bold_color" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/icon_after_divider"
style="@style/Widget.AppCompat.Toolbar.Button.Navigation"
android:layout_width="@dimen/favorites_icon_right_margin"
android:layout_height="@dimen/favorites_icon_right_margin"
android:layout_gravity="center"
android:layout_marginStart="@dimen/content_padding"
android:layout_marginLeft="@dimen/content_padding"
android:layout_marginEnd="@dimen/content_padding"
android:layout_marginRight="@dimen/content_padding"
app:srcCompat="@drawable/ic_action_track_line_bold_color" />
</LinearLayout>
</LinearLayout>
</LinearLayout>

View file

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/map_controls_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
tools:visibility="invisible">
<include
layout="@layout/map_ruler"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="start|bottom"
android:layout_marginStart="@dimen/fab_margin_right"
android:layout_marginLeft="@dimen/fab_margin_right"
android:layout_marginEnd="@dimen/fab_margin_right"
android:layout_marginRight="@dimen/fab_margin_right" />
<include
layout="@layout/map_hud_controls"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end|bottom"
android:layout_marginStart="@dimen/fab_margin_right"
android:layout_marginLeft="@dimen/fab_margin_right"
android:layout_marginEnd="@dimen/fab_margin_right"
android:layout_marginRight="@dimen/fab_margin_right" />
</FrameLayout>

View file

@ -42,25 +42,31 @@
android:textSize="@dimen/dialog_header_text_size"
osmand:typeface="@string/font_roboto_medium" />
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/btn_save"
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="@dimen/content_padding_half"
android:layout_marginEnd="@dimen/content_padding_half"
android:layout_gravity="center_vertical"
android:background="@drawable/btn_border_active"
android:paddingStart="@dimen/content_padding"
android:paddingLeft="@dimen/content_padding"
android:paddingTop="@dimen/content_padding_half"
android:paddingRight="@dimen/content_padding"
android:paddingEnd="@dimen/content_padding"
android:paddingBottom="@dimen/content_padding_half"
android:text="@string/shared_string_save"
android:textColor="?attr/active_color_basic"
android:textSize="@dimen/default_desc_text_size"
osmand:typeface="@string/font_roboto_medium" />
android:background="@drawable/btn_border_active">
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/btn_save"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackground"
android:paddingStart="@dimen/content_padding"
android:paddingLeft="@dimen/content_padding"
android:paddingTop="@dimen/content_padding_half"
android:paddingRight="@dimen/content_padding"
android:paddingEnd="@dimen/content_padding"
android:paddingBottom="@dimen/content_padding_half"
android:text="@string/shared_string_save"
android:textColor="?attr/active_color_basic"
android:textSize="@dimen/default_desc_text_size"
osmand:typeface="@string/font_roboto_medium" />
</FrameLayout>
</LinearLayout>
@ -69,17 +75,26 @@
android:layout_height="1dp"
android:background="?attr/divider_color" />
<net.osmand.plus.widgets.EditTextEx
android:id="@+id/description"
<ScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="@dimen/content_padding"
android:layout_marginLeft="@dimen/content_padding"
android:layout_marginRight="@dimen/content_padding"
android:background="?attr/card_and_list_background_basic"
android:textColor="?android:attr/textColorPrimary"
android:textSize="@dimen/default_list_text_size"
osmand:typeface="@string/font_roboto_regular"
tools:text="Amsterdam is the Netherlands' capital and financial, cultural and creative centre with more than 850,000 inhabitants. Amsterdam is known for the canals that criss-cross the city, its impressive architecture and more than 1,500 bridges. The city has a heritage dating back to the Dutch Golden Age in the 17th century as well as a diverse art scene and a bustling nightlife." />
android:layout_height="match_parent">
<net.osmand.plus.widgets.EditTextEx
android:id="@+id/description"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/content_padding"
android:layout_marginLeft="@dimen/content_padding"
android:layout_marginTop="@dimen/content_padding_half"
android:layout_marginRight="@dimen/content_padding"
android:layout_marginEnd="@dimen/content_padding"
android:layout_marginBottom="@dimen/content_padding_half"
android:background="?attr/card_and_list_background_basic"
android:textColor="?android:attr/textColorPrimary"
android:textSize="@dimen/default_list_text_size"
osmand:typeface="@string/font_roboto_regular"
tools:text="Amsterdam is the Netherlands' capital and financial, cultural and creative centre with more than 850,000 inhabitants. Amsterdam is known for the canals that criss-cross the city, its impressive architecture and more than 1,500 bridges. The city has a heritage dating back to the Dutch Golden Age in the 17th century as well as a diverse art scene and a bustling nightlife." />
</ScrollView>
</LinearLayout>

View file

@ -56,32 +56,40 @@
android:id="@+id/divider"
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="?attr/divider_color"
android:background="?attr/ctx_menu_info_divider"
android:visibility="gone"
tools:visibility="visible"/>
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/btn_edit"
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/content_padding"
android:layout_marginStart="@dimen/content_padding"
android:layout_marginTop="@dimen/context_menu_padding_margin_small"
android:layout_marginBottom="@dimen/context_menu_padding_margin_small"
android:gravity="center_vertical"
android:padding="@dimen/context_menu_padding_margin_small"
android:paddingStart="@dimen/context_menu_padding_margin_small"
android:paddingEnd="@dimen/context_menu_padding_margin_small"
android:drawablePadding="@dimen/list_content_padding_large"
osmand:drawableLeftCompat="@drawable/ic_action_edit_dark"
osmand:drawableStartCompat="@drawable/ic_action_edit_dark"
osmand:drawableTint="?attr/active_color_basic"
android:visibility="gone"
android:text="@string/shared_string_edit"
android:textColor="?attr/active_color_basic"
android:textSize="@dimen/default_list_text_size"
osmand:typeface="@string/font_roboto_medium"
tools:visibility="visible" />
android:background="@drawable/rounded_background_3dp">
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/btn_edit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:background="?attr/selectableItemBackgroundBorderless"
android:padding="@dimen/context_menu_padding_margin_small"
android:paddingStart="@dimen/context_menu_padding_margin_small"
android:paddingEnd="@dimen/context_menu_padding_margin_small"
android:drawablePadding="@dimen/list_content_padding_large"
osmand:drawableLeftCompat="@drawable/ic_action_edit_dark"
osmand:drawableStartCompat="@drawable/ic_action_edit_dark"
osmand:drawableTint="?attr/active_color_basic"
android:visibility="gone"
android:text="@string/shared_string_edit"
android:textColor="?attr/active_color_basic"
android:textSize="@dimen/default_list_text_size"
osmand:typeface="@string/font_roboto_medium"
tools:visibility="visible" />
</FrameLayout>
<FrameLayout
android:id="@+id/bottom_empty_space"

View file

@ -99,34 +99,7 @@
</LinearLayout>
<FrameLayout
android:id="@+id/map_controls_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
tools:visibility="invisible">
<include
layout="@layout/map_ruler"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="start|bottom"
android:layout_marginStart="@dimen/fab_margin_right"
android:layout_marginLeft="@dimen/fab_margin_right"
android:layout_marginEnd="@dimen/fab_margin_right"
android:layout_marginRight="@dimen/fab_margin_right" />
<include
layout="@layout/map_hud_controls"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end|bottom"
android:layout_marginStart="@dimen/fab_margin_right"
android:layout_marginLeft="@dimen/fab_margin_right"
android:layout_marginEnd="@dimen/fab_margin_right"
android:layout_marginRight="@dimen/fab_margin_right" />
</FrameLayout>
<include layout="@layout/context_menu_controls" />
<LinearLayout
android:id="@+id/control_buttons"

View file

@ -145,6 +145,14 @@
tools:drawableStart="@drawable/ic_action_markers_dark"
android:paddingEnd="@dimen/bottom_sheet_content_padding_small" />
<ProgressBar
android:id="@+id/gpx_progress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:padding="@dimen/bottom_sheet_content_padding_small"
android:visibility="gone" />
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/save_button"
android:layout_width="wrap_content"

View file

@ -40,69 +40,119 @@
tools:visibility="visible"
tools:src="@drawable/img_help_announcement_time_day"/>
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/description"
<LinearLayout
android:id="@id/description_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/content_padding"
android:layout_marginLeft="@dimen/content_padding"
android:layout_marginTop="@dimen/context_menu_padding_margin_small"
android:layout_marginRight="@dimen/content_padding"
android:layout_marginEnd="@dimen/content_padding"
android:textColor="?android:textColorPrimary"
android:textSize="@dimen/default_list_text_size"
android:lineSpacingMultiplier="1.1"
osmand:typeface="@string/font_roboto_regular"
tools:text="Amsterdam is the Netherlands' capital and financial, cultural and creative centre with more than 850,000 inhabitants. Amsterdam is known for the canals that criss-cross the city, its impressive architecture and more than 1,500 bridges. The city has a heritage dating back to the Dutch Golden Age in the 17th century as well as a diverse art scene and a bustling nightlife."/>
android:orientation="vertical">
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/description"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/content_padding"
android:layout_marginLeft="@dimen/content_padding"
android:layout_marginTop="@dimen/context_menu_padding_margin_small"
android:layout_marginRight="@dimen/content_padding"
android:layout_marginEnd="@dimen/content_padding"
android:textColor="?android:textColorPrimary"
android:textSize="@dimen/default_list_text_size"
android:lineSpacingMultiplier="1.1"
osmand:typeface="@string/font_roboto_regular"
tools:text="Amsterdam is the Netherlands' capital and financial, cultural and creative centre with more than 850,000 inhabitants. Amsterdam is known for the canals that criss-cross the city, its impressive architecture and more than 1,500 bridges. The city has a heritage dating back to the Dutch Golden Age in the 17th century as well as a diverse art scene and a bustling nightlife."/>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/context_menu_padding_margin_small"
android:orientation="horizontal">
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/context_menu_padding_margin_small"
android:layout_marginLeft="@dimen/context_menu_padding_margin_small"
android:background="@drawable/rounded_background_3dp">
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/btn_read_full"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="start"
android:gravity="center_vertical"
android:background="?attr/selectableItemBackgroundBorderless"
android:padding="@dimen/bottom_sheet_content_padding_small"
android:paddingStart="@dimen/bottom_sheet_content_padding_small"
android:paddingEnd="@dimen/bottom_sheet_content_padding_small"
android:drawablePadding="@dimen/bottom_sheet_content_padding_small"
osmand:drawableStartCompat="@drawable/ic_action_read_article"
osmand:drawableLeftCompat="@drawable/ic_action_read_article"
osmand:drawableTint="?attr/wikivoyage_active_color"
android:text="@string/context_menu_read_full"
android:textColor="?attr/wikivoyage_active_color"
android:textSize="@dimen/default_desc_text_size"
osmand:typeface="@string/font_roboto_medium" />
</FrameLayout>
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="@dimen/context_menu_padding_margin_small"
android:layout_marginEnd="@dimen/context_menu_padding_margin_small"
android:layout_gravity="end"
android:background="@drawable/rounded_background_3dp">
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/btn_edit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:background="?attr/selectableItemBackgroundBorderless"
android:padding="@dimen/bottom_sheet_content_padding_small"
android:paddingStart="@dimen/bottom_sheet_content_padding_small"
android:paddingEnd="@dimen/bottom_sheet_content_padding_small"
android:drawablePadding="@dimen/bottom_sheet_content_padding_small"
osmand:drawableRightCompat="@drawable/ic_action_edit_dark"
osmand:drawableEndCompat="@drawable/ic_action_edit_dark"
osmand:drawableTint="?attr/wikivoyage_active_color"
android:text="@string/shared_string_edit"
android:textColor="?attr/wikivoyage_active_color"
android:textSize="@dimen/default_desc_text_size"
osmand:typeface="@string/font_roboto_medium" />
</FrameLayout>
</FrameLayout>
</LinearLayout>
<FrameLayout
android:layout_width="match_parent"
android:id="@+id/btn_add"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/context_menu_padding_margin_small"
android:layout_marginBottom="@dimen/context_menu_padding_margin_small"
android:orientation="horizontal">
android:layout_marginStart="@dimen/card_padding"
android:layout_marginLeft="@dimen/card_padding"
android:layout_marginTop="@dimen/content_padding"
android:background="@drawable/rounded_background_3dp"
android:visibility="gone"
tools:visibility="visible">
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/btn_read_full"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/context_menu_padding_margin_small"
android:layout_marginLeft="@dimen/context_menu_padding_margin_small"
android:layout_gravity="start"
android:gravity="center_vertical"
android:paddingStart="@dimen/bottom_sheet_content_padding_small"
android:paddingLeft="@dimen/bottom_sheet_content_padding_small"
android:paddingTop="@dimen/bottom_sheet_content_padding_small"
android:paddingRight="@dimen/bottom_sheet_content_padding_small"
android:paddingEnd="@dimen/bottom_sheet_content_padding_small"
android:paddingBottom="@dimen/bottom_sheet_content_padding_small"
android:drawablePadding="@dimen/bottom_sheet_content_padding_small"
osmand:drawableStartCompat="@drawable/ic_action_read_article"
osmand:drawableLeftCompat="@drawable/ic_action_read_article"
osmand:drawableTint="?attr/wikivoyage_active_color"
android:text="@string/context_menu_read_full"
android:textColor="?attr/wikivoyage_active_color"
android:textSize="@dimen/default_desc_text_size"
osmand:typeface="@string/font_roboto_medium" />
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/btn_edit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="@dimen/context_menu_padding_margin_small"
android:layout_marginEnd="@dimen/context_menu_padding_margin_small"
android:layout_gravity="end"
android:gravity="center_vertical"
android:background="?attr/selectableItemBackgroundBorderless"
android:padding="@dimen/bottom_sheet_content_padding_small"
android:paddingStart="@dimen/bottom_sheet_content_padding_small"
android:paddingEnd="@dimen/bottom_sheet_content_padding_small"
android:drawablePadding="@dimen/bottom_sheet_content_padding_small"
osmand:drawableRightCompat="@drawable/ic_action_edit_dark"
osmand:drawableEndCompat="@drawable/ic_action_edit_dark"
android:drawablePadding="@dimen/dialog_button_height"
osmand:drawableStartCompat="@drawable/ic_action_add"
osmand:drawableLeftCompat="@drawable/ic_action_add"
osmand:drawableTint="?attr/wikivoyage_active_color"
android:text="@string/shared_string_edit"
android:text="@string/add_description"
android:textColor="?attr/wikivoyage_active_color"
android:textSize="@dimen/default_desc_text_size"
android:textSize="@dimen/default_list_text_size"
osmand:typeface="@string/font_roboto_medium" />
</FrameLayout>
@ -110,6 +160,7 @@
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/context_menu_padding_margin_small"
android:background="?attr/activity_background_basic">
<include

View file

@ -9,7 +9,7 @@
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_overview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_height="@dimen/list_header_height"
android:layout_marginBottom="@dimen/content_padding_small_half"
android:clipToPadding="false"
android:orientation="horizontal"
@ -48,55 +48,60 @@
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/content_padding"
android:layout_marginLeft="@dimen/content_padding"
android:layout_height="@dimen/setting_list_item_small_height"
android:layout_marginStart="@dimen/card_padding"
android:layout_marginLeft="@dimen/card_padding"
android:layout_marginTop="@dimen/content_padding_half"
android:layout_marginEnd="@dimen/content_padding"
android:layout_marginRight="@dimen/content_padding"
android:layout_marginEnd="@dimen/card_padding"
android:layout_marginRight="@dimen/card_padding"
android:layout_marginBottom="@dimen/content_padding"
android:baselineAligned="false"
android:minHeight="@dimen/context_menu_controller_height"
android:orientation="horizontal"
android:weightSum="4">
<!-- todo stretch buttons correctly -->
<include
android:id="@+id/show_button"
layout="@layout/item_gpx_action"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginStart="@dimen/list_item_button_padding"
android:layout_marginLeft="@dimen/list_item_button_padding"
android:layout_marginEnd="@dimen/list_item_button_padding"
android:layout_marginRight="@dimen/list_item_button_padding"
android:layout_weight="1" />
<Space
android:layout_width="@dimen/content_padding_half"
android:layout_height="match_parent" />
<include
android:id="@+id/appearance_button"
layout="@layout/item_gpx_action"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginStart="@dimen/list_item_button_padding"
android:layout_marginLeft="@dimen/list_item_button_padding"
android:layout_marginEnd="@dimen/list_item_button_padding"
android:layout_marginRight="@dimen/list_item_button_padding"
android:layout_weight="1" />
<Space
android:layout_width="@dimen/content_padding_half"
android:layout_height="match_parent" />
<include
android:id="@+id/edit_button"
layout="@layout/item_gpx_action"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginStart="@dimen/list_item_button_padding"
android:layout_marginLeft="@dimen/list_item_button_padding"
android:layout_marginEnd="@dimen/list_item_button_padding"
android:layout_marginRight="@dimen/list_item_button_padding"
android:layout_weight="1" />
<Space
android:layout_width="@dimen/content_padding_half"
android:layout_height="match_parent" />
<include
android:id="@+id/directions_button"
layout="@layout/item_gpx_action"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginStart="@dimen/list_item_button_padding"
android:layout_marginLeft="@dimen/list_item_button_padding"
android:layout_marginEnd="@dimen/list_item_button_padding"
android:layout_marginRight="@dimen/list_item_button_padding"
android:layout_weight="1" />
</LinearLayout>

View file

@ -1,13 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
android:minHeight="@dimen/context_menu_controller_height"
android:minWidth="@dimen/context_menu_top_right_button_min_width"
android:layout_width="@dimen/fab_recycler_view_padding_bottom"
android:layout_height="@dimen/setting_list_item_small_height">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/filled"
android:layout_width="@dimen/fab_recycler_view_padding_bottom"
android:layout_height="@dimen/setting_list_item_small_height"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:alpha="0.1"
tools:srcCompat="@drawable/bg_topbar_shield_exit_ref" />

View file

@ -3,42 +3,62 @@
xmlns:osmand="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
android:layout_height="@dimen/list_header_height"
android:layout_marginStart="@dimen/content_padding"
android:layout_marginLeft="@dimen/content_padding"
android:gravity="center_vertical"
android:orientation="horizontal">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginEnd="@dimen/content_padding"
android:layout_marginRight="@dimen/content_padding"
android:orientation="vertical">
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/value"
android:layout_width="match_parent"
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/value"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@null"
android:textColor="?android:attr/textColorPrimary"
android:textSize="@dimen/default_desc_text_size"
osmand:typeface="@string/font_roboto_medium"
tools:text="700 km" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/image"
android:layout_width="@dimen/context_menu_transport_icon_size"
android:layout_height="@dimen/context_menu_transport_icon_size"
android:layout_gravity="center_vertical"
android:layout_marginStart="@dimen/context_menu_first_line_top_margin"
android:layout_marginLeft="@dimen/context_menu_first_line_top_margin"
tools:src="@drawable/ic_action_track_16" />
</LinearLayout>
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@null"
android:textColor="?android:attr/textColorPrimary"
android:textColor="?android:attr/textColorSecondary"
android:textSize="@dimen/default_desc_text_size"
osmand:typeface="@string/font_roboto_medium"
tools:text="700 km" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/image"
android:layout_width="@dimen/context_menu_transport_icon_size"
android:layout_height="@dimen/context_menu_transport_icon_size"
android:layout_gravity="center_vertical"
android:layout_marginStart="@dimen/context_menu_first_line_top_margin"
android:layout_marginLeft="@dimen/context_menu_first_line_top_margin"
tools:src="@drawable/ic_action_track_16" />
tools:text="@string/distance" />
</LinearLayout>
<TextView
android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@null"
android:textColor="?android:attr/textColorSecondary"
android:textSize="@dimen/default_desc_text_size"
tools:text="@string/distance" />
<View
android:id="@+id/divider"
android:layout_width="1dp"
android:layout_height="match_parent"
android:layout_marginTop="@dimen/map_small_button_margin"
android:layout_marginBottom="@dimen/map_small_button_margin"
tools:background="@color/divider_color_light" />
</LinearLayout>

View file

@ -90,34 +90,7 @@
</LinearLayout>
<FrameLayout
android:id="@+id/map_controls_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
tools:visibility="invisible">
<include
layout="@layout/map_ruler"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="start|bottom"
android:layout_marginStart="@dimen/fab_margin_right"
android:layout_marginLeft="@dimen/fab_margin_right"
android:layout_marginEnd="@dimen/fab_margin_right"
android:layout_marginRight="@dimen/fab_margin_right" />
<include
layout="@layout/map_hud_controls"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end|bottom"
android:layout_marginStart="@dimen/fab_margin_right"
android:layout_marginLeft="@dimen/fab_margin_right"
android:layout_marginEnd="@dimen/fab_margin_right"
android:layout_marginRight="@dimen/fab_margin_right" />
</FrameLayout>
<include layout="@layout/context_menu_controls" />
<LinearLayout
android:id="@+id/control_buttons"

View file

@ -191,6 +191,8 @@
</com.google.android.material.appbar.AppBarLayout>
<include layout="@layout/context_menu_controls" />
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/bottom_navigation"
android:layout_width="match_parent"

View file

@ -1,114 +1,115 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns: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:orientation="vertical">
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:osmand="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:letterSpacing="@dimen/text_button_letter_spacing"
android:paddingStart="@dimen/content_padding"
android:paddingLeft="@dimen/content_padding"
android:paddingTop="@dimen/content_padding_small"
android:paddingEnd="@dimen/content_padding"
android:paddingRight="@dimen/content_padding"
android:paddingBottom="@dimen/content_padding_small"
android:text="@string/monitoring_settings"
android:textSize="@dimen/default_list_text_size"
osmand:typeface="@string/font_roboto_medium" />
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:letterSpacing="@dimen/text_button_letter_spacing"
android:paddingStart="@dimen/content_padding"
android:paddingLeft="@dimen/content_padding"
android:paddingTop="@dimen/content_padding_small"
android:paddingEnd="@dimen/content_padding"
android:paddingRight="@dimen/content_padding"
android:paddingBottom="@dimen/content_padding_small"
android:text="@string/monitoring_settings"
android:textSize="@dimen/default_list_text_size"
osmand:typeface="@string/font_roboto_medium" />
<include
android:id="@+id/show_track_on_map"
layout="@layout/bottom_sheet_with_switch_divider_and_additional_button" />
<include
android:id="@+id/show_track_on_map"
layout="@layout/bottom_sheet_with_switch_divider_and_additional_button" />
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="?attr/dashboard_divider" />
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="?attr/dashboard_divider" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_gravity="center_vertical"
android:layout_weight="1"
android:orientation="horizontal"
android:paddingStart="@dimen/content_padding"
android:paddingLeft="@dimen/content_padding"
android:paddingTop="@dimen/bottom_sheet_content_margin"
android:paddingEnd="@dimen/content_padding"
android:paddingRight="@dimen/content_padding">
<LinearLayout
android:id="@+id/interval_view_container"
android:background="?attr/selectableItemBackground"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_gravity="center_vertical"
android:layout_weight="1"
android:orientation="horizontal"
android:paddingStart="@dimen/content_padding"
android:paddingLeft="@dimen/content_padding"
android:paddingTop="@dimen/bottom_sheet_content_margin"
android:paddingBottom="@dimen/bottom_sheet_content_margin"
android:paddingEnd="@dimen/content_padding"
android:paddingRight="@dimen/content_padding">
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/interval_value"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:ellipsize="end"
android:maxLines="1"
android:textSize="@dimen/default_list_text_size"
tools:text="Interval value" />
<net.osmand.plus.widgets.TextViewEx
android:id="@+id/interval_value"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:ellipsize="end"
android:maxLines="1"
android:textSize="@dimen/default_list_text_size"
tools:text="Interval value" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/up_down_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@null"
app:srcCompat="@drawable/ic_action_arrow_down" />
</LinearLayout>
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/up_down_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@null"
app:srcCompat="@drawable/ic_action_arrow_down" />
</LinearLayout>
<LinearLayout
android:id="@+id/always_ask_and_range_slider_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingStart="@dimen/content_padding"
android:paddingLeft="@dimen/content_padding"
android:paddingEnd="@dimen/content_padding"
android:paddingRight="@dimen/content_padding">
<LinearLayout
android:id="@+id/always_ask_and_range_slider_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingStart="@dimen/content_padding"
android:paddingLeft="@dimen/content_padding"
android:paddingEnd="@dimen/content_padding"
android:paddingRight="@dimen/content_padding">
<com.google.android.material.slider.RangeSlider
android:id="@+id/interval_slider"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/save_track_interval_globally"
android:stepSize="1"
app:haloRadius="@dimen/content_padding_small"
app:labelBehavior="gone"
app:thumbColor="@color/profile_icon_color_blue_light"
app:thumbRadius="@dimen/content_padding_small_half"
app:trackColorActive="@color/profile_icon_color_blue_light"
app:trackColorInactive="#4D007EB3"
app:tickColorInactive="#007EB3"
app:trackHeight="@dimen/slider_track_height"
tools:visibility="visible" />
<com.google.android.material.slider.RangeSlider
android:id="@+id/interval_slider"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/save_track_interval_globally"
android:stepSize="1"
app:haloRadius="@dimen/content_padding_small"
app:labelBehavior="gone"
app:thumbColor="@color/profile_icon_color_blue_light"
app:thumbRadius="@dimen/content_padding_small_half"
app:trackColorActive="@color/profile_icon_color_blue_light"
app:trackColorInactive="#4D007EB3"
app:tickColorInactive="#007EB3"
app:trackHeight="@dimen/slider_track_height"
tools:visibility="visible" />
<androidx.appcompat.widget.SwitchCompat
android:id="@+id/confirm_every_run"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:letterSpacing="@dimen/text_button_letter_spacing"
android:minHeight="@dimen/context_menu_buttons_bottom_height"
android:paddingLeft="@dimen/content_padding_small"
android:paddingRight="@dimen/content_padding_small"
android:text="@string/confirm_every_run"
android:textColor="?attr/color_dialog_buttons"
android:textSize="@dimen/default_list_text_size"
osmand:typeface="@string/font_roboto_regular"
tools:visibility="visible" />
</LinearLayout>
<androidx.appcompat.widget.SwitchCompat
android:id="@+id/confirm_every_run"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:letterSpacing="@dimen/text_button_letter_spacing"
android:minHeight="@dimen/context_menu_buttons_bottom_height"
android:paddingLeft="@dimen/content_padding_small"
android:paddingRight="@dimen/content_padding_small"
android:text="@string/confirm_every_run"
android:textColor="?attr/color_dialog_buttons"
android:textSize="@dimen/default_list_text_size"
osmand:typeface="@string/font_roboto_regular"
tools:visibility="visible" />
</LinearLayout>
<View
android:id="@+id/second_divider"
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginTop="@dimen/content_padding"
android:layout_marginBottom="@dimen/bottom_sheet_content_margin_small"
android:background="?attr/dashboard_divider" />
<View
android:id="@+id/second_divider"
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="?attr/dashboard_divider" />
</LinearLayout>

View file

@ -3998,4 +3998,14 @@
<string name="routing_engine_vehicle_type_mtb">Mountainbike</string>
<string name="message_server_error">Server-Fehler: %1$s</string>
<string name="message_name_is_already_exists">Der Name ist bereits vorhanden</string>
<string name="announcement_time_passing">Beim Passieren</string>
<string name="announcement_time_off_route">Abweichung von der Route</string>
<string name="announcement_time_arrive">Ankunft am Ziel</string>
<string name="announcement_time_approach">Annährung ans Ziel</string>
<string name="context_menu_read_full">Vollständig lesen</string>
<string name="delete_online_routing_engine">Dieses Online-Routingmodul löschen\?</string>
<string name="context_menu_edit_descr">Beschreibung bearbeiten</string>
<string name="delete_waypoints">Wegpunkte löschen</string>
<string name="copy_to_map_favorites">In Favoriten kopieren</string>
<string name="copy_to_map_markers">In Kartenmarkierungen kopieren</string>
</resources>

View file

@ -4000,4 +4000,10 @@
<string name="announcement_time_intervals">Interspacoj distancaj kaj tempaj</string>
<string name="announcement_time_descr">Tempo de anonco de diversaj voĉaj sciigoj dependas de ilia specoj, nuna naviga kaj implicita naviga rapido.</string>
<string name="announcement_time_title">Tempo de anonco</string>
<string name="copy_to_map_favorites">Kopii al ŝatataj</string>
<string name="delete_online_routing_engine">Ĉu forigi tiun ĉi enretan navigilon\?</string>
<string name="context_menu_read_full">Legi pli</string>
<string name="context_menu_edit_descr">Redakti priskribon</string>
<string name="delete_waypoints">Forigi navigadpunktojn</string>
<string name="copy_to_map_markers">Kopii al mapmarkoj</string>
</resources>

View file

@ -3990,4 +3990,10 @@
<string name="routing_engine_vehicle_type_cycling_mountain">Vélo tout terrain</string>
<string name="routing_engine_vehicle_type_cycling_electric">Vélo électrique</string>
<string name="routing_engine_vehicle_type_cycling_regular">Vélo</string>
<string name="copy_to_map_markers">Copier vers les marques de carte</string>
<string name="copy_to_map_favorites">Copier vers les favoris</string>
<string name="delete_online_routing_engine">Supprimer ce moteur de routage en ligne \?</string>
<string name="context_menu_read_full">Lire la suite</string>
<string name="context_menu_edit_descr">Modifier la description</string>
<string name="delete_waypoints">Supprimer les points de passage</string>
</resources>

View file

@ -3976,4 +3976,26 @@ Lon %2$s</string>
<string name="select_folder_descr">Selecionar cartafol ou engadir un novo</string>
<string name="select_folder">Seleccionar cartafol</string>
<string name="shared_string_empty">Baleiro</string>
<string name="announcement_time_arrive">Chegar ao destino</string>
<string name="shared_string_turn">Xiro</string>
<string name="announcement_time_intervals">Intres de tempo e distancia</string>
<string name="announcement_time_descr">A hora do anuncio das diferentes indicacións por voz depende do tipo de mensaxe, a velocidade de navegación actual e a velocidade de navegación predefinida.</string>
<string name="announcement_time_title">Hora do anuncio</string>
<string name="start_recording">Comezar gravación</string>
<string name="show_track_on_map">Amosar pista no mapa</string>
<string name="routing_engine_vehicle_type_wheelchair">Cadeira de rodas</string>
<string name="routing_engine_vehicle_type_hiking">Sendeirismo</string>
<string name="routing_engine_vehicle_type_walking">Camiñando</string>
<string name="routing_engine_vehicle_type_cycling_electric">Ciclismo eléctrico</string>
<string name="routing_engine_vehicle_type_cycling_mountain">Ciclismo de montaña</string>
<string name="routing_engine_vehicle_type_cycling_road">Ciclismo de estrada</string>
<string name="routing_engine_vehicle_type_cycling_regular">Ciclismo regular</string>
<string name="routing_engine_vehicle_type_hgv">Vehículos pesados</string>
<string name="routing_engine_vehicle_type_small_truck">Camión pequeno</string>
<string name="routing_engine_vehicle_type_truck">Camión</string>
<string name="routing_engine_vehicle_type_scooter">Scooter</string>
<string name="routing_engine_vehicle_type_racingbike">Bicicleta de carreiras</string>
<string name="routing_engine_vehicle_type_mtb">Bicicleta de montaña</string>
<string name="message_server_error">Erro do servidor: %1$s</string>
<string name="message_name_is_already_exists">O nome xa existe</string>
</resources>

View file

@ -312,7 +312,7 @@
\n
\nÁtmenetileg átállítva online CloudMade-re.</string>
<string name="specified_dir_doesnt_exist">Nem sikerült megtalálni a megadott mappát.</string>
<string name="application_dir">Adatok tárolási helye</string>
<string name="application_dir">Adatok tárolási mappája</string>
<string name="build_installed">{0} verzió telepítve ({1}).</string>
<string name="downloading_build">Összeállítás letöltése…</string>
<string name="install_selected_build">OsmAnd {0} {1}, {2} MB. Telepíted?</string>
@ -362,7 +362,7 @@
<string name="transport_search_again">Tömegközlekedés keresésének alaphelyzetbe állítása</string>
<string name="voice">Felvett hang</string>
<string name="no_vector_map_loaded">Nincs betöltött vektoros térkép</string>
<string name="gpx_files_not_found">Nem található GPX fálj a tracks könyvtárban</string>
<string name="gpx_files_not_found">Nem található GPX-fálj a tracks mappában</string>
<string name="error_reading_gpx">Nem sikerült beolvasni a GPX-adatokat.</string>
<string name="vector_data">Vektoros OSM térkép</string>
<string name="transport_context_menu">Közlekedés keresése megállónál</string>
@ -491,7 +491,7 @@
<string name="route_general_information">Teljes távolság %1$s, utazási idő %2$d óra %3$d perc.</string>
<string name="router_service_descr">Online vagy offline útvonaltervező szolgáltatás.</string>
<string name="router_service">Útvonaltervező szolgáltatás</string>
<string name="sd_dir_not_accessible">A tárolási könyvtár nem érhető el a memóriakártyán!</string>
<string name="sd_dir_not_accessible">A tárolási mappa nem érhető el a memóriakártyán!</string>
<string name="download_question">Letöltés {0} - {1} ?</string>
<string name="download_question_exist">{0} régióhoz már le van töltve offline adat ({1}). Frissíted ({2})?</string>
<string name="address">Cím</string>
@ -547,7 +547,7 @@
<string name="save_current_track">Jelenlegi nyomvonal mentése</string>
<string name="save_track_interval_descr">A navigáció alatti nyomvonalfelvételhez adja meg a naplózási intervallumot</string>
<string name="save_track_interval">Naplózási intervallum navigáció közben</string>
<string name="save_track_to_gpx_descrp">Navigáció közben a GPX útvonal automatikusan mentésre kerül az OsmAnd „tracks” könyvtárába.</string>
<string name="save_track_to_gpx_descrp">Navigáció közben a GPX útvonal automatikusan mentésre kerül az OsmAnd „tracks” mappájába.</string>
<string name="reload_tile">Térképcsempe újratöltése</string>
<string name="mark_point">Célpont</string>
<string name="shared_string_add_to_favorites">Hozzáadás a „Kedvencek”-hez</string>
@ -661,7 +661,7 @@
\n
\nA csempés térképek letölthetők internetes forrásokból, vagy előkészíthetők kapcsolat nélküli használathoz (kézzel átmásolva az OsmAnd adatmappájába) SQLite adatbázisként, amely különféle harmadik féltől származó térkép-előkészítő eszközökkel állítható elő.</string>
<string name="osmand_background_plugin_description">Megjeleníti a háttérben futó nyomvonalrögzítés és navigáció beállításait, ami periodikusan felébreszti a GPS modult (kikapcsolt képernyőnél).</string>
<string name="osmand_accessibility_description">Elérhetővé teszi az eszköz akadálymentesítési lehetőségeit közvetlenül az OsmAndban. Ez megkönnyíti például a szövegfelolvasó (TTS) hangok beszédsebességének állítását, az irányító gombok képernyő navigációjának beállítását, egy görgető használatát a nagyítás vezérléséhez, vagy szövegfelolvasó visszajelzés használatát, például a pozíció automatikus bejelentésénél.</string>
<string name="osmand_accessibility_description">Elérhetővé teszi az eszköz akadálymentesítési lehetőségeit közvetlenül az OsmAndban. Ez megkönnyíti például a szövegfelolvasó (TTS) hangok beszédsebességének állítását, az irányító gombok képernyő navigációjának beállítását, egy görgető használatát a nagyítás vezérléséhez, vagy szövegfelolvasó visszajelzés használatát, például a pozíció automatikus bemondásánál.</string>
<string name="osmand_development_plugin_description">Beállítások fejlesztői és hibakeresési szolgáltatásokhoz, mint például navigáció szimulálása, a megjelenítés teljesítménye vagy hangutasítások. Fejlesztőknek szánt funkciók, nem szükségesek a normál használathoz.</string>
<string name="plugins_screen">Bővítmények</string>
<string name="prefs_plugins_descr">A bővítmények speciális beállításokat és kiegészítő funkciókat aktiválnak.</string>
@ -1178,7 +1178,7 @@
<string name="share_route_as_gpx">Útvonal megosztása GPX-ben</string>
<string name="share_route_subject">OsmAnd segítségével megosztott útvonal</string>
<string name="arrival_distance">Érkezés bemondása</string>
<string name="arrival_distance_descr">Milyen korán szeretnéd hallani az érkezés bejelentését\?</string>
<string name="arrival_distance_descr">Milyen korán szeretné hallani az érkezés bemondását\?</string>
<string name="keep_informing_never">Csak kézzel (koppintás a nyílra)</string>
<string name="keep_informing_descr">Navigációs utasítások újra bemondása rendszeres időközönként.</string>
<string name="keep_informing">Navigációs utasítások ismétlése</string>
@ -1818,7 +1818,7 @@
<string name="night">Éjjel</string>
<string name="select_month_and_country">Hónap és ország:</string>
<string name="shared_string_remove">Eltávolítás</string>
<string name="storage_directory_readonly_desc">Az alkalmazás átváltott belső memóriára, mert a kijelölt adattároló mappa írásvédett. Kérjük, jelöljön ki egy írható tárolási mappát.</string>
<string name="storage_directory_readonly_desc">Az alkalmazás átváltott belső memóriára, mert a kijelölt adattároló mappa írásvédett. Kérjük, jelöljön ki egy írható tárolómappát.</string>
<string name="storage_directory_shared">Osztott memória</string>
<string name="shared_string_topbar">Felső sáv</string>
<string name="recalculate_route">Útvonal újraszámítása</string>
@ -1948,10 +1948,10 @@
<string name="access_direction_audio_feedback_descr">Hanggal jelölje a célpont irányát.</string>
<string name="access_direction_haptic_feedback">Rezgő irányjelzés</string>
<string name="access_direction_haptic_feedback_descr">Rezgéssel jelölje a célpont irányát.</string>
<string name="access_smart_autoannounce">Okos automatikus bejelentés</string>
<string name="access_smart_autoannounce">Intelligens automatikus bemondás</string>
<string name="access_smart_autoannounce_descr">Figyelmeztetés, csak ha a célpont iránya megváltozott.</string>
<string name="access_autoannounce_period">Automatikus bejelentések időköz</string>
<string name="access_autoannounce_period_descr">A bejelentések közötti legkisebb időköz.</string>
<string name="access_autoannounce_period">Bemondások gyakorisága</string>
<string name="access_autoannounce_period_descr">A bemondások közötti legkisebb időköz.</string>
<string name="lang_hu_formal">magyar (magázó)</string>
<string name="current_track">Jelenlegi nyomvonal</string>
<string name="change_markers_position">Jelölő helyének módosítása</string>
@ -2157,7 +2157,7 @@
<string name="navigate_point_olc_info_area">Érvényes teljes OLC
\nA következő területet jeleníti meg: %1$s x %2$s</string>
<string name="quick_action_page_list_descr">Gomb, amely lépteti az alábbi listát.</string>
<string name="select_gpx_folder">GPX fájlok könyvtárának kijelölése</string>
<string name="select_gpx_folder">GPX-fájlok mappájának kijelölése</string>
<string name="file_can_not_be_moved">Nem sikerült áthelyezni a fájlt.</string>
<string name="shared_string_move">Áthelyezés</string>
<string name="shared_string_gpx_tracks">Nyomvonalak</string>
@ -2191,7 +2191,7 @@
<string name="routing_attr_driving_style_safety_name">Mellékutak előnyben részesítése</string>
<string name="relief_smoothness_factor_descr">Előnyben részesített terep: sík vagy dombos.</string>
<string name="shared_string_slope">Lejtő</string>
<string name="add_new_folder">Új mappa létrehozása</string>
<string name="add_new_folder">Új mappa hozzáadása</string>
<string name="points_delete_multiple_succesful">Pont(ok) törölve.</string>
<string name="points_delete_multiple">Biztosan törli ez(eke)t a ponto(ka)t: %1$d\?</string>
<string name="route_points_category_name">Érintendő fordulók az útvonalon</string>
@ -3051,7 +3051,7 @@
<string name="vehicle_parameters_descr">Tömeg, magasság, hossz, sebesség</string>
<string name="vehicle_parameters">Jármű paraméterek</string>
<string name="voice_announces_info">A hangbemondások csak navigáció közben kerülnek lejátszásra.</string>
<string name="voice_announces_descr">Navigációs utasítások és bejelentések</string>
<string name="voice_announces_descr">Navigációs utasítások és bemondások</string>
<string name="voice_announces">Hangutasítások</string>
<string name="screen_alerts">Képernyő riasztások</string>
<string name="route_parameters_descr">Útvonal paraméterek testreszabása</string>
@ -3059,7 +3059,7 @@
<string name="plugins_settings">Bővítménybeállítások</string>
<string name="download_detailed_map">Töltsd le a részletes %s térképet a terület megtekintéséhez.</string>
<string name="internal_app_storage_description">Az OsmAnd belső tárolója (felhasználók és más alkalmazások számára rejtett).</string>
<string name="change_data_storage_folder">Tárolás mappájának módosítása</string>
<string name="change_data_storage_folder">Tároló mappa módosítása</string>
<string name="routing_attr_width_name">Szélességkorlátozás</string>
<string name="routing_attr_width_description">Adja meg az útvonalakon a járművekre vonatkozó szélességkorlátozást.</string>
<string name="avoid_in_routing_descr_">Bizonyos útvonalak és úttípusok elkerülése</string>
@ -3086,10 +3086,10 @@
<string name="tts_initialization_error">Szövegfelolvasó motor indítása sikertelen.</string>
<string name="data_storage_preference_summary">%1$s • %2$s</string>
<string name="data_storage_space_description">%1$s GB szabad (%2$s GB-ból)</string>
<string name="enter_path_to_folder">Add meg a könyvtár elérési útvonalát</string>
<string name="shared_string_select_folder">Könyvtár</string>
<string name="paste_Osmand_data_folder_path">OsmAnd adatok elérési útvonalának beillesztése</string>
<string name="change_osmand_data_folder_question">Módosítod az OsmAnd adatokat tároló könyvtárat\?</string>
<string name="enter_path_to_folder">Add meg a mappa elérési útvonalát</string>
<string name="shared_string_select_folder">Mappa</string>
<string name="paste_Osmand_data_folder_path">Az OsmAnd-adatokat tartalmazó mappa elérési útvonalának beillesztése</string>
<string name="change_osmand_data_folder_question">Módosítod az OsmAnd adatok mappáját\?</string>
<string name="move_maps_to_new_destination">Áthelyezés az új helyre</string>
<string name="shared_string_memory_tb_desc">%1$s TB</string>
<string name="shared_string_memory_gb_desc">%1$s GB</string>
@ -3103,11 +3103,11 @@
<string name="quick_action_hillshade_show">Domborzatárnyékolás megjelenítése</string>
<string name="quick_action_hillshade_hide">Domborzatárnyékolás elrejtése</string>
<string name="quick_action_show_hide_hillshade">Domborzatárnyékolás megjelenítése/elrejtése</string>
<string name="track_storage_directory">Nyomvonal tárolási könyvtára</string>
<string name="track_storage_directory_descrp">A nyomvonalak a \'rec\' könyvtárban tárolhatók, havi vagy napi bontás szerinti könyvtárakban.</string>
<string name="track_storage_directory">Nyomvonal tárolási mappája</string>
<string name="track_storage_directory_descrp">A nyomvonalak tárolhatók a \'rec\' mappában, illetve havi vagy napi bontás szerinti mappákban.</string>
<string name="store_tracks_in_rec_directory">Nyomvonalak felvétele a \'rec\' mappába</string>
<string name="store_tracks_in_daily_directories">Nyomvonalak felvétele napi bontású mappákba</string>
<string name="store_tracks_in_daily_directories_descrp">Nyomvonalak rögzítése a rögzítés napja szerinti almappákba (pl. 2018-01-01).</string>
<string name="store_tracks_in_daily_directories_descrp">Nyomvonalak felvétele a felvétel napja szerinti almappákba (pl. 2018-01-01).</string>
<string name="export_profile">Profil exportálása</string>
<string name="exported_osmand_profile">OsmAnd profil: %1$s</string>
<string name="overwrite_profile_q">\'%1$s\' már létezik. Felülírja\?</string>
@ -3340,7 +3340,7 @@
<string name="video_notes">Videojegyzetek</string>
<string name="photo_notes">Fényképes jegyzetek</string>
<string name="route_recalculation">Útvonal újraszámítása</string>
<string name="accessibility_announce">Bejelentés</string>
<string name="accessibility_announce">Bemondás</string>
<string name="login_and_pass">Felhasználónév és jelszó</string>
<string name="plugin_global_prefs_info">Ezek a bővítménybeállítások globálisak, és minden profilra vonatkoznak</string>
<string name="osm_editing">OSM-szerkesztés</string>
@ -3986,9 +3986,18 @@
<string name="routing_engine_vehicle_type_cycling_mountain">Hegyi kerékpározás</string>
<string name="routing_engine_vehicle_type_cycling_road">Verenykerékpározás</string>
<string name="routing_engine_vehicle_type_cycling_regular">Rendes kerékpározás</string>
<string name="routing_engine_vehicle_type_truck">Tgk.</string>
<string name="routing_engine_vehicle_type_hgv">Nehéz tgk.</string>
<string name="routing_engine_vehicle_type_truck">Teherautó</string>
<string name="routing_engine_vehicle_type_hgv">Nehéz teherautó</string>
<string name="routing_engine_vehicle_type_small_truck">Kisteherautó</string>
<string name="message_server_error">Szerverhiba: %1$s</string>
<string name="message_name_is_already_exists">Ez a név már létezik</string>
<string name="announcement_time_descr">A különféle hangutasítások bemondási ideje függ az utasítás típusától, az aktuális navigációs sebességtől és az alapértelmezett navigációs sebességtől.</string>
<string name="announcement_time_title">Bemondás ideje</string>
<string name="routing_engine_vehicle_type_scooter">Roller</string>
<string name="delete_online_routing_engine">Törli ezt az online útvonaltervezőt\?</string>
<string name="context_menu_read_full">Az egész elolvasása</string>
<string name="context_menu_edit_descr">Leírás szerkesztése</string>
<string name="delete_waypoints">Útpontok törlése</string>
<string name="copy_to_map_markers">Másolás a térképjelölők közé</string>
<string name="copy_to_map_favorites">Másolás a kedvencek közé</string>
</resources>

View file

@ -3966,4 +3966,43 @@
<string name="routing_engine_vehicle_type_bike">Hjólandi</string>
<string name="routing_engine_vehicle_type_car">Bíll</string>
<string name="copy_address">Afrita heimilisfang</string>
<string name="online_routing_engine">Leiðagerð af netinu</string>
<string name="online_routing_engines">Leiðagerð af netinu</string>
<string name="shared_string_folders">Möppur</string>
<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="upload_to_openstreetmap">Senda inn í OpenStreetMap</string>
<string name="edit_track">Breyta ferli</string>
<string name="rename_track">Endurnefna feril</string>
<string name="change_folder">Skipta um möppu</string>
<string name="shared_string_sec">sek</string>
<string name="announcement_time_passing">Framhjá</string>
<string name="announcement_time_approach">Aðkoma</string>
<string name="announcement_time_prepare_long">Langur undirbúningur</string>
<string name="announcement_time_prepare">Undirbúa</string>
<string name="announcement_time_off_route">Utan leiðar</string>
<string name="announcement_time_arrive">Koma á áfangastað</string>
<string name="shared_string_turn">Beygja</string>
<string name="announcement_time_intervals">Millibil tíma og vegalengda</string>
<string name="announcement_time_descr">Tilkynningar mismunandi talskilaboða fara eftir tegund skilaboða, fyrirliggjandi hraða leiðsagnar og sjálfgefnum hraða leiðsagnar.</string>
<string name="announcement_time_title">Tími tilkynninga</string>
<string name="start_recording">Hefja upptöku</string>
<string name="show_track_on_map">Birta feril á korti</string>
<string name="routing_engine_vehicle_type_wheelchair">Hjólastólar</string>
<string name="routing_engine_vehicle_type_hiking">Gönguferðir</string>
<string name="routing_engine_vehicle_type_walking">Gangandi</string>
<string name="routing_engine_vehicle_type_cycling_electric">Rafmagnshjól</string>
<string name="routing_engine_vehicle_type_cycling_mountain">Fjallahjól</string>
<string name="routing_engine_vehicle_type_cycling_road">Götuhjól</string>
<string name="routing_engine_vehicle_type_cycling_regular">Venjulegar hjólreiðar</string>
<string name="routing_engine_vehicle_type_hgv">Þyngri vöruflutningabifreiðar</string>
<string name="routing_engine_vehicle_type_small_truck">Litlar vöruflutningabifreiðar</string>
<string name="routing_engine_vehicle_type_truck">Flutningabifreiðar</string>
<string name="routing_engine_vehicle_type_scooter">Skellinöðrur</string>
<string name="routing_engine_vehicle_type_racingbike">Götukeppnishjól</string>
<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>
</resources>

View file

@ -543,7 +543,7 @@
<string name="left_side_navigation">Circolazione a sinistra</string>
<string name="left_side_navigation_descr">Per i paesi in cui si guida nella parte sinistra della strada.</string>
<string name="unknown_from_location">Posizione di partenza non ancora determinata.</string>
<string name="confirm_interrupt_download">Annulla il download del file\?</string>
<string name="confirm_interrupt_download">Annulla il download\?</string>
<string name="basemap_was_selected_to_download">La mappa di base necessaria per il funzionamento è in coda per il download.</string>
<string name="map_online_plugin_is_not_installed">Abilita il plugin \'Mappe Online\' per scegliere altre sorgenti di mappe</string>
<string name="map_online_data">Mappe online e a tasselli</string>
@ -929,7 +929,7 @@
<string name="favourites_list_activity">Seleziona Preferito</string>
<string name="local_openstreetmap_act_title">Modifiche OSM</string>
<string name="download_using_mobile_internet">Non connesso al Wi-Fi. Usare la connessione a Internet attuale per il download\?</string>
<string name="cancel_route">Cancellare il percorso\?</string>
<string name="cancel_route">Ignora il percorso\?</string>
<string name="cancel_navigation">Interrompere la navigazione</string>
<string name="clear_destination">Cancella la destinazione</string>
<string name="other_location">Altra</string>
@ -1399,7 +1399,7 @@
<string name="shared_string_ellipsis"></string>
<string name="shared_string_ok">Ok</string>
<string name="shared_string_cancel">Annulla</string>
<string name="shared_string_dismiss">Annulla</string>
<string name="shared_string_dismiss">Ignora</string>
<string name="shared_string_yes"></string>
<string name="shared_string_no">No</string>
<string name="shared_string_on">Acceso</string>
@ -1989,7 +1989,7 @@
<string name="first_usage_greeting">Ottieni indicazioni e scopri nuovi luoghi senza una connessione a Internet</string>
<string name="search_another_country">Scegli un\'altra regione</string>
<string name="skip_map_downloading_desc">Non hai mappe offline installate. Si può scegliere una mappa dalla lista o scaricarle in seguito andando su \'Menù - %1$s\'.</string>
<string name="osm_live_payment_desc">Il costo della sottoscrizione verrà addebitato ogni mese. Puoi scegliere di annullare la sottoscrizione su Google Play in ogni momento.</string>
<string name="osm_live_payment_desc">La sottoscrizione viene addebitata ogni mese. Puoi annullarla su Google Play in ogni momento.</string>
<string name="donation_to_osm">Donazione per la comunità di OpenStreetMap</string>
<string name="donation_to_osm_desc">Parte della tua donazione verrà inviata agli utenti che fanno modifiche su OpenStreetMap. Il costo della sottoscrizione rimane inalterato.</string>
<string name="osm_live_subscription_desc">La sottoscrizione attiva aggiornamenti orari, quotidiani e settimanali e la possibilità di scaricare senza limiti tutte le mappe del mondo.</string>
@ -3134,7 +3134,7 @@
<string name="coordinates_format_info">Il formato selezionato sarà applicato per tutta l\'app.</string>
<string name="pref_selected_by_default_for_profiles">Questa impostazione è selezionata di default per i profili: %s</string>
<string name="change_default_settings">Cambia impostazioni</string>
<string name="discard_changes">Annulla cambiamenti</string>
<string name="discard_changes">Annulla modifiche</string>
<string name="apply_to_current_profile">Applica solo a \"%1$s\"</string>
<string name="apply_to_all_profiles">Applica a tutti i profili</string>
<string name="start_up_message_pref">Messaggio di avvio</string>
@ -3704,7 +3704,7 @@
<string name="use_volume_buttons_as_zoom_descr">Abilita per controllare il livello di zoom della mappa con i pulsanti del volume del dispositivo.</string>
<string name="use_volume_buttons_as_zoom">Pulsanti volume come zoom</string>
<string name="please_provide_point_name_error">Per favore indica un nome per il punto</string>
<string name="quick_action_remove_next_destination_descr">Il punto di destinazione corrente sul percorso verrà eliminato. Se sarà la Destinazione, la navigazione verrà interrotta.</string>
<string name="quick_action_remove_next_destination_descr">Elimina la destinazione successiva nel percorso. Se questa è la destinazione finale, la navigazione si fermerà.</string>
<string name="search_download_wikipedia_maps">Scarica mappe Wikipedia</string>
<string name="plugin_wikipedia_description">Ottieni informazioni sui punti di interesse da Wikipedia. È la tua guida tascabile offline - basta abilitare il plugin Wikipedia e goderti gli articoli sugli oggetti intorno a te.</string>
<string name="app_mode_enduro_motorcycle">Moto da enduro</string>

View file

@ -3986,4 +3986,19 @@
<string name="routing_engine_vehicle_type_mtb">אופני הרים</string>
<string name="message_server_error">שגיאת שרת: %1$s</string>
<string name="message_name_is_already_exists">השם כבר קיים</string>
<string name="announcement_time_off_route">סטייה ממסלול</string>
<string name="announcement_time_arrive">הגעה ליעד</string>
<string name="show_track_on_map">הצגת המסלול על המפה</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_cycling_regular">רכיבה רגילה</string>
<string name="routing_engine_vehicle_type_hiking">טיול שטח</string>
<string name="routing_engine_vehicle_type_hgv">משאית כבדה</string>
<string name="delete_online_routing_engine">למחוק את מנוע הניווט המקוון הזה\?</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>
</resources>

View file

@ -3995,4 +3995,10 @@
<string name="routing_engine_vehicle_type_mtb">MTB</string>
<string name="message_server_error">Erro de servidor: %1$s</string>
<string name="message_name_is_already_exists">O nome já existe</string>
<string name="context_menu_edit_descr">Editar descrição</string>
<string name="delete_waypoints">Apagar ponto fixo</string>
<string name="copy_to_map_markers">Copiar para marcadores de mapa</string>
<string name="copy_to_map_favorites">Copiar para favoritos</string>
<string name="delete_online_routing_engine">Excluir este mecanismo de roteamento online\?</string>
<string name="context_menu_read_full">Ler na íntegra</string>
</resources>

View file

@ -3964,4 +3964,22 @@
<string name="select_folder">Ischerta sa cartella</string>
<string name="select_folder_descr">Ischerta una cartella o crea·nde una noa</string>
<string name="shared_string_empty">Bòidu</string>
<string name="announcement_time_intervals">Intervallos de tempus e de distàntzia</string>
<string name="start_recording">Incumintza a registrare</string>
<string name="show_track_on_map">Ammustra sa rasta in sa mapa</string>
<string name="routing_engine_vehicle_type_wheelchair">Cadira a rodas</string>
<string name="routing_engine_vehicle_type_hiking">Escursionismu</string>
<string name="routing_engine_vehicle_type_walking">A pee</string>
<string name="routing_engine_vehicle_type_cycling_electric">Tziclismu elètricu</string>
<string name="routing_engine_vehicle_type_cycling_mountain">Tziclismu de monte</string>
<string name="routing_engine_vehicle_type_cycling_road">Tziclismu in carreras</string>
<string name="routing_engine_vehicle_type_cycling_regular">Tziclismu regulare</string>
<string name="routing_engine_vehicle_type_hgv">Veìculu de trasportu</string>
<string name="routing_engine_vehicle_type_small_truck">Camioneta</string>
<string name="routing_engine_vehicle_type_truck">Càmion</string>
<string name="routing_engine_vehicle_type_scooter">Motorinu (Scooter)</string>
<string name="routing_engine_vehicle_type_racingbike">Bitzicleta de cursa</string>
<string name="routing_engine_vehicle_type_mtb">MTB (motosilurante)</string>
<string name="message_server_error">Errore de su serbidore: %1$s</string>
<string name="message_name_is_already_exists">Su nùmene esistit giai</string>
</resources>

View file

@ -160,7 +160,7 @@
<string name="local_openstreetmap_delete">Vymazať úpravu</string>
<string name="local_openstreetmap_descr_title">Asynchrónne upravovanie OSM:</string>
<string name="local_openstreetmap_settings">OSM POI/poznámky uložené v zariadení</string>
<string name="local_openstreetmap_settings_descr">Zobraziť a spravovať OSM bodu záujmu/poznámky uložené v databáze v zariadení.</string>
<string name="local_openstreetmap_settings_descr">Zobraziť a spravovať OSM body záujmu/poznámky uložené v databáze v zariadení.</string>
<string name="live_monitoring_interval_descr">Určiť interval stopovania naživo.</string>
<string name="live_monitoring_interval">Interval stopovania naživo</string>
<string name="live_monitoring_url_descr">Zadajte webovú adresu stopovania naživo so syntaxom parametrov: lat={0}, lon={1}, timestamp={2}, hdop={3}, altitude={4}, speed={5}, bearing={6}.</string>
@ -698,7 +698,7 @@
<string name="edit_filter_create_message">Filter \'%1$s\' bol vytvorený</string>
<string name="unknown_from_location">Východzí bod nebol zatiaľ zistený.</string>
<string name="confirm_interrupt_download">Zrušiť sťahovanie\?</string>
<string name="basemap_was_selected_to_download">Základná potrebná pre základné funkcie aplikácie bola zaradená na stiahnutie.</string>
<string name="basemap_was_selected_to_download">Základná mapa potrebná pre základné funkcie aplikácie bola zaradená na stiahnutie.</string>
<string name="shared_string_name">Názov</string>
<string name="favourites_edit_dialog_category">Kategória</string>
<string name="navigate_point_format_D">DDD.DDDDD</string>
@ -1091,7 +1091,7 @@
<string name="index_item_world_altitude_correction">Svetové korekcie nadmorskej výšky</string>
<string name="index_item_world_seamarks">Svetové námorné značky</string>
<string name="index_item_world_bitcoin_payments">Svetové platby bitcoinom</string>
<string name="index_item_world_basemap">Svetová základná mapa</string>
<string name="index_item_world_basemap">Svetová prehľadová mapa</string>
<string name="index_item_world_ski">Svetová lyžiarska mapa</string>
<string name="lang_hr">Chorvátsky (Hrvatski)</string>
<string name="lang_zh">Čínsky (中国的)</string>
@ -2696,7 +2696,7 @@
<string name="shared_string_bookmark">Záložka</string>
<string name="hide_full_description">Skryť celý popis</string>
<string name="show_full_description">Zobraziť celý popis</string>
<string name="off_road_render_descr">Pre jazdenie mimo cesty v teréne (off-road) založený na štýle \'Topo\' a pre použitie s podkladovou mapou zo zelených satelitných snímok. Znížená hrúbka ciest, zvýšená hrúbka poľných ciest, chorníkov, cyklistických a iných trás.</string>
<string name="off_road_render_descr">Pre jazdenie mimo cesty v teréne (off-road) založený na štýle \'Topo\' a pre použitie s podkladovou mapou zo zelených satelitných snímok. Znížená hrúbka ciest, zvýšená hrúbka poľných ciest, chodníkov, cyklistických a iných trás.</string>
<string name="nautical_render_descr">Pre námornú navigáciu. Obsahuje bóje, majáky, vodné cesty, morské trasy a značky, prístavy, námorné služby a hĺbkové vrstevnice.</string>
<string name="ski_map_render_descr">Pre lyžovanie. Obsahuje zjazdovky, lyžiarske vleky a iné objekty pre lyžiarov. Druhoradé objekty na mape sú menej výrazné.</string>
<string name="light_rs_render_descr">Jednoduchý štýl pre navigáciu auta. Príjemný nočný režim, vrstevnice, kontrastné oranžové cesty, druhoradé objekty na mape sú menej výrazné.</string>

View file

@ -3271,4 +3271,38 @@
<string name="plan_route_create_new_route">Ustvari novo pot</string>
<string name="shared_string_done">Končano</string>
<string name="overwrite_track">Prepiši sled</string>
<string name="shared_string_folders">Mape</string>
<string name="select_folder">Izberi mapo</string>
<string name="select_folder_descr">Izberi mapo ali dodaj novo</string>
<string name="shared_string_empty">Prazno</string>
<string name="analyze_by_intervals">Analiziraj po intervalih (razdelitveni interval)</string>
<string name="upload_to_openstreetmap">Naloži v OpenStreetMap</string>
<string name="edit_track">Uredi sled</string>
<string name="rename_track">Preimenuj sled</string>
<string name="change_folder">Spremeni mapo</string>
<string name="shared_string_sec">sek</string>
<string name="announcement_time_approach">Pristop</string>
<string name="announcement_time_prepare">Pripravi se</string>
<string name="announcement_time_off_route">Izven poti</string>
<string name="announcement_time_arrive">Prihod na cilj</string>
<string name="shared_string_turn">Zavoj</string>
<string name="announcement_time_intervals">Intervali časa in razdalje</string>
<string name="announcement_time_descr">Čas objave različnih glasovnih pozivov je odvisen od vrste poziva, trenutne hitrosti navigacije in privzete hitrosti navigacije.</string>
<string name="announcement_time_title">Čas objave</string>
<string name="start_recording">Začni snemanje</string>
<string name="routing_engine_vehicle_type_wheelchair">Invalidski voziček</string>
<string name="routing_engine_vehicle_type_walking">Hoja</string>
<string name="routing_engine_vehicle_type_hiking">Pohodništvo</string>
<string name="routing_engine_vehicle_type_cycling_electric">Električno kolesarjenje</string>
<string name="routing_engine_vehicle_type_cycling_mountain">Gorsko kolesarjenje</string>
<string name="routing_engine_vehicle_type_cycling_road">Cestno kolesarjenje</string>
<string name="routing_engine_vehicle_type_cycling_regular">Redno kolesarjenje</string>
<string name="routing_engine_vehicle_type_hgv">Težko tovorno vozilo</string>
<string name="routing_engine_vehicle_type_small_truck">Majhno tovorno vozilo</string>
<string name="routing_engine_vehicle_type_truck">Tovorno vozilo</string>
<string name="routing_engine_vehicle_type_scooter">Skuter</string>
<string name="routing_engine_vehicle_type_racingbike">Dirkalno kolo</string>
<string name="routing_engine_vehicle_type_mtb">MTB</string>
<string name="message_server_error">Napaka strežnika: %1$s</string>
<string name="message_name_is_already_exists">To ime že obstaja</string>
</resources>

View file

@ -4001,4 +4001,10 @@
<string name="routing_engine_vehicle_type_racingbike">Yarış bisikleti</string>
<string name="message_server_error">Sunucu hatası: %1$s</string>
<string name="message_name_is_already_exists">Ad zaten var</string>
<string name="delete_waypoints">Ara noktaları sil</string>
<string name="copy_to_map_markers">Harita işaretleyicilerine kopyala</string>
<string name="copy_to_map_favorites">Sık kullanılanlara kopyala</string>
<string name="delete_online_routing_engine">Bu çevrim içi yönlendirme motoru silinsin mi\?</string>
<string name="context_menu_read_full">Tamamını oku</string>
<string name="context_menu_edit_descr">ıklamayı düzenle</string>
</resources>

View file

@ -2790,7 +2790,7 @@
<string name="poi_crop_rice">Вирощується культура: рис</string>
<string name="poi_nuclear_explosion_type_cratering_burst">Вид вибуху: неглибокого закладення</string>
<string name="poi_provided_for_adult_yes">Послуги надаються дорослим: так</string>
<string name="poi_xmas_note">Різдво: нотатка</string>
<string name="poi_xmas_note">Різдво: примітка</string>
<string name="poi_cuisine_wings">Крильця</string>
<string name="poi_cuisine_jamaican">Ямайська</string>
<string name="poi_outdoor_seating_pedestrian_zone">Місця на відкритому повітрі: пішохідна зона</string>
@ -3019,7 +3019,7 @@
<string name="poi_drink_wine_yes">Вино: так</string>
<string name="poi_vending_drinks_food">Напої і закуски</string>
<string name="poi_wetland_saltmarsh">Болото, періодично затоплюване морською водою</string>
<string name="poi_note">Нотатка</string>
<string name="poi_note">Примітка</string>
<string name="poi_crop_flowers">Вирощується культура: квіти</string>
<string name="poi_water_heater_no">Водонагрівач: відсутній</string>
<string name="poi_free_flying_site_orientation_e">Орієнтація майданчика для вільного польоту: схід (E)</string>

View file

@ -22,12 +22,12 @@
<string name="offline_navigation_not_available">Автономна навігація OsmAnd тимчасово не доступна.</string>
<string name="left_side_navigation">Лівосторонній рух</string>
<string name="left_side_navigation_descr">Для країн з лівостороннім рухом.</string>
<string name="unknown_from_location">Початкове місцезнаходження ще не визначено.</string>
<string name="unknown_from_location">Початкове місцеперебування ще не визначено.</string>
<string name="unknown_location">Розташування ще не визначено.</string>
<string name="modify_transparency">Встановити прозорість (0 прозорий, 255 непрозорий)</string>
<string name="confirm_interrupt_download">Скасувати завантаження\?</string>
<string name="first_time_msg">Дякуємо за користування OsmAnd. Завантажуйте регіональні дані для користування в автономному режимі за допомогою пункту меню \'Налаштування\' → \'Керування мапами\' для перегляду мап, пошуку адрес, POI, громадського транспорту тощо.</string>
<string name="basemap_was_selected_to_download">Основна мапа, необхідна для забезпечення основних можливостей, знаходиться у черзі завантаження.</string>
<string name="basemap_was_selected_to_download">Основна мапа, необхідна для забезпечення основних можливостей, перебуває у черзі завантаження.</string>
<string name="select_index_file_to_download">Нічого не знайдено. Якщо Ви не знайшли свій регіон, Ви можете створити його самостійно (див. https://osmand.net).</string>
<string name="local_indexes_cat_tile">Мережеві та кешовані растрові мапи</string>
<string name="local_indexes_cat_map">Звичайні мапи (векторні)</string>
@ -57,7 +57,7 @@
<string name="switch_to_raster_map_to_see">Для поточної місцевості відсутні векторні автономні мапи. Завантажте їх у \'Налаштуваннях\' (\'Керування файлами мап\') або перемкніться на втулок \'Мережеві мапи\'.</string>
<string name="send_files_to_osm">Відправити GPX файли в OSM?</string>
<string name="gpx_visibility_txt">Видимість</string>
<string name="gpx_tags_txt">Теги</string>
<string name="gpx_tags_txt">Мітки</string>
<string name="validate_gpx_upload_name_pwd">Для вивантаження GPX-файлів вкажіть ваше ім\'я користувача і пароль в OSM.</string>
<string name="default_buttons_support">Підтримка</string>
<string name="support_new_features">Підтримати розробку нових функцій</string>
@ -121,13 +121,13 @@
<string name="offline_edition_descr">Якщо ввімкнено редагування в автономному режимі, тоді зміни буде збережено спочатку локально та завантажено за запитом, інакше зміни буде завантажено негайно.</string>
<string name="update_poi_does_not_change_indexes">Зміни POI всередині застосунку не впливають на завантажені файли мап - вони зберігаються в окремий файл на Вашому пристрої.</string>
<string name="local_openstreetmap_uploading">Вивантаження…</string>
<string name="local_openstreetmap_were_uploaded">{0} POI/нотатки вивантажено</string>
<string name="local_openstreetmap_were_uploaded">{0} POI/примітки вивантажено</string>
<string name="local_openstreetmap_uploadall">Вивантажити усе</string>
<string name="local_openstreetmap_upload">Вивантажити правки в OSM</string>
<string name="local_openstreetmap_delete">Видалити редагування</string>
<string name="local_openstreetmap_descr_title">Асинхронне редагування OSM:</string>
<string name="local_openstreetmap_settings">OSM-POI/Нотатки, збережено на пристрої</string>
<string name="local_openstreetmap_settings_descr">Перегляд і керування OSM-POI/нотатками, збереженими у базі даних на пристрої.</string>
<string name="local_openstreetmap_settings">OSM-POI/примітки, збережено на пристрої</string>
<string name="local_openstreetmap_settings_descr">Перегляд і керування OSM-POI/примітками, збереженими у базі даних пристрою.</string>
<string name="live_monitoring_interval_descr">Вкажіть інтервал надсилання даних.</string>
<string name="live_monitoring_interval">Інтервал надсилання даних</string>
<string name="live_monitoring_url_descr">Вкажіть веб-адресу з наступними параметрами: lat={0}, lon={1}, timestamp={2}, hdop={3}, altitude={4}, speed={5}, bearing={6}.</string>
@ -312,8 +312,8 @@
<string name="send_location_way_choose_title">Поділитись, використовуючи</string>
<string name="send_location_sms_pattern">Координати: %1$s\n%2$s</string>
<string name="send_location_email_pattern">Щоб побачити розташування, перейдіть за веб-посиланням %1$s або intent-посиланням Android %2$s</string>
<string name="send_location">Надіслати місцезнаходження</string>
<string name="context_menu_item_share_location">Поділитись місцезнаходженням</string>
<string name="send_location">Надіслати місцеперебування</string>
<string name="context_menu_item_share_location">Поділитись місцеперебуванням</string>
<string name="add_waypoint_dialog_added">Маршрутну точку GPX \"{0}\" додано</string>
<string name="add_waypoint_dialog_title">Додати точку до записаного треку</string>
<string name="amenity_type_administrative">Адміністративні</string>
@ -435,7 +435,7 @@
<string name="layer_yandex_traffic">Яндекс Пробки</string>
<string name="layer_route">Маршрут</string>
<string name="shared_string_favorites">Закладки</string>
<string name="layer_osm_bugs">Нотатки OSM (мережеві)</string>
<string name="layer_osm_bugs">Примітки OSM (мережеві)</string>
<string name="layer_poi">POI-накладення…</string>
<string name="layer_map">Джерело мапи…</string>
<string name="menu_layers">Шари мапи</string>
@ -575,7 +575,7 @@
<string name="shared_string_close">Закрити</string>
<string name="loading_data">Дані завантажуються…</string>
<string name="reading_indexes">Зчитування даних…</string>
<string name="previous_run_crashed">Помилка у роботі застосунку. Файл журналу знаходиться тут {0}. Будь ласка, напишіть розробнику про помилку (з вкладеним журнальним файлом).</string>
<string name="previous_run_crashed">Помилка роботи застосунку. Файл журналу розміщено тут {0}. Повідомте розробника про помилку (з вкладеним файлом журналу).</string>
<string name="saving_gpx_tracks">Збереження GPX-файлу…</string>
<string name="finished_task">Закінчено</string>
<string name="use_online_routing_descr">Використовувати Інтернет для прокладання маршруту.</string>
@ -597,7 +597,7 @@
<string name="update_tile">Оновити мапу</string>
<string name="reload_tile">Оновити частину мапи</string>
<string name="mark_point">Точка</string>
<string name="shared_string_add_to_favorites">Додати в закладки</string>
<string name="shared_string_add_to_favorites">Додати до закладок</string>
<string name="use_english_names_descr">Вибір між місцевими та англійськими назвами.</string>
<string name="use_english_names">Використовувати англійські назви на мапах</string>
<string name="app_settings">Налаштування програми</string>
@ -657,7 +657,7 @@
<string name="shared_string_apply">Застосувати</string>
<string name="shared_string_add">Додати</string>
<string name="shared_string_no">Ні</string>
<string name="add_favorite_dialog_top_text">Введіть ім’я Закладки</string>
<string name="add_favorite_dialog_top_text">Введіть назву Закладки</string>
<string name="add_favorite_dialog_default_favourite_name">Закладка</string>
<string name="add_favorite_dialog_favourite_added_template">Точку Закладки \'\'{0}\'\' додано.</string>
<string name="favourites_context_menu_edit">Редагувати Закладку</string>
@ -683,7 +683,7 @@
<string name="poi_dialog_opening_hours">Відкрити</string>
<string name="poi_dialog_comment">Коментар</string>
<string name="poi_dialog_comment_default">Зміна POI</string>
<string name="poi_dialog_other_tags_message">Наступні теги POI не можуть бути змінені</string>
<string name="poi_dialog_other_tags_message">Всі інші мітки POI не буде змінено</string>
<string name="default_buttons_commit">Зберегти</string>
<string name="shared_string_clear">Очистити</string>
<string name="filter_current_poiButton">Фільтр</string>
@ -776,7 +776,7 @@
<string name="recording_photo_description">Світлина %1$s %2$s</string>
<string name="av_def_action_picture">Зробити світлину</string>
<string name="recording_context_menu_precord">Зробити світлину</string>
<string name="dropbox_plugin_description">Взаємозберігайте треки та звуко/відео-нотатки з Вашим обліковим записом Dropbox.</string>
<string name="dropbox_plugin_description">Синхронізуйте треки та звуко/відеопримітки з вашим обліковим записом Dropbox.</string>
<string name="dropbox_plugin_name">Втулок Dropbox</string>
<string name="intermediate_points_change_order">Змінити порядок</string>
<string name="srtm_paid_version_msg">Будь ласка, зверніть увагу на оплату втулка \"Горизонталі\" для підтримки подальшого розвитку.</string>
@ -795,7 +795,7 @@
<string name="recording_unavailable">недоступно</string>
<string name="shared_string_control_stop">Зупинити</string>
<string name="shared_string_control_start">Почати</string>
<string name="map_widget_av_notes">Звуко/відео-нотатки</string>
<string name="map_widget_av_notes">Звуко/відеопримітки</string>
<string name="osmand_srtm_short_description_80_chars">Втулок OsmAnd для показу горизонталей в автономному режимі</string>
<string name="av_use_external_camera">Використовувати програму Камера</string>
<string name="av_settings_descr">Налаштування аудіо/відео запису.</string>
@ -805,8 +805,8 @@
<string name="recording_default_name">Запис</string>
<string name="av_def_action_choose">За запитом\?</string>
<string name="recording_is_recorded">Аудіо/відео зараз записується. Для зупинки натисніть на AV-віджет.</string>
<string name="recording_context_menu_arecord">Створити аудіо-нотатку</string>
<string name="recording_context_menu_vrecord">Створити відео-нотатку</string>
<string name="recording_context_menu_arecord">Створити аудіопримітку</string>
<string name="recording_context_menu_vrecord">Створити відеопримітку</string>
<string name="recording_context_menu_delete">Вилучити запис</string>
<string name="recording_context_menu_play">Грати</string>
<string name="map_widget_intermediate_distance">Проміжний пункт призначення</string>
@ -820,9 +820,9 @@
\n
\nВсесвітні дані (між 70° на півночі і 70° на півдні) базуються на вимірюваннях SRTM (Shuttle Radar Topography Mission) і ASTER (Advanced Spaceborne Thermal Emission and Reflection Radiometer), даних інструменту відмальовуванню Terra, флагманського супутника системи спостереження Землі від NASA. ASTER — це підсумок спільної роботи NASA, міністерства економіки Японії, міністерства торгівлі і промисловості Японії (METI), агенції космічних систем Японії (J-spacesystems).</string>
<string name="map_widget_distancemeasurement">Вимірювання відстаней</string>
<string name="map_widget_audionotes">Звуко-нотатки</string>
<string name="audionotes_plugin_description">Зробіть звуко/світлино/відео нотатки під час подорожі, використовуючи або кнопку мапи, або контекстне меню розташування.</string>
<string name="audionotes_plugin_name">Звуко/відео-нотатки</string>
<string name="map_widget_audionotes">Аудіопримітки</string>
<string name="audionotes_plugin_description">Робіть звуко/світлино/відео примітки під час подорожі використовуючи кнопку мапи або контекстне меню розташування.</string>
<string name="audionotes_plugin_name">Звуко/відеопримітки</string>
<string name="index_srtm_parts">частин</string>
<string name="index_srtm_ele">Горизонталі</string>
<string name="srtm_plugin_description">Цей втулок показує як шар горизонталей, так і шар рельєфу поверх усталених мап OsmAnd. Ця функціональність стане в пригоді спортсменам, туристам, мандрівникам та будь-кому, хто цікавиться структурою рельєфу місцевості. (Зверніть увагу, що дані про горизонталі є окремими від даних про рельєф; додаткові завантаження доступні після задіювання втулку.)
@ -843,7 +843,7 @@
<string name="safe_mode_description">Запустити програму в безпечному режимі (використовує повільніші Android-функції замість власних).</string>
<string name="safe_mode">Безпечний режим</string>
<string name="native_library_not_running">Програму запущено в безпечному режимі (вимкніть його в \'Налаштуваннях\').</string>
<string name="audionotes_location_not_defined">Оберіть \"Використати місцезнаходження...\" для прив\'язки нотатки до даного місцезнаходження.</string>
<string name="audionotes_location_not_defined">Виберіть \"Використати місцеперебування...\" для прив\'язки примітки до поточного розташування.</string>
<string name="background_service_is_enabled_question">Службу OsmAnd у тлі досі запущено. Зупинити її роботу також\?</string>
<string name="close_changeset">Закрити набір змін</string>
<string name="zxing_barcode_scanner_not_found">Програма \'ZXing Barcode Scanner\' не встановлена. Шукати в Google Play?</string>
@ -1370,8 +1370,8 @@
<string name="navigate_point_northing">Північної широти</string>
<string name="shared_string_dismiss">Відхилити</string>
<string name="shared_string_audio">Аудіо</string>
<string name="share_note">Поділитись нотаткою</string>
<string name="notes">A/V нотатки</string>
<string name="share_note">Поділитись приміткою</string>
<string name="notes">A/V примітки</string>
<string name="online_map">Мережева мапа</string>
<string name="roads_only">Тільки дороги</string>
<string name="free">Вільно %1$s</string>
@ -1382,7 +1382,7 @@
<string name="nautical_maps_missing">Завантажте спеціальну безмережеву мапу, щоб відобразити морські подробиці.</string>
<string name="edit_group">Редагувати групу</string>
<string name="parking_place">Місце для стоянки</string>
<string name="remove_the_tag">ВИЛУЧИТИ ТЕҐ</string>
<string name="remove_the_tag">ВИЛУЧИТИ МІТКУ</string>
<string name="gps_status">Стан GPS</string>
<string name="version_settings_descr">Завантажити нічні збірки.</string>
<string name="version_settings">Збірки</string>
@ -1589,7 +1589,7 @@
<string name="lang_ceb">Себуанська</string>
<string name="archive_wikipedia_data">У Вас є старі несумісні дані з Вікіпедії. Заархівувати їх?</string>
<string name="download_wikipedia_files">Завантажити додаткові дані з Вікіпедії (%1$s Мб)\?</string>
<string name="gps_network_not_enabled">Служба визначення місцезнаходження вимкнена. Увімкнути?</string>
<string name="gps_network_not_enabled">Служба визначення розташування вимкнена. Увімкнути\?</string>
<string name="disable_recording_once_app_killed">Запобігти самостійному логуваню</string>
<string name="shared_string_import2osmand">Імпортувати до OsmAnd</string>
<string name="read_full_article">Читати повну статтю (мережево)</string>
@ -1624,19 +1624,19 @@
<string name="osm_save_offline">Зберегти локально</string>
<string name="osm_edit_modified_poi">OSM POI відредаговано</string>
<string name="osm_edit_deleted_poi">OSM POI видалено</string>
<string name="context_menu_item_open_note">Відкрити OSM-нотатку</string>
<string name="osm_edit_reopened_note">Відкрити заново OSM-нотатку</string>
<string name="osm_edit_commented_note">До OSM-нотатки додано коментар</string>
<string name="osm_edit_created_note">Створено OSM-нотатку</string>
<string name="osn_bug_name">OSM-нотатка</string>
<string name="osn_add_dialog_title">Створити нотатку</string>
<string name="context_menu_item_open_note">Відкрити примітку OSM</string>
<string name="osm_edit_reopened_note">Повторно відкрити примітку OSM</string>
<string name="osm_edit_commented_note">До примітки OSM додано коментар</string>
<string name="osm_edit_created_note">Створено примітку OSM</string>
<string name="osn_bug_name">Примітка OSM</string>
<string name="osn_add_dialog_title">Створити примітку</string>
<string name="osn_comment_dialog_title">Додати коментар</string>
<string name="osn_reopen_dialog_title">Перевідкрити нотатку</string>
<string name="osn_close_dialog_title">Закрити нотатку</string>
<string name="osn_add_dialog_success">Нотатку створено</string>
<string name="osn_add_dialog_error">Не вдалося створити нотатку.</string>
<string name="osn_close_dialog_success">Нотатку закрито</string>
<string name="osn_close_dialog_error">Не вдалося закрити нотатку.</string>
<string name="osn_reopen_dialog_title">Перевідкрити примітку</string>
<string name="osn_close_dialog_title">Закрити примітку</string>
<string name="osn_add_dialog_success">Примітку створено</string>
<string name="osn_add_dialog_error">Не вдалося створити примітку.</string>
<string name="osn_close_dialog_success">Примітку закрито</string>
<string name="osn_close_dialog_error">Не вдалося закрити примітку.</string>
<string name="shared_string_commit">Підтвердити</string>
<string name="context_menu_item_delete_waypoint">Вилучити GPX точку?</string>
<string name="context_menu_item_edit_waypoint">Редагувати GPX точку</string>
@ -1656,7 +1656,7 @@
<string name="go_to_map">Показати мапу</string>
<string name="simulate_initial_startup">Імітувати перший запуск застосунку</string>
<string name="share_geo">гео:</string>
<string name="share_menu_location">Поділитись місцезнаходженням</string>
<string name="share_menu_location">Поділитись місцеперебуванням</string>
<string name="shared_string_send">Надіслати</string>
<string name="favorite_category_dublicate_message">Будь ласка, використовуйте назву категорії, яка ще не існує.</string>
<string name="favorite_category_name">Назва категорії</string>
@ -1790,7 +1790,7 @@
<string name="share_osm_edits_subject">OSM правки, поширені через OsmAnd</string>
<string name="rendering_attr_hideProposed_name">Заплановані обʼєкти</string>
<string name="save_poi_without_poi_type_message">Ви дійсно хочете зберегти POI, не вказавши його тип?</string>
<string name="no_location_permission">Надання доступу до даних про місцезнаходження.</string>
<string name="no_location_permission">Надання доступу до даних про місцеперебування.</string>
<string name="no_camera_permission">Надання доступу до камери.</string>
<string name="no_microphone_permission">Надання доступу до мікрофона.</string>
<string name="route_distance">Відстань:</string>
@ -1947,8 +1947,8 @@
<string name="osm_live_header">Передплата дозволяє щогодини отримувати оновлення для мап по всьому світу.
\nЧастина від передплати переводиться спільноті OSM та виплачується кожному землеписцю за його внесок.
\nЯкщо Вам подобається OsmAnd та OSM, і хочете підтримати і бути підтриманими ними, це ідеальний спосіб зробити це.</string>
<string name="upload_osm_note_description">Надішліть Вашу OSM-нотатку таємно, або скориставшись обліковим записом на OSM.org.</string>
<string name="upload_osm_note">Надіслати нотатку в OSM</string>
<string name="upload_osm_note_description">Надішліть примітку OSM знеособлено чи скориставшись профілем OpenStreetMap.org.</string>
<string name="upload_osm_note">Надіслати примітку в OSM</string>
<string name="file_name_containes_illegal_char">Неприпустимі знаки в назві файлу</string>
<string name="follow_us">Слідкуйте за нами</string>
<string name="access_direction_audio_feedback">Звукові напрямки</string>
@ -2039,7 +2039,7 @@
<string name="location_not_found">Неможливо визначити місце розташування</string>
<string name="no_inet_connection">З’єднання з Інтернетом відсутнє</string>
<string name="no_inet_connection_desc_map">Необхідно завантажити мапи.</string>
<string name="search_location">Визначення місцезнаходження…</string>
<string name="search_location">Визначення місцеперебування…</string>
<string name="storage_free_space">Вільне місце</string>
<string name="storage_place_description">Сховище даних OsmAnd (мапи, файли з треками, тощо): %1$s.</string>
<string name="give_permission">Дати дозвіл</string>
@ -2162,19 +2162,19 @@
<string name="quick_action_map_underlay_action">Додати підкладку</string>
<string name="quick_action_map_source">Змінити джерело мапи</string>
<string name="quick_action_btn_tutorial_descr">Довге натискання з перетягуванням кнопки змінює її розташування на екрані.</string>
<string name="quick_action_add_osm_bug">Додати нотатку OSM</string>
<string name="quick_action_add_osm_bug">Додати примітку OSM</string>
<string name="rendering_value_fine_name">Дуже тонкий</string>
<string name="navigate_point_olc">Відкритий код розташування (OLC)</string>
<string name="quick_action_take_audio_note">Нова аудіонотатка</string>
<string name="quick_action_take_video_note">Нова відеонотатка</string>
<string name="quick_action_take_photo_note">Нова фотонотатка</string>
<string name="quick_action_take_audio_note">Нова аудіопримітка</string>
<string name="quick_action_take_video_note">Нова відеопримітка</string>
<string name="quick_action_take_photo_note">Нова фотопримітка</string>
<string name="quick_favorites_name_preset">Найменування</string>
<string name="quick_action_add_marker_descr">Кнопка для додавання позначки мапи посередині екрану.</string>
<string name="quick_action_add_gpx_descr">Натискання на цю кнопку додасть маршрутну точку GPX посередині екрану.</string>
<string name="quick_action_take_audio_note_descr">Натискання цієї кнопки додає аудіонотатку посередині екрану.</string>
<string name="quick_action_take_video_note_descr">Натискання цієї кнопки додає відеонотатку посередині екрану.</string>
<string name="quick_action_take_photo_note_descr">Натискання цієї кнопки додає фотонотатку посередині екрану.</string>
<string name="quick_action_add_osm_bug_descr">Натискання цієї кнопки додає OSM-нотатку посередині екрану.</string>
<string name="quick_action_take_audio_note_descr">Натискання цієї кнопки додає аудіопримітку посередині екрана.</string>
<string name="quick_action_take_video_note_descr">Натискання цієї кнопки додає відеопримітку посередині екрана.</string>
<string name="quick_action_take_photo_note_descr">Натискання цієї кнопки додає фотопримітку посередині екрана.</string>
<string name="quick_action_add_osm_bug_descr">Натискання цієї кнопки додає примітку OSM посередині екрану.</string>
<string name="quick_action_add_poi_descr">Натискання цієї кнопки додає POI посередині екрану.</string>
<string name="quick_action_navigation_voice_descr">Перемикач, щоб вимкнути або увімкнути голосові підказки під час навігації.</string>
<string name="quick_action_add_parking_descr">Кнопка для додавання місця паркування посередині екрана.</string>
@ -2210,12 +2210,12 @@
<string name="restart_search">Шукати знову</string>
<string name="increase_search_radius">Збільшити радіус пошуку</string>
<string name="nothing_found">Нічого не знайдено</string>
<string name="private_access_routing_req">Місце призначення знаходиться в області з приватним доступом. Дозволити доступ по приватних дорогах для цієї подорожі\?</string>
<string name="private_access_routing_req">Місце призначення розташовано в області з приватним доступом. Дозволити доступ до приватних доріг у цій подорожі\?</string>
<string name="nothing_found_descr">Змініть пошуковий запит або ж розширте пошуковий радіус.</string>
<string name="quick_action_showhide_osmbugs_title">Показати/приховати OSM-нотатки</string>
<string name="quick_action_osmbugs_show">Показати OSM-нотатки</string>
<string name="quick_action_osmbugs_hide">Приховати OSM-нотатки</string>
<string name="quick_action_showhide_osmbugs_descr">Натискання на кнопку дії покаже чи приховає OSM-нотатки на мапі.</string>
<string name="quick_action_showhide_osmbugs_title">Показати/приховати примітки OSM</string>
<string name="quick_action_osmbugs_show">Показати примітки OSM</string>
<string name="quick_action_osmbugs_hide">Приховати примітки OSM</string>
<string name="quick_action_showhide_osmbugs_descr">Натискання на кнопку дії покаже чи приховає примітки OSM на мапі.</string>
<string name="sorted_by_distance">Відсортоване за відстанню</string>
<string name="search_favorites">Пошук у закладках</string>
<string name="hillshade_menu_download_descr">Завантажте шар мапи «Пагорби», щоб показати вертикальне затінення.</string>
@ -2304,12 +2304,12 @@
\n</string>
<string name="osmand_extended_description_part4">Катання на лижах
\nOsmAnd-втулок лижних мап дозволяє бачити лижні траси з рівнем складності та деякою додатковими відомостями на зразок розташування підйомників та інших об’єктів.</string>
<string name="osmand_extended_description_part5">Їзда на велосипеді
\n• Знаходьте велосипедні доріжки на мапі
\n• GPS-навігація у велосипедному режимі будує маршрут з використанням велосипедних доріжок
\n• Ви можете бачити свою швидкість та висотне положення
\n• Опція запису GPX дозволяє вам записувати Вашу подорож та ділитися нею
\n• Через додатковий втулок Ви можете увімкнути відображення горизонталей та рельєфу</string>
<string name="osmand_extended_description_part5">Їзда на велосипеді
\n• Знаходьте велосипедні доріжки на мапі
\n• GPS-навігація у велосипедному режимі будує маршрут з використанням велосипедних доріжок
\n• Ви можете бачити свою швидкість та висотне положення
\n• Параметр запису GPX дозволяє вам записувати вашу подорож та ділитися нею
\n• Через додатковий втулок ви можете увімкнути показ горизонталей та рельєфу</string>
<string name="osmand_extended_description_part6">Прогулянки, походи, екскурсія по місту
\n• Мапа показує доріжки для прогулянок та походів
\n• Вікіпедія Вашою обраною мовою може багато розповісти під час екскурсії містом
@ -2382,9 +2382,9 @@
<string name="osmand_plus_extended_description_part7">Безпосередній вклад у OSM
\n• Звітуйте про помилки в даних
\n• Вивантажуйте GPX-треки в OSM безпосередньо з програми
\n• Додавайте POI (цікаві точки) та безпосередньо вивантажуйте їх в OSM (чи пізніше, якщо зараз Ви в офлайні)
\n• Опція запису подорожі також і в режимі тла (в той час як пристрій знаходиться в сплячому режимі)
\nOsmAnd — вільне й відкрите програмне забезпечення, що активно розвивається. Кожен може внести свій вклад, звітуючи про помилки, поліпшуючи переклад чи розробляючи нові функції. Також проєкт покладається на фінансові внески для оплати розробки та тестування нових функціональних можливостей.
\n• Додавайте POI (цікаві точки) та безпосередньо вивантажуйте їх в OSM (чи пізніше, якщо зараз ви в автономному режимі)
\n• Параметр запису подорожі також і в тлі (коли пристрій перебуває в режимі сну)
\nOsmAnd — вільне й відкрите програмне забезпечення, що активно розвивається. Кожен може допомогти, звітуючи про помилки, поліпшуючи переклад чи розробляючи нові функції. Також проєкт покладається на фінансові внески для оплати розробки та тестування нових функціональних можливостей.
\n</string>
<string name="osmand_plus_extended_description_part8">Приблизне охоплення мап та якість:
\n • Західна Європа: ****
@ -2505,7 +2505,7 @@
<string name="order_by">Сортувати за:</string>
<string name="use_location">Використовувати розташування</string>
<string name="add_location_as_first_point_descr">Додати Ваше місце розташування як точку початку при плануванні маршруту.</string>
<string name="my_location">Моє місцезнаходження</string>
<string name="my_location">Моє місцеперебування</string>
<string name="shared_string_finish">Фініш</string>
<string name="plan_route">Планувати маршрут</string>
<string name="shared_string_sort">Впорядкувати</string>
@ -2526,9 +2526,9 @@
<string name="routing_attr_avoid_ice_roads_fords_description">Уникає льодових доріг і бродів.</string>
<string name="make_round_trip_descr">Додати копію початкової точки як місце призначення.</string>
<string name="make_round_trip">Зробити кругову подорож</string>
<string name="osn_modify_dialog_error">Не вдалося змінити нотатку.</string>
<string name="osn_modify_dialog_title">Змінити нотатку</string>
<string name="context_menu_item_modify_note">Змінити OSM-нотатку</string>
<string name="osn_modify_dialog_error">Не вдалося змінити примітку.</string>
<string name="osn_modify_dialog_title">Змінити примітку</string>
<string name="context_menu_item_modify_note">Змінити примітку OSM</string>
<string name="wrong_input">Неправильний ввід</string>
<string name="wrong_format">Неправильний формат</string>
<string name="shared_string_road">Дорога</string>
@ -2576,15 +2576,15 @@
<string name="looking_for_tracks_with_waypoints">Пошук треків з шляховими точками</string>
<string name="shared_string_more_without_dots">Більше</string>
<string name="empty_state_osm_edits">Створити або змінити OSM-об\'єкти</string>
<string name="empty_state_osm_edits_descr">Створюйте або змінюйте цікаві точки в OSM, відкривайте або коментуйте OSM-нотатки, а також надсилайте записані GPX-файли.</string>
<string name="empty_state_osm_edits_descr">Створюйте або змінюйте OSM POI, відкривайте або коментуйте примітки OSM та надсилайте записані GPX-файли.</string>
<string name="shared_string_deleted">Вилучено</string>
<string name="shared_string_edited">Відредаговано</string>
<string name="shared_string_added">Додано</string>
<string name="marker_activated">Позначку %s задіяно.</string>
<string name="one_tap_active_descr">Натискання на позначку на мапі перемістить її на перше місце в списку задіяних позначок, не відкриваючи контекстне меню.</string>
<string name="one_tap_active">Задіювання одним натисненням</string>
<string name="empty_state_av_notes">Робіть нотатки!</string>
<string name="empty_state_av_notes_desc">Додайте аудіо, відео або фотонотатку в будь-яку точку на мапі, використовуючи віджет або контекстне меню.</string>
<string name="empty_state_av_notes">Робіть примітки!</string>
<string name="empty_state_av_notes_desc">Додайте аудіо, відео або фотопримітку в будь-яку точку на мапі використовуючи віджет або контекстне меню.</string>
<string name="notes_by_date">Примітки за датою</string>
<string name="by_date">За датою</string>
<string name="by_type">За типом</string>
@ -2620,14 +2620,14 @@
<string name="last_intermediate_dest_description">Додає проміжну зупинку</string>
<string name="first_intermediate_dest_description">Додає першу зупинку</string>
<string name="subsequent_dest_description">Пересунути призначення далі і створити його</string>
<string name="show_closed_notes">Показати закриті нотатки</string>
<string name="show_closed_notes">Показати закриті примітки</string>
<string name="switch_osm_notes_visibility_desc">Показати чи приховати примітки OSM на мапі.</string>
<string name="gpx_file_desc">GPX — підходить для експорту в JOSM та інші OSM-редактори.</string>
<string name="osc_file_desc">OSC — підходить для експорту в OSM.</string>
<string name="shared_string_gpx_file">GPX-файл</string>
<string name="osc_file">OSC-файл</string>
<string name="choose_file_type">Виберіть тип файлу</string>
<string name="osm_edits_export_desc">Виберіть вид експорту: OSM-нотатки, POI чи і те і те.</string>
<string name="osm_edits_export_desc">Виберіть вид експорту: примітки OSM, POI чи і те і те.</string>
<string name="all_data">Усі дані</string>
<string name="osm_notes">Примітки OSM</string>
<string name="will_open_tomorrow_at">Відкриється завтра о</string>
@ -2844,7 +2844,7 @@
<string name="routeInfo_steepness_name">Крутість</string>
<string name="run_full_osmand_header">Запустити OsmAnd\?</string>
<string name="shared_string_walk">Пішки</string>
<string name="save_poi_value_exceed_length">Довжина тегу \"%s\" має бути менше 255 символів.</string>
<string name="save_poi_value_exceed_length">Довжина мітки \"%s\" має бути менше 255 символів.</string>
<string name="public_transport_warning_descr_blog">Докладніше про те, як OsmAnd розраховує маршрути, читайте в нашому деннику.</string>
<string name="public_transport_warning_title">Навігація громадським транспортом на даний час проходить тестування, можливі помилки та неточності.</string>
<string name="add_intermediate">Додати проміжну точку</string>
@ -3339,13 +3339,13 @@
<string name="multimedia_notes_prefs_descr">Розмір зображення, якість звуку та відео</string>
<string name="osm_editing_prefs_descr">Логін, пароль, редагування в безмережному режимі</string>
<string name="accessibility_prefs_descr">Оберіть значок, колір та назву</string>
<string name="live_monitoring_descr">Дозволяє ділитися поточним місцезнаходженням, використовуючи запис поїздки.</string>
<string name="live_monitoring_descr">Дозволяє ділитися поточним місцеперебуванням, використовуючи запис поїздки.</string>
<string name="live_monitoring">Мережеве відстеження</string>
<string name="save_track_logging_accuracy">Точність журналювання</string>
<string name="tracks_view_descr">Ви можете знайти всі записи в %1$s або в теці OsmAnd за допомогою файлового провідника.</string>
<string name="multimedia_notes_view_descr">Ваші нотатки OSM знаходяться в %1$s.</string>
<string name="video_notes">Відеонотатки</string>
<string name="photo_notes">Фотонотатки</string>
<string name="multimedia_notes_view_descr">Ваші примітки OSM розміщено в %1$s.</string>
<string name="video_notes">Відеопримітки</string>
<string name="photo_notes">Фотопримітки</string>
<string name="route_recalculation">Перерахунок маршруту</string>
<string name="accessibility_announce">Оголошення</string>
<string name="login_and_pass">Ім\'я користувача і пароль</string>
@ -3617,7 +3617,7 @@
<string name="quick_action_show_hide_transport">Показати чи приховати громадський транспорт</string>
<string name="quick_action_transport_descr">Кнопка показу або приховування громадського транспорту на мапі.</string>
<string name="create_edit_poi">Створити чи змінити POI</string>
<string name="add_edit_favorite">Додати чи змінити вибране</string>
<string name="add_edit_favorite">Додати чи змінити закладку</string>
<string name="reset_deafult_order">Відновити усталене впорядкування</string>
<string name="back_to_editing">Повернутися до редагування</string>
<string name="additional_actions_descr">Ви можете отримати доступ до цих дій, торкнувшись кнопки “%1$s”.</string>
@ -3999,4 +3999,10 @@
<string name="routing_engine_vehicle_type_mtb">Гірський велосипед</string>
<string name="message_server_error">Помилка сервера: %1$s</string>
<string name="message_name_is_already_exists">Назва вже існує</string>
<string name="delete_online_routing_engine">Видалити цей рушій мережної маршрутизації\?</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>
</resources>

View file

@ -491,7 +491,7 @@
<string name="route_kr">靠右行驶</string>
<string name="rendering_attr_noPolygons_name">隐藏多边形</string>
<string name="rendering_attr_appMode_name">渲染模式</string>
<string name="rendering_attr_contourLines_name"/>
<string name="rendering_attr_contourLines_name">显示等高线</string>
<string name="rendering_attr_hmRendered_name">显示更多地图细节</string>
<string name="local_index_routing_data">路线规划数据</string>
<string name="navigate_point_format">格式</string>
@ -1120,7 +1120,7 @@
<string name="do_not_send_anonymous_app_usage">不要发送匿名应用使用统计信息</string>
<string name="restore_purchases">恢复购买内容</string>
<string name="shared_string_visible">可见性</string>
<string name="do_not_send_anonymous_app_usage_desc">OsmAnd 会搜集您打开应用的哪一部分的信息。您的位置永远不会被发送至服务器,您输入进应用的任何数据或者浏览的区域、搜索内容和下载内容同样不会被搜集。</string>
<string name="do_not_send_anonymous_app_usage_desc">OsmAnd 只会搜集您打开应用的那一部分的信息。您的位置永远不会被发送至服务器,您输入进应用的任何数据或者浏览的区域、搜索内容和下载内容同样不会被搜集。</string>
<string name="do_not_show_startup_messages">不要在启动时显示信息</string>
<string name="full_version_thanks">感谢您购买完整版本的 OsmAnd</string>
<string name="shared_string_action_name">操作名称</string>
@ -1915,7 +1915,7 @@
<string name="map_widget_av_notes">音频/视频注记</string>
<string name="audionotes_location_not_defined">轻触\"使用位置 …\"以在此添加注记。</string>
<string name="map_widget_audionotes">音频注记</string>
<string name="rendering_attr_alpineHiking_name"/>
<string name="rendering_attr_alpineHiking_name">高山远足表(SAC)</string>
<string name="rendering_attr_alpineHiking_description">依据 SAC 分级计算路径</string>
<string name="rendering_attr_hikingRoutesOSMC_name">徒步旅行符号叠加层</string>
<string name="rendering_attr_hikingRoutesOSMC_description">根据 OSMC 轨迹渲染路径。</string>
@ -3112,4 +3112,16 @@
<string name="add_address">添加地址</string>
<string name="access_hint_enter_address">输入地址</string>
<string name="monitoring_control_start">REC</string>
<string name="measurement_tool_snap_to_road_descr">OsmAnd将为选择的配置文件连接路线点。</string>
<string name="add_point_before">在之前添加点</string>
<string name="add_point_after">在之后添加点</string>
<string name="route_point">路线点</string>
<string name="save_as_route_point">保存为路线点</string>
<string name="route_point_one">路线点1</string>
<string name="save_route_point">保存路线点</string>
<string name="live_monitoring_max_interval_to_send">用于在线跟踪的时间缓冲区</string>
<string name="quick_action_add_gpx">添加轨迹航点</string>
<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>
</resources>

View file

@ -12,6 +12,11 @@
-->
<string name="toast_select_edits_for_upload">Select edits for upload</string>
<string name="uploaded_count">Uploaded %1$d of %2$d</string>
<string name="uploading_count">Uploading %1$d of %2$d</string>
<string name="upload_photo_completed">Upload completed</string>
<string name="upload_photo">Uploading</string>
<string name="copy_to_map_favorites">Copy to favorites</string>
<string name="copy_to_map_markers">Copy to map markers</string>
<string name="delete_waypoints">Delete waypoints</string>

View file

@ -153,12 +153,12 @@ public class GpxSelectionHelper {
return followTrackListener;
}
private static class GpxFileLoaderTask extends AsyncTask<Void, Void, GPXFile> {
public static class GpxFileLoaderTask extends AsyncTask<Void, Void, GPXFile> {
private File fileToLoad;
private CallbackWithObject<GPXFile> callback;
GpxFileLoaderTask(File fileToLoad, CallbackWithObject<GPXFile> callback) {
public GpxFileLoaderTask(File fileToLoad, CallbackWithObject<GPXFile> callback) {
this.fileToLoad = fileToLoad;
this.callback = callback;
}

View file

@ -636,7 +636,7 @@ public class UiUtilities {
int activeDisableColor = getColorWithAlpha(activeColor, 0.25f);
ColorStateList activeCsl = new ColorStateList(states, new int[] {activeColor, activeDisableColor});
int inactiveColor = ContextCompat.getColor(ctx, nightMode ? R.color.icon_color_default_dark : R.color.icon_color_secondary_light);
ColorStateList inactiveCsl = new ColorStateList(states, new int[] {inactiveColor, inactiveColor});
ColorStateList inactiveCsl = new ColorStateList(states, new int[] {activeDisableColor, inactiveColor});
slider.setTrackActiveTintList(activeCsl);
slider.setTrackInactiveTintList(inactiveCsl);
slider.setHaloTintList(activeCsl);

View file

@ -70,7 +70,6 @@ import net.osmand.plus.GpxSelectionHelper.GpxDisplayItem;
import net.osmand.plus.GpxSelectionHelper.SelectedGpxFile;
import net.osmand.plus.OnDismissDialogFragmentListener;
import net.osmand.plus.OsmAndConstants;
import net.osmand.plus.OsmAndLocationProvider;
import net.osmand.plus.OsmAndLocationProvider.OsmAndLocationListener;
import net.osmand.plus.OsmAndLocationSimulation;
import net.osmand.plus.OsmandApplication;
@ -1568,6 +1567,17 @@ public class MapActivity extends OsmandActionBarActivity implements DownloadEven
}
}
public boolean shouldHideTopControls() {
boolean hideTopControls = !mapContextMenu.shouldShowTopControls();
TrackMenuFragment fragment = getTrackMenuFragment();
if (fragment != null) {
hideTopControls = hideTopControls || !fragment.shouldShowTopControls();
}
return hideTopControls;
}
public OsmandMapTileView getMapView() {
return mapView;
}
@ -1628,8 +1638,8 @@ public class MapActivity extends OsmandActionBarActivity implements DownloadEven
launchMapActivityMoveToTop(activity, null);
}
public static void launchMapActivityMoveToTop(Context activity, Bundle intentParams) {
launchMapActivityMoveToTop(activity, intentParams, null, null);
public static void launchMapActivityMoveToTop(Context activity, Bundle prevIntentParams) {
launchMapActivityMoveToTop(activity, prevIntentParams, null, null);
}
public static void clearPrevActivityIntent() {

View file

@ -103,7 +103,7 @@ public abstract class ContextMenuFragment extends BaseOsmAndFragment
public interface ContextMenuFragmentListener {
void onContextMenuYPosChanged(@NonNull ContextMenuFragment fragment, int y, boolean needMapAdjust, boolean animated);
void onContextMenuStateChanged(@NonNull ContextMenuFragment fragment, int menuState);
void onContextMenuStateChanged(@NonNull ContextMenuFragment fragment, int menuState, int previousMenuState);
void onContextMenuDismiss(@NonNull ContextMenuFragment fragment);
}
@ -815,7 +815,7 @@ public abstract class ContextMenuFragment extends BaseOsmAndFragment
ContextMenuFragmentListener listener = this.listener;
if (listener != null) {
listener.onContextMenuStateChanged(this, newMenuState);
listener.onContextMenuStateChanged(this, newMenuState, currentMenuState);
}
}
@ -971,7 +971,8 @@ public abstract class ContextMenuFragment extends BaseOsmAndFragment
ContextMenuFragmentListener listener = ContextMenuFragment.this.listener;
if (listener != null) {
listener.onContextMenuStateChanged(ContextMenuFragment.this, getCurrentMenuState());
int menuState = getCurrentMenuState();
listener.onContextMenuStateChanged(ContextMenuFragment.this, menuState, menuState);
}
}
}

View file

@ -82,7 +82,7 @@ public abstract class ContextMenuScrollFragment extends ContextMenuFragment impl
}
@Override
public void onContextMenuStateChanged(@NonNull ContextMenuFragment fragment, int menuState) {
public void onContextMenuStateChanged(@NonNull ContextMenuFragment fragment, int menuState, int previousMenuState) {
updateMapControlsVisibility(menuState);
}

View file

@ -268,6 +268,18 @@ public abstract class MenuBottomSheetDialogFragment extends BottomSheetDialogFra
dismissButtonStringRes = stringRes;
}
protected int getDismissButtonHeight(){
return getResources().getDimensionPixelSize(R.dimen.bottom_sheet_cancel_button_height_small);
}
protected int getRightButtonHeight(){
return getResources().getDimensionPixelSize(R.dimen.bottom_sheet_cancel_button_height_small);
}
protected int getThirdButtonHeight(){
return getResources().getDimensionPixelSize(R.dimen.bottom_sheet_cancel_button_height_small);
}
protected DialogButtonType getDismissButtonType() {
return DialogButtonType.SECONDARY;
}
@ -360,6 +372,7 @@ public abstract class MenuBottomSheetDialogFragment extends BottomSheetDialogFra
private void setupDismissButton() {
dismissButton = buttonsContainer.findViewById(R.id.dismiss_button);
dismissButton.getLayoutParams().height = getDismissButtonHeight();
int buttonTextId = getDismissButtonTextId();
if (buttonTextId != DEFAULT_VALUE) {
UiUtilities.setupDialogButton(nightMode, dismissButton, getDismissButtonType(), buttonTextId);
@ -376,6 +389,7 @@ public abstract class MenuBottomSheetDialogFragment extends BottomSheetDialogFra
private void setupRightButton() {
rightButton = buttonsContainer.findViewById(R.id.right_bottom_button);
rightButton.getLayoutParams().height = getRightButtonHeight();
int buttonTextId = getRightBottomButtonTextId();
if (buttonTextId != DEFAULT_VALUE) {
UiUtilities.setupDialogButton(nightMode, rightButton, getRightBottomButtonType(), buttonTextId);
@ -398,6 +412,7 @@ public abstract class MenuBottomSheetDialogFragment extends BottomSheetDialogFra
protected void setupThirdButton() {
thirdButton = buttonsContainer.findViewById(R.id.third_button);
thirdButton.getLayoutParams().height = getThirdButtonHeight();
int buttonTextId = getThirdBottomButtonTextId();
if (buttonTextId != DEFAULT_VALUE) {
UiUtilities.setupDialogButton(nightMode, thirdButton, getThirdBottomButtonType(), buttonTextId);

View file

@ -0,0 +1,11 @@
package net.osmand.plus.base.bottomsheetmenu.simpleitems;
import net.osmand.plus.R;
import net.osmand.plus.base.bottomsheetmenu.SimpleBottomSheetItem;
public class ProgressItem extends SimpleBottomSheetItem {
public ProgressItem() {
this.layoutId = R.layout.bottom_sheet_item_progress;
}
}

View file

@ -99,7 +99,9 @@ public class RenameFileBottomSheet extends MenuBottomSheetDialogFragment {
}
private void updateFileName(String name) {
if (!Algorithms.isEmpty(name) && ILLEGAL_FILE_NAME_CHARACTERS.matcher(name).find()) {
if (Algorithms.isBlank(name)) {
nameTextBox.setError(getString(R.string.empty_filename));
} else if (ILLEGAL_FILE_NAME_CHARACTERS.matcher(name).find()) {
nameTextBox.setError(getString(R.string.file_name_containes_illegal_char));
} else {
selectedFileName = name;

View file

@ -0,0 +1,118 @@
package net.osmand.plus.dialogs;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnDismissListener;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ProgressBar;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.fragment.app.FragmentActivity;
import androidx.fragment.app.FragmentManager;
import net.osmand.plus.R;
import net.osmand.plus.UiUtilities;
import net.osmand.plus.base.MenuBottomSheetDialogFragment;
import net.osmand.plus.base.bottomsheetmenu.BaseBottomSheetItem;
import net.osmand.plus.base.bottomsheetmenu.BottomSheetItemWithDescription;
import net.osmand.plus.base.bottomsheetmenu.simpleitems.DividerSpaceItem;
import net.osmand.plus.mapcontextmenu.UploadPhotosAsyncTask.UploadPhotosListener;
public class UploadPhotoProgressBottomSheet extends MenuBottomSheetDialogFragment implements UploadPhotosListener {
public static final String TAG = UploadPhotoProgressBottomSheet.class.getSimpleName();
private ProgressBar progressBar;
private TextView uploadedPhotosTitle;
private TextView uploadedPhotosCounter;
private OnDismissListener onDismissListener;
private int progress;
private int maxProgress;
@Override
public void createMenuItems(Bundle savedInstanceState) {
Context context = requireContext();
LayoutInflater inflater = UiUtilities.getInflater(context, nightMode);
View view = inflater.inflate(R.layout.bottom_sheet_with_progress_bar, null);
uploadedPhotosTitle = view.findViewById(R.id.title);
uploadedPhotosCounter = view.findViewById(R.id.description);
progressBar = view.findViewById(R.id.progress_bar);
progressBar.setMax(maxProgress);
String titleProgress = getString(progress == maxProgress? R.string.upload_photo_completed: R.string.upload_photo);
String descriptionProgress;
if (progress == maxProgress) {
descriptionProgress = getString(R.string.uploaded_count, progress, maxProgress);
} else {
descriptionProgress = getString(R.string.uploading_count, progress, maxProgress);
}
BaseBottomSheetItem descriptionItem = new BottomSheetItemWithDescription.Builder()
.setDescription(descriptionProgress)
.setTitle(titleProgress)
.setCustomView(view)
.create();
items.add(descriptionItem);
updateProgress(progress);
int padding = getResources().getDimensionPixelSize(R.dimen.content_padding_small);
items.add(new DividerSpaceItem(context, padding));
}
public void setMaxProgress(int maxProgress) {
this.maxProgress = maxProgress;
}
public void setOnDismissListener(OnDismissListener onDismissListener) {
this.onDismissListener = onDismissListener;
}
private void updateProgress(int progress) {
progressBar.setProgress(progress);
uploadedPhotosCounter.setText((getString(R.string.uploading_count, progress, maxProgress)));
uploadedPhotosTitle.setText(progress == maxProgress ? R.string.upload_photo_completed : R.string.upload_photo);
}
@Override
public void uploadPhotosProgressUpdate(int progress) {
this.progress = progress;
updateProgress(progress);
}
@Override
public void uploadPhotosFinished() {
updateProgress(maxProgress);
if (progress == maxProgress) {
uploadedPhotosCounter.setText((getString(R.string.uploaded_count, progress, maxProgress)));
setDismissButtonTextId(R.string.shared_string_close);
UiUtilities.setupDialogButton(nightMode, dismissButton, getDismissButtonType(), getDismissButtonTextId());
}
}
@Override
public void onDismiss(@NonNull DialogInterface dialog) {
super.onDismiss(dialog);
FragmentActivity activity = getActivity();
if (onDismissListener != null && activity != null && !activity.isChangingConfigurations()) {
onDismissListener.onDismiss(dialog);
}
}
public static UploadPhotosListener showInstance(@NonNull FragmentManager fragmentManager, int maxProgress, OnDismissListener listener) {
UploadPhotoProgressBottomSheet fragment = new UploadPhotoProgressBottomSheet();
fragment.setRetainInstance(true);
fragment.setMaxProgress(maxProgress);
fragment.setOnDismissListener(listener);
fragmentManager.beginTransaction()
.add(fragment, UploadPhotoProgressBottomSheet.TAG)
.commitAllowingStateLoss();
return fragment;
}
}

View file

@ -13,6 +13,7 @@ import net.osmand.plus.OsmandApplication;
import net.osmand.plus.OsmandPlugin;
import net.osmand.plus.download.DownloadOsmandIndexesHelper.AssetIndexItem;
import net.osmand.plus.inapp.InAppPurchaseHelper;
import net.osmand.plus.wikivoyage.data.TravelDbHelper;
import net.osmand.util.Algorithms;
import org.apache.commons.logging.Log;
@ -358,7 +359,9 @@ public class DownloadResources extends DownloadResourceGroup {
continue;
}
if (ii.getType() == DownloadActivityType.WIKIVOYAGE_FILE) {
wikivoyageMaps.addItem(ii);
if (app.getTravelHelper() instanceof TravelDbHelper) {
wikivoyageMaps.addItem(ii);
}
continue;
}
if (ii.getType() == DownloadActivityType.TRAVEL_FILE) {

View file

@ -27,6 +27,7 @@ import net.osmand.plus.settings.backend.ApplicationMode;
import net.osmand.plus.settings.backend.OsmandSettings;
import net.osmand.plus.settings.fragments.BaseSettingsFragment;
import net.osmand.plus.settings.fragments.BaseSettingsFragment.SettingsScreenType;
import net.osmand.plus.track.TrackMenuFragment;
import net.osmand.util.Algorithms;
import org.apache.commons.logging.Log;
@ -37,6 +38,8 @@ import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static net.osmand.plus.activities.TrackActivity.CURRENT_RECORDING;
import static net.osmand.plus.activities.TrackActivity.TRACK_FILE_NAME;
import static net.osmand.plus.osmedit.oauth.OsmOAuthHelper.OsmAuthorizationListener;
public class IntentHelper {
@ -250,6 +253,12 @@ public class IntentHelper {
}
mapActivity.setIntent(null);
}
if (intent.hasExtra(TrackMenuFragment.OPEN_TRACK_MENU)) {
String path = intent.getStringExtra(TRACK_FILE_NAME);
boolean currentRecording = intent.getBooleanExtra(CURRENT_RECORDING, false);
TrackMenuFragment.showInstance(mapActivity, path, currentRecording);
mapActivity.setIntent(null);
}
}
}

View file

@ -29,7 +29,6 @@ import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import net.osmand.plus.activities.ActivityResultListener;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.activities.TrackActivity;
import net.osmand.plus.dialogs.ImportGpxBottomSheetDialogFragment;
import net.osmand.plus.helpers.GpxUiHelper;
import net.osmand.plus.helpers.GpxUiHelper.GPXInfo;
@ -37,6 +36,7 @@ import net.osmand.plus.measurementtool.MeasurementToolFragment;
import net.osmand.plus.settings.backend.ExportSettingsType;
import net.osmand.plus.settings.backend.backup.SettingsHelper;
import net.osmand.plus.settings.backend.backup.SettingsItem;
import net.osmand.plus.track.TrackMenuFragment;
import net.osmand.plus.views.OsmandMapTileView;
import net.osmand.util.Algorithms;
@ -596,10 +596,7 @@ public class ImportHelper {
private void showGpxInDetailsActivity(String gpxFilePath) {
if (!Algorithms.isEmpty(gpxFilePath)) {
Intent newIntent = new Intent(activity, app.getAppCustomization().getTrackActivity());
newIntent.putExtra(TrackActivity.TRACK_FILE_NAME, gpxFilePath);
newIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
activity.startActivity(newIntent);
TrackMenuFragment.openTrack(activity, new File(gpxFilePath), null);
}
}

View file

@ -22,18 +22,17 @@ import net.osmand.data.FavouritePoint;
import net.osmand.data.LatLon;
import net.osmand.data.PointDescription;
import net.osmand.data.TransportStop;
import net.osmand.plus.settings.backend.ApplicationMode;
import net.osmand.plus.ContextMenuAdapter;
import net.osmand.plus.GpxSelectionHelper.SelectedGpxFile;
import net.osmand.plus.mapmarkers.MapMarker;
import net.osmand.plus.mapmarkers.MapMarkersHelper.MapMarkerChangedListener;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.OsmandPlugin;
import net.osmand.plus.R;
import net.osmand.plus.TargetPointsHelper.TargetPoint;
import net.osmand.plus.TargetPointsHelper.TargetPointChangedListener;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.helpers.AndroidUiHelper;
import net.osmand.plus.helpers.GpxUiHelper;
import net.osmand.plus.mapcontextmenu.AdditionalActionsBottomSheetDialogFragment.ContextMenuItemClickListener;
import net.osmand.plus.mapcontextmenu.MenuController.ContextMenuToolbarController;
import net.osmand.plus.mapcontextmenu.MenuController.MenuState;
import net.osmand.plus.mapcontextmenu.MenuController.MenuType;
@ -47,12 +46,14 @@ import net.osmand.plus.mapcontextmenu.editors.RtePtEditor;
import net.osmand.plus.mapcontextmenu.editors.WptPtEditor;
import net.osmand.plus.mapcontextmenu.other.MapMultiSelectionMenu;
import net.osmand.plus.mapcontextmenu.other.ShareMenu;
import net.osmand.plus.mapcontextmenu.AdditionalActionsBottomSheetDialogFragment.ContextMenuItemClickListener;
import net.osmand.plus.mapmarkers.MapMarker;
import net.osmand.plus.mapmarkers.MapMarkersHelper.MapMarkerChangedListener;
import net.osmand.plus.monitoring.OsmandMonitoringPlugin;
import net.osmand.plus.routing.RoutingHelper;
import net.osmand.plus.settings.backend.ApplicationMode;
import net.osmand.plus.transport.TransportStopRoute;
import net.osmand.plus.views.layers.ContextMenuLayer;
import net.osmand.plus.views.OsmandMapLayer;
import net.osmand.plus.views.layers.ContextMenuLayer;
import net.osmand.plus.views.mapwidgets.MapInfoWidgetsFactory.TopToolbarController;
import net.osmand.plus.views.mapwidgets.MapInfoWidgetsFactory.TopToolbarControllerType;
import net.osmand.util.Algorithms;
@ -570,18 +571,21 @@ public class MapContextMenu extends MenuTitleController implements StateChangedL
public void updateControlsVisibility(boolean menuVisible) {
MapActivity mapActivity = getMapActivity();
if (mapActivity != null) {
int topControlsVisibility = shouldShowTopControls(menuVisible) ? View.VISIBLE : View.GONE;
mapActivity.findViewById(R.id.map_center_info).setVisibility(topControlsVisibility);
mapActivity.findViewById(R.id.map_left_widgets_panel).setVisibility(topControlsVisibility);
mapActivity.findViewById(R.id.map_right_widgets_panel).setVisibility(topControlsVisibility);
int bottomControlsVisibility = shouldShowBottomControls(menuVisible) ? View.VISIBLE : View.GONE;
mapActivity.findViewById(R.id.bottom_controls_container).setVisibility(bottomControlsVisibility);
mapActivity.refreshMap();
boolean topControlsVisible = shouldShowTopControls(menuVisible);
boolean bottomControlsVisible = shouldShowBottomControls(menuVisible);
updateControlsVisibility(mapActivity, topControlsVisible, bottomControlsVisible);
}
}
public static void updateControlsVisibility(@NonNull MapActivity mapActivity, boolean topControlsVisible, boolean bottomControlsVisible) {
AndroidUiHelper.updateVisibility(mapActivity.findViewById(R.id.map_center_info), topControlsVisible);
AndroidUiHelper.updateVisibility(mapActivity.findViewById(R.id.map_left_widgets_panel), topControlsVisible);
AndroidUiHelper.updateVisibility(mapActivity.findViewById(R.id.map_right_widgets_panel), topControlsVisible);
AndroidUiHelper.updateVisibility(mapActivity.findViewById(R.id.bottom_controls_container), bottomControlsVisible);
mapActivity.refreshMap();
}
public boolean shouldShowTopControls() {
return shouldShowTopControls(isVisible());
}

View file

@ -1,22 +1,19 @@
package net.osmand.plus.mapcontextmenu;
import android.app.Activity;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.res.ColorStateList;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Handler;
import android.os.Looper;
import android.os.Build;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.TextUtils;
@ -39,14 +36,12 @@ import androidx.core.content.ContextCompat;
import androidx.core.graphics.drawable.DrawableCompat;
import net.osmand.AndroidUtils;
import net.osmand.PlatformUtil;
import net.osmand.data.Amenity;
import net.osmand.data.LatLon;
import net.osmand.data.PointDescription;
import net.osmand.data.QuadRect;
import net.osmand.osm.PoiCategory;
import net.osmand.osm.PoiType;
import net.osmand.osm.io.NetworkUtils;
import net.osmand.plus.OsmAndFormatter;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.OsmandPlugin;
@ -54,6 +49,7 @@ import net.osmand.plus.R;
import net.osmand.plus.UiUtilities;
import net.osmand.plus.Version;
import net.osmand.plus.activities.ActivityResultListener;
import net.osmand.plus.activities.ActivityResultListener.OnActivityResultListener;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.helpers.FontCache;
import net.osmand.plus.mapcontextmenu.builders.cards.AbstractCard;
@ -79,13 +75,6 @@ import net.osmand.plus.widgets.tools.ClickableSpanTouchListener;
import net.osmand.util.Algorithms;
import net.osmand.util.MapUtils;
import org.apache.commons.logging.Log;
import org.openplacereviews.opendb.util.exception.FailedVerificationException;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
@ -99,8 +88,6 @@ import static net.osmand.plus.mapcontextmenu.builders.cards.ImageCard.GetImageCa
public class MenuBuilder {
private static final int PICK_IMAGE = 1231;
private static final int MAX_IMAGE_LENGTH = 2048;
private static final Log LOG = PlatformUtil.getLog(MenuBuilder.class);
public static final float SHADOW_HEIGHT_TOP_DP = 17f;
public static final int TITLE_LIMIT = 60;
protected static final String[] arrowChars = new String[] {"=>", " - "};
@ -133,7 +120,6 @@ public class MenuBuilder {
private String preferredMapLang;
private String preferredMapAppLang;
private boolean transliterateNames;
private View view;
private View photoButton;
private final OpenDBAPI openDBAPI = new OpenDBAPI();
@ -270,7 +256,6 @@ public class MenuBuilder {
}
public void build(View view) {
this.view = view;
firstRow = true;
hidden = false;
buildTopInternal(view);
@ -425,7 +410,7 @@ public class MenuBuilder {
if (false) {
AddPhotosBottomSheetDialogFragment.showInstance(mapActivity.getSupportFragmentManager());
} else {
registerResultListener(view);
registerResultListener();
final String baseUrl = OPRConstants.getBaseUrl(app);
final String name = app.getSettings().OPR_USERNAME.get();
final String privateKey = app.getSettings().OPR_ACCESS_TOKEN.get();
@ -443,6 +428,9 @@ public class MenuBuilder {
Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
if (Build.VERSION.SDK_INT > 18) {
intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
}
mapActivity.startActivityForResult(Intent.createChooser(intent,
mapActivity.getString(R.string.select_picture)), PICK_IMAGE);
}
@ -472,132 +460,33 @@ public class MenuBuilder {
false, null, false);
}
private void registerResultListener(final View view) {
mapActivity.registerActivityResultListener(new ActivityResultListener(PICK_IMAGE, new ActivityResultListener.
OnActivityResultListener() {
private void registerResultListener() {
mapActivity.registerActivityResultListener(new ActivityResultListener(PICK_IMAGE, new OnActivityResultListener() {
@Override
public void onResult(int resultCode, Intent resultData) {
if (resultData != null) {
handleSelectedImage(view, resultData.getData());
List<Uri> imagesUri = new ArrayList<>();
Uri data = resultData.getData();
if (data != null) {
imagesUri.add(data);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
ClipData clipData = resultData.getClipData();
if (clipData != null) {
for (int i = 0; i < clipData.getItemCount(); i++) {
Uri uri = resultData.getClipData().getItemAt(i).getUri();
if (uri != null) {
imagesUri.add(uri);
}
}
}
}
execute(new UploadPhotosAsyncTask(mapActivity, imagesUri, getLatLon(), placeId, getAdditionalCardParams(), imageCardListener));
}
}
}));
}
private void handleSelectedImage(final View view, final Uri uri) {
Thread t = new Thread(new Runnable() {
@Override
public void run() {
InputStream inputStream = null;
try {
inputStream = app.getContentResolver().openInputStream(uri);
if (inputStream != null) {
uploadImageToPlace(inputStream);
}
} catch (Exception e) {
LOG.error(e);
String str = app.getString(R.string.cannot_upload_image);
showToastMessage(str);
} finally {
Algorithms.closeStream(inputStream);
}
}
});
t.start();
}
private void uploadImageToPlace(InputStream image) {
InputStream serverData = new ByteArrayInputStream(compressImageToJpeg(image));
final String baseUrl = OPRConstants.getBaseUrl(app);
// all these should be constant
String url = baseUrl + "api/ipfs/image";
String response = NetworkUtils.sendPostDataRequest(url, "file", "compressed.jpeg", serverData);
if (response != null) {
int res = 0;
try {
StringBuilder error = new StringBuilder();
String privateKey = app.getSettings().OPR_ACCESS_TOKEN.get();
String username = app.getSettings().OPR_USERNAME.get();
res = openDBAPI.uploadImage(
placeId,
baseUrl,
privateKey,
username,
response, error);
if (res != 200) {
showToastMessage(error.toString());
} else {
//ok, continue
}
} catch (FailedVerificationException e) {
LOG.error(e);
checkTokenAndShowScreen();
}
if (res != 200) {
//image was uploaded but not added to blockchain
checkTokenAndShowScreen();
} else {
String str = app.getString(R.string.successfully_uploaded_pattern, 1, 1);
showToastMessage(str);
//refresh the image
execute(new GetImageCardsTask(mapActivity, getLatLon(), getAdditionalCardParams(), imageCardListener));
}
} else {
checkTokenAndShowScreen();
}
}
private void showToastMessage(final String str) {
new Handler(Looper.getMainLooper()).post(new Runnable() {
@Override
public void run() {
Toast.makeText(mapActivity.getBaseContext(), str, Toast.LENGTH_LONG).show();
}
});
}
//This method runs on non main thread
private void checkTokenAndShowScreen() {
final String baseUrl = OPRConstants.getBaseUrl(app);
final String name = app.getSettings().OPR_USERNAME.get();
final String privateKey = app.getSettings().OPR_ACCESS_TOKEN.get();
if (openDBAPI.checkPrivateKeyValid(baseUrl, name, privateKey)) {
String str = app.getString(R.string.cannot_upload_image);
showToastMessage(str);
} else {
app.runInUIThread(new Runnable() {
@Override
public void run() {
OprStartFragment.showInstance(mapActivity.getSupportFragmentManager());
}
});
}
}
private byte[] compressImageToJpeg(InputStream image) {
BufferedInputStream bufferedInputStream = new BufferedInputStream(image);
Bitmap bmp = BitmapFactory.decodeStream(bufferedInputStream);
ByteArrayOutputStream os = new ByteArrayOutputStream();
int h = bmp.getHeight();
int w = bmp.getWidth();
boolean scale = false;
while (w > MAX_IMAGE_LENGTH || h > MAX_IMAGE_LENGTH) {
w = w / 2;
h = h / 2;
scale = true;
}
if (scale) {
Matrix matrix = new Matrix();
matrix.postScale(w, h);
Bitmap resizedBitmap = Bitmap.createBitmap(
bmp, 0, 0, w, h, matrix, false);
bmp.recycle();
bmp = resizedBitmap;
}
bmp.compress(Bitmap.CompressFormat.JPEG, 90, os);
return os.toByteArray();
}
private void startLoadingImages() {
if (onlinePhotoCardsRow == null) {
return;

View file

@ -0,0 +1,220 @@
package net.osmand.plus.mapcontextmenu;
import android.content.DialogInterface;
import android.content.DialogInterface.OnDismissListener;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.net.Uri;
import android.os.AsyncTask;
import androidx.fragment.app.FragmentActivity;
import androidx.fragment.app.FragmentManager;
import net.osmand.AndroidUtils;
import net.osmand.PlatformUtil;
import net.osmand.data.LatLon;
import net.osmand.osm.io.NetworkUtils;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.dialogs.UploadPhotoProgressBottomSheet;
import net.osmand.plus.mapcontextmenu.builders.cards.ImageCard.GetImageCardsTask;
import net.osmand.plus.mapcontextmenu.builders.cards.ImageCard.GetImageCardsTask.GetImageCardsListener;
import net.osmand.plus.openplacereviews.OPRConstants;
import net.osmand.plus.openplacereviews.OprStartFragment;
import net.osmand.plus.osmedit.opr.OpenDBAPI;
import net.osmand.util.Algorithms;
import org.apache.commons.logging.Log;
import org.openplacereviews.opendb.util.exception.FailedVerificationException;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.lang.ref.WeakReference;
import java.util.List;
import java.util.Map;
public class UploadPhotosAsyncTask extends AsyncTask<Void, Integer, Void> {
private static final Log LOG = PlatformUtil.getLog(UploadPhotosAsyncTask.class);
private static final int MAX_IMAGE_LENGTH = 2048;
private final OsmandApplication app;
private final WeakReference<MapActivity> activityRef;
private UploadPhotosListener listener;
private final OpenDBAPI openDBAPI = new OpenDBAPI();
private final LatLon latLon;
private final List<Uri> data;
private final String[] placeId;
private final Map<String, String> params;
private final GetImageCardsListener imageCardListener;
public UploadPhotosAsyncTask(MapActivity activity, List<Uri> data, LatLon latLon, String[] placeId,
Map<String, String> params, GetImageCardsListener imageCardListener) {
app = (OsmandApplication) activity.getApplicationContext();
activityRef = new WeakReference<>(activity);
this.data = data;
this.latLon = latLon;
this.params = params;
this.placeId = placeId;
this.imageCardListener = imageCardListener;
}
@Override
protected void onPreExecute() {
FragmentActivity activity = activityRef.get();
if (AndroidUtils.isActivityNotDestroyed(activity)) {
FragmentManager manager = activity.getSupportFragmentManager();
listener = UploadPhotoProgressBottomSheet.showInstance(manager, data.size(), new OnDismissListener() {
@Override
public void onDismiss(DialogInterface dialog) {
cancel(false);
}
});
}
}
@Override
protected void onProgressUpdate(Integer... values) {
if (listener != null) {
listener.uploadPhotosProgressUpdate(values[0]);
}
}
protected Void doInBackground(Void... uris) {
for (int i = 0; i < data.size(); i++) {
if (isCancelled()) {
break;
}
Uri uri = data.get(i);
handleSelectedImage(uri);
publishProgress(i + 1);
}
return null;
}
@Override
protected void onPostExecute(Void aVoid) {
if (listener != null) {
listener.uploadPhotosFinished();
}
}
private void handleSelectedImage(final Uri uri) {
InputStream inputStream = null;
try {
inputStream = app.getContentResolver().openInputStream(uri);
if (inputStream != null) {
uploadImageToPlace(inputStream);
}
} catch (Exception e) {
LOG.error(e);
app.showToastMessage(R.string.cannot_upload_image);
} finally {
Algorithms.closeStream(inputStream);
}
}
private void uploadImageToPlace(InputStream image) {
InputStream serverData = new ByteArrayInputStream(compressImageToJpeg(image));
final String baseUrl = OPRConstants.getBaseUrl(app);
// all these should be constant
String url = baseUrl + "api/ipfs/image";
String response = NetworkUtils.sendPostDataRequest(url, "file", "compressed.jpeg", serverData);
if (response != null) {
int res = 0;
try {
StringBuilder error = new StringBuilder();
String privateKey = app.getSettings().OPR_ACCESS_TOKEN.get();
String username = app.getSettings().OPR_USERNAME.get();
res = openDBAPI.uploadImage(
placeId,
baseUrl,
privateKey,
username,
response, error);
if (res != 200) {
app.showToastMessage(error.toString());
} else {
//ok, continue
}
} catch (FailedVerificationException e) {
LOG.error(e);
checkTokenAndShowScreen();
}
if (res != 200) {
//image was uploaded but not added to blockchain
checkTokenAndShowScreen();
} else {
String str = app.getString(R.string.successfully_uploaded_pattern, 1, 1);
app.showToastMessage(str);
//refresh the image
MapActivity activity = activityRef.get();
if (activity != null) {
MenuBuilder.execute(new GetImageCardsTask(activity, latLon, params, imageCardListener));
}
}
} else {
checkTokenAndShowScreen();
}
}
//This method runs on non main thread
private void checkTokenAndShowScreen() {
String baseUrl = OPRConstants.getBaseUrl(app);
String name = app.getSettings().OPR_USERNAME.get();
String privateKey = app.getSettings().OPR_ACCESS_TOKEN.get();
if (openDBAPI.checkPrivateKeyValid(baseUrl, name, privateKey)) {
app.showToastMessage(R.string.cannot_upload_image);
} else {
app.runInUIThread(new Runnable() {
@Override
public void run() {
MapActivity activity = activityRef.get();
if (activity != null) {
OprStartFragment.showInstance(activity.getSupportFragmentManager());
}
}
});
}
}
private byte[] compressImageToJpeg(InputStream image) {
BufferedInputStream bufferedInputStream = new BufferedInputStream(image);
Bitmap bmp = BitmapFactory.decodeStream(bufferedInputStream);
ByteArrayOutputStream os = new ByteArrayOutputStream();
int h = bmp.getHeight();
int w = bmp.getWidth();
boolean scale = false;
while (w > MAX_IMAGE_LENGTH || h > MAX_IMAGE_LENGTH) {
w = w / 2;
h = h / 2;
scale = true;
}
if (scale) {
Matrix matrix = new Matrix();
matrix.postScale(w, h);
Bitmap resizedBitmap = Bitmap.createBitmap(
bmp, 0, 0, w, h, matrix, false);
bmp.recycle();
bmp = resizedBitmap;
}
bmp.compress(Bitmap.CompressFormat.JPEG, 90, os);
return os.toByteArray();
}
public interface UploadPhotosListener {
void uploadPhotosProgressUpdate(int progress);
void uploadPhotosFinished();
}
}

View file

@ -1,7 +1,6 @@
package net.osmand.plus.mapcontextmenu.builders;
import android.content.Context;
import android.content.Intent;
import android.view.View;
import android.widget.LinearLayout;
@ -16,13 +15,12 @@ import net.osmand.data.LatLon;
import net.osmand.data.PointDescription;
import net.osmand.plus.GpxSelectionHelper;
import net.osmand.plus.GpxSelectionHelper.SelectedGpxFile;
import net.osmand.plus.settings.backend.OsmAndAppCustomization;
import net.osmand.plus.OsmAndFormatter;
import net.osmand.plus.R;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.activities.TrackActivity;
import net.osmand.plus.mapcontextmenu.MenuBuilder;
import net.osmand.plus.mapcontextmenu.CollapsableView;
import net.osmand.plus.mapcontextmenu.MenuBuilder;
import net.osmand.plus.track.TrackMenuFragment;
import net.osmand.plus.views.layers.POIMapLayer;
import net.osmand.plus.widgets.TextViewEx;
import net.osmand.util.Algorithms;
@ -181,12 +179,7 @@ public class WptPtMenuBuilder extends MenuBuilder {
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
OsmAndAppCustomization appCustomization = app.getAppCustomization();
final Intent intent = new Intent(context, appCustomization.getTrackActivity());
intent.putExtra(TrackActivity.TRACK_FILE_NAME, gpxFile.path);
intent.putExtra(TrackActivity.OPEN_POINTS_TAB, true);
intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
context.startActivity(intent);
TrackMenuFragment.openTrack(mapActivity, new File(gpxFile.path), null);
}
});
view.addView(button);

View file

@ -1,7 +1,6 @@
package net.osmand.plus.mapcontextmenu.controllers;
import android.app.ProgressDialog;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
@ -17,9 +16,7 @@ import net.osmand.plus.GpxSelectionHelper;
import net.osmand.plus.GpxSelectionHelper.SelectedGpxFile;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import net.osmand.plus.Version;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.activities.TrackActivity;
import net.osmand.plus.helpers.GpxUiHelper;
import net.osmand.plus.mapcontextmenu.MenuController;
import net.osmand.plus.mapcontextmenu.builders.SelectedGpxMenuBuilder;
@ -45,21 +42,9 @@ public class SelectedGpxMenuController extends MenuController {
leftTitleButtonController = new TitleButtonController() {
@Override
public void buttonPressed() {
OsmandApplication app = mapActivity.getMyApplication();
SelectedGpxFile selectedGpxFile = selectedGpxPoint.getSelectedGpxFile();
if (Version.isDeveloperVersion(app)) {
mapActivity.getContextMenu().hide(false);
TrackMenuFragment.showInstance(mapActivity, selectedGpxFile.getGpxFile().path, selectedGpxFile.isShowCurrentTrack());
} else {
Intent intent = new Intent(mapActivity, mapActivity.getMyApplication().getAppCustomization().getTrackActivity());
if (selectedGpxFile.isShowCurrentTrack()) {
intent.putExtra(TrackActivity.CURRENT_RECORDING, true);
} else {
intent.putExtra(TrackActivity.TRACK_FILE_NAME, selectedGpxFile.getGpxFile().path);
}
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
mapActivity.startActivity(intent);
}
mapActivity.getContextMenu().hide(false);
TrackMenuFragment.showInstance(mapActivity, selectedGpxFile.getGpxFile().path, selectedGpxFile.isShowCurrentTrack());
}
};
leftTitleButtonController.caption = mapActivity.getString(R.string.shared_string_open_track);

View file

@ -5,7 +5,6 @@ import android.app.Dialog;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.Intent;
import android.content.res.ColorStateList;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
@ -66,7 +65,6 @@ import net.osmand.plus.GpxSelectionHelper;
import net.osmand.plus.OsmAndLocationProvider.OsmAndCompassListener;
import net.osmand.plus.OsmAndLocationProvider.OsmAndLocationListener;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.settings.backend.OsmandPreference;
import net.osmand.plus.R;
import net.osmand.plus.UiUtilities;
import net.osmand.plus.Version;
@ -78,6 +76,8 @@ import net.osmand.plus.mapmarkers.CoordinateInputFormats.DDM;
import net.osmand.plus.mapmarkers.CoordinateInputFormats.DMS;
import net.osmand.plus.mapmarkers.CoordinateInputFormats.Format;
import net.osmand.plus.mapmarkers.adapters.CoordinateInputAdapter;
import net.osmand.plus.settings.backend.OsmandPreference;
import net.osmand.plus.track.TrackMenuFragment;
import net.osmand.plus.widgets.EditTextEx;
import net.osmand.util.Algorithms;
import net.osmand.util.LocationParser;
@ -1097,11 +1097,7 @@ public class CoordinateInputDialogFragment extends DialogFragment implements Osm
.setAction(R.string.shared_string_show, new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(app, app.getAppCustomization().getTrackActivity());
intent.putExtra(TrackActivity.OPEN_POINTS_TAB, true);
intent.putExtra(TrackActivity.TRACK_FILE_NAME, getGpx().path);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
TrackMenuFragment.openTrack(app, new File(getGpx().path), null);
}
});
UiUtilities.setupSnackbar(snackbar, !lightTheme);

View file

@ -1,7 +1,6 @@
package net.osmand.plus.mapmarkers;
import android.app.Dialog;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Bundle;
@ -29,19 +28,20 @@ import net.osmand.AndroidUtils;
import net.osmand.Location;
import net.osmand.data.LatLon;
import net.osmand.plus.LockableViewPager;
import net.osmand.plus.mapmarkers.MapMarkersHelper.MapMarkersSortByDef;
import net.osmand.plus.mapmarkers.MapMarkersHelper.OnGroupSyncedListener;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import net.osmand.plus.UiUtilities;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.activities.TrackActivity;
import net.osmand.plus.mapmarkers.CoordinateInputDialogFragment.OnPointsSavedListener;
import net.osmand.plus.mapmarkers.DirectionIndicationDialogFragment.DirectionIndicationFragmentListener;
import net.osmand.plus.mapmarkers.MapMarkersHelper.MapMarkersSortByDef;
import net.osmand.plus.mapmarkers.MapMarkersHelper.OnGroupSyncedListener;
import net.osmand.plus.mapmarkers.OptionsBottomSheetDialogFragment.MarkerOptionsFragmentListener;
import net.osmand.plus.mapmarkers.OrderByBottomSheetDialogFragment.OrderByFragmentListener;
import net.osmand.plus.mapmarkers.SaveAsTrackBottomSheetDialogFragment.MarkerSaveAsTrackFragmentListener;
import net.osmand.plus.track.TrackMenuFragment;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@ -167,7 +167,7 @@ public class MapMarkersDialogFragment extends DialogFragment implements OnGroupS
viewPager.setAdapter(adapter);
progressBar = (ProgressBar) mainView.findViewById(R.id.progress_bar);
TextView toolbarTitle = mainView.findViewById(R.id.map_markers_toolbar_title);
bottomNav = mainView.findViewById(R.id.map_markers_bottom_navigation);
toolbarTitle.setTextColor(ContextCompat.getColor(getContext(), lightTheme ? R.color.active_buttons_and_links_text_light : R.color.text_color_primary_dark));
@ -486,11 +486,7 @@ public class MapMarkersDialogFragment extends DialogFragment implements OnGroupS
.setAction(R.string.shared_string_show, new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(mapActivity, getMyApplication().getAppCustomization().getTrackActivity());
intent.putExtra(TrackActivity.TRACK_FILE_NAME, gpxPath);
intent.putExtra(TrackActivity.OPEN_POINTS_TAB, true);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
TrackMenuFragment.openTrack(mapActivity, new File(gpxPath), null);
}
});
UiUtilities.setupSnackbar(snackbar, !lightTheme);

View file

@ -47,7 +47,6 @@ import net.osmand.plus.UiUtilities;
import net.osmand.plus.Version;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.activities.MapActivityActions;
import net.osmand.plus.activities.TrackActivity;
import net.osmand.plus.base.BaseOsmAndFragment;
import net.osmand.plus.base.ContextMenuFragment.MenuState;
import net.osmand.plus.helpers.AndroidUiHelper;
@ -76,6 +75,7 @@ import net.osmand.plus.routepreparationmenu.RouteOptionsBottomSheet.DialogMode;
import net.osmand.plus.routepreparationmenu.cards.BaseCard;
import net.osmand.plus.settings.backend.ApplicationMode;
import net.osmand.plus.settings.backend.OsmandSettings;
import net.osmand.plus.track.TrackMenuFragment;
import net.osmand.plus.views.layers.MapControlsLayer.MapControlsThemeInfoProvider;
import net.osmand.plus.views.mapwidgets.MapInfoWidgetsFactory.TopToolbarController;
import net.osmand.plus.views.mapwidgets.MapInfoWidgetsFactory.TopToolbarControllerType;
@ -1914,11 +1914,7 @@ public class MeasurementToolFragment extends BaseOsmAndFragment implements Route
GpxData gpxData = editingCtx.getGpxData();
GPXFile gpx = gpxData != null ? gpxData.getGpxFile() : null;
if (gpx != null) {
Intent newIntent = new Intent(mapActivity, app.getAppCustomization().getTrackActivity());
newIntent.putExtra(TrackActivity.TRACK_FILE_NAME, gpx.path);
newIntent.putExtra(TrackActivity.OPEN_TRACKS_LIST, true);
newIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(newIntent);
TrackMenuFragment.openTrack(mapActivity, new File(gpx.path), null);
}
}
editingCtx.resetRouteSettingsListener();

View file

@ -1,7 +1,6 @@
package net.osmand.plus.measurementtool;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
@ -10,16 +9,15 @@ import androidx.annotation.NonNull;
import androidx.fragment.app.FragmentActivity;
import androidx.fragment.app.FragmentManager;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import net.osmand.plus.UiUtilities;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.activities.TrackActivity;
import net.osmand.plus.base.MenuBottomSheetDialogFragment;
import net.osmand.plus.base.bottomsheetmenu.BottomSheetItemButton;
import net.osmand.plus.base.bottomsheetmenu.SimpleBottomSheetItem;
import net.osmand.plus.base.bottomsheetmenu.simpleitems.DividerItem;
import net.osmand.plus.helpers.GpxUiHelper;
import net.osmand.plus.track.TrackMenuFragment;
import net.osmand.util.Algorithms;
import java.io.File;
@ -60,11 +58,7 @@ public class SavedTrackBottomSheetDialogFragment extends MenuBottomSheetDialogFr
public void onClick(View v) {
FragmentActivity activity = getActivity();
if (activity != null && !Algorithms.isEmpty(fileName)) {
OsmandApplication app = ((OsmandApplication) activity.getApplication());
Intent newIntent = new Intent(activity, app.getAppCustomization().getTrackActivity());
newIntent.putExtra(TrackActivity.TRACK_FILE_NAME, fileName);
newIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
activity.startActivity(newIntent);
TrackMenuFragment.openTrack(activity, new File(fileName), null);
}
dismiss();
}

View file

@ -13,16 +13,14 @@ import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import net.osmand.IndexConstants;
import net.osmand.GPXUtilities;
import net.osmand.GPXUtilities.GPXFile;
import net.osmand.IndexConstants;
import net.osmand.plus.GpxSelectionHelper;
import net.osmand.plus.GpxSelectionHelper.SelectedGpxFile;
import net.osmand.plus.settings.backend.OsmAndAppCustomization;
import net.osmand.plus.OsmAndFormatter;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.OsmandPlugin;
import net.osmand.plus.settings.backend.OsmandSettings;
import net.osmand.plus.R;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.activities.SavingTrackHelper;
@ -33,6 +31,9 @@ import net.osmand.plus.helpers.GpxUiHelper;
import net.osmand.plus.helpers.GpxUiHelper.GPXInfo;
import net.osmand.plus.myplaces.AvailableGPXFragment;
import net.osmand.plus.myplaces.FavoritesActivity;
import net.osmand.plus.settings.backend.OsmAndAppCustomization;
import net.osmand.plus.settings.backend.OsmandSettings;
import net.osmand.plus.track.TrackMenuFragment;
import java.io.File;
import java.util.ArrayList;
@ -153,7 +154,7 @@ public class DashTrackFragment extends DashBaseFragment {
view.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
AvailableGPXFragment.openTrack(getActivity(), null);
TrackMenuFragment.openTrack(getActivity(), null, null);
}
});
view.findViewById(R.id.divider_dash).setVisibility(View.VISIBLE);
@ -172,7 +173,7 @@ public class DashTrackFragment extends DashBaseFragment {
v.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
AvailableGPXFragment.openTrack(getActivity(), f);
TrackMenuFragment.openTrack(getActivity(), f, null);
}
});
ImageButton showOnMap = ((ImageButton) v.findViewById(R.id.show_on_map));

View file

@ -29,6 +29,7 @@ import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.base.MenuBottomSheetDialogFragment;
import net.osmand.plus.base.bottomsheetmenu.SimpleBottomSheetItem;
import net.osmand.plus.myplaces.AvailableGPXFragment;
import net.osmand.plus.track.TrackMenuFragment;
import net.osmand.plus.views.OsmandMapTileView;
import net.osmand.plus.widgets.OsmandTextFieldBoxes;
import net.osmand.util.Algorithms;
@ -167,7 +168,7 @@ public class SaveGPXBottomSheetFragment extends MenuBottomSheetDialogFragment {
}
FragmentActivity activity = getActivity();
if (openTrack && activity != null) {
AvailableGPXFragment.openTrack(activity, file);
TrackMenuFragment.openTrack(activity, file, null);
}
}
}

View file

@ -9,6 +9,7 @@ import android.os.Bundle;
import android.text.SpannableString;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.ImageView;
@ -18,10 +19,12 @@ import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.SwitchCompat;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.FragmentManager;
import com.google.android.material.slider.RangeSlider;
import net.osmand.AndroidUtils;
import net.osmand.plus.GpxSelectionHelper.SelectedGpxFile;
import net.osmand.plus.NavigationService;
import net.osmand.plus.OsmandApplication;
@ -49,9 +52,9 @@ public class TripRecordingBottomSheet extends MenuBottomSheetDialogFragment {
private ImageView upDownBtn;
private SwitchCompat confirmEveryRun;
private RangeSlider intervalSlider;
private TextView intervalValueView;
private LinearLayout container;
private View divider;
private boolean infoExpanded;
@Override
@ -92,8 +95,10 @@ public class TripRecordingBottomSheet extends MenuBottomSheetDialogFragment {
}
});
divider = itemView.findViewById(R.id.second_divider);
LinearLayout expandHideIntervalContainer = itemView.findViewById(R.id.interval_view_container);
upDownBtn = itemView.findViewById(R.id.up_down_button);
upDownBtn.setOnClickListener(new View.OnClickListener() {
expandHideIntervalContainer.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
@ -108,8 +113,11 @@ public class TripRecordingBottomSheet extends MenuBottomSheetDialogFragment {
updateIntervalLegend();
container = itemView.findViewById(R.id.always_ask_and_range_slider_container);
intervalSlider = itemView.findViewById(R.id.interval_slider);
RangeSlider intervalSlider = itemView.findViewById(R.id.interval_slider);
intervalSlider.setValueTo(secondsLength + minutesLength - 1);
int currentModeColorRes = app.getSettings().getApplicationMode().getIconColorInfo().getColor(nightMode);
int currentModeColor = ContextCompat.getColor(app, currentModeColorRes);
UiUtilities.setupSlider(intervalSlider, nightMode, currentModeColor, true);
container.setVisibility(View.GONE);
intervalSlider.addOnChangeListener(new RangeSlider.OnChangeListener() {
@ -126,6 +134,7 @@ public class TripRecordingBottomSheet extends MenuBottomSheetDialogFragment {
updateIntervalLegend();
}
});
for (int i = 0; i < secondsLength + minutesLength; i++) {
if (i < secondsLength) {
if (settings.SAVE_GLOBAL_TRACK_INTERVAL.get() <= SECONDS[i] * 1000) {
@ -151,13 +160,15 @@ public class TripRecordingBottomSheet extends MenuBottomSheetDialogFragment {
}
});
SwitchCompat showTrackOnMapButton = showTrackOnMapView.findViewById(R.id.switch_button);
final SwitchCompat showTrackOnMapButton = showTrackOnMapView.findViewById(R.id.switch_button);
showTrackOnMapButton.setChecked(app.getSelectedGpxHelper().getSelectedCurrentRecordingTrack() != null);
showTrackOnMapButton.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
View basicItem = itemView.findViewById(R.id.basic_item_body);
basicItem.setOnClickListener(new View.OnClickListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
app.getSelectedGpxHelper().selectGpxFile(app.getSavingTrackHelper().getCurrentGpx(), isChecked, false);
public void onClick(View v) {
boolean checked = !showTrackOnMapButton.isChecked();
showTrackOnMapButton.setChecked(checked);
app.getSelectedGpxHelper().selectGpxFile(app.getSavingTrackHelper().getCurrentGpx(), checked, false);
}
});
UiUtilities.setupCompoundButton(showTrackOnMapButton, nightMode, PROFILE_DEPENDENT);
@ -217,6 +228,14 @@ public class TripRecordingBottomSheet extends MenuBottomSheetDialogFragment {
private void toggleInfoView() {
infoExpanded = !infoExpanded;
ViewGroup.MarginLayoutParams marginParams = (ViewGroup.MarginLayoutParams) divider.getLayoutParams();
final int dp8 = AndroidUtils.dpToPx(app, 8f);
final int dp16 = AndroidUtils.dpToPx(app, 16f);
if (infoExpanded) {
AndroidUtils.setMargins(marginParams, 0, dp16, 0, dp8);
} else {
AndroidUtils.setMargins(marginParams, 0, 0, 0, dp8);
}
AndroidUiHelper.updateVisibility(container, infoExpanded);
updateUpDownBtn();
}
@ -226,6 +245,16 @@ public class TripRecordingBottomSheet extends MenuBottomSheetDialogFragment {
return true;
}
@Override
protected int getRightButtonHeight(){
return getResources().getDimensionPixelSize(R.dimen.bottom_sheet_cancel_button_height);
}
@Override
protected int getDismissButtonHeight(){
return getResources().getDimensionPixelSize(R.dimen.bottom_sheet_cancel_button_height);
}
@Override
protected int getRightBottomButtonTextId() {
return R.string.start_recording;

View file

@ -13,8 +13,6 @@ import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
@ -27,7 +25,6 @@ import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.ExpandableListView;
import android.widget.Filter;
import android.widget.Filterable;
@ -75,7 +72,6 @@ import net.osmand.plus.UiUtilities;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.activities.OsmandBaseExpandableListAdapter;
import net.osmand.plus.activities.SavingTrackHelper;
import net.osmand.plus.activities.TrackActivity;
import net.osmand.plus.base.OsmandExpandableListFragment;
import net.osmand.plus.helpers.AndroidUiHelper;
import net.osmand.plus.helpers.GpxUiHelper.GPXDataSetType;
@ -103,14 +99,12 @@ import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;
import static net.osmand.plus.GpxSelectionHelper.CURRENT_TRACK;
import static net.osmand.plus.myplaces.FavoritesActivity.GPX_TAB;
import static net.osmand.plus.myplaces.FavoritesActivity.OPEN_GPX_REQUEST;
import static net.osmand.plus.myplaces.FavoritesActivity.TAB_ID;
import static net.osmand.plus.track.TrackMenuFragment.openTrack;
import static net.osmand.util.Algorithms.capitalizeFirstLetter;
import static net.osmand.util.Algorithms.collectDirs;
import static net.osmand.util.Algorithms.formatDuration;
import static net.osmand.util.Algorithms.objectEquals;
import static net.osmand.util.Algorithms.removeAllFiles;
@ -348,10 +342,10 @@ public class AvailableGPXFragment extends OsmandExpandableListFragment implement
currentGpxView.findViewById(R.id.current_track_info).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent newIntent = new Intent(getActivity(), getMyApplication().getAppCustomization().getTrackActivity());
newIntent.putExtra(TrackActivity.CURRENT_RECORDING, true);
newIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(newIntent);
FragmentActivity activity = getActivity();
if (activity != null) {
openTrack(activity, null, storeState());
}
}
});
listView.addHeaderView(currentGpxView);
@ -419,18 +413,6 @@ public class AvailableGPXFragment extends OsmandExpandableListFragment implement
updateCurrentTrack();
}
public static void openTrack(Activity a, final File f) {
Intent newIntent = new Intent(a, ((OsmandApplication) a.getApplication()).getAppCustomization().getTrackActivity());
// causes wrong position caching: newIntent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
if (f == null) {
newIntent.putExtra(TrackActivity.CURRENT_RECORDING, true);
} else {
newIntent.putExtra(TrackActivity.TRACK_FILE_NAME, f.getAbsolutePath());
}
newIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
a.startActivityForResult(newIntent, OPEN_GPX_REQUEST);
}
public void reloadTracks() {
asyncLoader = new LoadGpxTask();
asyncLoader.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, getActivity());
@ -840,7 +822,7 @@ public class AvailableGPXFragment extends OsmandExpandableListFragment implement
app.showToastMessage(R.string.file_can_not_be_moved);
}
}
public void renamedTo(File file) {
reloadTracks();
}
@ -1615,7 +1597,7 @@ public class AvailableGPXFragment extends OsmandExpandableListFragment implement
GpxInfo item = allGpxAdapter.getChild(groupPosition, childPosition);
if (!selectionMode) {
openTrack(getActivity(), item.file);
openTrack(getActivity(), item.file, storeState());
} else {
if (!selectedItems.contains(item)) {
selectedItems.add(item);

View file

@ -81,11 +81,15 @@ public class EditTrackGroupDialogFragment extends MenuBottomSheetDialogFragment
}
items.add(new TitleItem(getCategoryName(app, group.getName())));
boolean trackPoints = group.getType() == GpxDisplayItemType.TRACK_POINTS;
SelectedGpxFile selectedGpxFile = app.getSelectedGpxHelper().getSelectedFileByPath(group.getGpx().path);
if (group.getType() == GpxDisplayItemType.TRACK_POINTS && selectedGpxFile != null) {
if (trackPoints && selectedGpxFile != null) {
items.add(createShowOnMapItem(selectedGpxFile));
}
items.add(createEditNameItem());
if (trackPoints) {
items.add(createChangeColorItem());
}
items.add(new OptionsDividerItem(app));
// items.add(createCopyToMarkersItem());
@ -272,8 +276,10 @@ public class EditTrackGroupDialogFragment extends MenuBottomSheetDialogFragment
final int themeRes = nightMode ? R.style.OsmandDarkTheme : R.style.OsmandLightTheme;
final View changeColorView = View.inflate(new ContextThemeWrapper(getContext(), themeRes),
R.layout.change_fav_color, null);
((ImageView) changeColorView.findViewById(R.id.change_color_icon))
.setImageDrawable(getContentIcon(R.drawable.ic_action_appearance));
ImageView icon = ((ImageView) changeColorView.findViewById(R.id.change_color_icon));
icon.setImageDrawable(getContentIcon(R.drawable.ic_action_appearance));
int margin = getResources().getDimensionPixelSize(R.dimen.bottom_sheet_icon_margin_large);
UiUtilities.setMargins(icon, 0, 0, margin, 0);
updateColorView((ImageView) changeColorView.findViewById(R.id.colorImage));
return new BaseBottomSheetItem.Builder()
.setCustomView(changeColorView)

View file

@ -429,7 +429,7 @@ public class TrackActivityFragmentAdapter implements TrackBitmapDrawerListener {
String title = metadata.getArticleTitle();
String lang = metadata.getArticleLang();
if (!TextUtils.isEmpty(title) && !TextUtils.isEmpty(lang)) {
return app.getTravelHelper().getArticleByTitle(title, gpx.getRect(), lang);
return app.getTravelHelper().getArticleByTitle(title, gpx.getRect(), lang, false, null);
}
return null;
}

View file

@ -2,6 +2,7 @@ package net.osmand.plus.onlinerouting.ui;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.Gravity;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnFocusChangeListener;
@ -79,6 +80,7 @@ public class OnlineRoutingCard extends BaseCard {
int activeColor = ContextCompat.getColor(app, appMode.getIconColorInfo().getColor(nightMode));
textFieldBoxes.setPrimaryColor(activeColor);
textFieldBoxes.setGravityFloatingLabel(Gravity.START);
editText.addTextChangedListener(new TextWatcher() {
@Override

View file

@ -295,8 +295,12 @@ public class OsmEditsFragment extends OsmAndListFragment implements ProgressDial
item.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
uploadItems(osmEditsSelected.toArray(new OsmPoint[0]));
mode.finish();
if (Algorithms.isEmpty(osmEditsSelected)) {
app.showToastMessage(R.string.toast_select_edits_for_upload);
} else {
uploadItems(osmEditsSelected.toArray(new OsmPoint[0]));
mode.finish();
}
return true;
}
});

View file

@ -815,7 +815,7 @@ public class ChooseRouteFragment extends BaseOsmAndFragment implements ContextMe
}
@Override
public void onContextMenuStateChanged(@NonNull ContextMenuFragment fragment, int menuState) {
public void onContextMenuStateChanged(@NonNull ContextMenuFragment fragment, int menuState, int previousMenuState) {
LockableViewPager viewPager = this.viewPager;
RouteDetailsFragment current = getCurrentFragment();
if (viewPager != null && fragment == current) {

View file

@ -178,10 +178,6 @@ public class OsmAndAppCustomization {
return MapActivity.class;
}
public Class<TrackActivity> getTrackActivity() {
return TrackActivity.class;
}
public Class<FavoritesActivity> getFavoritesActivity() {
return FavoritesActivity.class;
}

View file

@ -1,14 +1,14 @@
package net.osmand.plus.track;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.appcompat.widget.AppCompatImageView;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import com.squareup.picasso.Callback;
import com.squareup.picasso.Picasso;
import com.squareup.picasso.RequestCreator;
import net.osmand.GPXUtilities;
import net.osmand.GPXUtilities.GPXFile;
import net.osmand.PicassoUtils;
import net.osmand.plus.R;
@ -19,6 +19,9 @@ import net.osmand.plus.widgets.TextViewEx;
import net.osmand.plus.wikipedia.WikiArticleHelper;
import net.osmand.util.Algorithms;
import androidx.annotation.NonNull;
import androidx.appcompat.widget.AppCompatImageView;
import static net.osmand.plus.myplaces.TrackActivityFragmentAdapter.getMetadataImageLink;
public class DescriptionCard extends BaseCard {
@ -37,11 +40,8 @@ public class DescriptionCard extends BaseCard {
@Override
protected void updateContent() {
if (gpxFile.metadata == null || gpxFile.metadata.getDescription() == null) {
AndroidUiHelper.updateVisibility(view, false);
return;
} else {
AndroidUiHelper.updateVisibility(view, true);
if (gpxFile.metadata == null) {
gpxFile.metadata = new GPXUtilities.Metadata();
}
final String title = gpxFile.metadata.getArticleTitle();
@ -50,6 +50,34 @@ public class DescriptionCard extends BaseCard {
setupImage(imageUrl);
if (Algorithms.isBlank(descriptionHtml)) {
showAddBtn();
} else {
showDescription(title, imageUrl, descriptionHtml);
}
}
private void showAddBtn() {
LinearLayout descriptionContainer = view.findViewById(R.id.description_container);
FrameLayout addBtn = view.findViewById(R.id.btn_add);
addBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
GpxEditDescriptionDialogFragment.showInstance(getMapActivity(), "", null);
}
});
AndroidUiHelper.updateVisibility(descriptionContainer, false);
AndroidUiHelper.updateVisibility(addBtn, true);
}
private void showDescription(final String title, final String imageUrl, final String descriptionHtml) {
LinearLayout descriptionContainer = view.findViewById(R.id.description_container);
FrameLayout addBtn = view.findViewById(R.id.btn_add);
AndroidUiHelper.updateVisibility(descriptionContainer, true);
AndroidUiHelper.updateVisibility(addBtn, false);
TextViewEx tvDescription = view.findViewById(R.id.description);
tvDescription.setText(getFirstParagraph(descriptionHtml));
@ -60,6 +88,7 @@ public class DescriptionCard extends BaseCard {
GpxReadDescriptionDialogFragment.showInstance(mapActivity, title, imageUrl, descriptionHtml);
}
});
TextViewEx editBtn = view.findViewById(R.id.btn_edit);
editBtn.setOnClickListener(new View.OnClickListener() {
@Override

View file

@ -1,5 +1,7 @@
package net.osmand.plus.track;
import android.content.Context;
import android.content.DialogInterface;
import android.os.AsyncTask;
import android.os.Bundle;
import android.text.Editable;
@ -7,12 +9,6 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import androidx.fragment.app.FragmentManager;
import net.osmand.GPXUtilities.GPXFile;
import net.osmand.PlatformUtil;
import net.osmand.plus.OsmandApplication;
@ -22,12 +18,18 @@ import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.base.BaseOsmAndDialogFragment;
import net.osmand.plus.track.SaveGpxAsyncTask.SaveGpxListener;
import net.osmand.plus.widgets.EditTextEx;
import net.osmand.util.Algorithms;
import org.apache.commons.logging.Log;
import java.io.File;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import androidx.fragment.app.FragmentManager;
public class GpxEditDescriptionDialogFragment extends BaseOsmAndDialogFragment {
public static final String TAG = GpxEditDescriptionDialogFragment.class.getSimpleName();
@ -37,6 +39,8 @@ public class GpxEditDescriptionDialogFragment extends BaseOsmAndDialogFragment {
private EditTextEx editableHtml;
private String htmlCode;
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
@ -46,11 +50,16 @@ public class GpxEditDescriptionDialogFragment extends BaseOsmAndDialogFragment {
View view = themedInflater.inflate(R.layout.dialog_edit_gpx_description, container, false);
editableHtml = view.findViewById(R.id.description);
editableHtml.requestFocus();
view.findViewById(R.id.btn_close).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
dismiss();
if (shouldClose()) {
dismiss();
} else {
showDismissDialog();
}
}
});
@ -58,7 +67,7 @@ public class GpxEditDescriptionDialogFragment extends BaseOsmAndDialogFragment {
@Override
public void onClick(View v) {
Editable editable = editableHtml.getText();
if (!Algorithms.isEmpty(editable) && !saveGpx(editable.toString())) {
if (editable != null && !saveGpx(editable.toString())) {
dismiss();
}
}
@ -66,15 +75,38 @@ public class GpxEditDescriptionDialogFragment extends BaseOsmAndDialogFragment {
Bundle args = getArguments();
if (args != null) {
String html = args.getString(CONTENT_KEY);
if (html != null) {
editableHtml.setText(html);
htmlCode = args.getString(CONTENT_KEY);
if (htmlCode != null) {
editableHtml.setText(htmlCode);
}
}
return view;
}
private boolean shouldClose() {
Editable editable = editableHtml.getText();
if (htmlCode == null || editable == null || editable.toString() == null) {
return true;
}
return htmlCode.equals(editable.toString());
}
private void showDismissDialog() {
Context themedContext = UiUtilities.getThemedContext(getMapActivity(), isNightMode(false));
AlertDialog.Builder dismissDialog = new AlertDialog.Builder(themedContext);
dismissDialog.setTitle(getString(R.string.shared_string_dismiss));
dismissDialog.setMessage(getString(R.string.exit_without_saving));
dismissDialog.setNegativeButton(R.string.shared_string_cancel, null);
dismissDialog.setPositiveButton(R.string.shared_string_exit, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dismiss();
}
});
dismissDialog.show();
}
private boolean saveGpx(final String html) {
MapActivity mapActivity = getMapActivity();
if (mapActivity == null || mapActivity.getTrackMenuFragment() == null) {

View file

@ -3,6 +3,7 @@ package net.osmand.plus.track;
import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Bundle;
import android.util.Base64;
import android.view.LayoutInflater;
@ -15,14 +16,6 @@ import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.AppCompatImageView;
import androidx.appcompat.widget.Toolbar;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.FragmentActivity;
import androidx.fragment.app.FragmentManager;
import com.squareup.picasso.Callback;
import com.squareup.picasso.Picasso;
import com.squareup.picasso.RequestCreator;
@ -39,6 +32,14 @@ import net.osmand.plus.widgets.WebViewEx;
import net.osmand.plus.wikivoyage.WikivoyageUtils;
import net.osmand.util.Algorithms;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.AppCompatImageView;
import androidx.appcompat.widget.Toolbar;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.FragmentActivity;
import androidx.fragment.app.FragmentManager;
public class GpxReadDescriptionDialogFragment extends BaseOsmAndDialogFragment {
public static final String TAG = GpxReadDescriptionDialogFragment.class.getSimpleName();
@ -181,10 +182,16 @@ public class GpxReadDescriptionDialogFragment extends BaseOsmAndDialogFragment {
private void setupWebView(final View view) {
webView = view.findViewById(R.id.content);
webView.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE);
if (Build.VERSION.SDK_INT >= 19) {
webView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
}
else {
webView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}
webView.setScrollbarFadingEnabled(true);
webView.setVerticalScrollBarEnabled(false);
webView.setBackgroundColor(Color.TRANSPARENT);
webView.setLayerType(WebView.LAYER_TYPE_HARDWARE, null);
webView.getSettings().setTextZoom((int) (getResources().getConfiguration().fontScale * 100f));
webView.getSettings().setDomStorageEnabled(true);
webView.getSettings().setLoadWithOverviewMode(true);

View file

@ -74,7 +74,9 @@ public class OptionsCard extends BaseCard {
items.add(createDirectionsItem());
}
items.add(createDividerItem());
items.add(createJoinGapsItem());
if (gpxFile.getGeneralTrack() != null) {
items.add(createJoinGapsItem());
}
items.add(createAnalyzeOnMapItem());
items.add(createAnalyzeByIntervalsItem());

View file

@ -1,10 +1,6 @@
package net.osmand.plus.track;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.view.LayoutInflater;
import android.view.MotionEvent;
@ -17,18 +13,20 @@ import androidx.annotation.ColorRes;
import androidx.annotation.DrawableRes;
import androidx.annotation.NonNull;
import androidx.appcompat.widget.AppCompatImageView;
import androidx.recyclerview.widget.DefaultItemAnimator;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.RecyclerView.ItemDecoration;
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.OsmAndFormatter;
import net.osmand.plus.R;
import net.osmand.plus.UiUtilities;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.helpers.AndroidUiHelper;
import net.osmand.plus.helpers.GpxUiHelper.GPXDataSetType;
import net.osmand.plus.myplaces.SegmentActionsListener;
import net.osmand.plus.routepreparationmenu.cards.BaseCard;
@ -36,7 +34,6 @@ import net.osmand.plus.widgets.TextViewEx;
import net.osmand.util.Algorithms;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import static net.osmand.plus.myplaces.TrackActivityFragmentAdapter.isGpxFileSelected;
@ -44,6 +41,7 @@ import static net.osmand.plus.track.OptionsCard.APPEARANCE_BUTTON_INDEX;
import static net.osmand.plus.track.OptionsCard.DIRECTIONS_BUTTON_INDEX;
import static net.osmand.plus.track.OptionsCard.EDIT_BUTTON_INDEX;
import static net.osmand.plus.track.OptionsCard.SHOW_ON_MAP_BUTTON_INDEX;
import static net.osmand.plus.track.OverviewCard.StatBlock.ItemType.*;
public class OverviewCard extends BaseCard {
@ -55,15 +53,22 @@ public class OverviewCard extends BaseCard {
private final TrackDisplayHelper displayHelper;
private final GPXFile gpxFile;
private final GpxDisplayItemType[] filterTypes = new GpxDisplayItemType[] {GpxDisplayItemType.TRACK_SEGMENT};
private final GpxDisplayItemType[] filterTypes = {GpxDisplayItemType.TRACK_SEGMENT};
private final SegmentActionsListener listener;
private boolean gpxFileSelected;
private GpxDisplayItem gpxItem;
public OverviewCard(@NonNull MapActivity mapActivity, @NonNull TrackDisplayHelper displayHelper,
@NonNull SegmentActionsListener listener) {
super(mapActivity);
this.displayHelper = displayHelper;
this.gpxFile = displayHelper.getGpx();
this.listener = listener;
gpxFile = displayHelper.getGpx();
gpxFileSelected = isGpxFileSelected(app, gpxFile);
List<GpxDisplayGroup> groups = displayHelper.getOriginalGroups(filterTypes);
if (!Algorithms.isEmpty(groups)) {
gpxItem = TrackDisplayHelper.flatten(displayHelper.getOriginalGroups(filterTypes)).get(0);
}
}
@Override
@ -73,7 +78,7 @@ public class OverviewCard extends BaseCard {
@Override
protected void updateContent() {
int iconColorDef = R.color.icon_color_active_light;
int iconColorDef = nightMode ? R.color.icon_color_active_dark : R.color.icon_color_active_light;
int iconColorPres = R.color.active_buttons_and_links_text_dark;
boolean fileAvailable = gpxFile.path != null && !gpxFile.showCurrentTrack;
@ -93,101 +98,94 @@ public class OverviewCard extends BaseCard {
}
void initStatBlocks() {
GpxDisplayItem gpxItem = TrackDisplayHelper.flatten(displayHelper.getOriginalGroups(filterTypes)).get(0);
GPXTrackAnalysis analysis = gpxItem.analysis;
boolean joinSegments = displayHelper.isJoinSegments();
float totalDistance = !joinSegments && gpxItem.isGeneralTrack() ? analysis.totalDistanceWithoutGaps : analysis.totalDistance;
float timeSpan = !joinSegments && gpxItem.isGeneralTrack() ? 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);
if (gpxItem != null) {
GPXTrackAnalysis analysis = gpxItem.analysis;
boolean joinSegments = displayHelper.isJoinSegments();
float totalDistance = !joinSegments && gpxItem.isGeneralTrack() ? analysis.totalDistanceWithoutGaps : analysis.totalDistance;
float timeSpan = !joinSegments && gpxItem.isGeneralTrack() ? 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);
List<StatBlock> items = new ArrayList<>();
StatBlock sDistance = new StatBlock(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);
StatBlock sAscent = new StatBlock(app.getString(R.string.altitude_ascent), asc,
R.drawable.ic_action_arrow_up_16, R.color.gpx_chart_red, GPXDataSetType.SLOPE, null);
StatBlock sDescent = new StatBlock(app.getString(R.string.altitude_descent), desc,
R.drawable.ic_action_arrow_down_16, R.color.gpx_pale_green, GPXDataSetType.ALTITUDE, GPXDataSetType.SLOPE);
StatBlock sAvSpeed = new StatBlock(app.getString(R.string.average_speed), avg,
R.drawable.ic_action_speed_16, R.color.icon_color_default_light, GPXDataSetType.SPEED, null);
StatBlock sMaxSpeed = new StatBlock(app.getString(R.string.max_speed), max,
R.drawable.ic_action_max_speed_16, R.color.icon_color_default_light, GPXDataSetType.SPEED, null);
StatBlock sTimeSpan = new StatBlock(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);
StatBlock.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, ITEM_DISTANCE);
StatBlock.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, ITEM_ALTITUDE);
StatBlock.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, ITEM_ALTITUDE);
StatBlock.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, ITEM_SPEED);
StatBlock.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, ITEM_SPEED);
StatBlock.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, ITEM_TIME);
LinearLayoutManager llManager = new LinearLayoutManager(app);
llManager.setOrientation(LinearLayoutManager.HORIZONTAL);
rvOverview.setLayoutManager(llManager);
rvOverview.setItemAnimator(new DefaultItemAnimator());
List<StatBlock> items = Arrays.asList(sDistance, sAscent, sDescent, sAvSpeed, sMaxSpeed, sTimeSpan);
final StatBlockAdapter siAdapter = new StatBlockAdapter(items);
rvOverview.setAdapter(siAdapter);
rvOverview.addItemDecoration(new HorizontalDividerDecoration(app));
if (Algorithms.isEmpty(items)) {
AndroidUiHelper.updateVisibility(rvOverview, false);
} else {
final StatBlockAdapter sbAdapter = new StatBlockAdapter(items);
rvOverview.setLayoutManager(new LinearLayoutManager(app, LinearLayoutManager.HORIZONTAL, false));
rvOverview.setAdapter(sbAdapter);
}
} else {
AndroidUiHelper.updateVisibility(rvOverview, false);
}
}
@DrawableRes
private int getActiveShowHideIcon() {
gpxFileSelected = isGpxFileSelected(app, gpxFile);
return gpxFileSelected ? R.drawable.ic_action_view : R.drawable.ic_action_hide;
}
private void initShowButton(final int iconColorDef, final int iconColorPres) {
final AppCompatImageView image = showButton.findViewById(R.id.image);
final AppCompatImageView filled = showButton.findViewById(R.id.filled);
final int iconShowResId = R.drawable.ic_action_view;
final int iconHideResId = R.drawable.ic_action_hide;
final boolean[] gpxFileSelected = {isGpxFileSelected(app, gpxFile)};
filled.setImageResource(R.drawable.bg_topbar_shield_exit_ref);
filled.setAlpha(gpxFileSelected[0] ? 1f : 0.1f);
setImageDrawable(image, gpxFileSelected[0] ? iconShowResId : iconHideResId,
gpxFileSelected[0] ? iconColorPres : iconColorDef);
showButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
gpxFileSelected[0] = !gpxFileSelected[0];
filled.setAlpha(gpxFileSelected[0] ? 1f : 0.1f);
setImageDrawable(image, gpxFileSelected[0] ? iconShowResId : iconHideResId,
gpxFileSelected[0] ? iconColorPres : iconColorDef);
CardListener listener = getListener();
if (listener != null) {
listener.onCardButtonPressed(OverviewCard.this, SHOW_ON_MAP_BUTTON_INDEX);
}
}
});
initButton(showButton, SHOW_ON_MAP_BUTTON_INDEX, getActiveShowHideIcon(), iconColorDef, iconColorPres);
}
private void initAppearanceButton(int iconColorDef, int iconColorPres) {
private void initAppearanceButton(@ColorRes int iconColorDef, @ColorRes int iconColorPres) {
initButton(appearanceButton, APPEARANCE_BUTTON_INDEX, R.drawable.ic_action_appearance, iconColorDef, iconColorPres);
}
private void initEditButton(int iconColorDef, int iconColorPres) {
private void initEditButton(@ColorRes int iconColorDef, @ColorRes int iconColorPres) {
initButton(editButton, EDIT_BUTTON_INDEX, R.drawable.ic_action_edit_dark, iconColorDef, iconColorPres);
}
private void initDirectionsButton(int iconColorDef, int iconColorPres) {
private void initDirectionsButton(@ColorRes int iconColorDef, @ColorRes int iconColorPres) {
initButton(directionsButton, DIRECTIONS_BUTTON_INDEX, R.drawable.ic_action_gdirections_dark, iconColorDef, iconColorPres);
}
private void initButton(View item, final int buttonIndex, int iconResId, int iconColorDef, int iconColorPres) {
final AppCompatImageView image = item.findViewById(R.id.image);
private void initButton(View item, final int buttonIndex, @DrawableRes Integer iconResId,
@ColorRes final int iconColorDef, @ColorRes int iconColorPres) {
final AppCompatImageView icon = item.findViewById(R.id.image);
final AppCompatImageView filled = item.findViewById(R.id.filled);
filled.setImageResource(R.drawable.bg_topbar_shield_exit_ref);
filled.setImageResource(nightMode ? R.drawable.bg_plugin_logo_enabled_dark : R.drawable.bg_topbar_shield_exit_ref);
filled.setAlpha(0.1f);
setImageDrawable(image, iconResId, iconColorDef);
setOnTouchItem(item, image, filled, iconResId, iconColorDef, iconColorPres);
setImageDrawable(icon, iconResId, iconColorDef);
setOnTouchItem(item, icon, filled, iconResId, iconColorDef, iconColorPres);
item.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
CardListener listener = getListener();
if (listener != null) {
listener.onCardButtonPressed(OverviewCard.this, buttonIndex);
if (buttonIndex == SHOW_ON_MAP_BUTTON_INDEX) {
setImageDrawable(icon, getActiveShowHideIcon(), iconColorDef);
}
}
}
});
}
private void setImageDrawable(ImageView iv, @DrawableRes int resId, @ColorRes int color) {
Drawable icon = app.getUIUtilities().getIcon(resId, color);
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);
}
private void setOnTouchItem(View item, final ImageView image, final ImageView filled, @DrawableRes final int resId, @ColorRes final int colorDef, @ColorRes final int colorPres) {
private void setOnTouchItem(View item, final ImageView image, final ImageView filled, @DrawableRes final Integer resId, @ColorRes final int colorDef, @ColorRes final int colorPres) {
item.setOnTouchListener(new View.OnTouchListener() {
@SuppressLint("ClickableViewAccessibility")
@Override
@ -234,26 +232,24 @@ public class OverviewCard extends BaseCard {
@Override
public void onBindViewHolder(StatBlockViewHolder holder, int position) {
final StatBlock item = statBlocks.get(position);
holder.valueText.setText(item.value);
holder.titleText.setText(item.title);
holder.valueText.setTextColor(app.getResources().getColor(R.color.active_color_primary_light));
holder.valueText.setTextColor(getActiveColor());
holder.titleText.setTextColor(app.getResources().getColor(R.color.text_color_secondary_light));
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
GpxDisplayItem gpxItem = TrackDisplayHelper.flatten(displayHelper.getOriginalGroups(filterTypes)).get(0);
if (gpxItem != null && gpxItem.analysis != null) {
ArrayList<GPXDataSetType> list = new ArrayList<>();
if (item.firstType != null) {
list.add(item.firstType);
}
if (item.secondType != null) {
list.add(item.secondType);
}
if (list.size() > 0) {
gpxItem.chartTypes = list.toArray(new GPXDataSetType[0]);
if (gpxItem.analysis.hasElevationData || gpxItem.analysis.isSpeedSpecified() || gpxItem.analysis.hasSpeedData) {
if (item.firstType != null) {
list.add(item.firstType);
}
if (item.secondType != null) {
list.add(item.secondType);
}
}
gpxItem.chartTypes = list.size() > 0 ? list.toArray(new GPXDataSetType[0]) : null;
gpxItem.locationOnMap = gpxItem.locationStart;
listener.openAnalyzeOnMap(gpxItem);
@ -261,6 +257,8 @@ public class OverviewCard extends BaseCard {
}
});
setImageDrawable(holder.imageView, item.imageResId, item.imageColorId);
AndroidUtils.setBackgroundColor(view.getContext(), holder.divider, nightMode, R.color.divider_color_light, R.color.divider_color_dark);
AndroidUiHelper.updateVisibility(holder.divider, position != statBlocks.size() - 1);
}
}
@ -269,55 +267,18 @@ public class OverviewCard extends BaseCard {
private final TextViewEx valueText;
private final TextView titleText;
private final AppCompatImageView imageView;
private final View divider;
StatBlockViewHolder(View view) {
super(view);
valueText = view.findViewById(R.id.value);
titleText = view.findViewById(R.id.title);
imageView = view.findViewById(R.id.image);
divider = view.findViewById(R.id.divider);
}
}
private static class HorizontalDividerDecoration extends ItemDecoration {
private final Drawable divider;
private final int marginV;
private final int marginH;
public HorizontalDividerDecoration(Context context) {
int[] ATTRS = new int[] {android.R.attr.listDivider};
final TypedArray ta = context.obtainStyledAttributes(ATTRS);
divider = ta.getDrawable(0);
// DrawableCompat.setTint(divider, context.getResources().getColor(R.color.divider_color_light)); //todo change drawable color
ta.recycle();
marginV = context.getResources().getDimensionPixelSize(R.dimen.map_small_button_margin);
marginH = context.getResources().getDimensionPixelSize(R.dimen.content_padding);
}
@Override
public void onDraw(@NonNull Canvas c, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
drawHorizontal(c, parent);
}
public void drawHorizontal(Canvas c, RecyclerView parent) {
for (int i = 0; i < parent.getChildCount(); i++) {
final View child = parent.getChildAt(i);
final int left = child.getRight() - divider.getIntrinsicWidth() + marginH;
final int right = left + divider.getIntrinsicHeight();
final int top = child.getTop() + marginV;
final int bottom = child.getBottom() - marginV;
divider.setBounds(left, top, right, bottom);
divider.draw(c);
}
}
@Override
public void getItemOffsets(Rect outRect, @NonNull View view, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
outRect.set(marginH - divider.getIntrinsicWidth(), marginV, marginH + divider.getIntrinsicWidth(), marginV);
}
}
private static class StatBlock {
protected static class StatBlock {
private final String title;
private final String value;
@ -325,15 +286,56 @@ public class OverviewCard extends BaseCard {
private final int imageColorId;
private final GPXDataSetType firstType;
private final GPXDataSetType secondType;
private final ItemType itemType;
public StatBlock(String title, String value, @DrawableRes int imageResId, @ColorRes int imageColorId,
GPXDataSetType firstType, GPXDataSetType secondType) {
GPXDataSetType firstType, GPXDataSetType secondType, ItemType itemType) {
this.title = title;
this.value = value;
this.imageResId = imageResId;
this.imageColorId = imageColorId;
this.firstType = firstType;
this.secondType = secondType;
this.itemType = itemType;
}
public static void prepareData(GPXTrackAnalysis analysis, List<StatBlock> listItems, 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);
}
break;
}
case ITEM_ALTITUDE: {
if (analysis.hasElevationData) {
listItems.add(statBlock);
}
break;
}
case ITEM_SPEED: {
if (analysis.isSpeedSpecified()) {
listItems.add(statBlock);
}
break;
}
case ITEM_TIME: {
if (analysis.hasSpeedData) {
listItems.add(statBlock);
}
break;
}
}
}
public enum ItemType {
ITEM_DISTANCE,
ITEM_ALTITUDE,
ITEM_SPEED,
ITEM_TIME;
}
}
}

View file

@ -2,6 +2,8 @@ package net.osmand.plus.track;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.res.ColorStateList;
import android.os.AsyncTask;
@ -22,6 +24,7 @@ import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.activity.OnBackPressedCallback;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.StringRes;
@ -32,6 +35,7 @@ import androidx.fragment.app.FragmentManager;
import com.google.android.material.bottomnavigation.BottomNavigationView;
import net.osmand.AndroidUtils;
import net.osmand.CallbackWithObject;
import net.osmand.FileUtils;
import net.osmand.FileUtils.RenameCallback;
import net.osmand.GPXUtilities.GPXFile;
@ -42,10 +46,10 @@ import net.osmand.data.LatLon;
import net.osmand.data.PointDescription;
import net.osmand.data.QuadRect;
import net.osmand.data.RotatedTileBox;
import net.osmand.plus.GpxDbHelper;
import net.osmand.plus.GpxSelectionHelper.GpxDisplayGroup;
import net.osmand.plus.GpxSelectionHelper.GpxDisplayItem;
import net.osmand.plus.GpxSelectionHelper.GpxDisplayItemType;
import net.osmand.plus.GpxSelectionHelper.GpxFileLoaderTask;
import net.osmand.plus.GpxSelectionHelper.SelectedGpxFile;
import net.osmand.plus.OsmAndLocationProvider.OsmAndCompassListener;
import net.osmand.plus.OsmAndLocationProvider.OsmAndLocationListener;
@ -86,6 +90,7 @@ import net.osmand.util.MapUtils;
import org.apache.commons.logging.Log;
import java.io.File;
import java.lang.ref.WeakReference;
import java.util.List;
import static net.osmand.plus.activities.TrackActivity.CURRENT_RECORDING;
@ -110,6 +115,8 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
SegmentActionsListener, RenameCallback, OnTrackFileMoveListener, OnPointsDeleteListener,
OsmAndLocationListener, OsmAndCompassListener {
public static final String OPEN_TRACK_MENU = "open_track_menu";
public static final String TAG = TrackMenuFragment.class.getName();
private static final Log log = PlatformUtil.getLog(TrackMenuFragment.class);
@ -144,6 +151,7 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
private int menuTitleHeight;
private int toolbarHeightPx;
private boolean mapPositionAdjusted;
public enum TrackMenuType {
OVERVIEW(R.id.action_overview, R.string.shared_string_overview),
@ -202,33 +210,39 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
app = requireMyApplication();
GpxDbHelper gpxDbHelper = app.getGpxDbHelper();
displayHelper = new TrackDisplayHelper(app);
updateLocationViewCache = app.getUIUtilities().getUpdateLocationViewCache();
Bundle arguments = getArguments();
if (arguments != null) {
String gpxFilePath = arguments.getString(TRACK_FILE_NAME);
boolean currentRecording = arguments.getBoolean(CURRENT_RECORDING, false);
if (currentRecording) {
selectedGpxFile = app.getSavingTrackHelper().getCurrentTrack();
} else {
File file = new File(gpxFilePath);
displayHelper.setFile(file);
displayHelper.setGpxDataItem(gpxDbHelper.getItem(file));
selectedGpxFile = app.getSelectedGpxHelper().getSelectedFileByPath(gpxFilePath);
}
displayHelper.setGpx(selectedGpxFile.getGpxFile());
String fileName = Algorithms.getFileWithoutDirs(getGpx().path);
gpxTitle = GpxUiHelper.getGpxTitle(fileName);
if (!selectedGpxFile.isShowCurrentTrack()) {
File file = new File(selectedGpxFile.getGpxFile().path);
displayHelper.setFile(file);
displayHelper.setGpxDataItem(app.getGpxDbHelper().getItem(file));
}
displayHelper.setGpx(selectedGpxFile.getGpxFile());
String fileName = Algorithms.getFileWithoutDirs(getGpx().path);
gpxTitle = GpxUiHelper.getGpxTitle(fileName);
toolbarHeightPx = getResources().getDimensionPixelSize(R.dimen.dashboard_map_toolbar);
FragmentActivity activity = requireMyActivity();
activity.getOnBackPressedDispatcher().addCallback(this, new OnBackPressedCallback(true) {
public void handleOnBackPressed() {
MapActivity mapActivity = getMapActivity();
if (mapActivity != null) {
mapActivity.launchPrevActivityIntent();
}
dismiss();
}
});
}
public GPXFile getGpx() {
return displayHelper.getGpx();
}
public void setSelectedGpxFile(SelectedGpxFile selectedGpxFile) {
this.selectedGpxFile = selectedGpxFile;
}
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = super.onCreateView(inflater, container, savedInstanceState);
@ -244,6 +258,7 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
if (isPortrait()) {
AndroidUiHelper.updateVisibility(getTopShadow(), true);
AndroidUiHelper.updateVisibility(view.findViewById(R.id.map_my_location_button), false);
} else {
int widthNoShadow = getLandscapeNoShadowWidth();
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(widthNoShadow, ViewGroup.LayoutParams.WRAP_CONTENT);
@ -255,7 +270,6 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
setupToolbar();
updateHeader();
setupButtons(view);
enterTrackAppearanceMode();
runLayoutListener();
}
return view;
@ -441,15 +455,21 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
adjustMapPosition(getHeight());
public void onContextMenuStateChanged(@NonNull ContextMenuFragment fragment, int currentMenuState, int previousMenuState) {
super.onContextMenuStateChanged(fragment, currentMenuState, previousMenuState);
boolean changed = currentMenuState != previousMenuState;
if (changed) {
updateControlsVisibility(true);
}
if (currentMenuState != MenuState.FULL_SCREEN && (changed || !mapPositionAdjusted)) {
adjustMapPosition(getViewY());
}
}
@Override
public void onDestroyView() {
super.onDestroyView();
exitTrackAppearanceMode();
updateStatusBarColor();
}
@ -460,6 +480,7 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
if (mapActivity != null && trackChartPoints != null) {
mapActivity.getMapLayers().getGpxLayer().setTrackChartPoints(trackChartPoints);
}
updateControlsVisibility(true);
startLocationUpdate();
}
@ -470,6 +491,7 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
if (mapActivity != null) {
mapActivity.getMapLayers().getGpxLayer().setTrackChartPoints(null);
}
updateControlsVisibility(false);
stopLocationUpdate();
}
@ -555,26 +577,25 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
updateContent();
}
private void enterTrackAppearanceMode() {
public void updateControlsVisibility(boolean menuVisible) {
MapActivity mapActivity = getMapActivity();
if (mapActivity != null) {
boolean portrait = AndroidUiHelper.isOrientationPortrait(mapActivity);
AndroidUiHelper.setVisibility(mapActivity, portrait ? View.INVISIBLE : View.GONE,
R.id.map_left_widgets_panel,
R.id.map_right_widgets_panel,
R.id.map_center_info);
boolean topControlsVisible = shouldShowTopControls(menuVisible);
boolean bottomControlsVisible = shouldShowBottomControls(menuVisible);
MapContextMenu.updateControlsVisibility(mapActivity, topControlsVisible, bottomControlsVisible);
}
}
private void exitTrackAppearanceMode() {
MapActivity mapActivity = getMapActivity();
if (mapActivity != null) {
AndroidUiHelper.setVisibility(mapActivity, View.VISIBLE,
R.id.map_left_widgets_panel,
R.id.map_right_widgets_panel,
R.id.map_center_info,
R.id.map_search_button);
}
public boolean shouldShowTopControls() {
return shouldShowTopControls(isVisible());
}
public boolean shouldShowTopControls(boolean menuVisible) {
return !menuVisible || !isPortrait() || getCurrentMenuState() == MenuState.HEADER_ONLY;
}
public boolean shouldShowBottomControls(boolean menuVisible) {
return !menuVisible || !isPortrait();
}
@Override
@ -746,15 +767,6 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
}
}
@Override
protected int applyPosY(int currentY, boolean needCloseMenu, boolean needMapAdjust, int previousMenuState, int newMenuState, int dZoom, boolean animated) {
int y = super.applyPosY(currentY, needCloseMenu, needMapAdjust, previousMenuState, newMenuState, dZoom, animated);
if (needMapAdjust) {
adjustMapPosition(y);
}
return y;
}
public void updateToolbar(int y, boolean animated) {
final MapActivity mapActivity = getMapActivity();
if (mapActivity != null) {
@ -807,6 +819,7 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
if (r.left != 0 && r.right != 0) {
mapActivity.getMapView().fitRectToMap(r.left, r.right, r.top, r.bottom, tileBoxWidthPx, tileBoxHeightPx, 0);
}
mapPositionAdjusted = true;
}
}
@ -996,7 +1009,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);
}
@ -1029,16 +1042,63 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
}
}
public static boolean showInstance(@NonNull MapActivity mapActivity, String path, boolean showCurrentTrack) {
public static void openTrack(@NonNull Context context, @Nullable File file, Bundle prevIntentParams) {
boolean currentRecording = file == null;
String path = file != null ? file.getAbsolutePath() : null;
if (context instanceof MapActivity) {
TrackMenuFragment.showInstance((MapActivity) context, path, currentRecording);
} else {
Bundle bundle = new Bundle();
bundle.putString(TRACK_FILE_NAME, path);
bundle.putBoolean(OPEN_TRACK_MENU, true);
bundle.putBoolean(CURRENT_RECORDING, currentRecording);
MapActivity.launchMapActivityMoveToTop(context, prevIntentParams, null, bundle);
}
}
public static void showInstance(@NonNull final MapActivity mapActivity, @Nullable String path, boolean showCurrentTrack) {
OsmandApplication app = mapActivity.getMyApplication();
SelectedGpxFile selectedGpxFile;
if (showCurrentTrack) {
selectedGpxFile = app.getSavingTrackHelper().getCurrentTrack();
} else {
selectedGpxFile = app.getSelectedGpxHelper().getSelectedFileByPath(path);
}
if (selectedGpxFile != null) {
showInstance(mapActivity, selectedGpxFile);
} else if (!Algorithms.isEmpty(path)) {
String title = app.getString(R.string.loading_smth, "");
final ProgressDialog progress = ProgressDialog.show(mapActivity, title, app.getString(R.string.loading_data));
final WeakReference<MapActivity> mapActivityRef = new WeakReference<>(mapActivity);
GpxFileLoaderTask gpxFileLoaderTask = new GpxFileLoaderTask(new File(path), new CallbackWithObject<GPXFile>() {
@Override
public boolean processResult(GPXFile result) {
MapActivity mapActivity = mapActivityRef.get();
if (mapActivity != null) {
OsmandApplication app = mapActivity.getMyApplication();
SelectedGpxFile selectedGpxFile = app.getSelectedGpxHelper().selectGpxFile(result, true, false);
showInstance(mapActivity, selectedGpxFile);
}
if (progress != null && AndroidUtils.isActivityNotDestroyed(mapActivity)) {
progress.dismiss();
}
return true;
}
});
gpxFileLoaderTask.execute();
}
}
public static boolean showInstance(@NonNull MapActivity mapActivity, SelectedGpxFile selectedGpxFile) {
try {
Bundle args = new Bundle();
args.putString(TRACK_FILE_NAME, path);
args.putBoolean(CURRENT_RECORDING, showCurrentTrack);
args.putInt(ContextMenuFragment.MENU_STATE_KEY, MenuState.HEADER_ONLY);
TrackMenuFragment fragment = new TrackMenuFragment();
fragment.setArguments(args);
fragment.setRetainInstance(true);
fragment.setSelectedGpxFile(selectedGpxFile);
mapActivity.getSupportFragmentManager()
.beginTransaction()

View file

@ -1,6 +1,5 @@
package net.osmand.plus.views;
import android.content.Intent;
import android.graphics.PointF;
import android.view.View;
import android.widget.ImageView;
@ -14,7 +13,6 @@ import net.osmand.data.RotatedTileBox;
import net.osmand.plus.R;
import net.osmand.plus.UiUtilities;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.activities.TrackActivity;
import net.osmand.plus.mapcontextmenu.MapContextMenu;
import net.osmand.plus.mapcontextmenu.editors.RtePtEditor;
import net.osmand.plus.mapcontextmenu.editors.WptPtEditor;
@ -22,6 +20,8 @@ import net.osmand.plus.mapcontextmenu.editors.WptPtEditor.OnDismissListener;
import net.osmand.plus.track.TrackMenuFragment;
import net.osmand.plus.views.layers.ContextMenuLayer;
import java.io.File;
public class AddGpxPointBottomSheetHelper implements OnDismissListener {
private final View view;
private final TextView title;
@ -149,18 +149,10 @@ public class AddGpxPointBottomSheetHelper implements OnDismissListener {
if (fragment != null) {
fragment.show();
} else {
openTrackActivity();
TrackMenuFragment.openTrack(mapActivity, new File(newGpxPoint.getGpx().path), null);
}
}
private void openTrackActivity() {
Intent newIntent = new Intent(mapActivity, mapActivity.getMyApplication().getAppCustomization().getTrackActivity());
newIntent.putExtra(TrackActivity.TRACK_FILE_NAME, newGpxPoint.getGpx().path);
newIntent.putExtra(TrackActivity.OPEN_POINTS_TAB, true);
newIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
mapActivity.startActivity(newIntent);
}
public static class NewGpxPoint {
private PointDescription pointDescription;
private GPXFile gpx;

View file

@ -859,30 +859,30 @@ public class MapControlsLayer extends OsmandMapLayer {
}
boolean routeFollowingMode = !routePlanningMode && rh.isFollowingMode();
boolean trackDialogOpened = mapActivity.getTrackDetailsMenu().isVisible();
boolean contextMenuOpened = !mapActivity.getContextMenu().shouldShowTopControls();
boolean shouldHideTopControls = mapActivity.shouldHideTopControls();
boolean showRouteCalculationControls = routePlanningMode ||
((app.accessibilityEnabled() || (System.currentTimeMillis() - touchEvent < TIMEOUT_TO_SHOW_BUTTONS)) && routeFollowingMode);
boolean routeDialogOpened = mapRouteInfoMenu.isVisible() || (showRouteCalculationControls && mapRouteInfoMenu.needShowMenu());
updateMyLocationVisibility(backToLocationControl, rh, routeDialogOpened || contextMenuOpened);
updateMyLocationVisibility(backToLocationControl, rh, routeDialogOpened || shouldHideTopControls);
//routePlanningBtn.setIconResId(routeFollowingMode ? R.drawable.ic_action_info_dark : R.drawable.ic_action_gdirections_dark);
updateRoutePlaningButton(rh, routePlanningMode);
boolean showBottomMenuButtons = (showRouteCalculationControls || !routeFollowingMode)
&& !isInMovingMarkerMode() && !isInGpxDetailsMode() && !isInMeasurementToolMode()
&& !isInPlanRouteMode() && !contextMenuOpened && !isInChoosingRoutesMode()
&& !isInPlanRouteMode() && !shouldHideTopControls && !isInChoosingRoutesMode()
&& !isInWaypointsChoosingMode() && !isInFollowTrackMode() && !isInTrackAppearanceMode();
routePlanningBtn.updateVisibility(showBottomMenuButtons);
menuControl.updateVisibility(showBottomMenuButtons);
boolean showZoomButtons = !routeDialogOpened && !contextMenuOpened && !isInTrackAppearanceMode()
boolean showZoomButtons = !routeDialogOpened && !shouldHideTopControls && !isInTrackAppearanceMode()
&& (!isInGpxApproximationMode() || !isPotrait())
&& !isInFollowTrackMode() && (!isInChoosingRoutesMode() || !isInWaypointsChoosingMode() || !portrait);
mapZoomIn.updateVisibility(showZoomButtons);
mapZoomOut.updateVisibility(showZoomButtons);
boolean forceHideCompass = routeDialogOpened || trackDialogOpened || isInMeasurementToolMode()
|| isInPlanRouteMode() || contextMenuOpened || isInChoosingRoutesMode()
|| isInPlanRouteMode() || shouldHideTopControls || isInChoosingRoutesMode()
|| isInTrackAppearanceMode() || isInWaypointsChoosingMode() || isInFollowTrackMode();
compassHud.forceHideCompass = forceHideCompass;
compassHud.updateVisibility(!forceHideCompass && shouldShowCompass());
@ -892,7 +892,7 @@ public class MapControlsLayer extends OsmandMapLayer {
if (layersHud.setIconResId(appMode.getIconRes())) {
layersHud.update(app, isNight);
}
boolean showTopButtons = !routeDialogOpened && !trackDialogOpened && !contextMenuOpened
boolean showTopButtons = !routeDialogOpened && !trackDialogOpened && !shouldHideTopControls
&& !isInMeasurementToolMode() && !isInPlanRouteMode() && !isInChoosingRoutesMode()
&& !isInTrackAppearanceMode() && !isInWaypointsChoosingMode() && !isInFollowTrackMode();
layersHud.updateVisibility(showTopButtons);

View file

@ -425,6 +425,7 @@ public class MapQuickActionLayer extends OsmandMapLayer implements QuickActionRe
measurementToolLayer.isInMeasurementMode() ||
mapMarkersLayer.isInPlanRouteMode() ||
gpxLayer.isInTrackAppearanceMode() ||
mapControlsLayer.isInTrackMenuMode() ||
mapRouteInfoMenu.isVisible() ||
MapRouteInfoMenu.chooseRoutesVisible ||
MapRouteInfoMenu.waypointsVisible ||

View file

@ -974,7 +974,7 @@ public class MapInfoWidgetsFactory {
}
}
}
if (map.isTopToolbarActive() || !map.getContextMenu().shouldShowTopControls() || MapRouteInfoMenu.chooseRoutesVisible || MapRouteInfoMenu.waypointsVisible) {
if (map.isTopToolbarActive() || map.shouldHideTopControls() || MapRouteInfoMenu.chooseRoutesVisible || MapRouteInfoMenu.waypointsVisible) {
updateVisibility(false);
} else if (showClosestWaypointFirstInAddress && updateWaypoint()) {
updateVisibility(true);
@ -1232,7 +1232,7 @@ public class MapInfoWidgetsFactory {
@SuppressLint("SetTextI18n")
public boolean updateInfo() {
boolean visible = settings.SHOW_COORDINATES_WIDGET.get() && map.getContextMenu().shouldShowTopControls()
boolean visible = settings.SHOW_COORDINATES_WIDGET.get() && !map.shouldHideTopControls()
&& map.getMapRouteInfoMenu().shouldShowTopControls() && !map.isTopToolbarActive()
&& !map.getMapLayers().getGpxLayer().isInTrackAppearanceMode()
&& !MapRouteInfoMenu.chooseRoutesVisible && !MapRouteInfoMenu.waypointsVisible

View file

@ -191,7 +191,7 @@ public class MapMarkersWidgetsFactory {
|| map.getMapRouteInfoMenu().isVisible()
|| addressTopBar.getVisibility() == View.VISIBLE
|| map.isTopToolbarActive()
|| !map.getContextMenu().shouldShowTopControls()
|| map.shouldHideTopControls()
|| map.getMapLayers().getGpxLayer().isInTrackAppearanceMode()
|| map.getMapLayers().getMapMarkersLayer().isInPlanRouteMode()) {
updateVisibility(false);

View file

@ -26,7 +26,30 @@ public class OsmandTextFieldBoxes extends TextFieldBoxes {
floatingLabel.setVisibility(View.GONE);
labelSpace.setVisibility(View.GONE);
labelSpaceBelow.setVisibility(View.GONE);
int paddingH = getResources().getDimensionPixelSize(R.dimen.route_info_card_details_margin);
inputLayout.setPadding(0, paddingH, 0, paddingH);
int paddingV = getResources().getDimensionPixelSize(R.dimen.route_info_card_details_margin);
inputLayout.setPadding(0, paddingV, 0, paddingV);
}
public void setGravityFloatingLabel(int gravity) {
floatingLabel.setGravity(gravity);
}
@Override
public void setLabelText(String labelText) {
super.setLabelText(labelText);
floatingLabel.post(new Runnable() {
@Override
public void run() {
if (floatingLabel.getLineCount() > 1) {
inputLayout.setPadding(
inputLayout.getPaddingLeft(),
getResources().getDimensionPixelOffset(useDenseSpacing ? R.dimen.dense_editTextLayout_padding_top : R.dimen.editTextLayout_padding_top) +
getResources().getDimensionPixelSize(useDenseSpacing ? R.dimen.context_menu_first_line_top_margin : R.dimen.content_padding_small),
inputLayout.getPaddingRight(),
inputLayout.getPaddingBottom()
);
}
}
});
}
}

View file

@ -15,6 +15,7 @@ import android.view.ViewGroup;
import android.webkit.JavascriptInterface;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.widget.ProgressBar;
import android.widget.TextView;
import androidx.annotation.NonNull;
@ -27,14 +28,12 @@ import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentManager.BackStackEntry;
import net.osmand.AndroidUtils;
import net.osmand.GPXUtilities;
import net.osmand.GPXUtilities.GPXFile;
import net.osmand.IndexConstants;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.OsmandPlugin;
import net.osmand.plus.R;
import net.osmand.plus.UiUtilities;
import net.osmand.plus.activities.TrackActivity;
import net.osmand.plus.development.OsmandDevelopmentPlugin;
import net.osmand.plus.helpers.FileNameTranslationHelper;
import net.osmand.plus.settings.backend.OsmandSettings;
@ -45,7 +44,9 @@ import net.osmand.plus.wikivoyage.WikivoyageWebViewClient;
import net.osmand.plus.wikivoyage.data.TravelArticle;
import net.osmand.plus.wikivoyage.data.TravelArticle.TravelArticleIdentifier;
import net.osmand.plus.wikivoyage.data.TravelHelper;
import net.osmand.plus.wikivoyage.data.TravelHelper.GpxReadCallback;
import net.osmand.plus.wikivoyage.data.TravelLocalDataHelper;
import net.osmand.plus.wikivoyage.explore.WikivoyageExploreActivity;
import net.osmand.util.Algorithms;
import java.io.File;
@ -53,6 +54,7 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import static net.osmand.plus.track.TrackMenuFragment.openTrack;
import static net.osmand.plus.wikipedia.WikiArticleShowImages.OFF;
@ -75,6 +77,7 @@ public class WikivoyageArticleDialogFragment extends WikiArticleBaseDialogFragme
private TravelArticle article;
private TextView trackButton;
private ProgressBar gpxProgress;
private TextView saveBtn;
private WikivoyageWebViewClient webViewClient;
@ -150,14 +153,18 @@ public class WikivoyageArticleDialogFragment extends WikiArticleBaseDialogFragme
if (article == null || activity == null || fm == null) {
return;
}
if (activity instanceof WikivoyageExploreActivity) {
WikivoyageExploreActivity exploreActivity = (WikivoyageExploreActivity) activity;
exploreActivity.setArticle(article);
}
TravelHelper travelHelper = getMyApplication().getTravelHelper();
File path = travelHelper.createGpxFile(article);
Intent newIntent = new Intent(activity, getMyApplication().getAppCustomization().getTrackActivity());
newIntent.putExtra(TrackActivity.TRACK_FILE_NAME, path.getAbsolutePath());
newIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(newIntent);
File file = travelHelper.createGpxFile(article);
openTrack(activity, new File(file.getAbsolutePath()), null);
}
});
trackButton.setVisibility(View.GONE);
gpxProgress = mainView.findViewById(R.id.gpx_progress);
gpxProgress.setVisibility(View.GONE);
saveBtn = (TextView) mainView.findViewById(R.id.save_button);
@ -305,19 +312,23 @@ public class WikivoyageArticleDialogFragment extends WikiArticleBaseDialogFragme
selectedLang = langs.get(0);
}
articleToolbarText.setText("");
article = getMyApplication().getTravelHelper().getArticleById(articleId, selectedLang);
article = getMyApplication().getTravelHelper().getArticleById(articleId, selectedLang, true,
new GpxReadCallback() {
@Override
public void onGpxFileReading() {
updateTrackButton(true, null);
}
@Override
public void onGpxFileRead(@Nullable GPXFile gpxFile) {
updateTrackButton(false, gpxFile);
}
});
if (article == null) {
return;
}
webViewClient.setArticle(article);
articleToolbarText.setText(article.getTitle());
GPXFile gpxFile = article.getGpxFile();
if (gpxFile != null && gpxFile.getPointsSize() > 0) {
trackButton.setVisibility(View.VISIBLE);
trackButton.setText(getString(R.string.shared_string_gpx_points) + " (" + gpxFile.getPointsSize() + ")");
} else {
trackButton.setVisibility(View.GONE);
}
TravelLocalDataHelper ldh = getMyApplication().getTravelHelper().getBookmarksHelper();
ldh.addToHistory(article);
@ -327,6 +338,21 @@ public class WikivoyageArticleDialogFragment extends WikiArticleBaseDialogFragme
contentWebView.loadDataWithBaseURL(getBaseUrl(), createHtmlContent(), "text/html", "UTF-8", null);
}
private void updateTrackButton(boolean processing, @Nullable GPXFile gpxFile) {
if (processing) {
trackButton.setVisibility(View.GONE);
gpxProgress.setVisibility(View.VISIBLE);
} else {
if (gpxFile != null && gpxFile.getPointsSize() > 0) {
trackButton.setVisibility(View.VISIBLE);
trackButton.setText(getString(R.string.shared_string_gpx_points) + " (" + gpxFile.getPointsSize() + ")");
} else {
trackButton.setVisibility(View.GONE);
}
gpxProgress.setVisibility(View.GONE);
}
}
@NonNull
@Override
protected String createHtmlContent() {

View file

@ -1,7 +1,9 @@
package net.osmand.plus.wikivoyage.article;
import android.app.Activity;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.LayoutInflater;
@ -20,10 +22,13 @@ import androidx.core.content.ContextCompat;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import net.osmand.plus.activities.OsmandBaseExpandableListAdapter;
import net.osmand.plus.base.MenuBottomSheetDialogFragment;
import net.osmand.plus.base.bottomsheetmenu.BaseBottomSheetItem;
import net.osmand.plus.base.bottomsheetmenu.SimpleBottomSheetItem;
import net.osmand.plus.base.bottomsheetmenu.simpleitems.ProgressItem;
import net.osmand.plus.base.bottomsheetmenu.simpleitems.TitleItem;
import net.osmand.plus.wikivoyage.data.TravelArticle;
import net.osmand.plus.wikivoyage.data.TravelArticle.TravelArticleIdentifier;
@ -52,6 +57,7 @@ public class WikivoyageArticleNavigationFragment extends MenuBottomSheetDialogFr
private List<String> parentsList;
private ExpandableListView expListView;
private Map<WikivoyageSearchResult, List<WikivoyageSearchResult>> navigationMap;
@Override
public void createMenuItems(Bundle savedInstanceState) {
@ -75,61 +81,28 @@ public class WikivoyageArticleNavigationFragment extends MenuBottomSheetDialogFr
return;
}
article = getMyApplication().getTravelHelper().getArticleById(articleId, selectedLang);
OsmandApplication app = requiredMyApplication();
article = app.getTravelHelper().getArticleById(articleId, selectedLang, false, null);
if (article == null) {
return;
}
parentsList = new ArrayList<>(Arrays.asList(article.getAggregatedPartOf().split(",")));
Map<WikivoyageSearchResult, List<WikivoyageSearchResult>> navigationMap
= getMyApplication().getTravelHelper().getNavigationMap(article);
items.add(new TitleItem(getString(R.string.shared_string_navigation)));
expListView = new ExpandableListView(ctx);
final ExpandableListAdapter listAdapter = new ExpandableListAdapter(ctx, navigationMap);
if (navigationMap == null) {
items.add(new ProgressItem());
new BuildNavigationTask(app).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
} else {
final ExpandableListAdapter listAdapter = createNavigationListView(navigationMap);
LinearLayout container = new LinearLayout(ctx);
container.addView(expListView);
expListView.setAdapter(listAdapter);
Drawable transparent = AppCompatResources.getDrawable(ctx, R.color.color_transparent);
expListView.setDivider(transparent);
expListView.setGroupIndicator(transparent);
expListView.setSelector(transparent);
expListView.setLayoutParams(new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.MATCH_PARENT)
);
items.add(new SimpleBottomSheetItem.Builder().setCustomView(container).create());
expListView.setOnChildClickListener(new ExpandableListView.OnChildClickListener() {
@Override
public boolean onChildClick(ExpandableListView parent, View v,
int groupPosition, int childPosition, long id) {
WikivoyageSearchResult articleItem = listAdapter.getArticleItem(groupPosition, childPosition);
sendResults(articleItem.getArticleTitle());
dismiss();
return true;
if (listAdapter.getGroupCount() > 0) {
expListView.expandGroup(listAdapter.getGroupCount() - 1);
}
});
expListView.setOnGroupClickListener(new ExpandableListView.OnGroupClickListener() {
@Override
public boolean onGroupClick(ExpandableListView parent, View v, int groupPosition, long id) {
WikivoyageSearchResult articleItem = (WikivoyageSearchResult) listAdapter.getGroup(groupPosition);
if (Algorithms.isEmpty(articleItem.getArticleTitle())) {
Toast.makeText(getContext(), R.string.wiki_article_not_found, Toast.LENGTH_LONG).show();
} else {
sendResults(articleItem.getArticleTitle());
dismiss();
}
return true;
}
});
LinearLayout container = new LinearLayout(ctx);
container.addView(expListView);
items.add(new SimpleBottomSheetItem.Builder().setCustomView(container).create());
if (listAdapter.getGroupCount() > 0) {
expListView.expandGroup(listAdapter.getGroupCount() - 1);
}
}
@ -307,4 +280,84 @@ public class WikivoyageArticleNavigationFragment extends MenuBottomSheetDialogFr
return true;
}
}
public void updateMenu() {
Activity activity = getActivity();
View mainView = getView();
if (activity != null && mainView != null) {
LinearLayout itemsContainer = (LinearLayout) mainView.findViewById(useScrollableItemsContainer()
? R.id.scrollable_items_container : R.id.non_scrollable_items_container);
if (itemsContainer != null) {
itemsContainer.removeAllViews();
}
items.clear();
createMenuItems(null);
for (BaseBottomSheetItem item : items) {
item.inflate(activity, itemsContainer, nightMode);
}
setupHeightAndBackground(mainView);
}
}
private ExpandableListAdapter createNavigationListView(Map<WikivoyageSearchResult, List<WikivoyageSearchResult>> navigationMap) {
final Context ctx = requireContext();
expListView = new ExpandableListView(ctx);
final ExpandableListAdapter listAdapter = new ExpandableListAdapter(ctx, navigationMap);
expListView.setAdapter(listAdapter);
Drawable transparent = AppCompatResources.getDrawable(ctx, R.color.color_transparent);
expListView.setDivider(transparent);
expListView.setGroupIndicator(transparent);
expListView.setSelector(transparent);
expListView.setLayoutParams(new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.MATCH_PARENT)
);
expListView.setOnChildClickListener(new ExpandableListView.OnChildClickListener() {
@Override
public boolean onChildClick(ExpandableListView parent, View v,
int groupPosition, int childPosition, long id) {
WikivoyageSearchResult articleItem = listAdapter.getArticleItem(groupPosition, childPosition);
sendResults(articleItem.getArticleTitle());
dismiss();
return true;
}
});
expListView.setOnGroupClickListener(new ExpandableListView.OnGroupClickListener() {
@Override
public boolean onGroupClick(ExpandableListView parent, View v, int groupPosition, long id) {
WikivoyageSearchResult articleItem = (WikivoyageSearchResult) listAdapter.getGroup(groupPosition);
if (Algorithms.isEmpty(articleItem.getArticleTitle())) {
Toast.makeText(ctx, R.string.wiki_article_not_found, Toast.LENGTH_LONG).show();
} else {
sendResults(articleItem.getArticleTitle());
dismiss();
}
return true;
}
});
return listAdapter;
}
private class BuildNavigationTask extends AsyncTask<Void, Void, Map<WikivoyageSearchResult, List<WikivoyageSearchResult>>> {
private final OsmandApplication app;
public BuildNavigationTask(@NonNull OsmandApplication app) {
this.app = app;
}
@Override
protected Map<WikivoyageSearchResult, List<WikivoyageSearchResult>> doInBackground(Void... voids) {
return app.getTravelHelper().getNavigationMap(article);
}
@Override
protected void onPostExecute(Map<WikivoyageSearchResult, List<WikivoyageSearchResult>> navigationMap) {
WikivoyageArticleNavigationFragment.this.navigationMap = navigationMap;
updateMenu();
}
}
}

View file

@ -44,6 +44,7 @@ public class TravelArticle {
String aggregatedPartOf;
long lastModified;
boolean gpxFileReading;
boolean gpxFileRead;
@NonNull

View file

@ -549,7 +549,7 @@ public class TravelDbHelper implements TravelHelper {
@Override
@Nullable
public TravelArticle getArticleById(@NonNull TravelArticleIdentifier articleId, @NonNull String lang) {
public TravelArticle getArticleById(@NonNull TravelArticleIdentifier articleId, @NonNull String lang, boolean readGpx, @Nullable GpxReadCallback callback) {
TravelArticle res = null;
SQLiteConnection conn = openConnection();
String routeId = articleId.routeId;
@ -566,24 +566,27 @@ public class TravelDbHelper implements TravelHelper {
if (res == null) {
res = localDataHelper.getSavedArticle(articleId.file, articleId.routeId, lang);
}
if (res != null && callback != null) {
callback.onGpxFileRead(res.gpxFile);
}
return res;
}
@Nullable
@Override
public TravelArticle getArticleByTitle(@NonNull final String title, @NonNull final String lang) {
return getArticleByTitle(title, new QuadRect(), lang);
public TravelArticle getArticleByTitle(@NonNull final String title, @NonNull final String lang, boolean readGpx, @Nullable GpxReadCallback callback) {
return getArticleByTitle(title, new QuadRect(), lang, readGpx, callback);
}
@Nullable
@Override
public TravelArticle getArticleByTitle(@NonNull final String title, @NonNull LatLon latLon, @NonNull final String lang) {
return getArticleByTitle(title, new QuadRect(), lang);
public TravelArticle getArticleByTitle(@NonNull final String title, @NonNull LatLon latLon, @NonNull final String lang, boolean readGpx, @Nullable GpxReadCallback callback) {
return getArticleByTitle(title, new QuadRect(), lang, readGpx, callback);
}
@Nullable
@Override
public TravelArticle getArticleByTitle(@NonNull final String title, @NonNull QuadRect rect, @NonNull final String lang) {
public TravelArticle getArticleByTitle(@NonNull final String title, @NonNull QuadRect rect, @NonNull final String lang, boolean readGpx, @Nullable GpxReadCallback callback) {
TravelArticle res = null;
SQLiteConnection conn = openConnection();
if (conn != null) {
@ -596,6 +599,9 @@ public class TravelDbHelper implements TravelHelper {
cursor.close();
}
}
if (res != null && callback != null) {
callback.onGpxFileRead(res.gpxFile);
}
return res;
}

View file

@ -3,6 +3,8 @@ 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;
import net.osmand.plus.wikivoyage.data.TravelArticle.TravelArticleIdentifier;
@ -14,6 +16,11 @@ import java.util.Map;
public interface TravelHelper {
interface GpxReadCallback {
void onGpxFileReading();
void onGpxFileRead(@Nullable GPXFile gpxFile);
}
TravelLocalDataHelper getBookmarksHelper();
void initializeDataOnAppStartup();
@ -29,19 +36,19 @@ public interface TravelHelper {
List<TravelArticle> getPopularArticles();
@NonNull
Map<WikivoyageSearchResult, List<WikivoyageSearchResult>> getNavigationMap(@NonNull final TravelArticle article);
Map<WikivoyageSearchResult, List<WikivoyageSearchResult>> getNavigationMap(@NonNull TravelArticle article);
@Nullable
TravelArticle getArticleById(@NonNull TravelArticleIdentifier articleId, @NonNull String lang);
TravelArticle getArticleById(@NonNull TravelArticleIdentifier articleId, @NonNull String lang, boolean readGpx, @Nullable GpxReadCallback callback);
@Nullable
public TravelArticle getArticleByTitle(@NonNull final String title, @NonNull final String lang);
TravelArticle getArticleByTitle(@NonNull String title, @NonNull String lang, boolean readGpx, @Nullable GpxReadCallback callback);
@Nullable
public TravelArticle getArticleByTitle(@NonNull final String title, @NonNull LatLon latLon, @NonNull final String lang);
TravelArticle getArticleByTitle(@NonNull String title, @NonNull LatLon latLon, @NonNull String lang, boolean readGpx, @Nullable GpxReadCallback callback);
@Nullable
TravelArticle getArticleByTitle(@NonNull String title, @NonNull QuadRect rect, @NonNull String lang);
TravelArticle getArticleByTitle(@NonNull String title, @NonNull QuadRect rect, @NonNull String lang, boolean readGpx, @Nullable GpxReadCallback callback);
@Nullable
TravelArticleIdentifier getArticleId(@NonNull String title, @NonNull String lang);
@ -50,10 +57,10 @@ public interface TravelHelper {
ArrayList<String> getArticleLangs(@NonNull TravelArticleIdentifier articleId);
@NonNull
String getGPXName(@NonNull final TravelArticle article);
String getGPXName(@NonNull TravelArticle article);
@NonNull
File createGpxFile(@NonNull final TravelArticle article);
File createGpxFile(@NonNull TravelArticle article);
// TODO: this method should be deleted once TravelDBHelper is deleted
@Nullable

View file

@ -420,7 +420,7 @@ public class TravelLocalDataHelper {
if (cursor.moveToFirst()) {
do {
TravelArticle dbArticle = readSavedArticle(cursor);
TravelArticle article = context.getTravelHelper().getArticleById(dbArticle.generateIdentifier(), dbArticle.lang);
TravelArticle article = context.getTravelHelper().getArticleById(dbArticle.generateIdentifier(), dbArticle.lang, false, null);
if (article != null && article.getLastModified() > dbArticle.getLastModified()) {
updateSavedArticle(dbArticle, article);
res.add(article);

View file

@ -1,5 +1,6 @@
package net.osmand.plus.wikivoyage.data;
import android.os.AsyncTask;
import android.text.TextUtils;
import androidx.annotation.NonNull;
@ -56,7 +57,7 @@ public class TravelObfHelper implements TravelHelper {
public static final String ROUTE_ARTICLE_POINT = "route_article_point";
public static final int POPULAR_ARTICLES_SEARCH_RADIUS = 100000;
public static final int ARTICLE_SEARCH_RADIUS = 50000;
public static final int MAX_POPULAR_ARTICLES_COUNT = 100;
public static final int MAX_POPULAR_ARTICLES_COUNT = 30;
private final OsmandApplication app;
private final Collator collator;
@ -97,9 +98,19 @@ public class TravelObfHelper implements TravelHelper {
location, POPULAR_ARTICLES_SEARCH_RADIUS, -1, getSearchFilter(false), null);
List<Amenity> amenities = reader.searchPoi(req);
if (amenities.size() > 0) {
Collections.sort(amenities, new Comparator<Amenity>() {
@Override
public int compare(Amenity a1, Amenity a2) {
int d1 = (int) (MapUtils.getDistance(a1.getLocation().getLatitude(), a1.getLocation().getLongitude(),
location.getLatitude(), location.getLongitude()));
int d2 = (int) (MapUtils.getDistance(a2.getLocation().getLatitude(), a2.getLocation().getLongitude(),
location.getLatitude(), location.getLongitude()));
return d1 < d2 ? -1 : (d1 == d2 ? 0 : 1);
}
});
for (Amenity amenity : amenities) {
if (!Algorithms.isEmpty(amenity.getName(lang))) {
TravelArticle article = cacheTravelArticles(reader.getFile(), amenity, lang, false);
TravelArticle article = cacheTravelArticles(reader.getFile(), amenity, lang, false, null);
if (article != null) {
popularArticles.add(article);
if (popularArticles.size() >= MAX_POPULAR_ARTICLES_COUNT) {
@ -108,16 +119,6 @@ public class TravelObfHelper implements TravelHelper {
}
}
}
Collections.sort(popularArticles, new Comparator<TravelArticle>() {
@Override
public int compare(TravelArticle article1, TravelArticle article2) {
int d1 = (int) (MapUtils.getDistance(article1.getLat(), article1.getLon(),
location.getLatitude(), location.getLongitude()));
int d2 = (int) (MapUtils.getDistance(article2.getLat(), article2.getLon(),
location.getLatitude(), location.getLongitude()));
return d1 < d2 ? -1 : (d1 == d2 ? 0 : 1);
}
});
}
} catch (Exception e) {
LOG.error(e.getMessage(), e);
@ -128,13 +129,13 @@ public class TravelObfHelper implements TravelHelper {
}
@Nullable
private TravelArticle cacheTravelArticles(File file, Amenity amenity, String lang, boolean readPoints) {
private TravelArticle cacheTravelArticles(File file, Amenity amenity, String lang, boolean readPoints, @Nullable GpxReadCallback callback) {
TravelArticle article = null;
Map<String, TravelArticle> articles = readArticles(file, amenity, false);
Map<String, TravelArticle> articles = readArticles(file, amenity);
if (!Algorithms.isEmpty(articles)) {
TravelArticleIdentifier newArticleId = articles.values().iterator().next().generateIdentifier();
cachedArticles.put(newArticleId, articles);
article = getCachedArticle(newArticleId, lang, readPoints);
article = getCachedArticle(newArticleId, lang, readPoints, callback);
}
return article;
}
@ -155,17 +156,17 @@ public class TravelObfHelper implements TravelHelper {
}
@NonNull
private Map<String, TravelArticle> readArticles(@NonNull File file, @NonNull Amenity amenity, boolean readPoints) {
private Map<String, TravelArticle> readArticles(@NonNull File file, @NonNull Amenity amenity) {
Map<String, TravelArticle> articles = new HashMap<>();
Set<String> langs = getLanguages(amenity);
for (String lang : langs) {
articles.put(lang, readArticle(file, amenity, lang, readPoints));
articles.put(lang, readArticle(file, amenity, lang));
}
return articles;
}
@NonNull
private TravelArticle readArticle(@NonNull File file, @NonNull Amenity amenity, @NonNull String lang, boolean readPoints) {
private TravelArticle readArticle(@NonNull File file, @NonNull Amenity amenity, @NonNull String lang) {
TravelArticle res = new TravelArticle();
res.file = file;
String title = amenity.getName(lang);
@ -182,29 +183,11 @@ public class TravelObfHelper implements TravelHelper {
res.lang = lang;
res.contentsJson = Algorithms.emptyIfNull(amenity.getTagContent(Amenity.CONTENT_JSON, lang));
res.aggregatedPartOf = Algorithms.emptyIfNull(amenity.getTagContent(Amenity.IS_AGGR_PART, lang));
if (readPoints) {
res.gpxFile = buildGpxFile(res);
res.gpxFileRead = true;
}
return res;
}
private GPXFile buildGpxFile(@NonNull TravelArticle article) {
GPXFile gpxFile = null;
List<Amenity> pointList = getPointList(article);
if (!Algorithms.isEmpty(pointList)) {
gpxFile = new GPXFile(article.getTitle(), article.getLang(), article.getContent());
gpxFile.metadata.link = TravelArticle.getImageUrl(article.getImageTitle(), false);
for (Amenity amenity : pointList) {
WptPt wptPt = createWptPt(amenity, article.getLang());
gpxFile.addPoint(wptPt);
}
}
return gpxFile;
}
@NonNull
private List<Amenity> getPointList(@NonNull final TravelArticle article) {
private synchronized List<Amenity> getPointList(@NonNull final TravelArticle article) {
final List<Amenity> pointList = new ArrayList<>();
final String lang = article.getLang();
for (BinaryMapIndexReader reader : getReaders()) {
@ -312,7 +295,7 @@ public class TravelObfHelper implements TravelHelper {
for (Amenity amenity : entry.getValue()) {
Set<String> nameLangs = getLanguages(amenity);
if (nameLangs.contains(appLang)) {
TravelArticle article = readArticle(file, amenity, appLang, false);
TravelArticle article = readArticle(file, amenity, appLang);
ArrayList<String> langs = new ArrayList<>(nameLangs);
Collections.sort(langs, new Comparator<String>() {
@Override
@ -379,7 +362,7 @@ public class TravelObfHelper implements TravelHelper {
@NonNull
@Override
public Map<WikivoyageSearchResult, List<WikivoyageSearchResult>> getNavigationMap(@NonNull final TravelArticle article) {
public synchronized Map<WikivoyageSearchResult, List<WikivoyageSearchResult>> getNavigationMap(@NonNull final TravelArticle article) {
final String lang = article.getLang();
final String title = article.getTitle();
if (TextUtils.isEmpty(lang) || TextUtils.isEmpty(title)) {
@ -481,20 +464,28 @@ public class TravelObfHelper implements TravelHelper {
LOG.error(e.getMessage());
}
if (!Algorithms.isEmpty(amenities)) {
article = readArticle(reader.getFile(), amenities.get(0), lang, false);
article = readArticle(reader.getFile(), amenities.get(0), lang);
}
}
return article;
}
@Override
public TravelArticle getArticleById(@NonNull TravelArticleIdentifier articleId, @NonNull String lang) {
TravelArticle article = getCachedArticle(articleId, lang, true);
return article == null ? localDataHelper.getSavedArticle(articleId.file, articleId.routeId, lang) : article;
public TravelArticle getArticleById(@NonNull TravelArticleIdentifier articleId, @NonNull 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);
if (article != null && callback != null && readGpx) {
callback.onGpxFileRead(article.gpxFile);
}
}
return article;
}
@Nullable
private TravelArticle getCachedArticle(@NonNull TravelArticleIdentifier articleId, @NonNull String lang, boolean forceReadPoints) {
private TravelArticle getCachedArticle(@NonNull TravelArticleIdentifier articleId, @NonNull String lang,
boolean forceReadPoints, @Nullable GpxReadCallback callback) {
TravelArticle article = null;
Map<String, TravelArticle> articles = cachedArticles.get(articleId);
if (articles != null) {
@ -510,17 +501,25 @@ public class TravelObfHelper implements TravelHelper {
}
}
}
if (article == null) {
article = findArticleById(articleId, lang);
if (article == null && articles == null) {
article = findArticleById(articleId, lang, callback);
}
if (article != null && !article.gpxFileRead && forceReadPoints) {
article.gpxFile = buildGpxFile(article);
article.gpxFileRead = true;
if (article != null && forceReadPoints && !Algorithms.isEmpty(lang)) {
readGpxFile(article, callback);
}
return article;
}
private TravelArticle findArticleById(@NonNull final TravelArticleIdentifier articleId, final String lang) {
private void readGpxFile(@NonNull TravelArticle article, @Nullable GpxReadCallback callback) {
if (!article.gpxFileRead) {
new GpxFileReader(article, callback).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
} else if (callback != null) {
callback.onGpxFileRead(article.gpxFile);
}
}
private TravelArticle findArticleById(@NonNull final TravelArticleIdentifier articleId,
final String lang, @Nullable GpxReadCallback callback) {
TravelArticle article = null;
final boolean isDbArticle = articleId.file != null && articleId.file.getName().endsWith(IndexConstants.BINARY_WIKIVOYAGE_MAP_INDEX_EXT);
final List<Amenity> amenities = new ArrayList<>();
@ -563,7 +562,7 @@ public class TravelObfHelper implements TravelHelper {
LOG.error(e.getMessage());
}
if (!Algorithms.isEmpty(amenities)) {
article = cacheTravelArticles(reader.getFile(), amenities.get(0), lang, true);
article = cacheTravelArticles(reader.getFile(), amenities.get(0), lang, true, callback);
}
}
return article;
@ -571,20 +570,23 @@ public class TravelObfHelper implements TravelHelper {
@Nullable
@Override
public TravelArticle getArticleByTitle(@NonNull final String title, @NonNull final String lang) {
return getArticleByTitle(title, new QuadRect(), lang);
public TravelArticle getArticleByTitle(@NonNull final String title, @NonNull final String lang,
boolean readGpx, @Nullable GpxReadCallback callback) {
return getArticleByTitle(title, new QuadRect(), lang, readGpx, callback);
}
@Nullable
@Override
public TravelArticle getArticleByTitle(@NonNull final String title, @NonNull LatLon latLon, @NonNull final String lang) {
QuadRect rect = latLon != null ? MapUtils.calculateLatLonBbox(latLon.getLatitude(), latLon.getLongitude(), ARTICLE_SEARCH_RADIUS) : new QuadRect();
return getArticleByTitle(title, rect, lang);
public TravelArticle getArticleByTitle(@NonNull final String title, @NonNull LatLon latLon,
@NonNull final String lang, boolean readGpx, @Nullable GpxReadCallback callback) {
QuadRect rect = MapUtils.calculateLatLonBbox(latLon.getLatitude(), latLon.getLongitude(), ARTICLE_SEARCH_RADIUS);
return getArticleByTitle(title, rect, lang, readGpx, callback);
}
@Nullable
@Override
public TravelArticle getArticleByTitle(@NonNull final String title, @NonNull QuadRect rect, @NonNull final String lang) {
public TravelArticle getArticleByTitle(@NonNull final String title, @NonNull QuadRect rect,
@NonNull final String lang, boolean readGpx, @Nullable GpxReadCallback callback) {
TravelArticle article = null;
final List<Amenity> amenities = new ArrayList<>();
int x = 0;
@ -627,7 +629,7 @@ public class TravelObfHelper implements TravelHelper {
LOG.error(e.getMessage());
}
if (!Algorithms.isEmpty(amenities)) {
article = cacheTravelArticles(reader.getFile(), amenities.get(0), lang, true);
article = cacheTravelArticles(reader.getFile(), amenities.get(0), lang, readGpx, callback);
}
}
return article;
@ -654,7 +656,7 @@ public class TravelObfHelper implements TravelHelper {
}
}
if (a == null) {
TravelArticle article = getArticleByTitle(title, lang);
TravelArticle article = getArticleByTitle(title, lang, false, null);
if (article != null) {
a = article;
}
@ -666,7 +668,7 @@ public class TravelObfHelper implements TravelHelper {
@Override
public ArrayList<String> getArticleLangs(@NonNull TravelArticleIdentifier articleId) {
ArrayList<String> res = new ArrayList<>();
TravelArticle article = getArticleById(articleId, "");
TravelArticle article = getArticleById(articleId, "", false, null);
if (article != null) {
Map<String, TravelArticle> articles = cachedArticles.get(article.generateIdentifier());
if (articles != null) {
@ -683,14 +685,14 @@ public class TravelObfHelper implements TravelHelper {
@NonNull
@Override
public String getGPXName(@NonNull final TravelArticle article) {
public String getGPXName(@NonNull TravelArticle article) {
return article.getTitle().replace('/', '_').replace('\'', '_')
.replace('\"', '_') + IndexConstants.GPX_FILE_EXT;
}
@NonNull
@Override
public File createGpxFile(@NonNull final TravelArticle article) {
public File createGpxFile(@NonNull TravelArticle article) {
final GPXFile gpx = article.getGpxFile();
File file = app.getAppPath(IndexConstants.GPX_TRAVEL_DIR + getGPXName(article));
writeGpxFile(file, gpx);
@ -706,4 +708,46 @@ public class TravelObfHelper implements TravelHelper {
public String getWikivoyageFileName() {
return WORLD_WIKIVOYAGE_FILE_NAME;
}
private class GpxFileReader extends AsyncTask<Void, Void, GPXFile> {
private final TravelArticle article;
private final GpxReadCallback callback;
public GpxFileReader(@NonNull TravelArticle article, @Nullable GpxReadCallback callback) {
this.article = article;
this.callback = callback;
}
@Override
protected void onPreExecute() {
if (callback != null) {
callback.onGpxFileReading();
}
}
@Override
protected GPXFile doInBackground(Void... voids) {
GPXFile gpxFile = null;
List<Amenity> pointList = getPointList(article);
if (!Algorithms.isEmpty(pointList)) {
gpxFile = new GPXFile(article.getTitle(), article.getLang(), article.getContent());
gpxFile.metadata.link = TravelArticle.getImageUrl(article.getImageTitle(), false);
for (Amenity amenity : pointList) {
WptPt wptPt = createWptPt(amenity, article.getLang());
gpxFile.addPoint(wptPt);
}
}
return gpxFile;
}
@Override
protected void onPostExecute(GPXFile gpxFile) {
article.gpxFileRead = true;
article.gpxFile = gpxFile;
if (callback != null) {
callback.onGpxFileRead(gpxFile);
}
}
}
}

View file

@ -10,6 +10,7 @@ import net.osmand.GPXUtilities.WptPt;
import net.osmand.data.LatLon;
import net.osmand.data.PointDescription;
import net.osmand.plus.GpxSelectionHelper.SelectedGpxFile;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.mapcontextmenu.controllers.WptPtMenuController;
@ -38,13 +39,14 @@ public class WikivoyageWptPtMenuController extends WptPtMenuController {
}
private static TravelArticle getTravelArticle(@NonNull MapActivity mapActivity, @NonNull WptPt wpt) {
SelectedGpxFile selectedGpxFile = mapActivity.getMyApplication().getSelectedGpxHelper().getSelectedGPXFile(wpt);
OsmandApplication app = mapActivity.getMyApplication();
SelectedGpxFile selectedGpxFile = app.getSelectedGpxHelper().getSelectedGPXFile(wpt);
GPXFile gpxFile = selectedGpxFile != null ? selectedGpxFile.getGpxFile() : null;
Metadata metadata = gpxFile != null ? gpxFile.metadata : null;
String title = metadata != null ? metadata.getArticleTitle() : null;
String lang = metadata != null ? metadata.getArticleLang() : null;
if (!TextUtils.isEmpty(title) && !TextUtils.isEmpty(lang)) {
return mapActivity.getMyApplication().getTravelHelper().getArticleByTitle(title, new LatLon(wpt.lat, wpt.lon), lang);
return app.getTravelHelper().getArticleByTitle(title, new LatLon(wpt.lat, wpt.lon), lang, false, null);
}
return null;
}

View file

@ -21,4 +21,4 @@
# UPDATE 3: Turn on D8 to recover builds with new gradle 6.5 and pluigin 4.1.1
#android.enableD8=false
android.enableJetifier=true
android.useAndroidX=true
android.useAndroidX=true