From 5e93fcc47648562ef9ec618edb9a5abe89743b26 Mon Sep 17 00:00:00 2001 From: Arnaud Vergnet Date: Wed, 25 Jan 2023 23:13:21 +0100 Subject: [PATCH] android: move wikipedia summary in own fragment Signed-off-by: Arnaud Vergnet --- android/res/layout/place_page_details.xml | 9 +- android/res/layout/place_page_wiki.xml | 24 ---- .../layout/place_page_wikipedia_fragment.xml | 32 +++++ .../widget/placepage/PlacePageUtils.java | 35 +++++- .../widget/placepage/PlacePageView.java | 113 +++--------------- .../placepage/PlacePageWikipediaFragment.java | 112 +++++++++++++++++ 6 files changed, 195 insertions(+), 130 deletions(-) delete mode 100644 android/res/layout/place_page_wiki.xml create mode 100644 android/res/layout/place_page_wikipedia_fragment.xml create mode 100644 android/src/app/organicmaps/widget/placepage/PlacePageWikipediaFragment.java diff --git a/android/res/layout/place_page_details.xml b/android/res/layout/place_page_details.xml index 56c7b8a3d8..06192f9dfd 100644 --- a/android/res/layout/place_page_details.xml +++ b/android/res/layout/place_page_details.xml @@ -27,12 +27,11 @@ android:layout_height="wrap_content" tools:layout="@layout/place_page_bookmark_fragment" /> - + tools:layout="@layout/place_page_wikipedia_fragment" /> @@ -68,8 +67,6 @@ - - diff --git a/android/res/layout/place_page_wiki.xml b/android/res/layout/place_page_wiki.xml deleted file mode 100644 index 4324def037..0000000000 --- a/android/res/layout/place_page_wiki.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - diff --git a/android/res/layout/place_page_wikipedia_fragment.xml b/android/res/layout/place_page_wikipedia_fragment.xml new file mode 100644 index 0000000000..0380b0cf8f --- /dev/null +++ b/android/res/layout/place_page_wikipedia_fragment.xml @@ -0,0 +1,32 @@ + + + + + + + + \ No newline at end of file diff --git a/android/src/app/organicmaps/widget/placepage/PlacePageUtils.java b/android/src/app/organicmaps/widget/placepage/PlacePageUtils.java index 38d27c9149..44f5dc5cc9 100644 --- a/android/src/app/organicmaps/widget/placepage/PlacePageUtils.java +++ b/android/src/app/organicmaps/widget/placepage/PlacePageUtils.java @@ -1,14 +1,19 @@ package app.organicmaps.widget.placepage; +import android.content.Context; import android.graphics.Rect; +import android.view.Menu; import android.view.View; import android.view.ViewGroup; +import android.widget.PopupMenu; import androidx.annotation.NonNull; - -import com.google.android.material.bottomsheet.BottomSheetBehavior; import app.organicmaps.Framework; import app.organicmaps.R; +import app.organicmaps.util.Utils; +import com.google.android.material.bottomsheet.BottomSheetBehavior; + +import java.util.List; class PlacePageUtils { @@ -78,7 +83,6 @@ class PlacePageUtils return state == BottomSheetBehavior.STATE_HALF_EXPANDED; } - static boolean isExpandedState(@BottomSheetBehavior.State int state) { return state == BottomSheetBehavior.STATE_EXPANDED; @@ -110,4 +114,29 @@ class PlacePageUtils throw new AssertionError("Unsupported state detected: " + state); } } + + static void copyToClipboard(Context context, View frame, String text) + { + Utils.copyTextToClipboard(context, text); + Utils.showSnackbarAbove(frame, + frame.getRootView().findViewById(R.id.pp_buttons_layout), + context.getString(R.string.copied_to_clipboard, text)); + } + + static void showCopyPopup(Context context, View popupAnchor, View frame, List items) + { + final PopupMenu popup = new PopupMenu(context, popupAnchor); + final Menu menu = popup.getMenu(); + final String copyText = context.getResources().getString(android.R.string.copy); + + for (int i = 0; i < items.size(); i++) + menu.add(Menu.NONE, i, i, String.format("%s %s", copyText, items.get(i))); + + popup.setOnMenuItemClickListener(item -> { + final String text = items.get(item.getItemId()); + copyToClipboard(context, frame, text); + return true; + }); + popup.show(); + } } diff --git a/android/src/app/organicmaps/widget/placepage/PlacePageView.java b/android/src/app/organicmaps/widget/placepage/PlacePageView.java index cc778d24dd..632a91e42c 100644 --- a/android/src/app/organicmaps/widget/placepage/PlacePageView.java +++ b/android/src/app/organicmaps/widget/placepage/PlacePageView.java @@ -6,17 +6,14 @@ import android.content.Intent; import android.content.res.Resources; import android.location.Location; import android.os.Bundle; -import android.text.Html; import android.text.SpannableStringBuilder; import android.text.Spanned; import android.text.TextUtils; import android.text.style.ForegroundColorSpan; import android.view.LayoutInflater; -import android.view.Menu; import android.view.View; import android.view.ViewGroup; import android.widget.LinearLayout; -import android.widget.PopupMenu; import android.widget.RelativeLayout; import android.widget.TextView; @@ -81,6 +78,7 @@ public class PlacePageView extends Fragment implements View.OnClickListener, private static final String PREF_COORDINATES_FORMAT = "coordinates_format"; private static final String BOOKMARK_FRAGMENT_TAG = "BOOKMARK_FRAGMENT_TAG"; + private static final String WIKIPEDIA_FRAGMENT_TAG = "WIKIPEDIA_FRAGMENT_TAG"; private static final String PHONE_FRAGMENT_TAG = "PHONE_FRAGMENT_TAG"; private static final List visibleCoordsFormat = @@ -88,7 +86,6 @@ public class PlacePageView extends Fragment implements View.OnClickListener, CoordinatesFormat.LatLonDecimal, CoordinatesFormat.OLCFull, CoordinatesFormat.OSMLink); - private int mDescriptionMaxLength; private View mFrame; // Preview. private ViewGroup mPreview; @@ -133,7 +130,6 @@ public class PlacePageView extends Fragment implements View.OnClickListener, private TextView mTvLevel; private View mCuisine; private TextView mTvCuisine; - private View mWiki; private View mEntrance; private TextView mTvEntrance; private View mEditPlace; @@ -141,18 +137,6 @@ public class PlacePageView extends Fragment implements View.OnClickListener, private View mAddPlace; private View mEditTopSpace; - @SuppressWarnings("NullableProblems") - @NonNull - private View mPlaceDescriptionContainer; - @SuppressWarnings("NotNullFieldNotInitialized") - @NonNull - private View mPlaceDescriptionHeaderContainer; - @SuppressWarnings("NullableProblems") - @NonNull - private TextView mPlaceDescriptionView; - @SuppressWarnings("NullableProblems") - @NonNull - private View mPlaceDescriptionMoreBtn; @SuppressWarnings("NullableProblems") @NonNull private View mPopularityView; @@ -268,7 +252,6 @@ public class PlacePageView extends Fragment implements View.OnClickListener, public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); - mDescriptionMaxLength = getResources().getInteger(R.integer.place_page_description_max_length); mCoordsFormat = CoordinatesFormat.fromId( MwmApplication.prefs(requireContext()).getInt( PREF_COORDINATES_FORMAT, CoordinatesFormat.LatLonDecimal.getId())); @@ -360,8 +343,6 @@ public class PlacePageView extends Fragment implements View.OnClickListener, mTvLevel = mFrame.findViewById(R.id.tv__place_level); mCuisine = mFrame.findViewById(R.id.ll__place_cuisine); mTvCuisine = mFrame.findViewById(R.id.tv__place_cuisine); - mWiki = mFrame.findViewById(R.id.ll__place_wiki); - mWiki.setOnClickListener(this); mEntrance = mFrame.findViewById(R.id.ll__place_entrance); mTvEntrance = mEntrance.findViewById(R.id.tv__place_entrance); mEditPlace = mFrame.findViewById(R.id.ll__place_editor); @@ -379,20 +360,11 @@ public class PlacePageView extends Fragment implements View.OnClickListener, mEmail.setOnLongClickListener(this); mOperator.setOnLongClickListener(this); mLevel.setOnLongClickListener(this); - mWiki.setOnLongClickListener(this); mDownloaderIcon = new DownloaderStatusIcon(mPreview.findViewById(R.id.downloader_status_frame)); mDownloaderInfo = mPreview.findViewById(R.id.tv__downloader_details); - // Place Description - mPlaceDescriptionContainer = mFrame.findViewById(R.id.poi_description_container); - mPlaceDescriptionView = mFrame.findViewById(R.id.poi_description); - mPlaceDescriptionView.setOnLongClickListener(this); - mPlaceDescriptionHeaderContainer = mFrame.findViewById(R.id.pp_description_header_container); - mPlaceDescriptionMoreBtn = mFrame.findViewById(R.id.more_btn); - mPlaceDescriptionMoreBtn.setOnClickListener(v -> showDescriptionScreen()); - viewModel = new ViewModelProvider(requireActivity()).get(PlacePageViewModel.class); viewModel.getMapObject().observe(requireActivity(), this); @@ -550,13 +522,6 @@ public class PlacePageView extends Fragment implements View.OnClickListener, mPlacePageViewListener.onPlacePageRequestToggleRouteSettings(roadType); } - private void showDescriptionScreen() - { - Context context = mPlaceDescriptionContainer.getContext(); - String description = mMapObject.getDescription(); - PlaceDescriptionActivity.start(context, description); - } - private void setCurrentCountry() { if (mCurrentCountry != null) @@ -583,12 +548,9 @@ public class PlacePageView extends Fragment implements View.OnClickListener, switch (mMapObject.getMapObjectType()) { case MapObject.BOOKMARK: - refreshDistanceToObject(loc); - break; case MapObject.POI: case MapObject.SEARCH: refreshDistanceToObject(loc); - setPlaceDescription(); break; case MapObject.API_POINT: refreshDistanceToObject(loc); @@ -638,35 +600,21 @@ public class PlacePageView extends Fragment implements View.OnClickListener, } } - private Spanned getShortDescription() + private void updateWikipediaView() { - String htmlDescription = mMapObject.getDescription(); - final int paragraphStart = htmlDescription.indexOf("

