Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ios] Implement the Recently Deleted screen to restore deleted categories #7978

Draft
wants to merge 6 commits into
base: master
Choose a base branch
from

Conversation

kirylkaveryn
Copy link
Contributor

@kirylkaveryn kirylkaveryn commented Apr 24, 2024

Closes (for iOS) #1026

This PR contains the default implementation of the Recently Deleted Screen in iOS to restore deleted categories.

Key concepts:

  • when the user deletes a file it will be moved to the .Trash directory rather than removed
  • when the user deletes a file from the Recently Deleted list it should be totally removed
  • when the user restores a file from the Recently Deleted list it should be moved back to the bookmarks directory
  • Recently deleted button is visible only when the .Trash is not empty
  • when the user deletes a file file.kml and trash contains the file with the same name the new deleted file should be renamed to avoid conflicts
  • when the user restores a file file.kml from the Recently Deleted and bookmarks contains the file with the same name the restored file should be renamed

Files structure:
root_directory/
--- bookmarks/
------ file1.kml
------ file2.kml
---.Trash/
------ bookmarks/file3.kml

Todo:

iOS

As a reference the Files app recently deleted screen is used.

  • Screen with UI elements
  • Recover the current file by a swipe
  • Recover All files at once
  • Delete file with swipe
  • Delete All files at once
  • Searching files
  • Multiple selection to restore/delete selected files
  • Hide the recently deleted button when there nothing to delete
  • Skip the removing for the empty categories
  • Fix removing animations for cells (optional)
  • Toast with UNDO when the file was deleted - this will be in the separate PR
  • Integrate with [ios] Base implementation of iCloud Synchronization #7641 - the deletion/restoration process should be supported by the cloud sync feature

Questions:

  • Should the alert be added to the final deletion?
  • Should the timeout for deletion be added? 30 days for example.

Core:

At the moment all code related to the file management functionality is temporary implemented in the MWMBookmarksManager but it should be moved to the cpp core.
Here the API:

@protocol RecentlyDeletedCategoriesManager <NSObject>
- (BOOL)areRecentlyDeletedCategoriesEmpty;
- (NSArray<NSURL *> *)getRecentlyDeletedCategories;
- (void)deleteRecentlyDeletedCategoryAtURLs:(NSArray<NSURL *> *)urls;
- (void)recoverRecentlyDeletedCategoriesAtURLs:(NSArray<NSURL *> *)urls;
@end
  • Method to check is the recently deleted empty
  • Method to move the delete category from the Recently Deleted
  • Method to move the restore category from the Recently Deleted
  • Method to get the list of removed files. It would be better to get an array of elements with: category_path, category_name, and deletion_date
  • Handle the name duplication conflicts on both delete and recover operations - see key concepts

@biodranik @rtsisyk please share your thoughts!


Files App (as a reference):
image image


Temporary results:

Simulator Screen Recording - iPhone 15 Pro - 2024-05-07 at 22 00 39
Simulator Screen Recording - iPhone 15 Pro - 2024-05-07 at 22 01 00
Simulator Screen Recording - iPhone 15 Pro - 2024-05-07 at 22 01 13
Simulator Screen Recording - iPhone 15 Pro - 2024-05-07 at 22 01 36
Simulator Screen Recording - iPhone 15 Pro - 2024-05-07 at 22 01 56
Simulator Screen Recording - iPhone 15 Pro - 2024-05-07 at 22 04 23

@kirylkaveryn kirylkaveryn changed the title Ios/restore catergories from the recently deleted [ios] Implement the Recently Deleted screen to restore deleted categories Apr 24, 2024
@biodranik
Copy link
Member

Multiple selections to restore/delete selected files <- This would be great to have for non-deleted lists first, but if you've already implemented it, that's ok.

deletion_date can be retrieved by checking the last modified file's time. It is updated when the file is moved, right?

Why recently_deleted_id is needed and how it will be retrieved?

Please consider keeping the API clean to be compatible with Android.

And what about the UI in the main bookmarks and tracks screen?

@kirylkaveryn
Copy link
Contributor Author

deletion_date can be retrieved by checking the last modified file's time. It is updated when the file is moved, right?

