From 101402a3c412cb437c3b0bdcae8a927d6b5a254e Mon Sep 17 00:00:00 2001 From: cepprice Date: Sat, 23 Jan 2021 21:06:59 +0500 Subject: [PATCH] Add description card --- .../main/java/net/osmand/GPXUtilities.java | 4 + .../layout/gpx_description_preview_card.xml | 128 ++++++++++++++++++ .../res/menu/track_menu_bottom_navigation.xml | 9 +- OsmAnd/res/values/strings.xml | 2 + OsmAnd/src/net/osmand/FileUtils.java | 4 + .../osmand/plus/track/DescriptionCard.java | 110 +++++++++++++++ .../osmand/plus/track/TrackMenuFragment.java | 60 ++++++-- 7 files changed, 302 insertions(+), 15 deletions(-) create mode 100644 OsmAnd/res/layout/gpx_description_preview_card.xml create mode 100644 OsmAnd/src/net/osmand/plus/track/DescriptionCard.java diff --git a/OsmAnd-java/src/main/java/net/osmand/GPXUtilities.java b/OsmAnd-java/src/main/java/net/osmand/GPXUtilities.java index ede3b6f8cf..ed80b55b05 100644 --- a/OsmAnd-java/src/main/java/net/osmand/GPXUtilities.java +++ b/OsmAnd-java/src/main/java/net/osmand/GPXUtilities.java @@ -449,6 +449,10 @@ public class GPXUtilities { public String getArticleLang() { return getExtensionsToRead().get("article_lang"); } + + public String getDescription() { + return getExtensionsToRead().get("desc"); + } } public static class Author extends GPXExtensions { diff --git a/OsmAnd/res/layout/gpx_description_preview_card.xml b/OsmAnd/res/layout/gpx_description_preview_card.xml new file mode 100644 index 0000000000..b9c4518b2d --- /dev/null +++ b/OsmAnd/res/layout/gpx_description_preview_card.xml @@ -0,0 +1,128 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/OsmAnd/res/menu/track_menu_bottom_navigation.xml b/OsmAnd/res/menu/track_menu_bottom_navigation.xml index fa07fb12a4..54f7d7e05e 100644 --- a/OsmAnd/res/menu/track_menu_bottom_navigation.xml +++ b/OsmAnd/res/menu/track_menu_bottom_navigation.xml @@ -1,9 +1,10 @@ - - - - + + + Edit description + Read full The name is already exists Server error: %1$s MTB diff --git a/OsmAnd/src/net/osmand/FileUtils.java b/OsmAnd/src/net/osmand/FileUtils.java index 580450df60..7fe28bf418 100644 --- a/OsmAnd/src/net/osmand/FileUtils.java +++ b/OsmAnd/src/net/osmand/FileUtils.java @@ -196,4 +196,8 @@ public class FileUtils { public interface RenameCallback { void renamedTo(File file); } + + public interface GpxEditedCallback { + void onGpxChanged(); + } } diff --git a/OsmAnd/src/net/osmand/plus/track/DescriptionCard.java b/OsmAnd/src/net/osmand/plus/track/DescriptionCard.java new file mode 100644 index 0000000000..2a6d460588 --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/track/DescriptionCard.java @@ -0,0 +1,110 @@ +package net.osmand.plus.track; + +import android.text.TextUtils; +import android.view.View; + +import com.squareup.picasso.Callback; +import com.squareup.picasso.Picasso; +import com.squareup.picasso.RequestCreator; + +import net.osmand.GPXUtilities; +import net.osmand.GPXUtilities.GPXFile; +import net.osmand.PicassoUtils; +import net.osmand.plus.R; +import net.osmand.plus.activities.MapActivity; +import net.osmand.plus.helpers.AndroidUiHelper; +import net.osmand.plus.routepreparationmenu.cards.BaseCard; +import net.osmand.plus.widgets.TextViewEx; +import net.osmand.plus.wikipedia.WikiArticleHelper; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.widget.AppCompatImageView; + +public class DescriptionCard extends BaseCard { + + private final GPXFile gpxFile; + + public DescriptionCard(MapActivity mapActivity, GPXFile gpxFile) { + super(mapActivity); + this.gpxFile = gpxFile; + } + + @Override + public int getCardLayoutId() { + return R.layout.gpx_description_preview_card; + } + + @Override + protected void updateContent() { + final String title = gpxFile.metadata.getArticleTitle(); + final String imageUrl = getMetadataImageLink(gpxFile.metadata); + final String descriptionHtml = gpxFile.metadata.getDescription(); + + setupImage(imageUrl); + + TextViewEx tvDescription = view.findViewById(R.id.description); + tvDescription.setText(getFirstParagraph(descriptionHtml)); + + TextViewEx readBtn = view.findViewById(R.id.btn_read_full); + readBtn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + } + }); + TextViewEx editBtn = view.findViewById(R.id.btn_edit); + editBtn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + } + }); + } + + @Nullable + private String getMetadataImageLink(@NonNull GPXUtilities.Metadata metadata) { + String link = metadata.link; + if (!TextUtils.isEmpty(link)) { + String lowerCaseLink = link.toLowerCase(); + if (lowerCaseLink.contains(".jpg") + || lowerCaseLink.contains(".jpeg") + || lowerCaseLink.contains(".png") + || lowerCaseLink.contains(".bmp") + || lowerCaseLink.contains(".webp")) { + return link; + } + } + return null; + } + + private String getFirstParagraph(String descriptionHtml) { + if (descriptionHtml != null) { + String firstParagraph = WikiArticleHelper.getPartialContent(descriptionHtml); + if (!TextUtils.isEmpty(firstParagraph)) { + return firstParagraph; + } + } + return descriptionHtml; + } + + private void setupImage(final String imageUrl) { + if (imageUrl == null) { + return; + } + final PicassoUtils picasso = PicassoUtils.getPicasso(app); + RequestCreator rc = Picasso.get().load(imageUrl); + final AppCompatImageView image = view.findViewById(R.id.main_image); + rc.into(image, new Callback() { + @Override + public void onSuccess() { + picasso.setResultLoaded(imageUrl, true); + AndroidUiHelper.updateVisibility(image, true); + } + + @Override + public void onError(Exception e) { + picasso.setResultLoaded(imageUrl, false); + } + }); + } + +} diff --git a/OsmAnd/src/net/osmand/plus/track/TrackMenuFragment.java b/OsmAnd/src/net/osmand/plus/track/TrackMenuFragment.java index 03f8ab374a..d284d820ce 100644 --- a/OsmAnd/src/net/osmand/plus/track/TrackMenuFragment.java +++ b/OsmAnd/src/net/osmand/plus/track/TrackMenuFragment.java @@ -15,19 +15,12 @@ import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.TextView; -import androidx.annotation.DrawableRes; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.annotation.StringRes; -import androidx.appcompat.app.AlertDialog; -import androidx.fragment.app.FragmentActivity; -import androidx.fragment.app.FragmentManager; - import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; import com.google.android.material.bottomnavigation.BottomNavigationView; import net.osmand.AndroidUtils; import net.osmand.FileUtils; +import net.osmand.FileUtils.GpxEditedCallback; import net.osmand.FileUtils.RenameCallback; import net.osmand.GPXUtilities.GPXFile; import net.osmand.GPXUtilities.Track; @@ -79,6 +72,14 @@ import org.apache.commons.logging.Log; import java.io.File; import java.util.List; +import androidx.annotation.DrawableRes; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.annotation.StringRes; +import androidx.appcompat.app.AlertDialog; +import androidx.fragment.app.FragmentActivity; +import androidx.fragment.app.FragmentManager; + import static net.osmand.plus.activities.TrackActivity.CURRENT_RECORDING; import static net.osmand.plus.activities.TrackActivity.TRACK_FILE_NAME; import static net.osmand.plus.myplaces.TrackActivityFragmentAdapter.isGpxFileSelected; @@ -96,7 +97,7 @@ import static net.osmand.plus.track.OptionsCard.SHOW_ON_MAP_BUTTON_INDEX; import static net.osmand.plus.track.OptionsCard.UPLOAD_OSM_BUTTON_INDEX; public class TrackMenuFragment extends ContextMenuScrollFragment implements CardListener, - SegmentActionsListener, RenameCallback, OnTrackFileMoveListener { + SegmentActionsListener, RenameCallback, OnTrackFileMoveListener, GpxEditedCallback { public static final String TAG = TrackMenuFragment.class.getName(); private static final Log log = PlatformUtil.getLog(TrackMenuFragment.class); @@ -109,15 +110,17 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card private TextView headerTitle; private ImageView headerIcon; private BottomNavigationView bottomNav; - private TrackMenuType menuType = TrackMenuType.TRACK; + private TrackMenuType menuType = TrackMenuType.OVERVIEW; private SegmentsCard segmentsCard; private OptionsCard optionsCard; + private DescriptionCard descriptionCard; private TrackChartPoints trackChartPoints; private int menuTitleHeight; public enum TrackMenuType { + OVERVIEW(R.id.action_overview, R.string.shared_string_overview), TRACK(R.id.action_track, R.string.shared_string_gpx_tracks), POINTS(R.id.action_points, R.string.shared_string_gpx_points), OPTIONS(R.id.action_options, R.string.shared_string_options); @@ -219,6 +222,10 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card } private void updateHeader() { + ViewGroup headerContainer = (ViewGroup) routeMenuTopShadowAll; + if (descriptionCard != null && descriptionCard.getView() != null) { + headerContainer.removeView(descriptionCard.getView()); + } if (menuType == TrackMenuType.OPTIONS) { headerTitle.setText(menuType.titleId); AndroidUiHelper.updateVisibility(headerIcon, false); @@ -226,7 +233,17 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card String fileName = Algorithms.getFileWithoutDirs(getGpx().path); headerTitle.setText(GpxUiHelper.getGpxTitle(fileName)); AndroidUiHelper.updateVisibility(headerIcon, true); + if (menuType == TrackMenuType.OVERVIEW) { + fillOverviewTab(headerContainer); + } } + runLayoutListener(); + headerContainer.post(new Runnable() { + @Override + public void run() { + openMenuScreen(menuType == TrackMenuType.OVERVIEW ? MenuState.HEADER_ONLY : MenuState.HALF_SCREEN, false); + } + }); } private void setupCards() { @@ -262,6 +279,19 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card } } + private void fillOverviewTab(ViewGroup headerContainer) { + if (descriptionCard != null && descriptionCard.getView() != null) { + ViewGroup parent = ((ViewGroup) descriptionCard.getView().getParent()); + if (parent != null) { + parent.removeView(descriptionCard.getView()); + } + headerContainer.addView(descriptionCard.getView()); + } else { + descriptionCard = new DescriptionCard(getMapActivity(), displayHelper.getGpx()); + headerContainer.addView(descriptionCard.build(getMapActivity())); + } + } + @Override protected void calculateLayout(View view, boolean initLayout) { menuTitleHeight = routeMenuTopShadowAll.getHeight() @@ -306,6 +336,7 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card if (mapActivity != null && trackChartPoints != null) { mapActivity.getMapLayers().getGpxLayer().setTrackChartPoints(trackChartPoints); } + updateHeader(); } @Override @@ -567,7 +598,7 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card BottomNavigationView bottomNav = view.findViewById(R.id.bottom_navigation); bottomNav.setItemIconTintList(navColorStateList); bottomNav.setItemTextColor(navColorStateList); - bottomNav.setSelectedItemId(R.id.action_track); + bottomNav.setSelectedItemId(R.id.action_overview); bottomNav.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() { @Override public boolean onNavigationItemSelected(@NonNull MenuItem item) { @@ -783,6 +814,13 @@ public class TrackMenuFragment extends ContextMenuScrollFragment implements Card } } + @Override + public void onGpxChanged() { + if (descriptionCard != null) { + descriptionCard.update(); + } + } + public static boolean showInstance(@NonNull MapActivity mapActivity, String path, boolean showCurrentTrack) { try { Bundle args = new Bundle();