"); - final int paragraphEnd = htmlDescription.indexOf("

"); - if (paragraphStart == 0 && paragraphEnd != -1) - htmlDescription = htmlDescription.substring(3, paragraphEnd); - - Spanned description = Html.fromHtml(htmlDescription); - if (description.length() > mDescriptionMaxLength) + final FragmentManager fManager = getChildFragmentManager(); + final PlacePageWikipediaFragment fragment = (PlacePageWikipediaFragment) fManager.findFragmentByTag(WIKIPEDIA_FRAGMENT_TAG); + if (!TextUtils.isEmpty(mMapObject.getDescription()) && fragment == null) { - description = (Spanned) new SpannableStringBuilder(description) - .insert(mDescriptionMaxLength - 3, "...") - .subSequence(0, mDescriptionMaxLength); + fManager.beginTransaction() + .add(R.id.place_page_wikipedia_fragment, PlacePageWikipediaFragment.class, null, WIKIPEDIA_FRAGMENT_TAG) + .commit(); } - - return description; - } - - private void setPlaceDescription() - { - if (TextUtils.isEmpty(mMapObject.getDescription())) + else if (TextUtils.isEmpty(mMapObject.getDescription()) && fragment != null) { - UiUtils.hide(mPlaceDescriptionContainer, mPlaceDescriptionHeaderContainer); - } - else - { - UiUtils.show(mPlaceDescriptionContainer, mPlaceDescriptionHeaderContainer); - mPlaceDescriptionView.setText(getShortDescription()); + fManager.beginTransaction() + .remove(fragment) + .commit(); } } @@ -716,7 +664,6 @@ public class PlacePageView extends Fragment implements View.OnClickListener, /// @todo I don't like it when we take all data from mapObject, but for cuisines, we should /// go into JNI Framework and rely on some "active object". refreshMetadataOrHide(Framework.nativeGetActiveObjectFormattedCuisine(), mCuisine, mTvCuisine); - refreshMetadataOrHide(mMapObject.getMetadata(Metadata.MetadataType.FMD_WIKIPEDIA), mWiki, null); refreshWiFi(); refreshMetadataOrHide(mMapObject.getMetadata(Metadata.MetadataType.FMD_FLATS), mEntrance, mTvEntrance); refreshOpeningHours(); @@ -738,7 +685,7 @@ public class PlacePageView extends Fragment implements View.OnClickListener, || UiUtils.isVisible(mAddOrganisation) || UiUtils.isVisible(mAddPlace), mEditTopSpace); } - setPlaceDescription(); + updateWikipediaView(); } private void refreshOpeningHours() @@ -1104,8 +1051,6 @@ public class PlacePageView extends Fragment implements View.OnClickListener, else Utils.openUrl(context, "https://line.me/R/ti/p/@" + linePage); } - else if (id == R.id.ll__place_wiki) - Utils.openUrl(context, mMapObject.getMetadata(Metadata.MetadataType.FMD_WIKIPEDIA)); else if (id == R.id.direction_frame) showBigDirection(); else if (id == R.id.ll__place_email) @@ -1135,8 +1080,6 @@ public class PlacePageView extends Fragment implements View.OnClickListener, items.add(mTvSecondaryTitle.getText().toString()); else if (id == R.id.tv__address) items.add(mTvAddress.getText().toString()); - else if (id == R.id.poi_description) - items.add(mPlaceDescriptionView.getText().toString()); else if (id == R.id.ll__place_latlon) { final double lat = mMapObject.getLat(); @@ -1197,38 +1140,14 @@ public class PlacePageView extends Fragment implements View.OnClickListener, } else if (id == R.id.ll__place_operator) items.add(mTvOperator.getText().toString()); - else if (id == R.id.ll__place_wiki) - items.add(mMapObject.getMetadata(Metadata.MetadataType.FMD_WIKIPEDIA)); else if (id == R.id.ll__place_level) items.add(mTvLevel.getText().toString()); - final Context ctx = getContext(); + final Context context = requireContext(); if (items.size() == 1) - { - Utils.copyTextToClipboard(ctx, items.get(0)); - Utils.showSnackbarAbove(mDetails, - mFrame.getRootView().findViewById(R.id.pp_buttons_layout), - ctx.getString(R.string.copied_to_clipboard, items.get(0))); - } + PlacePageUtils.copyToClipboard(context, mFrame, items.get(0)); else - { - final PopupMenu popup = new PopupMenu(getContext(), v); - final Menu menu = popup.getMenu(); - final String copyText = getResources().getString(android.R.string.copy); - - for (int i = 0; i < items.size(); i++) - menu.add(Menu.NONE, i, i, String.format("%s %s", copyText, items.get(i))); - - popup.setOnMenuItemClickListener(item -> { - final int itemId = item.getItemId(); - Utils.copyTextToClipboard(ctx, items.get(itemId)); - Utils.showSnackbarAbove(mDetails, - mFrame.getRootView().findViewById(R.id.pp_buttons_layout), - ctx.getString(R.string.copied_to_clipboard, items.get(itemId))); - return true; - }); - popup.show(); - } + PlacePageUtils.showCopyPopup(context, v, mFrame, items); return true; } diff --git a/android/src/app/organicmaps/widget/placepage/PlacePageWikipediaFragment.java b/android/src/app/organicmaps/widget/placepage/PlacePageWikipediaFragment.java new file mode 100644 index 0000000000..7a0007eb0f --- /dev/null +++ b/android/src/app/organicmaps/widget/placepage/PlacePageWikipediaFragment.java @@ -0,0 +1,112 @@ +package app.organicmaps.widget.placepage; + +import android.os.Bundle; +import android.text.Html; +import android.text.SpannableStringBuilder; +import android.text.Spanned; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; +import androidx.lifecycle.Observer; +import androidx.lifecycle.ViewModelProvider; +import app.organicmaps.R; +import app.organicmaps.bookmarks.data.MapObject; +import app.organicmaps.bookmarks.data.Metadata; +import app.organicmaps.util.Utils; + +public class PlacePageWikipediaFragment extends Fragment implements Observer +{ + private View mFrame; + private View mWiki; + + private TextView mPlaceDescriptionView; + + private PlacePageViewModel viewModel; + + private MapObject mMapObject; + + private int mDescriptionMaxLength; + + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) + { + return inflater.inflate(R.layout.place_page_wikipedia_fragment, container, false); + } + + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) + { + super.onViewCreated(view, savedInstanceState); + mDescriptionMaxLength = getResources().getInteger(R.integer.place_page_description_max_length); + + mFrame = view; + + mPlaceDescriptionView = view.findViewById(R.id.poi_description); + View placeDescriptionMoreBtn = view.findViewById(R.id.more_btn); + placeDescriptionMoreBtn.setOnClickListener(v -> showDescriptionScreen()); + mWiki = view.findViewById(R.id.ll__place_wiki); + + viewModel = new ViewModelProvider(requireActivity()).get(PlacePageViewModel.class); + viewModel.getMapObject().observe(requireActivity(), this); + } + + private void showDescriptionScreen() + { + PlaceDescriptionActivity.start(requireContext(), mMapObject.getDescription()); + } + + private Spanned getShortDescription() + { + String htmlDescription = mMapObject.getDescription(); + final int paragraphStart = htmlDescription.indexOf("