Yes.

Why recently_deleted_id is needed and how it will be retrieved?

This ID should be created to track the deleted files. It may be the same as MWMMarkGroupID that is used for the bookmark groups now but with a different naming to make API clearer:

@interface MWMBookmarkGroup : NSObject

@property(nonatomic, readonly) MWMMarkGroupID categoryId; // <--- ID
@property(nonatomic, readonly) NSString *title;
...
- (NSString *)getCategoryName:(MWMMarkGroupID)groupId
{
  return @(self.bm.GetCategoryName(groupId).c_str());
}

std::string BookmarkManager::GetCategoryName(kml::MarkGroupId categoryId) const

It will be easier to implement logic when we can pass only the ID to the core to restore files.

And what about the UI in the main bookmarks and tracks screen?

In the first implementation I've added a new button here:
image

@biodranik
Copy link
Member

Thanks! Will deleted IDs reuse the same API as non-deleted lists? Maybe it would be better to split it? And if it is split, can introducing an intermediate int ID be avoided in favor of using a full file path instead? It may simplify the support.

@kirylkaveryn
Copy link
Contributor Author

Thanks! Will deleted IDs reuse the same API as non-deleted lists? Maybe it would be better to split it? And if it is split, can introducing an intermediate int ID be avoided in favor of using a full file path instead? It may simplify the support.

The API splittting would be better! And we can use the full path, sure. So the frontend will wait from the core only the category name, path and timeInteraval (date). And we can restore using something like restoreCategoryAtPath:(string path) in core.

@kirylkaveryn kirylkaveryn force-pushed the ios/restore-catergories-from-the-recently-deleted branch from 1b56238 to d2f0ac4 Compare April 28, 2024 18:56
@biodranik
Copy link
Member

Should the alert be added to the final deletion?

No, cleaning should be easy.

Should the timeout for deletion be added? 30 days for example.

A first version likely can be released with manual deletion only. A presence of the button means that "something is in the trash". Scanning deleted files on each opening of bookmarks to show some counter doesn't make much sense.

As people travel and use OM a lot, an automated cleanup can be implemented. Maybe make it in a friendly way: when bookmarks dialog is opened, a confirmation asks to clean up trash, to see the trash, or to ignore and do nothing.


  1. Shouldn't Edit mode in Trash always be active? Why an additional click on the Edit button is required?

  2. Empty lists should not get into the trash.

  3. Showing a name of the deleted list instead of a file name is required, file names can be completely unknown/unexpected to users.

  4. Showing a number of objects in a file is also useful. We can add some API stubs for it, and add implementation later.

  5. The name "Recently deleted" implies that items are not stored there for a longer time.

@organicmaps/contributors WDYT on the topic? Any ideas/improvements/suggestions? Can anyone help @kirylkaveryn with the C++ core API design/implementation part, and then with Android part?

@pastk
Copy link
Contributor

pastk commented May 8, 2024

As people travel and use OM a lot, an automated cleanup can be implemented. Maybe make it in a friendly way: when bookmarks dialog is opened, a confirmation asks to clean up trash, to see the trash, or to ignore and do nothing.

I think a sudden popup could be very disruptive for user's flow. Maybe there could be a red dot on "recently deleted" to attract some attention.

@pastk
Copy link
Contributor

pastk commented May 8, 2024

Overall I think its important to design this feature in a way so that it could support undo deletion of individual bookmarks in the future.

Signed-off-by: Kiryl Kaveryn <kirylkaveryn@gmail.com>
Signed-off-by: Kiryl Kaveryn <kirylkaveryn@gmail.com>
Signed-off-by: Kiryl Kaveryn <kirylkaveryn@gmail.com>
delete_all, recover, recover_all, bookmarks_recently_deleted

Signed-off-by: Kiryl Kaveryn <kirylkaveryn@gmail.com>
Signed-off-by: Kiryl Kaveryn <kirylkaveryn@gmail.com>
- replace #imageLiteral with the convenient UIImage
- set the images rendering mode to the `template` to support a programmatically tinting
- set the image's tint color directly

