commit
76c65130fa
32 changed files with 990 additions and 947 deletions
|
@ -4,7 +4,7 @@
|
|||
|
||||
<application
|
||||
android:icon="@mipmap/icon_free"
|
||||
android:label="@string/app_name_free"
|
||||
android:label="@string/app_name"
|
||||
tools:replace="android:icon, android:label">
|
||||
|
||||
<meta-data
|
||||
|
|
|
@ -24,6 +24,7 @@ android {
|
|||
// Build that doesn't include 3D OpenGL
|
||||
legacy {
|
||||
dimension "coreversion"
|
||||
resValue "string", "app_edition", ""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
android:layout_marginRight="@dimen/dialog_content_margin"
|
||||
android:layout_marginEnd="@dimen/dialog_content_margin"
|
||||
android:clickable="false"
|
||||
android:scrollbars="none"
|
||||
android:focusableInTouchMode="false" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
|
|
|
@ -1,198 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:osmand="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="@dimen/text_margin_small"
|
||||
android:layout_marginRight="@dimen/text_margin_small"
|
||||
android:background="?attr/wikivoyage_travel_card_bg"
|
||||
android:orientation="vertical"
|
||||
android:layout_marginEnd="@dimen/text_margin_small"
|
||||
android:layout_marginStart="@dimen/text_margin_small">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="@dimen/content_padding"
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="@dimen/bottom_sheet_content_padding_small">
|
||||
|
||||
<net.osmand.plus.widgets.TextViewEx
|
||||
android:id="@+id/title"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="@dimen/content_padding"
|
||||
android:layout_marginRight="@dimen/content_padding"
|
||||
android:layout_marginTop="4dp"
|
||||
android:layout_weight="1"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:textColor="?attr/wikivoyage_primary_text_color"
|
||||
android:textSize="@dimen/travel_card_primary_text_size"
|
||||
osmand:typeface="@string/font_roboto_medium"
|
||||
tools:text="Download file"/>
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:id="@+id/icon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
tools:ignore="ContentDescription"
|
||||
tools:src="@drawable/travel_card_download_icon"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<net.osmand.plus.widgets.TextViewEx
|
||||
android:id="@+id/description"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:lineSpacingMultiplier="@dimen/text_button_line_spacing_multiplier"
|
||||
android:textColor="@color/wikivoyage_secondary_text"
|
||||
android:textSize="@dimen/travel_card_primary_text_size"
|
||||
osmand:typeface="@string/font_roboto_regular"
|
||||
tools:text="Download this Wikivoyage travel guides file to view articles about places around the world without an internet connection."/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/file_data_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="@dimen/content_padding"
|
||||
android:layout_marginLeft="@dimen/bottom_sheet_content_margin_small"
|
||||
android:layout_marginRight="@dimen/bottom_sheet_content_margin_small"
|
||||
android:background="?attr/wikivoyage_travel_card_stroke_bg"
|
||||
android:minHeight="@dimen/bottom_sheet_selected_item_title_height"
|
||||
android:paddingLeft="@dimen/content_padding"
|
||||
android:paddingRight="@dimen/content_padding"
|
||||
android:layout_marginStart="@dimen/bottom_sheet_content_margin_small"
|
||||
android:paddingEnd="@dimen/content_padding"
|
||||
android:paddingStart="@dimen/content_padding"
|
||||
android:layout_marginEnd="@dimen/bottom_sheet_content_margin_small">
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:id="@+id/file_icon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginEnd="@dimen/content_padding"
|
||||
android:layout_marginRight="@dimen/content_padding"
|
||||
tools:ignore="ContentDescription"
|
||||
tools:src="@drawable/ic_action_read_article"
|
||||
tools:tint="?attr/wikivoyage_active_color"/>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical">
|
||||
|
||||
<net.osmand.plus.widgets.TextViewEx
|
||||
android:id="@+id/file_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:textColor="?attr/wikivoyage_primary_text_color"
|
||||
android:textSize="@dimen/default_list_text_size"
|
||||
osmand:typeface="@string/font_roboto_regular"
|
||||
tools:text="Wikivoyage"/>
|
||||
|
||||
<net.osmand.plus.widgets.TextViewEx
|
||||
android:id="@+id/file_description"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:textColor="@color/wikivoyage_secondary_text"
|
||||
android:textSize="@dimen/default_sub_text_size"
|
||||
osmand:typeface="@string/font_roboto_regular"
|
||||
tools:text="255 Mb • Update 11 April"/>
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progress_bar"
|
||||
style="?android:attr/progressBarStyleHorizontal"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="2dp"
|
||||
android:minHeight="0dp"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="@dimen/bottom_sheet_content_margin_small"
|
||||
android:layout_marginLeft="@dimen/bottom_sheet_content_margin_small"
|
||||
android:layout_marginRight="@dimen/bottom_sheet_content_margin_small"
|
||||
android:layout_marginEnd="@dimen/bottom_sheet_content_margin_small"
|
||||
android:layout_marginStart="@dimen/bottom_sheet_content_margin_small">
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/secondary_btn_container"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:background="?attr/wikivoyage_secondary_btn_bg">
|
||||
|
||||
<net.osmand.plus.widgets.TextViewEx
|
||||
android:id="@+id/secondary_button"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/wikivoyage_card_button_height"
|
||||
android:layout_gravity="center"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:ellipsize="end"
|
||||
android:gravity="center"
|
||||
android:letterSpacing="@dimen/text_button_letter_spacing"
|
||||
android:maxLines="1"
|
||||
android:textColor="?attr/wikivoyage_active_color"
|
||||
android:textSize="@dimen/text_button_text_size"
|
||||
osmand:typeface="@string/font_roboto_medium"
|
||||
tools:ignore="UnusedAttribute"
|
||||
tools:text="Later"/>
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
<View
|
||||
android:id="@+id/buttons_divider"
|
||||
android:layout_width="@dimen/bottom_sheet_content_margin_small"
|
||||
android:layout_height="match_parent"/>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/primary_btn_container"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:background="?attr/wikivoyage_primary_btn_bg">
|
||||
|
||||
<net.osmand.plus.widgets.TextViewEx
|
||||
android:id="@+id/primary_button"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/wikivoyage_card_button_height"
|
||||
android:layout_gravity="center"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:ellipsize="end"
|
||||
android:gravity="center"
|
||||
android:letterSpacing="@dimen/text_button_letter_spacing"
|
||||
android:maxLines="1"
|
||||
android:textColor="?attr/wikivoyage_primary_btn_text_color"
|
||||
android:textSize="@dimen/text_button_text_size"
|
||||
osmand:typeface="@string/font_roboto_medium"
|
||||
tools:ignore="UnusedAttribute"
|
||||
tools:text="Update"/>
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
|
@ -18,16 +18,34 @@
|
|||
android:layout_margin="@dimen/content_padding"
|
||||
android:orientation="vertical">
|
||||
|
||||
<net.osmand.plus.widgets.TextViewEx
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="@dimen/content_padding"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:text="@string/maps_you_need"
|
||||
android:textColor="?attr/wikivoyage_primary_text_color"
|
||||
android:textSize="@dimen/travel_card_primary_text_size"
|
||||
osmand:typeface="@string/font_roboto_medium"/>
|
||||
android:layout_marginBottom="@dimen/bottom_sheet_content_padding_small">
|
||||
|
||||
<net.osmand.plus.widgets.TextViewEx
|
||||
android:id="@+id/title"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="@dimen/content_padding"
|
||||
android:layout_marginRight="@dimen/content_padding"
|
||||
android:layout_marginTop="4dp"
|
||||
android:layout_weight="1"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:textColor="?attr/wikivoyage_primary_text_color"
|
||||
android:textSize="@dimen/travel_card_primary_text_size"
|
||||
osmand:typeface="@string/font_roboto_medium"
|
||||
tools:text="Download file" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:id="@+id/icon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
tools:ignore="ContentDescription"
|
||||
tools:src="@drawable/travel_card_download_icon" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<net.osmand.plus.widgets.TextViewEx
|
||||
android:id="@+id/description"
|
||||
|
|
26
OsmAnd/res/layout/wikivoyage_button_card.xml
Normal file
26
OsmAnd/res/layout/wikivoyage_button_card.xml
Normal file
|
@ -0,0 +1,26 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="@dimen/content_padding"
|
||||
android:background="?attr/wikivoyage_card_bg_color"
|
||||
android:gravity="center_vertical">
|
||||
|
||||
<include
|
||||
android:id="@+id/button"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/dialog_button_height"
|
||||
layout="@layout/bottom_sheet_dialog_button" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<include
|
||||
android:id="@+id/shadow"
|
||||
layout="@layout/card_bottom_divider"
|
||||
android:visibility="visible" />
|
||||
</LinearLayout>
|
|
@ -103,6 +103,7 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:maxLines="2"
|
||||
android:scrollbars="none"
|
||||
android:textColor="@color/wikivoyage_secondary_text"
|
||||
android:textSize="@dimen/default_sub_text_size"
|
||||
osmand:typeface="@string/font_roboto_regular"
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -3881,4 +3881,14 @@
|
|||
<string name="poi_wildlife_crossing_bat_bridge">Ponto por vespertoj</string>
|
||||
<string name="poi_wildlife_crossing">Trairejo por sovaĝaj bestoj</string>
|
||||
<string name="poi_swimming_area">Naĝejo natura</string>
|
||||
<string name="poi_piste_status_closed">Stato de skivojo: fermita</string>
|
||||
<string name="poi_piste_status_open">Stato de skivojo: malfermita</string>
|
||||
<string name="poi_patrolled_no">Kontrolata: ne</string>
|
||||
<string name="poi_patrolled_yes">Kontrolata: jes</string>
|
||||
<string name="poi_gladed_yes">Senarbigita: jes</string>
|
||||
<string name="poi_piste_name">Nomo de skivojo</string>
|
||||
<string name="poi_piste_ski_jump">Skisaltejo</string>
|
||||
<string name="poi_mobile_library">Movebla biblioteko (haltloko)</string>
|
||||
<string name="poi_summit_register_no">Pint‑taglibro: ne</string>
|
||||
<string name="poi_summit_register_yes">Pint‑taglibro: jes</string>
|
||||
</resources>
|
|
@ -4020,4 +4020,17 @@
|
|||
<string name="open_place_reviews">OpenPlaceReviews</string>
|
||||
<string name="opr_use_dev_url">Uzi test.openplacereviews.org</string>
|
||||
<string name="login_open_place_reviews">Ensaluti al OpenPlaceReviews</string>
|
||||
<string name="activity_type_water_name">Akvo</string>
|
||||
<string name="activity_type_winter_name">Vintro</string>
|
||||
<string name="activity_type_snowmobile_name">Motorsledo</string>
|
||||
<string name="activity_type_riding_name">Rajdado</string>
|
||||
<string name="activity_type_racing_name">Kurkonkurso</string>
|
||||
<string name="activity_type_mountainbike_name">Montbiciklo</string>
|
||||
<string name="activity_type_cycling_name">Biciklado</string>
|
||||
<string name="activity_type_hiking_name">Marŝado</string>
|
||||
<string name="activity_type_running_name">Kurado</string>
|
||||
<string name="activity_type_walking_name">Piedirado</string>
|
||||
<string name="activity_type_offroad_name">Ekstervoje</string>
|
||||
<string name="activity_type_motorbike_name">Motorciklo</string>
|
||||
<string name="activity_type_car_name">Aŭto</string>
|
||||
</resources>
|
|
@ -4005,4 +4005,13 @@
|
|||
<string name="open_place_reviews">OpenPlaceReviews</string>
|
||||
<string name="opr_use_dev_url">Utilisez test.openplacereviews.org</string>
|
||||
<string name="login_open_place_reviews">Se connecter à OpenPlaceReviews</string>
|
||||
<string name="activity_type_water_name">Eau</string>
|
||||
<string name="activity_type_winter_name">Hiver</string>
|
||||
<string name="activity_type_snowmobile_name">Motoneige</string>
|
||||
<string name="activity_type_cycling_name">Vélo</string>
|
||||
<string name="activity_type_mountainbike_name">VTT</string>
|
||||
<string name="activity_type_hiking_name">Randonnée</string>
|
||||
<string name="activity_type_running_name">Course à pied</string>
|
||||
<string name="activity_type_walking_name">Marche</string>
|
||||
<string name="activity_type_car_name">Voiture</string>
|
||||
</resources>
|
|
@ -54,7 +54,7 @@
|
|||
<string name="poi_service_tyres">Autógumi-szerelő</string>
|
||||
<string name="poi_car_wash">Autómosó</string>
|
||||
<string name="poi_fuel">Benzinkút;Töltőállomás;Gázolajtöltő-állomás</string>
|
||||
<string name="poi_electricity_combined_charging">Elektromos töltőállomás</string>
|
||||
<string name="poi_electricity_combined_charging">Elektromos töltőállomás;Elektromos autó töltése;Villanyautó töltése;Elektromos töltőpont</string>
|
||||
<string name="poi_compressed_air">Sűrített levegő</string>
|
||||
<string name="poi_parking">Parkoló</string>
|
||||
<string name="poi_motorcycle_parking">Motorkerékpár-parkoló</string>
|
||||
|
@ -3879,4 +3879,14 @@
|
|||
<string name="poi_wildlife_crossing_bat_tunnel">Denevéralagút</string>
|
||||
<string name="poi_wildlife_crossing_bat_bridge">Denevérhíd</string>
|
||||
<string name="poi_wildlife_crossing">Vadátjáró</string>
|
||||
<string name="poi_summit_register_no">Csúcsnapló nincs</string>
|
||||
<string name="poi_summit_register_yes">Csúcsnapló van</string>
|
||||
<string name="poi_patrolled_no">Hegyi mentő nincs</string>
|
||||
<string name="poi_patrolled_yes">Hegyi mentő van</string>
|
||||
<string name="poi_gladed_yes">Erdei pálya</string>
|
||||
<string name="poi_mobile_library">Mozgó könyvtár tartózkodási helye</string>
|
||||
<string name="poi_piste_status_closed">Pálya állapota: zárva</string>
|
||||
<string name="poi_piste_status_open">Pálya állapota: nyitva</string>
|
||||
<string name="poi_piste_name">Pálya neve</string>
|
||||
<string name="poi_piste_ski_jump">Síugrósánc</string>
|
||||
</resources>
|
|
@ -3881,4 +3881,14 @@
|
|||
<string name="poi_wildlife_crossing_bat_bridge">Brú fyrir leðurblökur</string>
|
||||
<string name="poi_wildlife_crossing">Þverun villtra dýra</string>
|
||||
<string name="poi_swimming_area">Sundsvæði</string>
|
||||
<string name="poi_mobile_library">Stæði fyrir bókabíl</string>
|
||||
<string name="poi_summit_register_no">Skráning á tind: nei</string>
|
||||
<string name="poi_summit_register_yes">Skráning á tind: já</string>
|
||||
<string name="poi_piste_status_closed">Staða brautar: lokuð</string>
|
||||
<string name="poi_piste_status_open">Staða brautar: opin</string>
|
||||
<string name="poi_patrolled_no">Eftirlit: nei</string>
|
||||
<string name="poi_patrolled_yes">Eftirlit: já</string>
|
||||
<string name="poi_gladed_yes">Skafið: já</string>
|
||||
<string name="poi_piste_name">Heiti brautar</string>
|
||||
<string name="poi_piste_ski_jump">Skíðastökk</string>
|
||||
</resources>
|
|
@ -3972,7 +3972,7 @@
|
|||
<string name="select_folder">Veldu möppu</string>
|
||||
<string name="select_folder_descr">Veldu möppu eða bættu við nýrri</string>
|
||||
<string name="shared_string_empty">Tómt</string>
|
||||
<string name="analyze_by_intervals">Greina eftir millibilum (uppskipting millibila)</string>
|
||||
<string name="analyze_by_intervals">Greina eftir uppskiptingu millibila</string>
|
||||
<string name="upload_to_openstreetmap">Senda inn í OpenStreetMap</string>
|
||||
<string name="edit_track">Breyta ferli</string>
|
||||
<string name="rename_track">Endurnefna feril</string>
|
||||
|
@ -4005,4 +4005,32 @@
|
|||
<string name="routing_engine_vehicle_type_mtb">Fjallahjól</string>
|
||||
<string name="message_server_error">Villa í netþjóni: %1$s</string>
|
||||
<string name="message_name_is_already_exists">Nafnið er þegar til staðar</string>
|
||||
<string name="delete_online_routing_engine">Eyða þessari leiðagerð á netinu\?</string>
|
||||
<string name="context_menu_read_full">Lesa óstytt</string>
|
||||
<string name="context_menu_edit_descr">Breyta lýsingu</string>
|
||||
<string name="delete_waypoints">Eyða ferilpunktum</string>
|
||||
<string name="copy_to_map_markers">Afrita í kortamerki</string>
|
||||
<string name="copy_to_map_favorites">Afrita í eftirlæti</string>
|
||||
<string name="upload_photo">Sendi inn</string>
|
||||
<string name="upload_photo_completed">Innsendingu er lokið</string>
|
||||
<string name="uploading_count">Sendi inn %1$d af %2$d</string>
|
||||
<string name="uploaded_count">Sent inn %1$d af %2$d</string>
|
||||
<string name="toast_select_edits_for_upload">Veldu breytingar til að senda inn</string>
|
||||
<string name="hillshade_slope_contour_lines">Hæðaskygging / Halli / Hæðarlínur</string>
|
||||
<string name="open_place_reviews">OpenPlaceReviews</string>
|
||||
<string name="opr_use_dev_url">Nota test.openplacereviews.org</string>
|
||||
<string name="login_open_place_reviews">Skrá inn á OpenPlaceReviews</string>
|
||||
<string name="activity_type_water_name">Vatn</string>
|
||||
<string name="activity_type_winter_name">Vetur</string>
|
||||
<string name="activity_type_snowmobile_name">Vélsleðar</string>
|
||||
<string name="activity_type_riding_name">Útreiðar</string>
|
||||
<string name="activity_type_racing_name">Kappakstur</string>
|
||||
<string name="activity_type_mountainbike_name">Fjallahjól</string>
|
||||
<string name="activity_type_cycling_name">Hjólreiðar</string>
|
||||
<string name="activity_type_hiking_name">Gönguferðir</string>
|
||||
<string name="activity_type_running_name">Hlaup</string>
|
||||
<string name="activity_type_walking_name">Gangandi</string>
|
||||
<string name="activity_type_offroad_name">Utanvegaakstur</string>
|
||||
<string name="activity_type_motorbike_name">Vélhjól</string>
|
||||
<string name="activity_type_car_name">Akandi</string>
|
||||
</resources>
|
|
@ -3970,7 +3970,7 @@
|
|||
<string name="select_folder">בחירת תקינה</string>
|
||||
<string name="select_folder_descr">נא לבחור תיקייה או להוסיף אחת חדשה</string>
|
||||
<string name="shared_string_empty">ריק</string>
|
||||
<string name="analyze_by_intervals">ניתוח לפי מרווחים (פיצול מרווחים)</string>
|
||||
<string name="analyze_by_intervals">ניתוח מרווחי פיצול</string>
|
||||
<string name="upload_to_openstreetmap">העלאה ל־OpenStreetMap</string>
|
||||
<string name="edit_track">עריכת מסלול</string>
|
||||
<string name="rename_track">שינוי שם מסלול</string>
|
||||
|
@ -4016,4 +4016,11 @@
|
|||
<string name="open_place_reviews">OpenPlaceReviews</string>
|
||||
<string name="opr_use_dev_url">להשתמש ב־test.openplacereviews.org</string>
|
||||
<string name="login_open_place_reviews">כניסה ל־OpenPlaceReviews</string>
|
||||
<string name="announcement_time_descr">זמן ההכרזה של ההנחיות הקוליות השונות תלוי בסוג ההכרזה, במהירות הניווט הנוכחית ובמהירות הניווט כבררת מחדל.</string>
|
||||
<string name="hillshade_slope_contour_lines">הצללה / מדרון / קווי מתאר</string>
|
||||
<string name="open_place_reviews_plugin_description">OpenPlaceReviews הוא מיזם בהובלת הקהילה בנוגע למקומות ציבוריים כגון מסעדות, מלונות, מוזיאונים ונקודות דרך. הוא אוסף מידע ציבורי עליהם כגון תמונות, סקירות, קישורים למערכות אחרות שמקושרות ל־OpenStreetMap, ויקיפדיה.
|
||||
\n
|
||||
\nכל הנתונים של OpenPlaceReview הם פתוחים וזמינים לציבור הרחב: http://openplacereviews.org/data.
|
||||
\n
|
||||
\nניתן לקרוא עוד באתר: http://openplacereviews.org</string>
|
||||
</resources>
|
|
@ -502,7 +502,7 @@
|
|||
<string name="poi_climbing">Tırmanma</string>
|
||||
<string name="poi_cricket">Kriket</string>
|
||||
<string name="poi_croquet">Kroket</string>
|
||||
<string name="poi_cycling">Bisiklete binme</string>
|
||||
<string name="poi_cycling">Bisiklet sürme</string>
|
||||
<string name="poi_diving">Dalış</string>
|
||||
<string name="poi_scuba_diving">Tüplü dalış</string>
|
||||
<string name="poi_dog_racing">Köpek yarışı</string>
|
||||
|
|
|
@ -2227,7 +2227,7 @@
|
|||
<string name="marker_save_as_track_descr">İşaretleyicilerinizi şu GPX dosyasına aktarın:</string>
|
||||
<string name="show_arrows_on_the_map">Haritada yön gösterici okları göster</string>
|
||||
<string name="measurement_tool_snap_to_road_descr">OsmAnd seçilmiş profil için rotalı noktalara bağlanacak.</string>
|
||||
<string name="none_point_error">Lütfen en az bir nokta ekleyiniz.</string>
|
||||
<string name="none_point_error">Lütfen en az bir nokta ekleyin.</string>
|
||||
<string name="measurement_tool_action_bar">Haritayı görüntüle ve nokta ekle</string>
|
||||
<string name="store_tracks_in_monthly_directories">Kaydedilmiş izlenen yolları aylık klasörlerde depola</string>
|
||||
<string name="mapillary_menu_filter_description">Resimleri göndericiye, tarihe ya da türüne göre filtreleyin. Sadece yakın mesafe yakınlaştırmasında etkin.</string>
|
||||
|
@ -3738,7 +3738,7 @@
|
|||
<string name="track_coloring_solid">Koyu</string>
|
||||
<string name="plan_route_last_edited">Son düzenleme</string>
|
||||
<string name="plan_route_import_track">Yolu içe aktar</string>
|
||||
<string name="plan_route_open_existing_track">Mevcut yolu aç</string>
|
||||
<string name="plan_route_open_existing_track">Var olan yolu aç</string>
|
||||
<string name="plan_route_create_new_route">Yeni güzergah oluştur</string>
|
||||
<string name="plan_route_select_track_file_for_open">Açmak için bir yol dosyası seçin.</string>
|
||||
<string name="shared_string_done">Bitti</string>
|
||||
|
@ -3968,7 +3968,7 @@
|
|||
<string name="select_folder">Klasör seç</string>
|
||||
<string name="select_folder_descr">Klasör seçin veya yeni bir tane ekleyin</string>
|
||||
<string name="shared_string_empty">Boş</string>
|
||||
<string name="analyze_by_intervals">Aralıklara göre analiz et (bölme aralığı)</string>
|
||||
<string name="analyze_by_intervals">Bölünmüş aralıkları analiz et</string>
|
||||
<string name="upload_to_openstreetmap">OpenStreetMap\'e yükle</string>
|
||||
<string name="edit_track">Yolu düzenle</string>
|
||||
<string name="rename_track">Yolu yeniden adlandır</string>
|
||||
|
@ -4012,4 +4012,26 @@
|
|||
<string name="uploading_count">%1$d / %2$d karşıya yükleniyor</string>
|
||||
<string name="uploaded_count">%1$d / %2$d karşıya yüklendi</string>
|
||||
<string name="toast_select_edits_for_upload">Karşıya yüklenecek düzenlemeleri seçin</string>
|
||||
<string name="hillshade_slope_contour_lines">tepe gölgesi / yamaç / eş yükselti eğrileri</string>
|
||||
<string name="open_place_reviews_plugin_description">OpenPlaceReviews, restoranlar, oteller, müzeler, ara noktalar gibi halka açık yerler hakkında topluluk tarafından yürütülen bir projedir. Fotoğraflar, yorumlar, OpenStreetMap, Wikipedia gibi diğer sistemlere bağlantılar gibi onlar hakkındaki tüm halka açık bilgileri toplar.
|
||||
\n
|
||||
\nTüm OpenPlaceReview verileri açık ve herkes tarafından kullanılabilir: http://openplacereviews.org/data
|
||||
\n
|
||||
\nDaha fazlasını şu adresten okuyabilirsiniz: http://openplacereviews.org</string>
|
||||
<string name="open_place_reviews">OpenPlaceReviews</string>
|
||||
<string name="opr_use_dev_url">test.openplacereviews.org adresini kullan</string>
|
||||
<string name="login_open_place_reviews">OpenPlaceReviews\'te oturum aç</string>
|
||||
<string name="activity_type_water_name">Su</string>
|
||||
<string name="activity_type_winter_name">Kış</string>
|
||||
<string name="activity_type_snowmobile_name">Kar arabası</string>
|
||||
<string name="activity_type_riding_name">Binme</string>
|
||||
<string name="activity_type_racing_name">Yarış</string>
|
||||
<string name="activity_type_mountainbike_name">Dağ bisikleti</string>
|
||||
<string name="activity_type_cycling_name">Bisiklet sürme</string>
|
||||
<string name="activity_type_hiking_name">Yürüyüş</string>
|
||||
<string name="activity_type_running_name">Koşma</string>
|
||||
<string name="activity_type_walking_name">Yürüme</string>
|
||||
<string name="activity_type_offroad_name">Arazi</string>
|
||||
<string name="activity_type_motorbike_name">Motosiklet</string>
|
||||
<string name="activity_type_car_name">Araba</string>
|
||||
</resources>
|
|
@ -2663,7 +2663,7 @@
|
|||
<string name="shared_string_travel_book">旅游书</string>
|
||||
<string name="download_images">下载图片</string>
|
||||
<string name="rendering_value_black_name">黑色</string>
|
||||
<string name="rendering_attr_surface_wood_name">木</string>
|
||||
<string name="rendering_attr_surface_wood_name">木头</string>
|
||||
<string name="app_mode_subway">地铁</string>
|
||||
<string name="app_mode_horse">骑马</string>
|
||||
<string name="shared_string_color_magenta">品红色</string>
|
||||
|
@ -2674,7 +2674,7 @@
|
|||
<string name="points_of_interests">兴趣点(POI)</string>
|
||||
<string name="shared_string_capacity">容量</string>
|
||||
<string name="rendering_attr_surface_metal_name">金属</string>
|
||||
<string name="rendering_attr_highway_class_path_name">路径</string>
|
||||
<string name="rendering_attr_highway_class_path_name">走道</string>
|
||||
<string name="app_mode_helicopter">直升机</string>
|
||||
<string name="app_mode_skiing">滑雪</string>
|
||||
<string name="base_profile_descr_ski">滑雪</string>
|
||||
|
@ -2839,7 +2839,7 @@
|
|||
<string name="show_closed_notes">显示关闭的注记</string>
|
||||
<string name="osm_edit_closed_note">关闭的OSM注记</string>
|
||||
<string name="add_online_source">添加在线资源</string>
|
||||
<string name="rendering_attr_highway_class_bridleway_name"/>
|
||||
<string name="rendering_attr_highway_class_bridleway_name">驮道</string>
|
||||
<string name="rendering_attr_surface_gravel_name">砾石</string>
|
||||
<string name="rendering_attr_surface_sett_name">比利时石砌路</string>
|
||||
<string name="routing_attr_allow_expert_name">允许专家路线</string>
|
||||
|
@ -3124,4 +3124,79 @@
|
|||
<string name="context_menu_item_add_waypoint">添加轨迹航点</string>
|
||||
<string name="save_track_to_gpx_globally">将轨迹记录到GPX文件</string>
|
||||
<string name="disable_recording_once_app_killed_descrp">当应用程序被杀死时,跟踪日志将被暂停(通过最近的应用程序)。(OsmAnd背景指示会从Android通知栏中消失)。</string>
|
||||
<string name="add_online_routing_engine">添加在线路线引擎</string>
|
||||
<string name="edit_online_routing_engine">编辑在线路线引擎</string>
|
||||
<string name="shared_string_subtype">子类型</string>
|
||||
<string name="shared_string_vehicle">车辆</string>
|
||||
<string name="shared_string_api_key">API 密钥</string>
|
||||
<string name="shared_string_server_url">服务器 URL</string>
|
||||
<string name="shared_string_enter_param">输入参数</string>
|
||||
<string name="keep_it_empty_if_not">否则请保持空白</string>
|
||||
<string name="test_route_calculation">测试路线计算</string>
|
||||
<string name="routing_engine_vehicle_type_driving">驾驶</string>
|
||||
<string name="routing_engine_vehicle_type_car">汽车</string>
|
||||
<string name="copy_address">复制地址</string>
|
||||
<string name="online_routing_engine">在线路线引擎</string>
|
||||
<string name="online_routing_engines">在线路线引擎</string>
|
||||
<string name="shared_string_folders">文件夹</string>
|
||||
<string name="select_folder">选择文件夹</string>
|
||||
<string name="select_folder_descr">选择文件夹或添加新文件夹</string>
|
||||
<string name="upload_to_openstreetmap">上传到 OpenStreetMap</string>
|
||||
<string name="edit_track">编辑轨迹</string>
|
||||
<string name="rename_track">重命名轨迹</string>
|
||||
<string name="change_folder">更改文件夹</string>
|
||||
<string name="shared_string_sec">秒</string>
|
||||
<string name="announcement_time_passing">通过</string>
|
||||
<string name="announcement_time_prepare_long">长时间准备</string>
|
||||
<string name="announcement_time_prepare">准备</string>
|
||||
<string name="announcement_time_off_route">偏离路线</string>
|
||||
<string name="announcement_time_arrive">到达目的地</string>
|
||||
<string name="shared_string_turn">转弯</string>
|
||||
<string name="announcement_time_intervals">时间和距离间隔</string>
|
||||
<string name="announcement_time_descr">不同语音提示的公告时间取决于提示类型、当前导航速度和默认导航速度。</string>
|
||||
<string name="announcement_time_title">公告时间</string>
|
||||
<string name="start_recording">开始录制</string>
|
||||
<string name="show_track_on_map">在地图上显示轨迹</string>
|
||||
<string name="routing_engine_vehicle_type_wheelchair">轮椅</string>
|
||||
<string name="routing_engine_vehicle_type_hiking">徒步</string>
|
||||
<string name="routing_engine_vehicle_type_walking">步行</string>
|
||||
<string name="routing_engine_vehicle_type_cycling_electric">电动自行车</string>
|
||||
<string name="routing_engine_vehicle_type_cycling_mountain">山地自行车</string>
|
||||
<string name="routing_engine_vehicle_type_cycling_road">公路自行车</string>
|
||||
<string name="routing_engine_vehicle_type_hgv">重型货车</string>
|
||||
<string name="routing_engine_vehicle_type_small_truck">小型卡车</string>
|
||||
<string name="routing_engine_vehicle_type_truck">卡车</string>
|
||||
<string name="routing_engine_vehicle_type_scooter">踏板车</string>
|
||||
<string name="routing_engine_vehicle_type_racingbike">竞速自行车</string>
|
||||
<string name="routing_engine_vehicle_type_mtb">山地车</string>
|
||||
<string name="message_server_error">服务器错误:%1$s</string>
|
||||
<string name="delete_online_routing_engine">删除这个在线路线引擎?</string>
|
||||
<string name="message_name_is_already_exists">名字已经存在</string>
|
||||
<string name="context_menu_read_full">阅读全文</string>
|
||||
<string name="context_menu_edit_descr">编辑描述</string>
|
||||
<string name="delete_waypoints">删除航点</string>
|
||||
<string name="copy_to_map_markers">复制到地图标记</string>
|
||||
<string name="copy_to_map_favorites">复制到收藏</string>
|
||||
<string name="upload_photo">上传中</string>
|
||||
<string name="upload_photo_completed">上传完成</string>
|
||||
<string name="uploading_count">正在上传 %1$d,共 %2$d</string>
|
||||
<string name="toast_select_edits_for_upload">选择要上传的编辑</string>
|
||||
<string name="uploaded_count">已上传 %1$d,共 %2$d</string>
|
||||
<string name="hillshade_slope_contour_lines">山体阴影/斜坡/等高线</string>
|
||||
<string name="open_place_reviews_plugin_description">OpenPlaceReviews 是一个社区驱动的项目,关于公共场所,如餐馆,酒店,博物馆,航点。它收集了所有关于它们的公共信息,如照片、评论、链接到其他系统的 OpenStreetMap、维基百科。
|
||||
\n
|
||||
\n所有 OpenPlaceReview 的数据都是开放的,所有人都可以使用:http://openplacereviews.org/data。
|
||||
\n
|
||||
\n你可以在以下网站阅读更多信息:http://openplacereviews.org</string>
|
||||
<string name="open_place_reviews">OpenPlaceReviews</string>
|
||||
<string name="opr_use_dev_url">使用 test.openplacereviews.org</string>
|
||||
<string name="login_open_place_reviews">登录 OpenPlaceReviews</string>
|
||||
<string name="activity_type_winter_name">冬季</string>
|
||||
<string name="activity_type_snowmobile_name">雪地摩托</string>
|
||||
<string name="activity_type_riding_name">骑行</string>
|
||||
<string name="activity_type_cycling_name">骑车</string>
|
||||
<string name="activity_type_hiking_name">健行</string>
|
||||
<string name="activity_type_running_name">跑步</string>
|
||||
<string name="activity_type_walking_name">步行</string>
|
||||
<string name="activity_type_motorbike_name">摩托车</string>
|
||||
</resources>
|
|
@ -36,6 +36,7 @@ import net.osmand.data.LatLon;
|
|||
import net.osmand.data.QuadRect;
|
||||
import net.osmand.data.RotatedTileBox;
|
||||
import net.osmand.plus.GpxSelectionHelper.GpxDisplayItem;
|
||||
import net.osmand.plus.GpxSelectionHelper.SelectedGpxFile;
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.UiUtilities;
|
||||
|
@ -66,6 +67,8 @@ public class TrackDetailsMenu {
|
|||
@Nullable
|
||||
private GpxDisplayItem gpxItem;
|
||||
@Nullable
|
||||
private SelectedGpxFile selectedGpxFile;
|
||||
@Nullable
|
||||
private TrackDetailsBarController toolbarController;
|
||||
@Nullable
|
||||
private TrkSegment segment;
|
||||
|
@ -101,6 +104,15 @@ public class TrackDetailsMenu {
|
|||
this.gpxItem = gpxItem;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public SelectedGpxFile getSelectedGpxFile() {
|
||||
return selectedGpxFile;
|
||||
}
|
||||
|
||||
public void setSelectedGpxFile(@NonNull SelectedGpxFile selectedGpxFile) {
|
||||
this.selectedGpxFile = selectedGpxFile;
|
||||
}
|
||||
|
||||
public boolean isVisible() {
|
||||
return visible;
|
||||
}
|
||||
|
@ -539,7 +551,7 @@ public class TrackDetailsMenu {
|
|||
}
|
||||
}
|
||||
|
||||
public boolean shouldShowXAxisPoints () {
|
||||
public boolean shouldShowXAxisPoints() {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -707,18 +719,19 @@ public class TrackDetailsMenu {
|
|||
if (gpxItem.chartTypes != null && gpxItem.chartTypes.length > 0) {
|
||||
for (int i = 0; i < gpxItem.chartTypes.length; i++) {
|
||||
OrderedLineDataSet dataSet = null;
|
||||
boolean withoutGaps = selectedGpxFile != null && (!selectedGpxFile.isJoinSegments() && gpxItem.isGeneralTrack());
|
||||
switch (gpxItem.chartTypes[i]) {
|
||||
case ALTITUDE:
|
||||
dataSet = GpxUiHelper.createGPXElevationDataSet(app, chart, analysis,
|
||||
gpxItem.chartAxisType, false, true, false);
|
||||
gpxItem.chartAxisType, false, true, withoutGaps);
|
||||
break;
|
||||
case SPEED:
|
||||
dataSet = GpxUiHelper.createGPXSpeedDataSet(app, chart, analysis,
|
||||
gpxItem.chartAxisType, gpxItem.chartTypes.length > 1, true, false);
|
||||
gpxItem.chartAxisType, gpxItem.chartTypes.length > 1, true, withoutGaps);
|
||||
break;
|
||||
case SLOPE:
|
||||
dataSet = GpxUiHelper.createGPXSlopeDataSet(app, chart, analysis,
|
||||
gpxItem.chartAxisType, null, gpxItem.chartTypes.length > 1, true, false);
|
||||
gpxItem.chartAxisType, null, gpxItem.chartTypes.length > 1, true, withoutGaps);
|
||||
break;
|
||||
}
|
||||
if (dataSet != null) {
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
package net.osmand.plus.track;
|
||||
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Handler;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.ColorInt;
|
||||
|
@ -12,21 +12,19 @@ import androidx.annotation.ColorRes;
|
|||
import androidx.annotation.DrawableRes;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.widget.AppCompatImageView;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import net.osmand.AndroidUtils;
|
||||
import net.osmand.GPXUtilities.GPXFile;
|
||||
import net.osmand.GPXUtilities.GPXTrackAnalysis;
|
||||
import net.osmand.plus.GpxSelectionHelper.GpxDisplayGroup;
|
||||
import net.osmand.plus.GpxSelectionHelper.GpxDisplayItem;
|
||||
import net.osmand.plus.GpxSelectionHelper.GpxDisplayItemType;
|
||||
import net.osmand.plus.GpxSelectionHelper.SelectedGpxFile;
|
||||
import net.osmand.plus.OsmAndFormatter;
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.UiUtilities;
|
||||
import net.osmand.plus.helpers.AndroidUiHelper;
|
||||
import net.osmand.plus.helpers.GpxUiHelper;
|
||||
import net.osmand.plus.helpers.GpxUiHelper.GPXDataSetType;
|
||||
import net.osmand.plus.myplaces.SegmentActionsListener;
|
||||
import net.osmand.plus.widgets.TextViewEx;
|
||||
|
@ -40,101 +38,134 @@ public class GpxBlockStatisticsBuilder {
|
|||
private final OsmandApplication app;
|
||||
private RecyclerView blocksView;
|
||||
private final SelectedGpxFile selectedGpxFile;
|
||||
private final TrackDisplayHelper displayHelper;
|
||||
private final GpxDisplayItemType[] filterTypes = {GpxDisplayItemType.TRACK_SEGMENT};
|
||||
|
||||
public GpxBlockStatisticsBuilder(OsmandApplication app, SelectedGpxFile selectedGpxFile, TrackDisplayHelper displayHelper) {
|
||||
private BlockStatisticsAdapter adapter;
|
||||
private final List<StatBlock> items = new ArrayList<>();
|
||||
|
||||
private final Handler handler = new Handler();
|
||||
private Runnable updatingItems;
|
||||
private boolean updateRunning = false;
|
||||
|
||||
public GpxBlockStatisticsBuilder(OsmandApplication app, SelectedGpxFile selectedGpxFile) {
|
||||
this.app = app;
|
||||
this.selectedGpxFile = selectedGpxFile;
|
||||
this.displayHelper = displayHelper;
|
||||
}
|
||||
|
||||
public void setBlocksView(RecyclerView blocksView) {
|
||||
this.blocksView = blocksView;
|
||||
}
|
||||
|
||||
private GPXTrackAnalysis getAnalysis() {
|
||||
return selectedGpxFile.getTrackAnalysis(app);
|
||||
private GpxDisplayItem getDisplayItem(GPXFile gpxFile) {
|
||||
return GpxUiHelper.makeGpxDisplayItem(app, gpxFile);
|
||||
}
|
||||
|
||||
private GPXFile getGPXFile() {
|
||||
return selectedGpxFile.getGpxFile();
|
||||
}
|
||||
|
||||
public void initStatBlocks(SegmentActionsListener actionsListener, @ColorInt int activeColor, boolean nightMode) {
|
||||
GPXTrackAnalysis analysis = getAnalysis();
|
||||
float totalDistance = analysis.totalDistance;
|
||||
float timeSpan = analysis.timeSpan;
|
||||
String asc = OsmAndFormatter.getFormattedAlt(analysis.diffElevationUp, app);
|
||||
String desc = OsmAndFormatter.getFormattedAlt(analysis.diffElevationDown, app);
|
||||
String avg = OsmAndFormatter.getFormattedSpeed(analysis.avgSpeed, app);
|
||||
String max = OsmAndFormatter.getFormattedSpeed(analysis.maxSpeed, app);
|
||||
List<StatBlock> items = new ArrayList<>();
|
||||
|
||||
prepareData(analysis, items, app.getString(R.string.distance), OsmAndFormatter.getFormattedDistance(totalDistance, app),
|
||||
R.drawable.ic_action_track_16, R.color.icon_color_default_light, GPXDataSetType.ALTITUDE, GPXDataSetType.SPEED, ItemType.ITEM_DISTANCE);
|
||||
prepareData(analysis, items, app.getString(R.string.altitude_ascent), asc,
|
||||
R.drawable.ic_action_arrow_up_16, R.color.gpx_chart_red, GPXDataSetType.SLOPE, null, ItemType.ITEM_ALTITUDE);
|
||||
prepareData(analysis, items, app.getString(R.string.altitude_descent), desc,
|
||||
R.drawable.ic_action_arrow_down_16, R.color.gpx_pale_green, GPXDataSetType.ALTITUDE, GPXDataSetType.SLOPE, ItemType.ITEM_ALTITUDE);
|
||||
prepareData(analysis, items, app.getString(R.string.average_speed), avg,
|
||||
R.drawable.ic_action_speed_16, R.color.icon_color_default_light, GPXDataSetType.SPEED, null, ItemType.ITEM_SPEED);
|
||||
prepareData(analysis, items, app.getString(R.string.max_speed), max,
|
||||
R.drawable.ic_action_max_speed_16, R.color.icon_color_default_light, GPXDataSetType.SPEED, null, ItemType.ITEM_SPEED);
|
||||
prepareData(analysis, items, app.getString(R.string.shared_string_time_span),
|
||||
Algorithms.formatDuration((int) (timeSpan / 1000), app.accessibilityEnabled()),
|
||||
R.drawable.ic_action_time_span_16, R.color.icon_color_default_light, GPXDataSetType.SPEED, null, ItemType.ITEM_TIME);
|
||||
|
||||
if (Algorithms.isEmpty(items)) {
|
||||
AndroidUiHelper.updateVisibility(blocksView, false);
|
||||
} else {
|
||||
final BlockStatisticsAdapter sbAdapter = new BlockStatisticsAdapter(items, actionsListener, activeColor, nightMode);
|
||||
initItems();
|
||||
boolean isNotEmpty = !Algorithms.isEmpty(items);
|
||||
AndroidUiHelper.updateVisibility(blocksView, isNotEmpty);
|
||||
if (isNotEmpty) {
|
||||
adapter = new BlockStatisticsAdapter(getDisplayItem(getGPXFile()), actionsListener, activeColor, nightMode);
|
||||
adapter.setItems(items);
|
||||
blocksView.setLayoutManager(new LinearLayoutManager(app, LinearLayoutManager.HORIZONTAL, false));
|
||||
blocksView.setAdapter(sbAdapter);
|
||||
blocksView.setAdapter(adapter);
|
||||
}
|
||||
}
|
||||
|
||||
public void prepareData(GPXTrackAnalysis analysis, List<StatBlock> listItems, String title,
|
||||
String value, @DrawableRes int imageResId, @ColorRes int imageColorId,
|
||||
public void stopUpdatingStatBlocks() {
|
||||
handler.removeCallbacks(updatingItems);
|
||||
updateRunning = false;
|
||||
}
|
||||
|
||||
public void runUpdatingStatBlocks() {
|
||||
updatingItems = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (adapter != null) {
|
||||
initItems();
|
||||
adapter.setItems(items);
|
||||
AndroidUiHelper.updateVisibility(blocksView, !Algorithms.isEmpty(items));
|
||||
}
|
||||
int interval = app.getSettings().SAVE_GLOBAL_TRACK_INTERVAL.get();
|
||||
handler.postDelayed(this, Math.max(1000, interval));
|
||||
}
|
||||
};
|
||||
updateRunning = handler.post(updatingItems);
|
||||
}
|
||||
|
||||
public void initItems() {
|
||||
GPXFile gpxFile = getGPXFile();
|
||||
GpxDisplayItem gpxDisplayItem = null;
|
||||
GPXTrackAnalysis analysis = null;
|
||||
boolean withoutGaps = true;
|
||||
if (gpxFile.tracks.size() > 0) {
|
||||
gpxDisplayItem = getDisplayItem(gpxFile);
|
||||
}
|
||||
if (gpxDisplayItem != null) {
|
||||
analysis = gpxDisplayItem.analysis;
|
||||
withoutGaps = !selectedGpxFile.isJoinSegments() && gpxDisplayItem.isGeneralTrack();
|
||||
}
|
||||
if (analysis != null) {
|
||||
float totalDistance = withoutGaps ? analysis.totalDistanceWithoutGaps : analysis.totalDistance;
|
||||
float timeSpan = withoutGaps ? analysis.timeSpanWithoutGaps : analysis.timeSpan;
|
||||
String asc = OsmAndFormatter.getFormattedAlt(analysis.diffElevationUp, app);
|
||||
String desc = OsmAndFormatter.getFormattedAlt(analysis.diffElevationDown, app);
|
||||
String avg = OsmAndFormatter.getFormattedSpeed(analysis.avgSpeed, app);
|
||||
String max = OsmAndFormatter.getFormattedSpeed(analysis.maxSpeed, app);
|
||||
|
||||
items.clear();
|
||||
prepareData(analysis, app.getString(R.string.distance), OsmAndFormatter.getFormattedDistance(totalDistance, app),
|
||||
R.drawable.ic_action_track_16, R.color.icon_color_default_light, GPXDataSetType.ALTITUDE, GPXDataSetType.SPEED, ItemType.ITEM_DISTANCE);
|
||||
prepareData(analysis, app.getString(R.string.altitude_ascent), asc,
|
||||
R.drawable.ic_action_arrow_up_16, R.color.gpx_chart_red, GPXDataSetType.SLOPE, null, ItemType.ITEM_ALTITUDE);
|
||||
prepareData(analysis, app.getString(R.string.altitude_descent), desc,
|
||||
R.drawable.ic_action_arrow_down_16, R.color.gpx_pale_green, GPXDataSetType.ALTITUDE, GPXDataSetType.SLOPE, ItemType.ITEM_ALTITUDE);
|
||||
prepareData(analysis, app.getString(R.string.average_speed), avg,
|
||||
R.drawable.ic_action_speed_16, R.color.icon_color_default_light, GPXDataSetType.SPEED, null, ItemType.ITEM_SPEED);
|
||||
prepareData(analysis, app.getString(R.string.max_speed), max,
|
||||
R.drawable.ic_action_max_speed_16, R.color.icon_color_default_light, GPXDataSetType.SPEED, null, ItemType.ITEM_SPEED);
|
||||
prepareData(analysis, app.getString(R.string.shared_string_time_span),
|
||||
Algorithms.formatDuration((int) (timeSpan / 1000), app.accessibilityEnabled()),
|
||||
R.drawable.ic_action_time_span_16, R.color.icon_color_default_light, GPXDataSetType.SPEED, null, ItemType.ITEM_TIME);
|
||||
}
|
||||
}
|
||||
|
||||
public void prepareData(GPXTrackAnalysis analysis, String title, String value,
|
||||
@DrawableRes int imageResId, @ColorRes int imageColorId,
|
||||
GPXDataSetType firstType, GPXDataSetType secondType, ItemType itemType) {
|
||||
StatBlock statBlock = new StatBlock(title, value, imageResId, imageColorId, firstType, secondType, itemType);
|
||||
switch (statBlock.itemType) {
|
||||
case ITEM_DISTANCE: {
|
||||
if (analysis.totalDistance != 0f) {
|
||||
listItems.add(statBlock);
|
||||
items.add(statBlock);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ITEM_ALTITUDE: {
|
||||
if (analysis.hasElevationData) {
|
||||
listItems.add(statBlock);
|
||||
items.add(statBlock);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ITEM_SPEED: {
|
||||
if (analysis.isSpeedSpecified()) {
|
||||
listItems.add(statBlock);
|
||||
items.add(statBlock);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ITEM_TIME: {
|
||||
if (analysis.hasSpeedData) {
|
||||
listItems.add(statBlock);
|
||||
items.add(statBlock);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void setImageDrawable(ImageView iv, @DrawableRes Integer resId, @ColorRes int color) {
|
||||
Drawable icon = resId != null ? app.getUIUtilities().getIcon(resId, color)
|
||||
: UiUtilities.tintDrawable(iv.getDrawable(), getResolvedColor(color));
|
||||
iv.setImageDrawable(icon);
|
||||
}
|
||||
|
||||
@ColorInt
|
||||
protected int getResolvedColor(@ColorRes int colorId) {
|
||||
return ContextCompat.getColor(app, colorId);
|
||||
}
|
||||
|
||||
public class StatBlock {
|
||||
|
||||
private final String title;
|
||||
private final String value;
|
||||
private final int imageResId;
|
||||
|
@ -164,14 +195,16 @@ public class GpxBlockStatisticsBuilder {
|
|||
|
||||
private class BlockStatisticsAdapter extends RecyclerView.Adapter<BlockStatisticsViewHolder> {
|
||||
|
||||
private final List<StatBlock> items = new ArrayList<>();
|
||||
private final GpxDisplayItem displayItem;
|
||||
private final SegmentActionsListener actionsListener;
|
||||
@ColorInt
|
||||
private final int activeColor;
|
||||
private final List<StatBlock> statBlocks;
|
||||
private final boolean nightMode;
|
||||
private final SegmentActionsListener actionsListener;
|
||||
|
||||
public BlockStatisticsAdapter(List<StatBlock> statBlocks, SegmentActionsListener actionsListener, @ColorInt int activeColor, boolean nightMode) {
|
||||
this.statBlocks = statBlocks;
|
||||
public BlockStatisticsAdapter(GpxDisplayItem displayItem, SegmentActionsListener actionsListener,
|
||||
@ColorInt int activeColor, boolean nightMode) {
|
||||
this.displayItem = displayItem;
|
||||
this.actionsListener = actionsListener;
|
||||
this.activeColor = activeColor;
|
||||
this.nightMode = nightMode;
|
||||
|
@ -179,7 +212,7 @@ public class GpxBlockStatisticsBuilder {
|
|||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return statBlocks.size();
|
||||
return items.size();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
|
@ -192,46 +225,44 @@ public class GpxBlockStatisticsBuilder {
|
|||
|
||||
@Override
|
||||
public void onBindViewHolder(BlockStatisticsViewHolder holder, int position) {
|
||||
final StatBlock item = statBlocks.get(position);
|
||||
final StatBlock item = items.get(position);
|
||||
holder.valueText.setText(item.value);
|
||||
holder.titleText.setText(item.title);
|
||||
if (updateRunning) {
|
||||
holder.titleText.setWidth(app.getResources().getDimensionPixelSize(R.dimen.map_route_buttons_width));
|
||||
}
|
||||
holder.valueText.setTextColor(activeColor);
|
||||
holder.titleText.setTextColor(app.getResources().getColor(R.color.text_color_secondary_light));
|
||||
holder.itemView.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
List<GpxDisplayGroup> groups = displayHelper.getDisplayGroups(filterTypes);
|
||||
GpxDisplayGroup group = null;
|
||||
for (GpxDisplayGroup g : groups) {
|
||||
if (g.isGeneralTrack()) {
|
||||
group = g;
|
||||
}
|
||||
}
|
||||
if (group == null && !groups.isEmpty()) {
|
||||
group = groups.get(0);
|
||||
}
|
||||
if (group != null) {
|
||||
GpxDisplayItem displayItem = group.getModifiableList().get(0);
|
||||
if (displayItem != null && displayItem.analysis != null) {
|
||||
ArrayList<GPXDataSetType> list = new ArrayList<>();
|
||||
if (displayItem.analysis.hasElevationData || displayItem.analysis.isSpeedSpecified() || displayItem.analysis.hasSpeedData) {
|
||||
if (item.firstType != null) {
|
||||
list.add(item.firstType);
|
||||
}
|
||||
if (item.secondType != null) {
|
||||
list.add(item.secondType);
|
||||
}
|
||||
GPXTrackAnalysis analysis = displayItem != null ? displayItem.analysis : null;
|
||||
if (analysis != null) {
|
||||
ArrayList<GPXDataSetType> list = new ArrayList<>();
|
||||
if (analysis.hasElevationData || analysis.isSpeedSpecified() || analysis.hasSpeedData) {
|
||||
if (item.firstType != null) {
|
||||
list.add(item.firstType);
|
||||
}
|
||||
if (item.secondType != null) {
|
||||
list.add(item.secondType);
|
||||
}
|
||||
displayItem.chartTypes = list.size() > 0 ? list.toArray(new GPXDataSetType[0]) : null;
|
||||
displayItem.locationOnMap = displayItem.locationStart;
|
||||
actionsListener.openAnalyzeOnMap(displayItem);
|
||||
}
|
||||
displayItem.chartTypes = list.size() > 0 ? list.toArray(new GPXDataSetType[0]) : null;
|
||||
displayItem.locationOnMap = displayItem.locationStart;
|
||||
actionsListener.openAnalyzeOnMap(displayItem);
|
||||
}
|
||||
}
|
||||
});
|
||||
setImageDrawable(holder.imageView, item.imageResId, item.imageColorId);
|
||||
Drawable icon = app.getUIUtilities().getIcon(item.imageResId, item.imageColorId);
|
||||
holder.imageView.setImageDrawable(icon);
|
||||
AndroidUtils.setBackgroundColor(app, holder.divider, nightMode, R.color.divider_color_light, R.color.divider_color_dark);
|
||||
AndroidUiHelper.updateVisibility(holder.divider, position != statBlocks.size() - 1);
|
||||
AndroidUiHelper.updateVisibility(holder.divider, position != items.size() - 1);
|
||||
}
|
||||
|
||||
public void setItems(List<StatBlock> items) {
|
||||
this.items.clear();
|
||||
this.items.addAll(items);
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -43,12 +43,11 @@ public class OverviewCard extends BaseCard {
|
|||
private final SelectedGpxFile selectedGpxFile;
|
||||
private final GpxBlockStatisticsBuilder blockStatisticsBuilder;
|
||||
|
||||
public OverviewCard(@NonNull MapActivity mapActivity, @NonNull TrackDisplayHelper displayHelper,
|
||||
@NonNull SegmentActionsListener actionsListener, SelectedGpxFile selectedGpxFile) {
|
||||
public OverviewCard(@NonNull MapActivity mapActivity, @NonNull SegmentActionsListener actionsListener, SelectedGpxFile selectedGpxFile) {
|
||||
super(mapActivity);
|
||||
this.actionsListener = actionsListener;
|
||||
this.selectedGpxFile = selectedGpxFile;
|
||||
blockStatisticsBuilder = new GpxBlockStatisticsBuilder(app, selectedGpxFile, displayHelper);
|
||||
blockStatisticsBuilder = new GpxBlockStatisticsBuilder(app, selectedGpxFile);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -326,7 +326,7 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
|
|||
}
|
||||
headerContainer.addView(overviewCard.getView());
|
||||
} else {
|
||||
overviewCard = new OverviewCard(getMapActivity(), displayHelper, this, selectedGpxFile);
|
||||
overviewCard = new OverviewCard(getMapActivity(), this, selectedGpxFile);
|
||||
overviewCard.setListener(this);
|
||||
headerContainer.addView(overviewCard.build(getMapActivity()));
|
||||
}
|
||||
|
@ -760,7 +760,7 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
|
|||
segment = segments.get(0);
|
||||
}
|
||||
}
|
||||
GpxDisplayItemType[] filterTypes = new GpxDisplayItemType[] {GpxDisplayItemType.TRACK_SEGMENT};
|
||||
GpxDisplayItemType[] filterTypes = new GpxDisplayItemType[]{GpxDisplayItemType.TRACK_SEGMENT};
|
||||
List<GpxDisplayItem> items = TrackDisplayHelper.flatten(displayHelper.getOriginalGroups(filterTypes));
|
||||
if (segment != null && !Algorithms.isEmpty(items)) {
|
||||
SplitSegmentDialogFragment.showInstance(fragmentManager, displayHelper, items.get(0), segment);
|
||||
|
@ -1013,6 +1013,7 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
|
|||
public void openAnalyzeOnMap(GpxDisplayItem gpxItem) {
|
||||
TrackDetailsMenu trackDetailsMenu = getMapActivity().getTrackDetailsMenu();
|
||||
trackDetailsMenu.setGpxItem(gpxItem);
|
||||
trackDetailsMenu.setSelectedGpxFile(selectedGpxFile);
|
||||
trackDetailsMenu.show();
|
||||
hide();
|
||||
}
|
||||
|
@ -1110,7 +1111,7 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card
|
|||
@Override
|
||||
public void gpxSavingFinished(Exception errorMessage) {
|
||||
if (selectedGpxFile != null) {
|
||||
List<GpxDisplayGroup> groups = displayHelper.getDisplayGroups(new GpxDisplayItemType[] {GpxDisplayItemType.TRACK_SEGMENT});
|
||||
List<GpxDisplayGroup> groups = displayHelper.getDisplayGroups(new GpxDisplayItemType[]{GpxDisplayItemType.TRACK_SEGMENT});
|
||||
selectedGpxFile.setDisplayGroups(groups, app);
|
||||
selectedGpxFile.processPoints(app);
|
||||
}
|
||||
|
|
|
@ -169,6 +169,26 @@ public class TravelArticle {
|
|||
return new String[]{md5.substring(0, 1), md5.substring(0, 2)};
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
TravelArticle that = (TravelArticle) o;
|
||||
return TravelArticleIdentifier.areLatLonEqual(that.lat, that.lon, lat, lon) &&
|
||||
Algorithms.objectEquals(file, that.file) &&
|
||||
Algorithms.stringsEqual(routeId, that.routeId) &&
|
||||
Algorithms.stringsEqual(routeSource, that.routeSource);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Algorithms.hash(file, lat, lon, routeId, routeSource);
|
||||
}
|
||||
|
||||
public static class TravelArticleIdentifier implements Parcelable {
|
||||
@Nullable File file;
|
||||
double lat;
|
||||
|
@ -249,7 +269,7 @@ public class TravelArticle {
|
|||
return Algorithms.hash(file, lat, lon, routeId, routeSource);
|
||||
}
|
||||
|
||||
private static boolean areLatLonEqual(double lat1, double lon1, double lat2, double lon2) {
|
||||
public static boolean areLatLonEqual(double lat1, double lon1, double lat2, double lon2) {
|
||||
boolean latEqual = (Double.isNaN(lat1) && Double.isNaN(lat2)) || Math.abs(lat1 - lat2) < 0.00001;
|
||||
boolean lonEqual = (Double.isNaN(lon1) && Double.isNaN(lon2)) || Math.abs(lon1 - lon2) < 0.00001;
|
||||
return latEqual && lonEqual;
|
||||
|
|
|
@ -174,7 +174,7 @@ public class TravelDbHelper implements TravelHelper {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void initializeDataToDisplay() {
|
||||
public void initializeDataToDisplay(boolean resetData) {
|
||||
localDataHelper.refreshCachedData();
|
||||
loadPopularArticles();
|
||||
}
|
||||
|
@ -292,7 +292,7 @@ public class TravelDbHelper implements TravelHelper {
|
|||
}
|
||||
String LANG_WHERE = " WHERE " + ARTICLES_COL_LANG + " = '" + language + "'";
|
||||
SQLiteCursor cursor = conn.rawQuery(POP_ARTICLES_TABLE_SELECT + LANG_WHERE, null);
|
||||
if(cursor == null) {
|
||||
if (cursor == null) {
|
||||
return popularArticles;
|
||||
}
|
||||
// read popular articles
|
||||
|
@ -549,13 +549,13 @@ public class TravelDbHelper implements TravelHelper {
|
|||
|
||||
@Override
|
||||
@Nullable
|
||||
public TravelArticle getArticleById(@NonNull TravelArticleIdentifier articleId, @NonNull String lang, boolean readGpx, @Nullable GpxReadCallback callback) {
|
||||
public TravelArticle getArticleById(@NonNull TravelArticleIdentifier articleId, @Nullable String lang, boolean readGpx, @Nullable GpxReadCallback callback) {
|
||||
TravelArticle res = null;
|
||||
SQLiteConnection conn = openConnection();
|
||||
String routeId = articleId.routeId;
|
||||
if (conn != null && !Algorithms.isEmpty(routeId)) {
|
||||
if (conn != null && !Algorithms.isEmpty(routeId) && lang != null) {
|
||||
SQLiteCursor cursor = conn.rawQuery(ARTICLES_TABLE_SELECT + " WHERE " + ARTICLES_COL_TRIP_ID + " = ? AND "
|
||||
+ ARTICLES_COL_LANG + " = ?", new String[] { routeId, lang });
|
||||
+ ARTICLES_COL_LANG + " = ?", new String[]{routeId, lang});
|
||||
if (cursor != null) {
|
||||
if (cursor.moveToFirst()) {
|
||||
res = readArticle(cursor);
|
||||
|
|
|
@ -3,7 +3,6 @@ package net.osmand.plus.wikivoyage.data;
|
|||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import net.osmand.GPXUtilities;
|
||||
import net.osmand.GPXUtilities.GPXFile;
|
||||
import net.osmand.data.LatLon;
|
||||
import net.osmand.data.QuadRect;
|
||||
|
@ -18,6 +17,7 @@ public interface TravelHelper {
|
|||
|
||||
interface GpxReadCallback {
|
||||
void onGpxFileReading();
|
||||
|
||||
void onGpxFileRead(@Nullable GPXFile gpxFile);
|
||||
}
|
||||
|
||||
|
@ -25,7 +25,7 @@ public interface TravelHelper {
|
|||
|
||||
void initializeDataOnAppStartup();
|
||||
|
||||
void initializeDataToDisplay();
|
||||
void initializeDataToDisplay(boolean resetData);
|
||||
|
||||
boolean isAnyTravelBookPresent();
|
||||
|
||||
|
@ -39,7 +39,7 @@ public interface TravelHelper {
|
|||
Map<WikivoyageSearchResult, List<WikivoyageSearchResult>> getNavigationMap(@NonNull TravelArticle article);
|
||||
|
||||
@Nullable
|
||||
TravelArticle getArticleById(@NonNull TravelArticleIdentifier articleId, @NonNull String lang, boolean readGpx, @Nullable GpxReadCallback callback);
|
||||
TravelArticle getArticleById(@NonNull TravelArticleIdentifier articleId, @Nullable String lang, boolean readGpx, @Nullable GpxReadCallback callback);
|
||||
|
||||
@Nullable
|
||||
TravelArticle getArticleByTitle(@NonNull String title, @NonNull String lang, boolean readGpx, @Nullable GpxReadCallback callback);
|
||||
|
|
|
@ -69,9 +69,7 @@ public class TravelObfHelper implements TravelHelper {
|
|||
public static final String ROUTE_ARTICLE = "route_article";
|
||||
public static final String ROUTE_ARTICLE_POINT = "route_article_point";
|
||||
public static final String ROUTE_TRACK = "route_track";
|
||||
public static final int POPULAR_ARTICLES_SEARCH_RADIUS = 100000;
|
||||
public static final int ARTICLE_SEARCH_RADIUS = 50000;
|
||||
public static final int GPX_TRACKS_SEARCH_RADIUS = 10000;
|
||||
public static final int MAX_POPULAR_ARTICLES_COUNT = 30;
|
||||
public static final String REF_TAG = "ref";
|
||||
public static final String NAME_TAG = "name";
|
||||
|
@ -82,6 +80,9 @@ public class TravelObfHelper implements TravelHelper {
|
|||
private List<TravelArticle> popularArticles = new ArrayList<>();
|
||||
private final Map<TravelArticleIdentifier, Map<String, TravelArticle>> cachedArticles = new ConcurrentHashMap<>();
|
||||
private final TravelLocalDataHelper localDataHelper;
|
||||
private int searchRadius = ARTICLE_SEARCH_RADIUS;
|
||||
private int foundAmenitiesIndex = 0;
|
||||
private final List<Pair<File, Amenity>> foundAmenities = new ArrayList<>();
|
||||
|
||||
public TravelObfHelper(OsmandApplication app) {
|
||||
this.app = app;
|
||||
|
@ -99,7 +100,13 @@ public class TravelObfHelper implements TravelHelper {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void initializeDataToDisplay() {
|
||||
public void initializeDataToDisplay(boolean resetData) {
|
||||
if (resetData) {
|
||||
foundAmenities.clear();
|
||||
foundAmenitiesIndex = 0;
|
||||
popularArticles.clear();
|
||||
searchRadius = ARTICLE_SEARCH_RADIUS;
|
||||
}
|
||||
localDataHelper.refreshCachedData();
|
||||
loadPopularArticles();
|
||||
}
|
||||
|
@ -107,38 +114,47 @@ public class TravelObfHelper implements TravelHelper {
|
|||
@NonNull
|
||||
public synchronized List<TravelArticle> loadPopularArticles() {
|
||||
String lang = app.getLanguage();
|
||||
List<TravelArticle> popularArticles = new ArrayList<>();
|
||||
final List<Pair<File, Amenity>> amenities = new ArrayList<>();
|
||||
final LatLon location = app.getMapViewTrackingUtilities().getMapLocation();
|
||||
for (final BinaryMapIndexReader reader : getReaders()) {
|
||||
try {
|
||||
searchAmenity(amenities, location, reader, POPULAR_ARTICLES_SEARCH_RADIUS, -1, ROUTE_ARTICLE);
|
||||
searchAmenity(amenities, location, reader, GPX_TRACKS_SEARCH_RADIUS, 15, ROUTE_TRACK);
|
||||
} catch (Exception e) {
|
||||
LOG.error(e.getMessage(), e);
|
||||
List<TravelArticle> popularArticles = new ArrayList<>(this.popularArticles);
|
||||
if (foundAmenities.size() - foundAmenitiesIndex < MAX_POPULAR_ARTICLES_COUNT) {
|
||||
final LatLon location = app.getMapViewTrackingUtilities().getMapLocation();
|
||||
for (final BinaryMapIndexReader reader : getReaders()) {
|
||||
try {
|
||||
searchAmenity(foundAmenities, location, reader, searchRadius, -1, ROUTE_ARTICLE);
|
||||
searchAmenity(foundAmenities, location, reader, searchRadius / 5, 15, ROUTE_TRACK);
|
||||
} catch (Exception e) {
|
||||
LOG.error(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
if (foundAmenities.size() > 0) {
|
||||
Collections.sort(foundAmenities, new Comparator<Pair<File, Amenity>>() {
|
||||
@Override
|
||||
public int compare(Pair article1, Pair article2) {
|
||||
Amenity amenity1 = (Amenity) article1.second;
|
||||
double d1 = MapUtils.getDistance(amenity1.getLocation(), location)
|
||||
/ (ROUTE_ARTICLE.equals(amenity1.getSubType()) ? 5 : 1);
|
||||
Amenity amenity2 = (Amenity) article2.second;
|
||||
double d2 = MapUtils.getDistance(amenity2.getLocation(), location)
|
||||
/ (ROUTE_ARTICLE.equals(amenity2.getSubType()) ? 5 : 1);
|
||||
return Double.compare(d1, d2);
|
||||
}
|
||||
});
|
||||
}
|
||||
searchRadius *= 2;
|
||||
}
|
||||
|
||||
if (amenities.size() > 0) {
|
||||
Collections.sort(amenities, new Comparator<Pair<File, Amenity>>() {
|
||||
@Override
|
||||
public int compare(Pair article1, Pair article2) {
|
||||
int d1 = (int) (MapUtils.getDistance(((Amenity) article1.second).getLocation(), location));
|
||||
int d2 = (int) (MapUtils.getDistance(((Amenity) article2.second).getLocation(), location));
|
||||
return d1 < d2 ? -1 : (d1 == d2 ? 0 : 1);
|
||||
}
|
||||
});
|
||||
for (Pair<File, Amenity> amenity : amenities) {
|
||||
if (!Algorithms.isEmpty(amenity.second.getName(lang))) {
|
||||
TravelArticle article = cacheTravelArticles(amenity.first, amenity.second, lang, false, null);
|
||||
if (article != null) {
|
||||
popularArticles.add(article);
|
||||
if (popularArticles.size() >= MAX_POPULAR_ARTICLES_COUNT) {
|
||||
break;
|
||||
}
|
||||
int pagesCount = popularArticles.size() / MAX_POPULAR_ARTICLES_COUNT;
|
||||
while (foundAmenitiesIndex < foundAmenities.size() - 1) {
|
||||
Pair<File, Amenity> amenity = foundAmenities.get(foundAmenitiesIndex);
|
||||
if (!Algorithms.isEmpty(amenity.second.getName(lang))) {
|
||||
TravelArticle article = cacheTravelArticles(amenity.first, amenity.second, lang, false, null);
|
||||
if (article != null && !popularArticles.contains(article)) {
|
||||
popularArticles.add(article);
|
||||
if (popularArticles.size() >= (pagesCount + 1) * MAX_POPULAR_ARTICLES_COUNT) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
foundAmenitiesIndex++;
|
||||
}
|
||||
this.popularArticles = popularArticles;
|
||||
return popularArticles;
|
||||
|
@ -616,8 +632,8 @@ public class TravelObfHelper implements TravelHelper {
|
|||
}
|
||||
|
||||
@Override
|
||||
public TravelArticle getArticleById(@NonNull TravelArticleIdentifier articleId, @NonNull String lang,
|
||||
boolean readGpx, @Nullable GpxReadCallback callback) {
|
||||
public TravelArticle getArticleById(@NonNull TravelArticleIdentifier articleId, @Nullable String lang,
|
||||
boolean readGpx, @Nullable GpxReadCallback callback) {
|
||||
TravelArticle article = getCachedArticle(articleId, lang, readGpx, callback);
|
||||
if (article == null) {
|
||||
article = localDataHelper.getSavedArticle(articleId.file, articleId.routeId, lang);
|
||||
|
@ -629,8 +645,8 @@ public class TravelObfHelper implements TravelHelper {
|
|||
}
|
||||
|
||||
@Nullable
|
||||
private TravelArticle getCachedArticle(@NonNull TravelArticleIdentifier articleId, @NonNull String lang,
|
||||
boolean readGpx, @Nullable GpxReadCallback callback) {
|
||||
private TravelArticle getCachedArticle(@NonNull TravelArticleIdentifier articleId, @Nullable String lang,
|
||||
boolean readGpx, @Nullable GpxReadCallback callback) {
|
||||
TravelArticle article = null;
|
||||
Map<String, TravelArticle> articles = cachedArticles.get(articleId);
|
||||
if (articles != null) {
|
||||
|
|
|
@ -18,8 +18,9 @@ import net.osmand.plus.wikivoyage.explore.travelcards.OpenBetaTravelCard;
|
|||
import net.osmand.plus.wikivoyage.explore.travelcards.OpenBetaTravelCard.OpenBetaTravelVH;
|
||||
import net.osmand.plus.wikivoyage.explore.travelcards.StartEditingTravelCard;
|
||||
import net.osmand.plus.wikivoyage.explore.travelcards.StartEditingTravelCard.StartEditingTravelVH;
|
||||
import net.osmand.plus.wikivoyage.explore.travelcards.TravelButtonCard;
|
||||
import net.osmand.plus.wikivoyage.explore.travelcards.TravelButtonCard.TravelButtonVH;
|
||||
import net.osmand.plus.wikivoyage.explore.travelcards.TravelDownloadUpdateCard;
|
||||
import net.osmand.plus.wikivoyage.explore.travelcards.TravelDownloadUpdateCard.DownloadUpdateVH;
|
||||
import net.osmand.plus.wikivoyage.explore.travelcards.TravelGpxCard;
|
||||
import net.osmand.plus.wikivoyage.explore.travelcards.TravelGpxCard.TravelGpxVH;
|
||||
import net.osmand.plus.wikivoyage.explore.travelcards.TravelNeededMapsCard;
|
||||
|
@ -53,12 +54,13 @@ public class ExploreRvAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
|
|||
case TravelGpxCard.TYPE:
|
||||
return new TravelGpxVH(inflate(parent, R.layout.wikivoyage_travel_gpx_card));
|
||||
|
||||
case TravelDownloadUpdateCard.TYPE:
|
||||
return new DownloadUpdateVH(inflate(parent, R.layout.travel_download_update_card));
|
||||
|
||||
case HeaderTravelCard.TYPE:
|
||||
return new HeaderTravelVH(inflate(parent, R.layout.wikivoyage_list_header));
|
||||
|
||||
case TravelButtonCard.TYPE:
|
||||
return new TravelButtonVH(inflate(parent, R.layout.wikivoyage_button_card));
|
||||
|
||||
case TravelDownloadUpdateCard.TYPE:
|
||||
case TravelNeededMapsCard.TYPE:
|
||||
return new NeededMapsVH(inflate(parent, R.layout.travel_needed_maps_card));
|
||||
|
||||
|
@ -115,6 +117,9 @@ public class ExploreRvAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
|
|||
private int getLastArticleItemIndex() {
|
||||
for (int i = items.size() - 1; i > 0; i--) {
|
||||
BaseTravelCard o = items.get(i);
|
||||
if (o instanceof TravelButtonCard) {
|
||||
return 0;
|
||||
}
|
||||
if (o instanceof ArticleTravelCard || o instanceof TravelGpxCard) {
|
||||
return i;
|
||||
}
|
||||
|
@ -205,7 +210,7 @@ public class ExploreRvAdapter extends RecyclerView.Adapter<RecyclerView.ViewHold
|
|||
if(onlyProgress) {
|
||||
TravelDownloadUpdateCard dc = this.downloadCard;
|
||||
if(dc != null) {
|
||||
dc.updateProgresBar();
|
||||
dc.updateView();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package net.osmand.plus.wikivoyage.explore;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.util.Pair;
|
||||
|
@ -37,6 +36,7 @@ import net.osmand.plus.wikivoyage.explore.travelcards.BaseTravelCard;
|
|||
import net.osmand.plus.wikivoyage.explore.travelcards.HeaderTravelCard;
|
||||
import net.osmand.plus.wikivoyage.explore.travelcards.OpenBetaTravelCard;
|
||||
import net.osmand.plus.wikivoyage.explore.travelcards.StartEditingTravelCard;
|
||||
import net.osmand.plus.wikivoyage.explore.travelcards.TravelButtonCard;
|
||||
import net.osmand.plus.wikivoyage.explore.travelcards.TravelDownloadUpdateCard;
|
||||
import net.osmand.plus.wikivoyage.explore.travelcards.TravelGpxCard;
|
||||
import net.osmand.plus.wikivoyage.explore.travelcards.TravelNeededMapsCard;
|
||||
|
@ -46,6 +46,8 @@ import java.lang.ref.WeakReference;
|
|||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static net.osmand.plus.wikivoyage.explore.WikivoyageExploreActivity.*;
|
||||
|
||||
public class ExploreTabFragment extends BaseOsmAndFragment implements DownloadEvents, TravelLocalDataHelper.Listener {
|
||||
|
||||
private static boolean SHOW_TRAVEL_UPDATE_CARD = true;
|
||||
|
@ -63,9 +65,7 @@ public class ExploreTabFragment extends BaseOsmAndFragment implements DownloadEv
|
|||
private DownloadValidationManager downloadManager;
|
||||
@Nullable
|
||||
private IndexItem currentDownloadingIndexItem;
|
||||
@Nullable
|
||||
private IndexItem mainIndexItem;
|
||||
|
||||
private final List<IndexItem> mainIndexItems = new ArrayList<>();
|
||||
private final List<IndexItem> neededIndexItems = new ArrayList<>();
|
||||
private boolean waitForIndexes;
|
||||
|
||||
|
@ -175,17 +175,39 @@ public class ExploreTabFragment extends BaseOsmAndFragment implements DownloadEv
|
|||
if (!Version.isPaidVersion(app) && !OpenBetaTravelCard.isClosed()) {
|
||||
items.add(new OpenBetaTravelCard(activity, nightMode));
|
||||
}
|
||||
List<TravelArticle> popularArticles = app.getTravelHelper().getPopularArticles();
|
||||
final List<TravelArticle> popularArticles = app.getTravelHelper().getPopularArticles();
|
||||
if (!popularArticles.isEmpty()) {
|
||||
items.add(new HeaderTravelCard(app, nightMode, getString(R.string.popular_destinations)));
|
||||
for (TravelArticle article : popularArticles) {
|
||||
if (article instanceof TravelGpx) {
|
||||
items.add(new TravelGpxCard(app, nightMode, (TravelGpx) article, getActivity()));
|
||||
items.add(new TravelGpxCard(app, nightMode, (TravelGpx) article, activity));
|
||||
} else {
|
||||
items.add(new ArticleTravelCard(app, nightMode, article, activity.getSupportFragmentManager()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TravelButtonCard travelButtonCard = new TravelButtonCard(app, nightMode);
|
||||
travelButtonCard.setListener(new TravelNeededMapsCard.CardListener() {
|
||||
@Override
|
||||
public void onPrimaryButtonClick() {
|
||||
if (activity instanceof WikivoyageExploreActivity) {
|
||||
new LoadWikivoyageData((WikivoyageExploreActivity) activity,false).execute();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSecondaryButtonClick() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onIndexItemClick(IndexItem item) {
|
||||
|
||||
}
|
||||
});
|
||||
items.add(travelButtonCard);
|
||||
|
||||
items.add(new StartEditingTravelCard(activity, nightMode));
|
||||
adapter.setItems(items);
|
||||
final DownloadIndexesThread downloadThread = app.getDownloadThread();
|
||||
|
@ -199,17 +221,24 @@ public class ExploreTabFragment extends BaseOsmAndFragment implements DownloadEv
|
|||
}
|
||||
|
||||
private void removeRedundantCards() {
|
||||
if (mainIndexItem != null && mainIndexItem.isDownloaded() && !mainIndexItem.isOutdated()) {
|
||||
removeDownloadUpdateCard();
|
||||
}
|
||||
boolean allMapsDownloaded = true;
|
||||
for (IndexItem item : neededIndexItems) {
|
||||
boolean allTravelGuideDownloaded = true;
|
||||
for (IndexItem item : mainIndexItems) {
|
||||
if (!item.isDownloaded()) {
|
||||
allMapsDownloaded = false;
|
||||
allTravelGuideDownloaded = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (allMapsDownloaded) {
|
||||
if (allTravelGuideDownloaded) {
|
||||
removeDownloadUpdateCard();
|
||||
}
|
||||
boolean neededMapsDownloaded = true;
|
||||
for (IndexItem item : neededIndexItems) {
|
||||
if (!item.isDownloaded()) {
|
||||
neededMapsDownloaded = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (neededMapsDownloaded) {
|
||||
removeNeededMapsCard();
|
||||
}
|
||||
}
|
||||
|
@ -218,8 +247,9 @@ public class ExploreTabFragment extends BaseOsmAndFragment implements DownloadEv
|
|||
new ProcessIndexItemsTask(this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
}
|
||||
|
||||
private void addIndexItemCards(IndexItem mainIndexItem, List<IndexItem> neededIndexItems) {
|
||||
this.mainIndexItem = mainIndexItem;
|
||||
private void addIndexItemCards(List<IndexItem> mainIndexItem, List<IndexItem> neededIndexItems) {
|
||||
this.mainIndexItems.clear();
|
||||
this.mainIndexItems.addAll(mainIndexItem);
|
||||
this.neededIndexItems.clear();
|
||||
this.neededIndexItems.addAll(neededIndexItems);
|
||||
addDownloadUpdateCard();
|
||||
|
@ -228,53 +258,58 @@ public class ExploreTabFragment extends BaseOsmAndFragment implements DownloadEv
|
|||
|
||||
private void addDownloadUpdateCard() {
|
||||
final OsmandApplication app = getMyApplication();
|
||||
if (app != null) {
|
||||
final DownloadIndexesThread downloadThread = app.getDownloadThread();
|
||||
|
||||
boolean outdated = mainIndexItem != null && mainIndexItem.isOutdated();
|
||||
boolean needsDownloading = mainIndexItem != null && !mainIndexItem.isDownloaded();
|
||||
|
||||
if (!app.getTravelHelper().isAnyTravelBookPresent() || needsDownloading || (outdated && SHOW_TRAVEL_UPDATE_CARD)) {
|
||||
boolean showOtherMaps = false;
|
||||
if (needsDownloading) {
|
||||
List<IndexItem> items = downloadThread.getIndexes().getWikivoyageItems();
|
||||
showOtherMaps = items != null && items.size() > 1;
|
||||
if (app != null && !mainIndexItems.isEmpty() && SHOW_TRAVEL_UPDATE_CARD) {
|
||||
boolean outdated = isMapsOutdated();
|
||||
downloadUpdateCard = new TravelDownloadUpdateCard(app, nightMode, mainIndexItems, !outdated);
|
||||
downloadUpdateCard.setListener(new TravelDownloadUpdateCard.CardListener() {
|
||||
@Override
|
||||
public void onPrimaryButtonClick() {
|
||||
if (downloadManager != null) {
|
||||
downloadManager.startDownload(getMyActivity(), getAllItemsForDownload(mainIndexItems));
|
||||
adapter.updateDownloadUpdateCard(false);
|
||||
}
|
||||
}
|
||||
|
||||
downloadUpdateCard = new TravelDownloadUpdateCard(app, nightMode, !outdated);
|
||||
downloadUpdateCard.setShowOtherMapsBtn(showOtherMaps);
|
||||
downloadUpdateCard.setListener(new TravelDownloadUpdateCard.ClickListener() {
|
||||
@Override
|
||||
public void onPrimaryButtonClick() {
|
||||
if (mainIndexItem != null && downloadManager != null) {
|
||||
downloadManager.startDownload(getMyActivity(), mainIndexItem);
|
||||
adapter.updateDownloadUpdateCard(false);
|
||||
}
|
||||
@Override
|
||||
public void onSecondaryButtonClick() {
|
||||
if (downloadUpdateCard.isDownloading()) {
|
||||
app.getDownloadThread().cancelDownload(mainIndexItems);
|
||||
adapter.updateDownloadUpdateCard(false);
|
||||
} else {
|
||||
SHOW_TRAVEL_UPDATE_CARD = false;
|
||||
removeDownloadUpdateCard();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSecondaryButtonClick() {
|
||||
if (downloadUpdateCard.isLoading()) {
|
||||
downloadThread.cancelDownload(mainIndexItem);
|
||||
adapter.updateDownloadUpdateCard(false);
|
||||
} else if (!downloadUpdateCard.isDownload()) {
|
||||
SHOW_TRAVEL_UPDATE_CARD = false;
|
||||
removeDownloadUpdateCard();
|
||||
} else if (downloadUpdateCard.isShowOtherMapsBtn()) {
|
||||
Activity activity = getActivity();
|
||||
if (activity != null) {
|
||||
Intent newIntent = new Intent(activity,
|
||||
((OsmandApplication) activity.getApplication()).getAppCustomization().getDownloadActivity());
|
||||
newIntent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
|
||||
activity.startActivity(newIntent);
|
||||
}
|
||||
@Override
|
||||
public void onIndexItemClick(IndexItem item) {
|
||||
if (item.getType() == DownloadActivityType.WIKIPEDIA_FILE && !Version.isPaidVersion(app)) {
|
||||
FragmentManager fm = getFragmentManager();
|
||||
if (fm != null) {
|
||||
ChoosePlanDialogFragment.showWikipediaInstance(fm);
|
||||
}
|
||||
} else {
|
||||
DownloadIndexesThread downloadThread = app.getDownloadThread();
|
||||
if (downloadThread.isDownloading(item)) {
|
||||
downloadThread.cancelDownload(item);
|
||||
} else if (!item.isDownloaded() && downloadManager != null) {
|
||||
downloadManager.startDownload(getMyActivity(), item);
|
||||
}
|
||||
adapter.updateDownloadUpdateCard(false);
|
||||
}
|
||||
});
|
||||
downloadUpdateCard.setIndexItem(mainIndexItem);
|
||||
adapter.addDownloadUpdateCard(downloadUpdateCard);
|
||||
}
|
||||
});
|
||||
adapter.addDownloadUpdateCard(downloadUpdateCard);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isMapsOutdated() {
|
||||
for (IndexItem indexItem : mainIndexItems) {
|
||||
if (indexItem.isOutdated()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void addNeededMapsCard() {
|
||||
|
@ -285,7 +320,7 @@ public class ExploreTabFragment extends BaseOsmAndFragment implements DownloadEv
|
|||
@Override
|
||||
public void onPrimaryButtonClick() {
|
||||
if (downloadManager != null) {
|
||||
downloadManager.startDownload(getMyActivity(), getAllItemsForDownload());
|
||||
downloadManager.startDownload(getMyActivity(), getAllItemsForDownload(neededIndexItems));
|
||||
adapter.updateNeededMapsCard(false);
|
||||
}
|
||||
}
|
||||
|
@ -323,10 +358,10 @@ public class ExploreTabFragment extends BaseOsmAndFragment implements DownloadEv
|
|||
}
|
||||
}
|
||||
|
||||
private IndexItem[] getAllItemsForDownload() {
|
||||
private IndexItem[] getAllItemsForDownload(List<IndexItem> indexItems) {
|
||||
boolean paidVersion = Version.isPaidVersion(getMyApplication());
|
||||
ArrayList<IndexItem> res = new ArrayList<>();
|
||||
for (IndexItem item : neededIndexItems) {
|
||||
for (IndexItem item : indexItems) {
|
||||
if (!item.isDownloaded() && (paidVersion || item.getType() != DownloadActivityType.WIKIPEDIA_FILE)) {
|
||||
res.add(item);
|
||||
}
|
||||
|
@ -344,7 +379,7 @@ public class ExploreTabFragment extends BaseOsmAndFragment implements DownloadEv
|
|||
neededMapsCard = null;
|
||||
}
|
||||
|
||||
private static class ProcessIndexItemsTask extends AsyncTask<Void, Void, Pair<IndexItem, List<IndexItem>>> {
|
||||
private static class ProcessIndexItemsTask extends AsyncTask<Void, Void, Pair<List<IndexItem>, List<IndexItem>>> {
|
||||
|
||||
private static final DownloadActivityType[] types = new DownloadActivityType[]{
|
||||
DownloadActivityType.NORMAL_FILE,
|
||||
|
@ -354,40 +389,41 @@ public class ExploreTabFragment extends BaseOsmAndFragment implements DownloadEv
|
|||
private final OsmandApplication app;
|
||||
private final WeakReference<ExploreTabFragment> weakFragment;
|
||||
|
||||
private final String fileName;
|
||||
|
||||
ProcessIndexItemsTask(ExploreTabFragment fragment) {
|
||||
app = fragment.getMyApplication();
|
||||
weakFragment = new WeakReference<>(fragment);
|
||||
fileName = app != null ? app.getTravelHelper().getWikivoyageFileName() : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Pair<IndexItem, List<IndexItem>> doInBackground(Void... voids) {
|
||||
if (fileName != null) {
|
||||
IndexItem mainItem = app.getDownloadThread().getIndexes().getWikivoyageItem(fileName);
|
||||
|
||||
List<IndexItem> neededItems = new ArrayList<>();
|
||||
for (TravelArticle article : app.getTravelHelper().getBookmarksHelper().getSavedArticles()) {
|
||||
LatLon latLon = new LatLon(article.getLat(), article.getLon());
|
||||
try {
|
||||
for (DownloadActivityType type : types) {
|
||||
IndexItem item = DownloadResources.findSmallestIndexItemAt(app, latLon, type);
|
||||
if (item != null && !item.isDownloaded() && !neededItems.contains(item)) {
|
||||
neededItems.add(item);
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
// ignore
|
||||
protected Pair<List<IndexItem>, List<IndexItem>> doInBackground(Void... voids) {
|
||||
List<IndexItem> mainItems = new ArrayList<>();
|
||||
List<IndexItem> allWikivoyageItems = app.getDownloadThread().getIndexes().getWikivoyageItems();
|
||||
if (allWikivoyageItems != null) {
|
||||
for (IndexItem item : allWikivoyageItems) {
|
||||
if (!item.isDownloaded() && !mainItems.contains(item)) {
|
||||
mainItems.add(item);
|
||||
}
|
||||
}
|
||||
return new Pair<>(mainItem, neededItems);
|
||||
}
|
||||
return null;
|
||||
List<IndexItem> neededItems = new ArrayList<>();
|
||||
for (TravelArticle article : app.getTravelHelper().getBookmarksHelper().getSavedArticles()) {
|
||||
LatLon latLon = new LatLon(article.getLat(), article.getLon());
|
||||
try {
|
||||
for (DownloadActivityType type : types) {
|
||||
IndexItem item = DownloadResources.findSmallestIndexItemAt(app, latLon, type);
|
||||
if (item != null && !item.isDownloaded() && !neededItems.contains(item)) {
|
||||
neededItems.add(item);
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
return new Pair<>(mainItems, neededItems);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Pair<IndexItem, List<IndexItem>> res) {
|
||||
protected void onPostExecute(Pair<List<IndexItem>, List<IndexItem>> res) {
|
||||
ExploreTabFragment fragment = weakFragment.get();
|
||||
if (res != null && fragment != null && fragment.isResumed()) {
|
||||
fragment.addIndexItemCards(res.first, res.second);
|
||||
|
|
|
@ -326,12 +326,12 @@ public class WikivoyageExploreActivity extends TabActivity implements DownloadEv
|
|||
public void onFinish(AppInitializer init) {
|
||||
WikivoyageExploreActivity activity = activityRef.get();
|
||||
if (AndroidUtils.isActivityNotDestroyed(activity)) {
|
||||
new LoadWikivoyageData(activity).execute();
|
||||
new LoadWikivoyageData(activity,true).execute();
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
new LoadWikivoyageData(this).execute();
|
||||
new LoadWikivoyageData(this,true).execute();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -380,19 +380,21 @@ public class WikivoyageExploreActivity extends TabActivity implements DownloadEv
|
|||
updateFragments();
|
||||
}
|
||||
|
||||
private static class LoadWikivoyageData extends AsyncTask<Void, Void, Void> {
|
||||
public static class LoadWikivoyageData extends AsyncTask<Void, Void, Void> {
|
||||
|
||||
private final WeakReference<WikivoyageExploreActivity> activityRef;
|
||||
private final TravelHelper travelHelper;
|
||||
private final boolean resetData;
|
||||
|
||||
LoadWikivoyageData(WikivoyageExploreActivity activity) {
|
||||
LoadWikivoyageData(WikivoyageExploreActivity activity, boolean resetData) {
|
||||
travelHelper = activity.getMyApplication().getTravelHelper();
|
||||
activityRef = new WeakReference<>(activity);
|
||||
this.resetData = resetData;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Void doInBackground(Void... params) {
|
||||
travelHelper.initializeDataToDisplay();
|
||||
travelHelper.initializeDataToDisplay(resetData);
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
package net.osmand.plus.wikivoyage.explore.travelcards;
|
||||
|
||||
import android.view.View;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.UiUtilities;
|
||||
import net.osmand.plus.wikivoyage.explore.travelcards.TravelNeededMapsCard.CardListener;
|
||||
|
||||
public class TravelButtonCard extends BaseTravelCard {
|
||||
|
||||
public static final int TYPE = 5;
|
||||
private CardListener listener;
|
||||
|
||||
public TravelButtonCard(OsmandApplication app, boolean nightMode) {
|
||||
super(app, nightMode);
|
||||
}
|
||||
|
||||
public void setListener(CardListener listener) {
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder) {
|
||||
if (viewHolder instanceof TravelButtonVH) {
|
||||
final TravelButtonVH holder = (TravelButtonVH) viewHolder;
|
||||
UiUtilities.setupDialogButton(nightMode, holder.button, UiUtilities.DialogButtonType.SECONDARY, R.string.show_more);
|
||||
holder.button.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
if (listener != null) {
|
||||
listener.onPrimaryButtonClick();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public static class TravelButtonVH extends RecyclerView.ViewHolder {
|
||||
|
||||
final View button;
|
||||
|
||||
public TravelButtonVH(View itemView) {
|
||||
super(itemView);
|
||||
button = itemView.findViewById(R.id.button);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCardType() {
|
||||
return TYPE;
|
||||
}
|
||||
}
|
|
@ -1,257 +1,47 @@
|
|||
package net.osmand.plus.wikivoyage.explore.travelcards;
|
||||
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.download.IndexItem;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.text.DateFormat;
|
||||
import java.util.List;
|
||||
|
||||
public class TravelDownloadUpdateCard extends BaseTravelCard {
|
||||
public class TravelDownloadUpdateCard extends TravelNeededMapsCard {
|
||||
|
||||
public static final int TYPE = 50;
|
||||
|
||||
private boolean download;
|
||||
private boolean showOtherMapsBtn;
|
||||
private WeakReference<DownloadUpdateVH> ref;
|
||||
private final boolean download;
|
||||
|
||||
private ClickListener listener;
|
||||
|
||||
@Nullable
|
||||
private IndexItem indexItem;
|
||||
|
||||
private DateFormat dateFormat;
|
||||
|
||||
public boolean isDownload() {
|
||||
return download;
|
||||
}
|
||||
|
||||
public boolean isShowOtherMapsBtn() {
|
||||
return showOtherMapsBtn;
|
||||
}
|
||||
|
||||
public void setShowOtherMapsBtn(boolean showOtherMapsBtn) {
|
||||
this.showOtherMapsBtn = showOtherMapsBtn;
|
||||
}
|
||||
|
||||
public void setListener(ClickListener listener) {
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
public void setIndexItem(@Nullable IndexItem indexItem) {
|
||||
this.indexItem = indexItem;
|
||||
}
|
||||
|
||||
public TravelDownloadUpdateCard(OsmandApplication app, boolean nightMode, boolean download) {
|
||||
super(app, nightMode);
|
||||
public TravelDownloadUpdateCard(@NonNull OsmandApplication app, boolean nightMode, @NonNull List<IndexItem> items,
|
||||
boolean download) {
|
||||
super(app, nightMode, items);
|
||||
this.download = download;
|
||||
dateFormat = android.text.format.DateFormat.getMediumDateFormat(app);
|
||||
}
|
||||
|
||||
public int getTitle() {
|
||||
if (isDownloading()) {
|
||||
return R.string.shared_string_downloading;
|
||||
}
|
||||
return download ? R.string.download_file : R.string.update_is_available;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder) {
|
||||
if (viewHolder instanceof DownloadUpdateVH) {
|
||||
boolean loading = isLoading();
|
||||
DownloadUpdateVH holder = (DownloadUpdateVH) viewHolder;
|
||||
this.ref = new WeakReference<TravelDownloadUpdateCard.DownloadUpdateVH>(holder);
|
||||
holder.title.setText(getTitle(loading));
|
||||
holder.icon.setImageResource(getIconRes());
|
||||
holder.description.setText(getDescription());
|
||||
if (indexItem == null) {
|
||||
holder.fileDataContainer.setVisibility(View.GONE);
|
||||
} else {
|
||||
holder.fileDataContainer.setVisibility(View.VISIBLE);
|
||||
holder.fileIcon.setImageDrawable(getFileIcon());
|
||||
holder.fileTitle.setText(getFileTitle());
|
||||
holder.fileDescription.setText(getFileDescription());
|
||||
holder.progressBar.setVisibility(loading ? View.VISIBLE : View.GONE);
|
||||
updateProgressBar(holder);
|
||||
}
|
||||
boolean primaryBtnVisible = updatePrimaryButton(holder, loading);
|
||||
boolean secondaryBtnVisible = updateSecondaryButton(holder, loading);
|
||||
holder.buttonsDivider.setVisibility(primaryBtnVisible && secondaryBtnVisible ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
public void updateProgresBar() {
|
||||
if(ref != null) {
|
||||
DownloadUpdateVH holder = ref.get();
|
||||
if (holder != null && holder.itemView.isShown()) {
|
||||
updateProgressBar(holder);
|
||||
}
|
||||
public int getDescription() {
|
||||
if (!isInternetAvailable()) {
|
||||
return R.string.no_index_file_to_download;
|
||||
}
|
||||
return download ? R.string.travel_card_download_descr : R.string.travel_card_update_descr;
|
||||
}
|
||||
|
||||
private void updateProgressBar(DownloadUpdateVH holder) {
|
||||
if (isLoadingInProgress()) {
|
||||
int progress = app.getDownloadThread().getCurrentDownloadingItemProgress();
|
||||
holder.progressBar.setProgress(progress < 0 ? 0 : progress);
|
||||
} else {
|
||||
holder.progressBar.setProgress(0);
|
||||
}
|
||||
@Override
|
||||
public int getIconRes() {
|
||||
return download ? R.drawable.travel_card_download_icon : R.drawable.travel_card_update_icon;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCardType() {
|
||||
return TYPE;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private String getTitle(boolean loading) {
|
||||
if (loading) {
|
||||
return app.getString(R.string.shared_string_downloading);
|
||||
}
|
||||
return app.getString(download ? R.string.download_file : R.string.update_is_available);
|
||||
}
|
||||
|
||||
private int getIconRes() {
|
||||
return download ? R.drawable.travel_card_download_icon : R.drawable.travel_card_update_icon;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private String getDescription() {
|
||||
if (!isInternetAvailable()) {
|
||||
return app.getString(R.string.no_index_file_to_download);
|
||||
}
|
||||
return app.getString(download ? R.string.travel_card_download_descr : R.string.travel_card_update_descr);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private String getFileTitle() {
|
||||
return indexItem == null ? "" : indexItem.getVisibleName(app, app.getRegions(), false);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private String getFileDescription() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (indexItem != null) {
|
||||
sb.append(app.getString(R.string.file_size_in_mb, indexItem.getArchiveSizeMB()));
|
||||
sb.append(" • ");
|
||||
sb.append(indexItem.getRemoteDate(dateFormat));
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private Drawable getFileIcon() {
|
||||
return getActiveIcon(R.drawable.ic_action_read_article);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if button is visible, false otherwise.
|
||||
*/
|
||||
private boolean updateSecondaryButton(DownloadUpdateVH vh, boolean loading) {
|
||||
if (loading || !download || showOtherMapsBtn) {
|
||||
vh.secondaryBtnContainer.setVisibility(View.VISIBLE);
|
||||
vh.secondaryBtn.setText(getSecondaryBtnTextId(loading));
|
||||
vh.secondaryBtn.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (listener != null) {
|
||||
listener.onSecondaryButtonClick();
|
||||
}
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
vh.secondaryBtnContainer.setVisibility(View.GONE);
|
||||
return false;
|
||||
}
|
||||
|
||||
@StringRes
|
||||
private int getSecondaryBtnTextId(boolean loading) {
|
||||
if (loading) {
|
||||
return R.string.shared_string_cancel;
|
||||
}
|
||||
if (!download) {
|
||||
return R.string.later;
|
||||
}
|
||||
return R.string.download_select_map_types;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if button is visible, false otherwise.
|
||||
*/
|
||||
private boolean updatePrimaryButton(DownloadUpdateVH vh, boolean loading) {
|
||||
if (!loading) {
|
||||
boolean enabled = isInternetAvailable();
|
||||
vh.primaryBtnContainer.setVisibility(View.VISIBLE);
|
||||
vh.primaryBtnContainer.setBackgroundResource(getPrimaryBtnBgRes(enabled));
|
||||
vh.primaryButton.setTextColor(getResolvedColor(getPrimaryBtnTextColorRes(enabled)));
|
||||
vh.primaryButton.setEnabled(enabled);
|
||||
vh.primaryButton.setText(download ? R.string.shared_string_download : R.string.shared_string_update);
|
||||
vh.primaryButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (listener != null) {
|
||||
listener.onPrimaryButtonClick();
|
||||
}
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
vh.primaryBtnContainer.setVisibility(View.GONE);
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isLoading() {
|
||||
return indexItem != null && app.getDownloadThread().isDownloading(indexItem);
|
||||
}
|
||||
|
||||
private boolean isLoadingInProgress() {
|
||||
IndexItem current = app.getDownloadThread().getCurrentDownloadingItem();
|
||||
return indexItem != null && current != null && indexItem == current;
|
||||
}
|
||||
|
||||
public interface ClickListener {
|
||||
|
||||
void onPrimaryButtonClick();
|
||||
|
||||
void onSecondaryButtonClick();
|
||||
}
|
||||
|
||||
public static class DownloadUpdateVH extends RecyclerView.ViewHolder {
|
||||
|
||||
final TextView title;
|
||||
final ImageView icon;
|
||||
final TextView description;
|
||||
final View fileDataContainer;
|
||||
final ImageView fileIcon;
|
||||
final TextView fileTitle;
|
||||
final TextView fileDescription;
|
||||
final ProgressBar progressBar;
|
||||
final View secondaryBtnContainer;
|
||||
final TextView secondaryBtn;
|
||||
final View buttonsDivider;
|
||||
final View primaryBtnContainer;
|
||||
final TextView primaryButton;
|
||||
|
||||
@SuppressWarnings("RedundantCast")
|
||||
public DownloadUpdateVH(View itemView) {
|
||||
super(itemView);
|
||||
title = (TextView) itemView.findViewById(R.id.title);
|
||||
icon = (ImageView) itemView.findViewById(R.id.icon);
|
||||
description = (TextView) itemView.findViewById(R.id.description);
|
||||
fileDataContainer = itemView.findViewById(R.id.file_data_container);
|
||||
fileIcon = (ImageView) itemView.findViewById(R.id.file_icon);
|
||||
fileTitle = (TextView) itemView.findViewById(R.id.file_title);
|
||||
fileDescription = (TextView) itemView.findViewById(R.id.file_description);
|
||||
progressBar = (ProgressBar) itemView.findViewById(R.id.progress_bar);
|
||||
secondaryBtnContainer = itemView.findViewById(R.id.secondary_btn_container);
|
||||
secondaryBtn = (TextView) itemView.findViewById(R.id.secondary_button);
|
||||
buttonsDivider = itemView.findViewById(R.id.buttons_divider);
|
||||
primaryBtnContainer = itemView.findViewById(R.id.primary_btn_container);
|
||||
primaryButton = (TextView) itemView.findViewById(R.id.primary_button);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,7 +9,9 @@ import android.widget.LinearLayout;
|
|||
import android.widget.ProgressBar;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.DrawableRes;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
|
@ -60,8 +62,12 @@ public class TravelNeededMapsCard extends BaseTravelCard {
|
|||
if (viewHolder instanceof NeededMapsVH) {
|
||||
NeededMapsVH holder = (NeededMapsVH) viewHolder;
|
||||
ref = new WeakReference<NeededMapsVH>(holder);
|
||||
holder.description.setText(isInternetAvailable()
|
||||
? R.string.maps_you_need_descr : R.string.no_index_file_to_download);
|
||||
holder.title.setText(getTitle());
|
||||
holder.description.setText(getDescription());
|
||||
int iconRes = getIconRes();
|
||||
if (iconRes > 0) {
|
||||
holder.icon.setImageResource(iconRes);
|
||||
}
|
||||
adjustChildCount(holder.itemsContainer);
|
||||
|
||||
updateView(holder);
|
||||
|
@ -71,7 +77,23 @@ public class TravelNeededMapsCard extends BaseTravelCard {
|
|||
holder.buttonsDivider.setVisibility(primaryBtnVisible && secondaryBtnVisible ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@StringRes
|
||||
public int getTitle() {
|
||||
return R.string.maps_you_need;
|
||||
}
|
||||
|
||||
@StringRes
|
||||
public int getDescription() {
|
||||
return isInternetAvailable()
|
||||
? R.string.maps_you_need_descr : R.string.no_index_file_to_download;
|
||||
}
|
||||
|
||||
@DrawableRes
|
||||
public int getIconRes() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public void updateView() {
|
||||
if (ref != null) {
|
||||
NeededMapsVH holder = ref.get();
|
||||
|
@ -227,7 +249,9 @@ public class TravelNeededMapsCard extends BaseTravelCard {
|
|||
|
||||
public static class NeededMapsVH extends RecyclerView.ViewHolder {
|
||||
|
||||
final TextView title;
|
||||
final TextView description;
|
||||
final ImageView icon;
|
||||
final LinearLayout itemsContainer;
|
||||
final View secondaryBtnContainer;
|
||||
final TextView secondaryBtn;
|
||||
|
@ -238,7 +262,9 @@ public class TravelNeededMapsCard extends BaseTravelCard {
|
|||
@SuppressWarnings("RedundantCast")
|
||||
public NeededMapsVH(View itemView) {
|
||||
super(itemView);
|
||||
title = (TextView) itemView.findViewById(R.id.title);
|
||||
description = (TextView) itemView.findViewById(R.id.description);
|
||||
icon = (ImageView) itemView.findViewById(R.id.icon);
|
||||
itemsContainer = (LinearLayout) itemView.findViewById(R.id.items_container);
|
||||
secondaryBtnContainer = itemView.findViewById(R.id.secondary_btn_container);
|
||||
secondaryBtn = (TextView) itemView.findViewById(R.id.secondary_button);
|
||||
|
|
Loading…
Reference in a new issue