"); + final int paragraphEnd = htmlDescription.indexOf("

"); + if (paragraphStart == 0 && paragraphEnd != -1) + htmlDescription = htmlDescription.substring(3, paragraphEnd); + + Spanned description = Html.fromHtml(htmlDescription); + if (description.length() > mDescriptionMaxLength) + { + description = (Spanned) new SpannableStringBuilder(description) + .insert(mDescriptionMaxLength - 3, "...") + .subSequence(0, mDescriptionMaxLength); + } + + return description; + } + + private void updateViews() + { + mPlaceDescriptionView.setText(getShortDescription()); + mPlaceDescriptionView.setOnLongClickListener((v) -> { + PlacePageUtils.copyToClipboard(requireContext(), mFrame, mPlaceDescriptionView.getText() + .toString()); + return true; + }); + final String wikipediaLink = mMapObject.getMetadata(Metadata.MetadataType.FMD_WIKIPEDIA); + mWiki.setOnClickListener((v) -> Utils.openUrl(requireContext(), wikipediaLink)); + mWiki.setOnLongClickListener((v) -> { + PlacePageUtils.copyToClipboard(requireContext(), mFrame, wikipediaLink); + return true; + }); + } + + @Override + public void onDestroy() + { + super.onDestroy(); + viewModel.getMapObject().removeObserver(this); + } + + @Override + public void onChanged(MapObject mapObject) + { + mMapObject = mapObject; + updateViews(); + } +}