Signed-off-by: Kiryl Kaveryn <kirylkaveryn@gmail.com>
@kirylkaveryn kirylkaveryn force-pushed the ios/restore-catergories-from-the-recently-deleted branch from d2f0ac4 to acdf9fe Compare May 8, 2024 08:36
@kirylkaveryn
Copy link
Contributor Author

  • Shouldn't Edit mode in Trash always be active? Why an additional click on the Edit button is required?

While the selection mode is active the trailing swipes cannot be triggered in ios. Deletion with a swipe is widely used. I repeated the system's native behavior so the user shouldn't adatp and delete rows as he can make in Mail, Files, Notes, Reminder etc.

  • Empty lists should not get into the trash.

Done!

  • Showing a name of the deleted list instead of a file name is required, file names can be completely unknown/unexpected to users.
  • Showing a number of objects in a file is also useful. We can add some API stubs for it, and add implementation later.

This information should be retrieved as a result of parsing files by the core.

5. The name "Recently deleted" implies that items are not stored there for a longer time.

Maybe we can use Deleted Categories?

@biodranik
Copy link
Member

Deleting rows from the trash is not the main function of the trash )

Categories internally in the code are facing users as "Lists" translation.
"Categories" for users are the different feature types :) We may need to do some renaming to avoid confusion.

Let's focus again on the main function of the trash: easily restore an accidentally deleted list. Or a recently deleted list. Restoring a recently deleted bookmark or track can also be an option. Any other functionality from the Files app is an unnecessary overhead.

Thinking about bookmarks and tracks, can we move them (instead of deleting them) to some pre-defined lists like "Deleted Bookmarks" and "Deleted Tracks"?

@pastk
Copy link
Contributor

pastk commented May 9, 2024

Thinking about bookmarks and tracks, can we move them (instead of deleting them) to some pre-defined lists like "Deleted Bookmarks" and "Deleted Tracks"?

Its an option, but it'd be better to restore a deleted bookmark back to its original list (maybe its possible to store the original list value in some metadata?).

Also from a UX POV it could be confusing to see some surrogate "Deleted bookmarks" list amongst other deleted lists :/

IMO for a user it'd be more logical if a deleted bookmark from the "My Places" list could be found under the same "My Places" grouping in "recently deleted". But that means it should be possible to enter "deleted lists" and restore individual items and if the whole deleted list is being restored then it should be merged with the current one with the same name (if exists).

Another option is to list deleted bookmarks / tracks at the same level as deleted lists (but still need to preserve the original list).

Yet another option is to handle bookmarks deletion very differently via a separate UI, e.g. by marking them as "deleted" inside the list and adding a list action to browse and restore "deleted" items.

As this functionality is not needed often then it makes sense to choose the most simple option.

@biodranik
Copy link
Member

but it'd be better to restore a deleted bookmark back to its original list

What if the original list has been deleted/renamed?

Generally, I agree that we're overengineering a simple task. Currently, users are complaining only about restoring accidentally deleted bookmarks or lists. So providing an immediate way of restoring something recently deleted could be sufficient and simple enough to release sooner.

Another idea:

  1. Deleting list just stores some special piece of data in kml that "it's deleted". Loading/rendering code ignores deleted lists. UI shows them for example at the bottom in a separate Recently deleted section.
  2. Deleting a bookmark or a track also leaves it in the kml list, but marks it with a special piece of data. This approach can be applied only when a bookmark is deleted on the map, and when user taps again on the same place to bookmark it, a "deleted" bookmark is restored instead of creating a new one. An educational toast can be displayed once or several times when user deletes a bookmark on the map.

@pastk
Copy link
Contributor

pastk commented May 9, 2024

What if the original list has been deleted/renamed?

Then the restored bookmark will be the only one in that list.

@pastk
Copy link
Contributor

pastk commented May 9, 2024

Generally, I agree that we're overengineering a simple task. Currently, users are complaining only about restoring accidentally deleted bookmarks or lists.

Actually my impression is that its mostly about bookmarks. Accidental list deletion is much more rare.

And actually an easily accessible autobackup (just to some user-accessible folder on the same device) might be a simpler solution for restoration of whole lists.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants