diff --git a/iphone/Maps/Bookmarks/BookmarksList/BookmarksListInteractor.swift b/iphone/Maps/Bookmarks/BookmarksList/BookmarksListInteractor.swift index af144e5151..1c5cd47c1a 100644 --- a/iphone/Maps/Bookmarks/BookmarksList/BookmarksListInteractor.swift +++ b/iphone/Maps/Bookmarks/BookmarksList/BookmarksListInteractor.swift @@ -121,14 +121,24 @@ extension BookmarksListInteractor: IBookmarksListInteractor { return BookmarksListSortingType(bookmarksManager.lastSortingType(markGroupId)) } - func deleteBookmark(_ bookmarkId: MWMMarkID) { + func deleteBookmark(_ bookmarkId: MWMMarkID, completion: (Bookmark) -> Void) { + completion(bookmarksManager.bookmark(withId: bookmarkId)) bookmarksManager.deleteBookmark(bookmarkId) } - func deleteTrack(_ trackId: MWMTrackID) { + func deleteTrack(_ trackId: MWMTrackID, completion: (Track) -> Void) { + completion(bookmarksManager.track(withId: trackId)) bookmarksManager.deleteTrack(trackId) } + func recoverBookmark(_ bookmarkId: MWMMarkID) { + bookmarksManager.recoverBookmark(bookmarkId) + } + + func recoverTrack(_ trackId: MWMTrackID) { + bookmarksManager.recoverTrack(trackId) + } + func moveBookmark(_ bookmarkId: MWMMarkID, toGroupId groupId: MWMMarkGroupID) { bookmarksManager.moveBookmark(bookmarkId, toGroupId: groupId) } @@ -183,4 +193,9 @@ extension BookmarksListInteractor: BookmarksObserver { func onBookmarksCategoryDeleted(_ groupId: MWMMarkGroupID) { reloadCategory() } + + func onBookmarksCategoryUpdated(_ groupId: MWMMarkGroupID) { + guard groupId == markGroupId else { return } + reloadCategory() + } } diff --git a/iphone/Maps/Bookmarks/BookmarksList/BookmarksListInterfaces.swift b/iphone/Maps/Bookmarks/BookmarksList/BookmarksListInterfaces.swift index 6767d392d3..6dcdf92f5f 100644 --- a/iphone/Maps/Bookmarks/BookmarksList/BookmarksListInterfaces.swift +++ b/iphone/Maps/Bookmarks/BookmarksList/BookmarksListInterfaces.swift @@ -110,8 +110,10 @@ protocol IBookmarksListInteractor { completion: @escaping ([BookmarksSection]) -> Void) func resetSort() func lastSortingType() -> BookmarksListSortingType? - func deleteBookmark(_ bookmarkId: MWMMarkID) - func deleteTrack(_ trackId: MWMTrackID) + func deleteBookmark(_ bookmarkId: MWMMarkID, completion: (Bookmark) -> Void) + func deleteTrack(_ trackId: MWMTrackID, completion: (Track) -> Void) + func recoverBookmark(_ bookmarkId: MWMMarkID) + func recoverTrack(_ trackId: MWMTrackID) func moveBookmark(_ bookmarkId: MWMMarkID, toGroupId: MWMMarkGroupID) func moveTrack(_ trackId: MWMTrackID, toGroupId: MWMMarkGroupID) func updateBookmark(_ bookmarkId: MWMMarkID, setGroupId groupId: MWMMarkGroupID, title: String, color: BookmarkColor, description: String) diff --git a/iphone/Maps/Bookmarks/BookmarksList/BookmarksListPresenter.swift b/iphone/Maps/Bookmarks/BookmarksList/BookmarksListPresenter.swift index b944c80db5..3546dff123 100644 --- a/iphone/Maps/Bookmarks/BookmarksList/BookmarksListPresenter.swift +++ b/iphone/Maps/Bookmarks/BookmarksList/BookmarksListPresenter.swift @@ -273,11 +273,25 @@ extension BookmarksListPresenter: IBookmarksListPresenter { switch section { case let bookmarksSection as IBookmarksSectionViewModel: guard let bookmark = bookmarksSection.bookmarks[index] as? BookmarkViewModel else { fatalError() } - interactor.deleteBookmark(bookmark.bookmarkId) + interactor.deleteBookmark(bookmark.bookmarkId) { bookmark in + // TODO: localize texts + Toast.undoToast(deletedObject: bookmark.bookmarkName, + undoAction: { [weak self, interactor] in + interactor.recoverBookmark(bookmark.bookmarkId) + self?.reload() + }).show() + } reload() case let tracksSection as ITracksSectionViewModel: guard let track = tracksSection.tracks[index] as? TrackViewModel else { fatalError() } - interactor.deleteTrack(track.trackId) + interactor.deleteTrack(track.trackId) { track in + // TODO: localize texts + Toast.undoToast(deletedObject: track.trackName, + undoAction: { [weak self, interactor] in + interactor.recoverTrack(track.trackId) + self?.reload() + }).show() + } reload() default: fatalError("Cannot delete item: unsupported section type: \(section.self)") diff --git a/iphone/Maps/Bookmarks/Categories/BMCView/BMCViewController.swift b/iphone/Maps/Bookmarks/Categories/BMCView/BMCViewController.swift index 51fbd45775..91f7698579 100644 --- a/iphone/Maps/Bookmarks/Categories/BMCView/BMCViewController.swift +++ b/iphone/Maps/Bookmarks/Categories/BMCView/BMCViewController.swift @@ -185,6 +185,10 @@ extension BMCViewController: BMCView { } } } + + func isVisible() -> Bool { + isViewLoaded && view.window != nil + } } extension BMCViewController: UITableViewDataSource { diff --git a/iphone/Maps/Bookmarks/Categories/BMCViewModel/BMCDefaultViewModel.swift b/iphone/Maps/Bookmarks/Categories/BMCViewModel/BMCDefaultViewModel.swift index 69195c361b..d742d60db2 100644 --- a/iphone/Maps/Bookmarks/Categories/BMCViewModel/BMCDefaultViewModel.swift +++ b/iphone/Maps/Bookmarks/Categories/BMCViewModel/BMCDefaultViewModel.swift @@ -3,6 +3,7 @@ protocol BMCView: AnyObject { func delete(at indexPaths: [IndexPath]) func insert(at indexPaths: [IndexPath]) func conversionFinished(success: Bool) + func isVisible() -> Bool } final class BMCDefaultViewModel: NSObject { @@ -169,10 +170,12 @@ extension BMCDefaultViewModel: BookmarksObserver { } func onBookmarksCategoryDeleted(_ groupId: MWMMarkGroupID) { + guard let view, view.isVisible() else { return } reloadData() } - func onBookmarkDeleted(_: MWMMarkID) { + func onBookmarksCategoryUpdated(_ groupId: MWMMarkGroupID) { + guard let view, view.isVisible() else { return } reloadData() } } diff --git a/iphone/Maps/UI/EditBookmark/EditBookmarkViewController.swift b/iphone/Maps/UI/EditBookmark/EditBookmarkViewController.swift index 2d0911df1b..3f5272c712 100644 --- a/iphone/Maps/UI/EditBookmark/EditBookmarkViewController.swift +++ b/iphone/Maps/UI/EditBookmark/EditBookmarkViewController.swift @@ -235,6 +235,10 @@ extension EditBookmarkViewController: MWMNoteCellDelegate { extension EditBookmarkViewController: MWMButtonCellDelegate { func cellDidPressButton(_ cell: UITableViewCell) { BookmarksManager.shared().deleteBookmark(bookmarkId) + Toast.undoToast(deletedObject: bookmarkTitle ?? L("bookmark"), + undoAction: { [bookmarkId] in + BookmarksManager.shared().recoverBookmark(bookmarkId) + }).show() if let placePageData = placePageData { FrameworkHelper.updateAfterDeleteBookmark() placePageData.updateBookmarkStatus() diff --git a/iphone/Maps/UI/EditBookmark/EditTrackViewController.swift b/iphone/Maps/UI/EditBookmark/EditTrackViewController.swift index f82e3d956a..de8e1e45bb 100644 --- a/iphone/Maps/UI/EditBookmark/EditTrackViewController.swift +++ b/iphone/Maps/UI/EditBookmark/EditTrackViewController.swift @@ -186,7 +186,12 @@ extension EditTrackViewController: BookmarkTitleCellDelegate { extension EditTrackViewController: MWMButtonCellDelegate { func cellDidPressButton(_ cell: UITableViewCell) { - bookmarksManager.deleteTrack(trackId) + BookmarksManager.shared().deleteTrack(trackId) + Toast.undoToast(withText: trackTitle ?? L("track_title"), + undoAction: { [trackId] in + BookmarksManager.shared().recoverTrack(trackId) + }).show() + // TODO: When the PlacePage screen will be implemented it should be reloaded here (see EditBookmarkViewController). goBack() } } diff --git a/iphone/Maps/UI/PlacePage/Components/ActionBarViewController.swift b/iphone/Maps/UI/PlacePage/Components/ActionBarViewController.swift index 35c8843e3f..6a93474886 100644 --- a/iphone/Maps/UI/PlacePage/Components/ActionBarViewController.swift +++ b/iphone/Maps/UI/PlacePage/Components/ActionBarViewController.swift @@ -64,6 +64,13 @@ class ActionBarViewController: UIViewController { configureButtons() } + func setBookmarkSelected(_ isSelected: Bool) { + guard let bookmarkButton = stackView.arrangedSubviews.first(where: { ($0 as? ActionBarButton)?.type == .bookmark }) as? ActionBarButton else { + return + } + bookmarkButton.setBookmarkSelected(isSelected) + } + override func viewDidLoad() { super.viewDidLoad() diff --git a/iphone/Maps/UI/PlacePage/PlacePageLayout/ActionBar/MWMActionBarButton.h b/iphone/Maps/UI/PlacePage/PlacePageLayout/ActionBar/MWMActionBarButton.h index 52ea9baa63..e8aab9bf6c 100644 --- a/iphone/Maps/UI/PlacePage/PlacePageLayout/ActionBar/MWMActionBarButton.h +++ b/iphone/Maps/UI/PlacePage/PlacePageLayout/ActionBar/MWMActionBarButton.h @@ -47,6 +47,8 @@ NS_SWIFT_NAME(ActionBarButton) isSelected:(BOOL)isSelected isEnabled:(BOOL)isEnabled; +- (void)setBookmarkSelected:(BOOL)isSelected; + @end NS_ASSUME_NONNULL_END diff --git a/iphone/Maps/UI/PlacePage/PlacePageLayout/ActionBar/MWMActionBarButton.m b/iphone/Maps/UI/PlacePage/PlacePageLayout/ActionBar/MWMActionBarButton.m index 1b4da13d6a..4cb3e07e5c 100644 --- a/iphone/Maps/UI/PlacePage/PlacePageLayout/ActionBar/MWMActionBarButton.m +++ b/iphone/Maps/UI/PlacePage/PlacePageLayout/ActionBar/MWMActionBarButton.m @@ -155,8 +155,6 @@ NSString *titleForButton(MWMActionBarButtonType type, BOOL isSelected) { } - (IBAction)tap { - if (self.type == MWMActionBarButtonTypeBookmark) - [self setBookmarkSelected:!self.button.isSelected]; if (self.type == MWMActionBarButtonTypeRouteTo) [self disableRouteToButtonHighlight]; @@ -164,7 +162,10 @@ NSString *titleForButton(MWMActionBarButtonType type, BOOL isSelected) { } - (void)setBookmarkSelected:(BOOL)isSelected { - if (isSelected) + if (self.type != MWMActionBarButtonTypeBookmark) + return; + + if (!self.button.isSelected && isSelected) [self.button.imageView startAnimating]; self.button.selected = isSelected; diff --git a/iphone/Maps/UI/PlacePage/PlacePageLayout/Layouts/PlacePageCommonLayout.swift b/iphone/Maps/UI/PlacePage/PlacePageLayout/Layouts/PlacePageCommonLayout.swift index 2e9ec14f88..a24ff0817b 100644 --- a/iphone/Maps/UI/PlacePage/PlacePageLayout/Layouts/PlacePageCommonLayout.swift +++ b/iphone/Maps/UI/PlacePage/PlacePageLayout/Layouts/PlacePageCommonLayout.swift @@ -187,6 +187,7 @@ extension PlacePageCommonLayout { bookmarkViewController.bookmarkData = bookmarkData isBookmark = true } + actionBarViewController.setBookmarkSelected(isBookmark) if let title = placePageData.previewData.title, let headerViewController = headerViewControllers.compactMap({ $0 as? PlacePageHeaderViewController }).first { let secondaryTitle = placePageData.previewData.secondaryTitle headerViewController.setTitle(title, secondaryTitle: secondaryTitle) @@ -195,6 +196,7 @@ extension PlacePageCommonLayout { self.presenter?.layoutIfNeeded() UIView.animate(withDuration: kDefaultAnimationDuration) { [unowned self] in self.bookmarkViewController.view.isHidden = !isBookmark + self.actionBar?.placePageData = self.placePageData self.presenter?.layoutIfNeeded() } } diff --git a/iphone/Maps/UI/PlacePage/PlacePageManager/MWMPlacePageManager.mm b/iphone/Maps/UI/PlacePage/PlacePageManager/MWMPlacePageManager.mm index 779c5e90d4..80c36996a1 100644 --- a/iphone/Maps/UI/PlacePage/PlacePageManager/MWMPlacePageManager.mm +++ b/iphone/Maps/UI/PlacePage/PlacePageManager/MWMPlacePageManager.mm @@ -187,11 +187,28 @@ using namespace storage; - (void)removeBookmark:(PlacePageData *)data { - auto &f = GetFramework(); - f.GetBookmarkManager().GetEditSession().DeleteBookmark(data.bookmarkData.bookmarkId); + PlacePageBookmarkData * bookmarkData = data.bookmarkData; + NSString * bookmarkTitle = data.previewData.title; + + [MWMBookmarksManager.sharedManager deleteBookmark:bookmarkData.bookmarkId]; + + [[MWMToast undoToastWithDeletedObject:bookmarkTitle undoAction:^{ + [MWMBookmarksManager.sharedManager recoverBookmark:bookmarkData.bookmarkId]; + + // Skip updating PP if it's closed. + if (![self isPPShown]) + return; + + auto & f = GetFramework(); + auto & info = f.GetCurrentPlacePageInfo(); + auto buildInfo = info.GetBuildInfo(); + buildInfo.m_match = place_page::BuildInfo::Match::Everything; + buildInfo.m_userMarkId = bookmarkData.bookmarkId; + f.UpdatePlacePageInfoForCurrentSelection(buildInfo); + [data updateBookmarkStatus]; + }] show]; [MWMFrameworkHelper updateAfterDeleteBookmark]; - [data updateBookmarkStatus]; }