diff --git a/android/res/drawable-hdpi/ic_24_px_settings.webp b/android/res/drawable-hdpi/ic_24_px_settings.webp deleted file mode 100644 index e287c8a654..0000000000 Binary files a/android/res/drawable-hdpi/ic_24_px_settings.webp and /dev/null differ diff --git a/android/res/drawable-hdpi/ic_edit.webp b/android/res/drawable-hdpi/ic_edit.webp deleted file mode 100644 index dc4d141043..0000000000 Binary files a/android/res/drawable-hdpi/ic_edit.webp and /dev/null differ diff --git a/android/res/drawable-hdpi/ic_hide.webp b/android/res/drawable-hdpi/ic_hide.webp deleted file mode 100644 index 0245227116..0000000000 Binary files a/android/res/drawable-hdpi/ic_hide.webp and /dev/null differ diff --git a/android/res/drawable-mdpi/ic_24_px_settings.webp b/android/res/drawable-mdpi/ic_24_px_settings.webp deleted file mode 100644 index 5340cee725..0000000000 Binary files a/android/res/drawable-mdpi/ic_24_px_settings.webp and /dev/null differ diff --git a/android/res/drawable-mdpi/ic_edit.webp b/android/res/drawable-mdpi/ic_edit.webp deleted file mode 100644 index 5590ce0a88..0000000000 Binary files a/android/res/drawable-mdpi/ic_edit.webp and /dev/null differ diff --git a/android/res/drawable-mdpi/ic_hide.webp b/android/res/drawable-mdpi/ic_hide.webp deleted file mode 100644 index 0e983a3ace..0000000000 Binary files a/android/res/drawable-mdpi/ic_hide.webp and /dev/null differ diff --git a/android/res/drawable-xhdpi/ic_24_px_settings.webp b/android/res/drawable-xhdpi/ic_24_px_settings.webp deleted file mode 100644 index 9915ac3dd3..0000000000 Binary files a/android/res/drawable-xhdpi/ic_24_px_settings.webp and /dev/null differ diff --git a/android/res/drawable-xhdpi/ic_edit.webp b/android/res/drawable-xhdpi/ic_edit.webp deleted file mode 100644 index 7430088b38..0000000000 Binary files a/android/res/drawable-xhdpi/ic_edit.webp and /dev/null differ diff --git a/android/res/drawable-xhdpi/ic_hide.webp b/android/res/drawable-xhdpi/ic_hide.webp deleted file mode 100644 index 6f18084976..0000000000 Binary files a/android/res/drawable-xhdpi/ic_hide.webp and /dev/null differ diff --git a/android/res/drawable-xxhdpi/ic_24_px_settings.webp b/android/res/drawable-xxhdpi/ic_24_px_settings.webp deleted file mode 100644 index 8db5e3465d..0000000000 Binary files a/android/res/drawable-xxhdpi/ic_24_px_settings.webp and /dev/null differ diff --git a/android/res/drawable-xxhdpi/ic_edit.webp b/android/res/drawable-xxhdpi/ic_edit.webp deleted file mode 100644 index 68f9937bea..0000000000 Binary files a/android/res/drawable-xxhdpi/ic_edit.webp and /dev/null differ diff --git a/android/res/drawable-xxhdpi/ic_hide.webp b/android/res/drawable-xxhdpi/ic_hide.webp deleted file mode 100644 index 7c6ebe7b9c..0000000000 Binary files a/android/res/drawable-xxhdpi/ic_hide.webp and /dev/null differ diff --git a/android/res/drawable-xxxhdpi/ic_24_px_settings.webp b/android/res/drawable-xxxhdpi/ic_24_px_settings.webp deleted file mode 100644 index 00bc942a17..0000000000 Binary files a/android/res/drawable-xxxhdpi/ic_24_px_settings.webp and /dev/null differ diff --git a/android/res/drawable-xxxhdpi/ic_edit.webp b/android/res/drawable-xxxhdpi/ic_edit.webp deleted file mode 100644 index 8ed43896b2..0000000000 Binary files a/android/res/drawable-xxxhdpi/ic_edit.webp and /dev/null differ diff --git a/android/res/drawable-xxxhdpi/ic_hide.webp b/android/res/drawable-xxxhdpi/ic_hide.webp deleted file mode 100644 index 9b21cce76f..0000000000 Binary files a/android/res/drawable-xxxhdpi/ic_hide.webp and /dev/null differ diff --git a/android/res/drawable/ic_edit.xml b/android/res/drawable/ic_edit.xml new file mode 100644 index 0000000000..faddfce421 --- /dev/null +++ b/android/res/drawable/ic_edit.xml @@ -0,0 +1,5 @@ + + + diff --git a/android/res/drawable/ic_hide.xml b/android/res/drawable/ic_hide.xml new file mode 100644 index 0000000000..32ab2aed69 --- /dev/null +++ b/android/res/drawable/ic_hide.xml @@ -0,0 +1,5 @@ + + + diff --git a/android/res/drawable/ic_settings.xml b/android/res/drawable/ic_settings.xml new file mode 100644 index 0000000000..b240b83007 --- /dev/null +++ b/android/res/drawable/ic_settings.xml @@ -0,0 +1,5 @@ + + + diff --git a/android/res/layout/bottom_sheet.xml b/android/res/layout/bottom_sheet.xml new file mode 100644 index 0000000000..e7e57b33ca --- /dev/null +++ b/android/res/layout/bottom_sheet.xml @@ -0,0 +1,25 @@ + + + + + + + + \ No newline at end of file diff --git a/android/res/layout/bottom_sheet_menu_item.xml b/android/res/layout/bottom_sheet_menu_item.xml new file mode 100644 index 0000000000..8fd70d2438 --- /dev/null +++ b/android/res/layout/bottom_sheet_menu_item.xml @@ -0,0 +1,39 @@ + + + + + + + diff --git a/android/res/menu/menu_bookmark_categories.xml b/android/res/menu/menu_bookmark_categories.xml deleted file mode 100644 index 15c36f8b3c..0000000000 --- a/android/res/menu/menu_bookmark_categories.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - diff --git a/android/res/menu/menu_bookmarks.xml b/android/res/menu/menu_bookmarks.xml deleted file mode 100644 index 1d3830f4d4..0000000000 --- a/android/res/menu/menu_bookmarks.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - diff --git a/android/res/menu/menu_bookmarks_list.xml b/android/res/menu/menu_bookmarks_list.xml deleted file mode 100644 index 4b56f751a4..0000000000 --- a/android/res/menu/menu_bookmarks_list.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - diff --git a/android/src/com/mapswithme/maps/bookmarks/BookmarkCategoriesFragment.java b/android/src/com/mapswithme/maps/bookmarks/BookmarkCategoriesFragment.java index c8fef0f0f9..c48c10e66e 100644 --- a/android/src/com/mapswithme/maps/bookmarks/BookmarkCategoriesFragment.java +++ b/android/src/com/mapswithme/maps/bookmarks/BookmarkCategoriesFragment.java @@ -20,7 +20,6 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.recyclerview.widget.RecyclerView; -import com.cocosw.bottomsheet.BottomSheet; import com.mapswithme.maps.MwmApplication; import com.mapswithme.maps.R; import com.mapswithme.maps.adapter.OnItemClickListener; @@ -33,20 +32,21 @@ import com.mapswithme.maps.dialog.DialogUtils; import com.mapswithme.maps.dialog.EditTextDialogFragment; import com.mapswithme.maps.widget.PlaceholderView; import com.mapswithme.maps.widget.recycler.ItemDecoratorFactory; -import com.mapswithme.util.BottomSheetHelper; +import com.mapswithme.util.bottomsheet.MenuBottomSheetFragment; import com.mapswithme.util.StorageUtils; +import com.mapswithme.util.bottomsheet.MenuBottomSheetItem; import com.mapswithme.util.concurrency.ThreadPool; import com.mapswithme.util.concurrency.UiThread; import com.mapswithme.util.log.Logger; import com.mapswithme.util.log.LoggerFactory; import java.io.File; +import java.util.ArrayList; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; public class BookmarkCategoriesFragment extends BaseMwmRecyclerFragment - implements MenuItem.OnMenuItemClickListener, - BookmarkManager.BookmarksLoadingListener, + implements BookmarkManager.BookmarksLoadingListener, CategoryListCallback, OnItemClickListener, OnItemMoreClickListener, @@ -155,49 +155,27 @@ public class BookmarkCategoriesFragment extends BaseMwmRecyclerFragment getMenuItems(@NonNull BookmarkCategory item) { - BottomSheetHelper.Builder bs = BottomSheetHelper.create(getActivity(), item.getName()) - .sheet(getCategoryMenuResId()) - .listener(this); + ArrayList items = new ArrayList<>(); + items.add(new MenuBottomSheetItem(R.string.list_settings, R.drawable.ic_settings, () -> onSettingsActionSelected(item))); + items.add(new MenuBottomSheetItem( + item.isVisible() ? R.string.hide : R.string.show, + item.isVisible() ? R.drawable.ic_hide : R.drawable.ic_show, + () -> onShowActionSelected(item))); + items.add(new MenuBottomSheetItem(R.string.export_file, R.drawable.ic_share, () -> onShareActionSelected(item))); + // Disallow deleting the last category + if (getAdapter().getBookmarkCategories().size() > 1) + items.add(new MenuBottomSheetItem(R.string.delete, R.drawable.ic_delete, () -> onDeleteActionSelected(item))); - BottomSheet bottomSheet = bs.build(); - prepareBottomMenuItems(bottomSheet); - MenuItem menuItem = BottomSheetHelper.findItemById(bottomSheet, R.id.show_on_map); - menuItem.setIcon(item.isVisible() ? R.drawable.ic_hide : R.drawable.ic_show) - .setTitle(item.isVisible() ? R.string.hide : R.string.show); - BottomSheetHelper.tint(bottomSheet); - bottomSheet.show(); - } - - protected void prepareBottomMenuItems(@NonNull BottomSheet bottomSheet) - { - boolean isMultipleItems = getAdapter().getBookmarkCategories().size() > 1; - setEnableForMenuItem(R.id.delete, bottomSheet, isMultipleItems); - } - - @MenuRes - protected int getCategoryMenuResId() - { - return R.menu.menu_bookmark_categories; + return items; } @Override @@ -264,21 +242,26 @@ public class BookmarkCategoriesFragment extends BaseMwmRecyclerFragment { @Nullable diff --git a/android/src/com/mapswithme/maps/bookmarks/BookmarksListFragment.java b/android/src/com/mapswithme/maps/bookmarks/BookmarksListFragment.java index d5380d2113..710214d4fe 100644 --- a/android/src/com/mapswithme/maps/bookmarks/BookmarksListFragment.java +++ b/android/src/com/mapswithme/maps/bookmarks/BookmarksListFragment.java @@ -21,7 +21,6 @@ import androidx.recyclerview.widget.ConcatAdapter; import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.SimpleItemAnimator; -import com.cocosw.bottomsheet.BottomSheet; import com.google.android.material.floatingactionbutton.FloatingActionButton; import com.mapswithme.maps.MwmActivity; import com.mapswithme.maps.R; @@ -40,11 +39,13 @@ import com.mapswithme.maps.search.SearchEngine; import com.mapswithme.maps.widget.SearchToolbarController; import com.mapswithme.maps.widget.placepage.EditBookmarkFragment; import com.mapswithme.maps.widget.recycler.ItemDecoratorFactory; -import com.mapswithme.util.BottomSheetHelper; import com.mapswithme.util.CrashlyticsUtils; import com.mapswithme.util.SharingUtils; import com.mapswithme.util.UiUtils; +import com.mapswithme.util.bottomsheet.MenuBottomSheetFragment; +import com.mapswithme.util.bottomsheet.MenuBottomSheetItem; +import java.util.ArrayList; import java.util.List; public class BookmarksListFragment extends BaseMwmRecyclerFragment @@ -615,24 +616,14 @@ public class BookmarksListFragment extends BaseMwmRecyclerFragment onTrackMenuItemClicked(track.getTrackId())) - .build(); - - BottomSheetHelper.tint(bottomSheet); - bottomSheet.show(); + new MenuBottomSheetFragment(track.getName(), getTrackMenuItems(track)) + .show(getParentFragmentManager(), "trackBottomSheet"); break; } } @@ -644,69 +635,8 @@ public class BookmarksListFragment extends BaseMwmRecyclerFragment - { - if (movedFromCategory) - resetSearchAndSort(); - else - adapter.notifyDataSetChanged(); - }); - break; - - case R.id.delete: - adapter.onDelete(mSelectedPosition); - BookmarkManager.INSTANCE.deleteBookmark(item.getBookmarkId()); - adapter.notifyDataSetChanged(); - if (mSearchMode) - mNeedUpdateSorting = true; - updateSearchVisibility(); - updateRecyclerVisibility(); - break; - } - return false; - } - - public boolean onListMoreMenuItemClick(@NonNull MenuItem menuItem) - { - switch (menuItem.getItemId()) - { - case R.id.sort: - ChooseBookmarksSortingTypeFragment.chooseSortingType(getAvailableSortingTypes(), - getLastSortingType(), requireActivity(), getChildFragmentManager()); - return false; - - case R.id.share_category: - long catId = mCategoryDataSource.getData().getId(); - BookmarksSharingHelper.INSTANCE.prepareBookmarkCategoryForSharing(requireActivity(), catId); - return false; - - case R.id.settings: - BookmarkCategorySettingsActivity.startForResult(this, mCategoryDataSource.getData()); - return false; - - case R.id.delete_category: - requireActivity().setResult(Activity.RESULT_OK); - requireActivity().finish(); - return false; - } - return false; - } - @Override - public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) + public void onCreateOptionsMenu(@NonNull Menu menu, MenuInflater inflater) { inflater.inflate(R.menu.option_menu_bookmarks, menu); @@ -715,7 +645,7 @@ public class BookmarksListFragment extends BaseMwmRecyclerFragment 0 && !isEmpty()); - moreMenu.findItem(R.id.delete_category).setVisible(!isLastOwnedCategory()); - moreMenu.findItem(R.id.share_category).setVisible(!isEmpty()); - - BottomSheetHelper.tint(bs); - bs.show(); + new MenuBottomSheetFragment(mCategoryDataSource.getData().getName(), getOptionsMenuItems()) + .show(getParentFragmentManager(), "optionsBottomSheet"); return true; } return super.onOptionsItemSelected(item); } + private void onShareActionSelected() + { + BookmarkInfo info = (BookmarkInfo) getBookmarkListAdapter().getItem(mSelectedPosition); + SharingUtils.shareBookmark(requireContext(), info); + } + + private void onEditActionSelected() + { + BookmarkListAdapter adapter = getBookmarkListAdapter(); + BookmarkInfo info = (BookmarkInfo) adapter.getItem(mSelectedPosition); + EditBookmarkFragment.editBookmark( + info.getCategoryId(), info.getBookmarkId(), requireActivity(), getChildFragmentManager(), + (bookmarkId, movedFromCategory) -> + { + if (movedFromCategory) + resetSearchAndSort(); + else + adapter.notifyDataSetChanged(); + }); + } + + private void onDeleteActionSelected() + { + BookmarkListAdapter adapter = getBookmarkListAdapter(); + BookmarkInfo info = (BookmarkInfo) getBookmarkListAdapter().getItem(mSelectedPosition); + adapter.onDelete(mSelectedPosition); + BookmarkManager.INSTANCE.deleteBookmark(info.getBookmarkId()); + adapter.notifyDataSetChanged(); + if (mSearchMode) + mNeedUpdateSorting = true; + updateSearchVisibility(); + updateRecyclerVisibility(); + } + + private void onSortOptionSelected() + { + ChooseBookmarksSortingTypeFragment.chooseSortingType(getAvailableSortingTypes(), + getLastSortingType(), requireActivity(), getChildFragmentManager()); + } + + private void onShareOptionSelected() + { + long catId = mCategoryDataSource.getData().getId(); + BookmarksSharingHelper.INSTANCE.prepareBookmarkCategoryForSharing(requireActivity(), catId); + } + + private void onSettingsOptionSelected() + { + BookmarkCategorySettingsActivity.startForResult(this, mCategoryDataSource.getData()); + } + + private void onDeleteOptionSelected() + { + requireActivity().setResult(Activity.RESULT_OK); + requireActivity().finish(); + } + + private ArrayList getOptionsMenuItems() + { + @BookmarkManager.SortingType int[] types = getAvailableSortingTypes(); + ArrayList items = new ArrayList<>(); + if (!isEmpty()) + { + if (types.length > 0) + items.add(new MenuBottomSheetItem(R.string.sort, R.drawable.ic_sort, this::onSortOptionSelected)); + items.add(new MenuBottomSheetItem(R.string.export_file, R.drawable.ic_share, this::onShareOptionSelected)); + } + items.add(new MenuBottomSheetItem(R.string.list_settings, R.drawable.ic_settings, this::onSettingsOptionSelected)); + if (!isLastOwnedCategory()) + items.add(new MenuBottomSheetItem(R.string.delete_list, R.drawable.ic_delete, this::onDeleteOptionSelected)); + return items; + } + + private ArrayList getBookmarkMenuItems() + { + ArrayList items = new ArrayList<>(); + items.add(new MenuBottomSheetItem(R.string.share, R.drawable.ic_share, this::onShareActionSelected)); + items.add(new MenuBottomSheetItem(R.string.edit, R.drawable.ic_edit, this::onEditActionSelected)); + items.add(new MenuBottomSheetItem(R.string.delete, R.drawable.ic_delete, this::onDeleteActionSelected)); + return items; + } + + private ArrayList getTrackMenuItems(final Track track) + { + ArrayList items = new ArrayList<>(); + items.add(new MenuBottomSheetItem(R.string.delete, R.drawable.ic_delete, () -> onTrackMenuItemClicked(track.getTrackId()))); + return items; + } + @Override public void onPreparedFileForSharing(@NonNull BookmarkSharingResult result) { diff --git a/android/src/com/mapswithme/maps/downloader/DownloaderAdapter.java b/android/src/com/mapswithme/maps/downloader/DownloaderAdapter.java index b9f59a661f..3af7834645 100644 --- a/android/src/com/mapswithme/maps/downloader/DownloaderAdapter.java +++ b/android/src/com/mapswithme/maps/downloader/DownloaderAdapter.java @@ -1,7 +1,6 @@ package com.mapswithme.maps.downloader; import android.app.Activity; -import android.content.DialogInterface; import android.content.Intent; import android.graphics.Typeface; import android.location.Location; @@ -15,24 +14,22 @@ import android.view.View; import android.view.ViewGroup; import android.widget.TextView; -import androidx.annotation.DrawableRes; import androidx.annotation.LayoutRes; import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import androidx.annotation.StringRes; import androidx.appcompat.app.AlertDialog; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; -import com.cocosw.bottomsheet.BottomSheet; import com.mapswithme.maps.MwmActivity; import com.mapswithme.maps.R; import com.mapswithme.maps.intent.Factory; import com.mapswithme.maps.location.LocationHelper; import com.mapswithme.maps.routing.RoutingController; -import com.mapswithme.util.BottomSheetHelper; import com.mapswithme.util.StringUtils; import com.mapswithme.util.UiUtils; +import com.mapswithme.util.bottomsheet.MenuBottomSheetFragment; +import com.mapswithme.util.bottomsheet.MenuBottomSheetItem; import com.timehop.stickyheadersrecyclerview.StickyRecyclerHeadersAdapter; import com.timehop.stickyheadersrecyclerview.StickyRecyclerHeadersDecoration; @@ -72,124 +69,74 @@ class DownloaderAdapter extends RecyclerView.Adapter MapManager.nativeUpdate(item.id)); + } + + private void onExploreActionSelected(CountryItem item, DownloaderAdapter adapter) + { + Intent intent = new Intent(adapter.mActivity, MwmActivity.class); + intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION); + intent.putExtra(MwmActivity.EXTRA_TASK, new Factory.ShowCountryTask(item.id)); + adapter.mActivity.startActivity(intent); + + if (!(adapter.mActivity instanceof MwmActivity)) + adapter.mActivity.finish(); + } + + void onDeleteActionSelected(final CountryItem item, final DownloaderAdapter adapter) + { + if (RoutingController.get().isNavigating()) { - @Override - void invoke(final CountryItem item, DownloaderAdapter adapter) - { - MapManager.warn3gAndDownload(adapter.mActivity, item.id, null); - } - }, - - DELETE(R.drawable.ic_delete, R.string.delete) - { - private void deleteNode(CountryItem item) - { - MapManager.nativeCancel(item.id); - MapManager.nativeDelete(item.id); - OnmapDownloader.setAutodownloadLocked(true); - } - - @Override - void invoke(final CountryItem item, final DownloaderAdapter adapter) - { - if (RoutingController.get().isNavigating()) - { - new AlertDialog.Builder(adapter.mActivity) - .setTitle(R.string.downloader_delete_map) - .setMessage(R.string.downloader_delete_map_while_routing_dialog) - .setPositiveButton(android.R.string.ok, null) - .show(); - return; - } - - if (!MapManager.nativeHasUnsavedEditorChanges(item.id)) - { - deleteNode(item, adapter); - return; - } - - new AlertDialog.Builder(adapter.mActivity) - .setTitle(R.string.downloader_delete_map) - .setMessage(R.string.downloader_delete_map_dialog) - .setNegativeButton(android.R.string.no, null) - .setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() - { - @Override - public void onClick(DialogInterface dialog, int which) - { - deleteNode(item, adapter); - } - }).show(); - } - - private void deleteNode(CountryItem item, DownloaderAdapter adapter) - { - if (adapter.mActivity instanceof MwmActivity) - { - ((MwmActivity) adapter.mActivity).closePlacePage(); - } - deleteNode(item); - } - }, - - CANCEL(R.drawable.ic_cancel, R.string.cancel) - { - @Override - void invoke(CountryItem item, DownloaderAdapter adapter) - { - MapManager.nativeCancel(item.id); - } - }, - - EXPLORE(R.drawable.ic_explore, R.string.zoom_to_country) - { - @Override - void invoke(CountryItem item, DownloaderAdapter adapter) - { - Intent intent = new Intent(adapter.mActivity, MwmActivity.class); - intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION); - intent.putExtra(MwmActivity.EXTRA_TASK, new Factory.ShowCountryTask(item.id)); - adapter.mActivity.startActivity(intent); - - if (!(adapter.mActivity instanceof MwmActivity)) - adapter.mActivity.finish(); - } - }, - - UPDATE(R.drawable.ic_update, R.string.downloader_update_map) - { - @Override - void invoke(final CountryItem item, DownloaderAdapter adapter) - { - item.update(); - - if (item.status != CountryItem.STATUS_UPDATABLE) - return; - - MapManager.warnOn3gUpdate(adapter.mActivity, item.id, new Runnable() - { - @Override - public void run() - { - MapManager.nativeUpdate(item.id); - } - }); - } - }; - - final @DrawableRes int icon; - final @StringRes int title; - - MenuItem(@DrawableRes int icon, @StringRes int title) - { - this.icon = icon; - this.title = title; + new AlertDialog.Builder(adapter.mActivity) + .setTitle(R.string.downloader_delete_map) + .setMessage(R.string.downloader_delete_map_while_routing_dialog) + .setPositiveButton(android.R.string.ok, null) + .show(); + return; } - abstract void invoke(CountryItem item, DownloaderAdapter adapter); + if (!MapManager.nativeHasUnsavedEditorChanges(item.id)) + { + deleteNode(item, adapter); + return; + } + + new AlertDialog.Builder(adapter.mActivity) + .setTitle(R.string.downloader_delete_map) + .setMessage(R.string.downloader_delete_map_dialog) + .setNegativeButton(android.R.string.no, null) + .setPositiveButton(android.R.string.yes, (dialog, which) -> deleteNode(item, adapter)).show(); + } + + private void onCancelActionSelected(CountryItem item, DownloaderAdapter adapter) + { + MapManager.nativeCancel(item.id); + } + + private void deleteNode(CountryItem item) + { + MapManager.nativeCancel(item.id); + MapManager.nativeDelete(item.id); + OnmapDownloader.setAutodownloadLocked(true); + } + + private void deleteNode(CountryItem item, DownloaderAdapter adapter) + { + if (adapter.mActivity instanceof MwmActivity) + { + ((MwmActivity) adapter.mActivity).closePlacePage(); + } + deleteNode(item); } private static class PathEntry @@ -335,7 +282,7 @@ class DownloaderAdapter extends RecyclerView.Adapter items = new ArrayList<>(); + ArrayList items = getMenuItems(); + new MenuBottomSheetFragment(mItem.name, items) + .show(mFragment.getParentFragmentManager(), "downloaderBottomSheet"); + } + private MenuBottomSheetItem getDownloadMenuItem() + { + return new MenuBottomSheetItem(R.string.downloader_download_map, R.drawable.ic_download, + () -> onDownloadActionSelected(mItem, DownloaderAdapter.this)); + } + + private MenuBottomSheetItem getUpdateMenuItem() + { + return new MenuBottomSheetItem(R.string.downloader_update_map, R.drawable.ic_update, + () -> onUpdateActionSelected(mItem, DownloaderAdapter.this)); + } + + private MenuBottomSheetItem getExploreMenuItem() + { + return new MenuBottomSheetItem(R.string.zoom_to_country, R.drawable.ic_explore, + () -> onExploreActionSelected(mItem, DownloaderAdapter.this)); + } + + private MenuBottomSheetItem getDeleteMenuItem() + { + return new MenuBottomSheetItem(R.string.delete, R.drawable.ic_delete, + () -> onDeleteActionSelected(mItem, DownloaderAdapter.this)); + } + + private MenuBottomSheetItem getCancelMenuItem() + { + return new MenuBottomSheetItem(R.string.cancel, R.drawable.ic_cancel, + () -> onCancelActionSelected(mItem, DownloaderAdapter.this)); + } + + private ArrayList getMenuItems() + { + ArrayList items = new ArrayList<>(); switch (mItem.status) { - case CountryItem.STATUS_DOWNLOADABLE: - items.add(MenuItem.DOWNLOAD); - break; + case CountryItem.STATUS_DOWNLOADABLE: + items.add(getDownloadMenuItem()); + break; - case CountryItem.STATUS_UPDATABLE: - items.add(MenuItem.UPDATE); - // No break + case CountryItem.STATUS_UPDATABLE: + items.add(getUpdateMenuItem()); + // Fallthrough - case CountryItem.STATUS_DONE: - if (!mItem.isExpandable()) - items.add(MenuItem.EXPLORE); + case CountryItem.STATUS_DONE: + if (!mItem.isExpandable()) + items.add(getExploreMenuItem()); + items.add(getDeleteMenuItem()); + break; - items.add(MenuItem.DELETE); - break; + case CountryItem.STATUS_FAILED: + items.add(getCancelMenuItem()); - case CountryItem.STATUS_FAILED: - items.add(MenuItem.CANCEL); + if (mItem.present) + { + items.add(getDeleteMenuItem()); + items.add(getExploreMenuItem()); + } + break; - if (mItem.present) - { - items.add(MenuItem.DELETE); - items.add(MenuItem.EXPLORE); - } - break; + case CountryItem.STATUS_PROGRESS: + case CountryItem.STATUS_APPLYING: + case CountryItem.STATUS_ENQUEUED: + items.add(getCancelMenuItem()); - case CountryItem.STATUS_PROGRESS: - case CountryItem.STATUS_APPLYING: - case CountryItem.STATUS_ENQUEUED: - items.add(MenuItem.CANCEL); + if (mItem.present) + items.add(getExploreMenuItem()); + break; - if (mItem.present) - items.add(MenuItem.EXPLORE); - break; - - case CountryItem.STATUS_PARTLY: - items.add(MenuItem.DOWNLOAD); - items.add(MenuItem.DELETE); - break; + case CountryItem.STATUS_PARTLY: + items.add(getDownloadMenuItem()); + items.add(getDeleteMenuItem()); + break; } - - if (items.isEmpty()) - return; - - BottomSheetHelper.Builder bs = BottomSheetHelper.create(mActivity, mItem.name); - for (MenuItem item: items) - bs.sheet(item.ordinal(), item.icon, item.title); - - BottomSheet bottomSheet = bs.listener(new android.view.MenuItem.OnMenuItemClickListener() - { - @Override - public boolean onMenuItemClick(android.view.MenuItem item) - { - MenuItem.values()[item.getItemId()].invoke(mItem, DownloaderAdapter.this); - return false; - } - }).build(); - BottomSheetHelper.tint(bottomSheet); - bottomSheet.show(); + return items; } ItemViewHolder(View frame) diff --git a/android/src/com/mapswithme/maps/editor/ProfileFragment.java b/android/src/com/mapswithme/maps/editor/ProfileFragment.java index 8bcb85a75e..7bad8e4283 100644 --- a/android/src/com/mapswithme/maps/editor/ProfileFragment.java +++ b/android/src/com/mapswithme/maps/editor/ProfileFragment.java @@ -1,29 +1,25 @@ package com.mapswithme.maps.editor; -import android.content.DialogInterface; import android.content.Intent; import android.net.Uri; import android.os.Bundle; import android.view.View; 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 com.cocosw.bottomsheet.BottomSheet; import com.mapswithme.maps.BuildConfig; import com.mapswithme.maps.R; -import com.mapswithme.util.BottomSheetHelper; import com.mapswithme.util.Constants; import com.mapswithme.util.UiUtils; +import com.mapswithme.util.bottomsheet.MenuBottomSheetFragment; +import com.mapswithme.util.bottomsheet.MenuBottomSheetItem; import com.mapswithme.util.concurrency.ThreadPool; import com.mapswithme.util.concurrency.UiThread; import java.util.ArrayList; -import java.util.List; public class ProfileFragment extends AuthFragment implements View.OnClickListener { @@ -33,40 +29,18 @@ public class ProfileFragment extends AuthFragment implements View.OnClickListene private View mAuthBlock; private View mRatingBlock; - private enum MenuItem + private void onLogoutActionSelected(final ProfileFragment fragment) { - LOGOUT(R.drawable.ic_logout, R.string.logout) - { - @Override - void invoke(final ProfileFragment fragment) - { - new AlertDialog.Builder(fragment.requireContext()) - .setMessage(R.string.are_you_sure) - .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() - { - @Override - public void onClick(DialogInterface dialog, int which) - { - OsmOAuth.clearAuthorization(fragment.requireContext()); - fragment.refreshViews(); - } - }) - .setNegativeButton(android.R.string.no, null) - .create() - .show(); - } - }; - - final @DrawableRes int icon; - final @StringRes int title; - - MenuItem(@DrawableRes int icon, @StringRes int title) - { - this.icon = icon; - this.title = title; - } - - abstract void invoke(ProfileFragment fragment); + new AlertDialog.Builder(fragment.requireContext()) + .setMessage(R.string.are_you_sure) + .setPositiveButton(android.R.string.ok, (dialog, which) -> + { + OsmOAuth.clearAuthorization(fragment.requireContext()); + fragment.refreshViews(); + }) + .setNegativeButton(android.R.string.no, null) + .create() + .show(); } @Override @@ -135,23 +109,8 @@ public class ProfileFragment extends AuthFragment implements View.OnClickListene private void showBottomSheet() { - List items = new ArrayList<>(); - items.add(MenuItem.LOGOUT); - - BottomSheetHelper.Builder bs = BottomSheetHelper.create(getActivity()); - for (MenuItem item: items) - bs.sheet(item.ordinal(), item.icon, item.title); - - BottomSheet bottomSheet = bs.listener(new android.view.MenuItem.OnMenuItemClickListener() - { - @Override - public boolean onMenuItemClick(android.view.MenuItem item) - { - MenuItem.values()[item.getItemId()].invoke(ProfileFragment.this); - return false; - } - }).build(); - BottomSheetHelper.tint(bottomSheet); - bottomSheet.show(); + ArrayList items = new ArrayList<>(); + items.add(new MenuBottomSheetItem(R.string.logout, R.drawable.ic_logout, () -> onLogoutActionSelected(ProfileFragment.this))); + new MenuBottomSheetFragment(items).show(getParentFragmentManager(), "profileBottomSheet"); } } diff --git a/android/src/com/mapswithme/maps/widget/placepage/PlacePageButtons.java b/android/src/com/mapswithme/maps/widget/placepage/PlacePageButtons.java index 84f5058f86..21200e9eab 100644 --- a/android/src/com/mapswithme/maps/widget/placepage/PlacePageButtons.java +++ b/android/src/com/mapswithme/maps/widget/placepage/PlacePageButtons.java @@ -2,7 +2,6 @@ package com.mapswithme.maps.widget.placepage; import android.content.Context; import android.view.LayoutInflater; -import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; @@ -12,13 +11,13 @@ import androidx.annotation.DrawableRes; import androidx.annotation.NonNull; import androidx.annotation.StringRes; -import com.cocosw.bottomsheet.BottomSheet; import com.mapswithme.maps.MwmApplication; import com.mapswithme.maps.R; import com.mapswithme.maps.routing.RoutingController; -import com.mapswithme.util.BottomSheetHelper; import com.mapswithme.util.ThemeUtils; import com.mapswithme.util.UiUtils; +import com.mapswithme.util.bottomsheet.MenuBottomSheetFragment; +import com.mapswithme.util.bottomsheet.MenuBottomSheetItem; import java.util.ArrayList; import java.util.Collections; @@ -309,27 +308,22 @@ public final class PlacePageButtons } } - private void showPopup(final List buttons) + private ArrayList getMenuItems(final List buttons) { - BottomSheetHelper.Builder bs = new BottomSheetHelper.Builder(mPlacePage.getActivity()); + ArrayList items = new ArrayList<>(); for (int i = mMaxButtons; i < buttons.size(); i++) { PlacePageButton bsItem = buttons.get(i); int iconRes = bsItem.getIcon().getEnabledStateResId(mPlacePage.getContext()); - bs.sheet(i, iconRes, bsItem.getTitle()); + items.add(new MenuBottomSheetItem(bsItem.getTitle(), iconRes, () -> mItemListener.onItemClick(bsItem))); } + return items; + } - BottomSheet bottomSheet = bs.listener(new MenuItem.OnMenuItemClickListener() - { - @Override - public boolean onMenuItemClick(MenuItem item) - { - mItemListener.onItemClick(buttons.get(item.getItemId())); - return true; - } - }).build(); - BottomSheetHelper.tint(bottomSheet); - bottomSheet.show(); + private void showPopup(final List buttons) + { + new MenuBottomSheetFragment(getMenuItems(buttons)) + .show(mPlacePage.getActivity().getSupportFragmentManager(), "moreBottomSheet"); } private View createButton(@NonNull final List items, diff --git a/android/src/com/mapswithme/util/bottomsheet/MenuAdapter.java b/android/src/com/mapswithme/util/bottomsheet/MenuAdapter.java new file mode 100644 index 0000000000..622d0252ab --- /dev/null +++ b/android/src/com/mapswithme/util/bottomsheet/MenuAdapter.java @@ -0,0 +1,106 @@ +package com.mapswithme.util.bottomsheet; + +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.recyclerview.widget.RecyclerView; + +import com.mapswithme.maps.R; + +import java.util.ArrayList; + +public class MenuAdapter extends RecyclerView.Adapter +{ + private final ArrayList dataSet; + @Nullable + private final MenuBottomSheetItem.OnClickListener onClickListener; + + public MenuAdapter(ArrayList dataSet, @Nullable MenuBottomSheetItem.OnClickListener onClickListener) + { + this.dataSet = dataSet; + this.onClickListener = onClickListener; + } + + private void onMenuItemClick(MenuBottomSheetItem item) + { + if (onClickListener != null) + onClickListener.onClick(); + item.onClickListener.onClick(); + } + + @NonNull + @Override + public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) + { + View view = LayoutInflater.from(viewGroup.getContext()) + .inflate(R.layout.bottom_sheet_menu_item, viewGroup, false); + return new ViewHolder(view); + } + + @Override + public void onBindViewHolder(ViewHolder viewHolder, final int position) + { + final MenuBottomSheetItem item = dataSet.get(position); + viewHolder.getContainer().setOnClickListener((v) -> onMenuItemClick(item)); + viewHolder.getIconImageView().setImageResource(item.iconRes); + viewHolder.getTitleTextView().setText(item.titleRes); + TextView badge = viewHolder.getBadgeTextView(); + if (item.badgeCount > 0) + { + badge.setText(String.valueOf(item.badgeCount)); + badge.setVisibility(View.VISIBLE); + } else { + badge.setVisibility(View.GONE); + } + } + + @Override + public int getItemCount() + { + return dataSet.size(); + } + + public static class ViewHolder extends RecyclerView.ViewHolder + { + private final LinearLayout container; + private final ImageView iconImageView; + private final TextView titleTextView; + private final TextView badgeTextView; + + public ViewHolder(View view) + { + super(view); + container = view.findViewById(R.id.bottom_sheet_menu_item); + iconImageView = view.findViewById(R.id.bottom_sheet_menu_item_icon); + titleTextView = view.findViewById(R.id.bottom_sheet_menu_item_text); + badgeTextView = view.findViewById(R.id.bottom_sheet_menu_item_badge); + } + + public ImageView getIconImageView() + { + return iconImageView; + } + + public TextView getTitleTextView() + { + return titleTextView; + } + + public TextView getBadgeTextView() + { + return badgeTextView; + } + + public LinearLayout getContainer() + { + return container; + } + } + +} diff --git a/android/src/com/mapswithme/util/bottomsheet/MenuBottomSheetFragment.java b/android/src/com/mapswithme/util/bottomsheet/MenuBottomSheetFragment.java new file mode 100644 index 0000000000..602fa85bbb --- /dev/null +++ b/android/src/com/mapswithme/util/bottomsheet/MenuBottomSheetFragment.java @@ -0,0 +1,79 @@ +package com.mapswithme.util.bottomsheet; + +import android.os.Bundle; +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.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import com.google.android.material.bottomsheet.BottomSheetBehavior; +import com.google.android.material.bottomsheet.BottomSheetDialogFragment; +import com.mapswithme.maps.R; + +import java.util.ArrayList; + +public class MenuBottomSheetFragment extends BottomSheetDialogFragment +{ + @Nullable + private final String title; + private final ArrayList menuBottomSheetItems; + + public MenuBottomSheetFragment(@NonNull String title, ArrayList menuBottomSheetItems) + { + this.title = title; + this.menuBottomSheetItems = menuBottomSheetItems; + } + + public MenuBottomSheetFragment(ArrayList menuBottomSheetItems) + { + this.title = null; + this.menuBottomSheetItems = menuBottomSheetItems; + } + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) + { + super.onCreate(savedInstanceState); + } + + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) + { + return inflater.inflate(R.layout.bottom_sheet, container); + } + + @Override + public void onStart() + { + super.onStart(); + BottomSheetBehavior behavior = BottomSheetBehavior.from((View) requireView().getParent()); + // By default sheets in landscape start at their peek height. + // We fix this by forcing the expanded state and disabling the collapsed one + behavior.setState(BottomSheetBehavior.STATE_EXPANDED); + behavior.setSkipCollapsed(true); + } + + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) + { + super.onViewCreated(view, savedInstanceState); + TextView titleView = view.findViewById(R.id.bottomSheetTitle); + RecyclerView recyclerView = view.findViewById(R.id.bottomSheetMenuContainer); + if (title != null) + { + titleView.setVisibility(View.VISIBLE); + titleView.setText(title); + } else + titleView.setVisibility(View.GONE); + + MenuAdapter menuAdapter = new MenuAdapter(menuBottomSheetItems, this::dismiss); + recyclerView.setAdapter(menuAdapter); + recyclerView.setLayoutManager(new LinearLayoutManager(requireActivity())); + } +} diff --git a/android/src/com/mapswithme/util/bottomsheet/MenuBottomSheetItem.java b/android/src/com/mapswithme/util/bottomsheet/MenuBottomSheetItem.java new file mode 100644 index 0000000000..3d8c5e9f60 --- /dev/null +++ b/android/src/com/mapswithme/util/bottomsheet/MenuBottomSheetItem.java @@ -0,0 +1,30 @@ +package com.mapswithme.util.bottomsheet; + +public class MenuBottomSheetItem +{ + public final int titleRes; + public final int iconRes; + public final int badgeCount; + public final OnClickListener onClickListener; + + public MenuBottomSheetItem(int titleRes, int iconRes, OnClickListener onClickListener) + { + this.titleRes = titleRes; + this.iconRes = iconRes; + this.badgeCount = 0; + this.onClickListener = onClickListener; + } + + public MenuBottomSheetItem(int titleRes, int iconRes, int badgeCount, OnClickListener onClickListener) + { + this.titleRes = titleRes; + this.iconRes = iconRes; + this.badgeCount = badgeCount; + this.onClickListener = onClickListener; + } + + public interface OnClickListener + { + void onClick(); + } +}