From 05fd7f181fbd84f1499efaf11a15f3c4821c98c7 Mon Sep 17 00:00:00 2001 From: Nikolay Pultsin Date: Sun, 27 Jul 2014 22:10:55 +0100 Subject: [PATCH] new synchronisation-related actions in library menus --- assets/resources/application/en.xml | 12 +- .../fbreader/library/LibraryActivity.java | 159 +++++++++++++----- .../synchroniser/SynchroniserService.java | 3 +- .../fbreader/library/SyncLabelTree.java | 6 +- 4 files changed, 126 insertions(+), 54 deletions(-) diff --git a/assets/resources/application/en.xml b/assets/resources/application/en.xml index daa279691..109b9201b 100644 --- a/assets/resources/application/en.xml +++ b/assets/resources/application/en.xml @@ -53,10 +53,8 @@ - - - - + + @@ -66,6 +64,8 @@ + + @@ -849,6 +849,10 @@ + + + + diff --git a/src/org/geometerplus/android/fbreader/library/LibraryActivity.java b/src/org/geometerplus/android/fbreader/library/LibraryActivity.java index eac2e4cae..446ccf529 100644 --- a/src/org/geometerplus/android/fbreader/library/LibraryActivity.java +++ b/src/org/geometerplus/android/fbreader/library/LibraryActivity.java @@ -19,7 +19,7 @@ package org.geometerplus.android.fbreader.library; -import java.util.List; +import java.util.*; import android.app.AlertDialog; import android.app.SearchManager; @@ -154,10 +154,7 @@ public class LibraryActivity extends TreeActivity implements MenuIt return true; } - // - // Context menu - // - private interface ItemId { + private interface ContextItemId { int OpenBook = 0; int ShowBookInfo = 1; int ShareBook = 2; @@ -168,6 +165,12 @@ public class LibraryActivity extends TreeActivity implements MenuIt int DeleteBook = 7; int SyncAgain = 8; } + private interface OptionsItemId { + int Search = 0; + int Rescan = 1; + int SyncAgain = 2; + int DeleteAll = 3; + } @Override public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo) { @@ -182,26 +185,26 @@ public class LibraryActivity extends TreeActivity implements MenuIt final ZLResource resource = LibraryTree.resource(); final List labels = book.labels(); menu.setHeaderTitle(book.getTitle()); - menu.add(0, ItemId.OpenBook, 0, resource.getResource("openBook").getValue()); - menu.add(0, ItemId.ShowBookInfo, 0, resource.getResource("showBookInfo").getValue()); + menu.add(0, ContextItemId.OpenBook, 0, resource.getResource("openBook").getValue()); + menu.add(0, ContextItemId.ShowBookInfo, 0, resource.getResource("showBookInfo").getValue()); if (book.File.getPhysicalFile() != null) { - menu.add(0, ItemId.ShareBook, 0, resource.getResource("shareBook").getValue()); + menu.add(0, ContextItemId.ShareBook, 0, resource.getResource("shareBook").getValue()); } if (labels.contains(Book.FAVORITE_LABEL)) { - menu.add(0, ItemId.RemoveFromFavorites, 0, resource.getResource("removeFromFavorites").getValue()); + menu.add(0, ContextItemId.RemoveFromFavorites, 0, resource.getResource("removeFromFavorites").getValue()); } else { - menu.add(0, ItemId.AddToFavorites, 0, resource.getResource("addToFavorites").getValue()); + menu.add(0, ContextItemId.AddToFavorites, 0, resource.getResource("addToFavorites").getValue()); } if (labels.contains(Book.READ_LABEL)) { - menu.add(0, ItemId.MarkAsUnread, 0, resource.getResource("markAsUnread").getValue()); + menu.add(0, ContextItemId.MarkAsUnread, 0, resource.getResource("markAsUnread").getValue()); } else { - menu.add(0, ItemId.MarkAsRead, 0, resource.getResource("markAsRead").getValue()); + menu.add(0, ContextItemId.MarkAsRead, 0, resource.getResource("markAsRead").getValue()); } if (BookUtil.canRemoveBookFile(book)) { - menu.add(0, ItemId.DeleteBook, 0, resource.getResource("deleteBook").getValue()); + menu.add(0, ContextItemId.DeleteBook, 0, resource.getResource("deleteBook").getValue()); } if (labels.contains(Book.SYNC_FAILURE_LABEL) || labels.contains(Book.SYNC_DELETED_LABEL)) { - menu.add(0, ItemId.SyncAgain, 0, resource.getResource("syncAgain").getValue()); + menu.add(0, ContextItemId.SyncAgain, 0, resource.getResource("syncAgain").getValue()); } } @@ -215,46 +218,50 @@ public class LibraryActivity extends TreeActivity implements MenuIt return super.onContextItemSelected(item); } + private void syncAgain(Book book) { + book.removeLabel(Book.SYNC_FAILURE_LABEL); + book.removeLabel(Book.SYNC_DELETED_LABEL); + book.addLabel(Book.SYNC_TOSYNC_LABEL); + myRootTree.Collection.saveBook(book); + } + private boolean onContextItemSelected(int itemId, Book book) { switch (itemId) { - case ItemId.OpenBook: + case ContextItemId.OpenBook: FBReader.openBookActivity(this, book, null); return true; - case ItemId.ShowBookInfo: + case ContextItemId.ShowBookInfo: showBookInfo(book); return true; - case ItemId.ShareBook: + case ContextItemId.ShareBook: FBUtil.shareBook(this, book); return true; - case ItemId.AddToFavorites: + case ContextItemId.AddToFavorites: book.addLabel(Book.FAVORITE_LABEL); myRootTree.Collection.saveBook(book); return true; - case ItemId.RemoveFromFavorites: + case ContextItemId.RemoveFromFavorites: book.removeLabel(Book.FAVORITE_LABEL); myRootTree.Collection.saveBook(book); if (getCurrentTree().onBookEvent(BookEvent.Updated, book)) { getListAdapter().replaceAll(getCurrentTree().subtrees(), true); } return true; - case ItemId.MarkAsRead: + case ContextItemId.MarkAsRead: book.addLabel(Book.READ_LABEL); myRootTree.Collection.saveBook(book); getListView().invalidateViews(); return true; - case ItemId.MarkAsUnread: + case ContextItemId.MarkAsUnread: book.removeLabel(Book.READ_LABEL); myRootTree.Collection.saveBook(book); getListView().invalidateViews(); return true; - case ItemId.DeleteBook: + case ContextItemId.DeleteBook: tryToDeleteBook(book); return true; - case ItemId.SyncAgain: - book.removeLabel(Book.SYNC_FAILURE_LABEL); - book.removeLabel(Book.SYNC_DELETED_LABEL); - book.addLabel(Book.SYNC_TOSYNC_LABEL); - myRootTree.Collection.saveBook(book); + case ContextItemId.SyncAgain: + syncAgain(book); if (getCurrentTree().onBookEvent(BookEvent.Updated, book)) { getListAdapter().replaceAll(getCurrentTree().subtrees(), true); } @@ -270,20 +277,39 @@ public class LibraryActivity extends TreeActivity implements MenuIt @Override public boolean onCreateOptionsMenu(Menu menu) { super.onCreateOptionsMenu(menu); - addMenuItem(menu, 1, "localSearch", R.drawable.ic_menu_search); - addMenuItem(menu, 2, "rescan", R.drawable.ic_menu_refresh); + addMenuItem(menu, OptionsItemId.Search, "localSearch", R.drawable.ic_menu_search); + addMenuItem(menu, OptionsItemId.Rescan, "rescan", R.drawable.ic_menu_refresh); + addMenuItem(menu, OptionsItemId.SyncAgain, "syncAgain", -1); + addMenuItem(menu, OptionsItemId.DeleteAll, "deleteAll", -1); return true; } @Override public boolean onPrepareOptionsMenu(Menu menu) { super.onPrepareOptionsMenu(menu); - menu.findItem(2).setEnabled(myRootTree.Collection.status().IsCompleted); + + boolean enableSyncAgain = false; + boolean enableDeleteAll = false; + final LibraryTree tree = getCurrentTree(); + if (tree instanceof SyncLabelTree) { + final String label = ((SyncLabelTree)tree).Label; + if (Book.SYNC_DELETED_LABEL.equals(label)) { + enableSyncAgain = true; + enableDeleteAll = true; + } else if (Book.SYNC_FAILURE_LABEL.equals(label)) { + enableSyncAgain = true; + } + } + + menu.findItem(OptionsItemId.Rescan).setEnabled(myRootTree.Collection.status().IsCompleted); + menu.findItem(OptionsItemId.SyncAgain).setVisible(enableSyncAgain); + menu.findItem(OptionsItemId.DeleteAll).setVisible(enableDeleteAll); + return true; } private MenuItem addMenuItem(Menu menu, int id, String resourceKey, int iconId) { - final String label = LibraryTree.resource().getResource("menu").getResource(resourceKey).getValue(); + final String label = LibraryTree.resource().getResource(resourceKey).getValue(); final MenuItem item = menu.add(0, id, Menu.NONE, label); item.setOnMenuItemClickListener(this); item.setIcon(iconId); @@ -292,14 +318,32 @@ public class LibraryActivity extends TreeActivity implements MenuIt public boolean onMenuItemClick(MenuItem item) { switch (item.getItemId()) { - case 1: + case OptionsItemId.Search: return onSearchRequested(); - case 2: + case OptionsItemId.Rescan: if (myRootTree.Collection.status().IsCompleted) { ((BookCollectionShadow)myRootTree.Collection).reset(true); openTree(myRootTree); } return true; + case OptionsItemId.SyncAgain: + for (FBTree tree : getCurrentTree().subtrees()) { + if (tree instanceof BookTree) { + syncAgain(((BookTree)tree).Book); + } + } + getListAdapter().replaceAll(getCurrentTree().subtrees(), true); + return true; + case OptionsItemId.DeleteAll: + { + final List books = new LinkedList(); + for (FBTree tree : getCurrentTree().subtrees()) { + if (tree instanceof BookTree) { + books.add(((BookTree)tree).Book); + } + } + tryToDeleteBooks(books); + } default: return true; } @@ -309,37 +353,60 @@ public class LibraryActivity extends TreeActivity implements MenuIt // Book deletion // private class BookDeleter implements DialogInterface.OnClickListener { - private final Book myBook; + private final List myBooks; - BookDeleter(Book book) { - myBook = book; + BookDeleter(List books) { + myBooks = new ArrayList(books); } public void onClick(DialogInterface dialog, int which) { if (getCurrentTree() instanceof FileTree) { - getListAdapter().remove(new FileTree((FileTree)getCurrentTree(), myBook.File)); + for (Book book : myBooks) { + getListAdapter().remove(new FileTree((FileTree)getCurrentTree(), book.File)); + myRootTree.Collection.removeBook(book, true); + } getListView().invalidateViews(); - } else if (getCurrentTree().onBookEvent(BookEvent.Removed, myBook)) { - getListAdapter().replaceAll(getCurrentTree().subtrees(), true); + } else { + boolean doReplace = false; + for (Book book : myBooks) { + doReplace |= getCurrentTree().onBookEvent(BookEvent.Removed, book); + myRootTree.Collection.removeBook(book, true); + } + if (doReplace) { + getListAdapter().replaceAll(getCurrentTree().subtrees(), true); + } } - - myRootTree.Collection.removeBook(myBook, true); } } - private void tryToDeleteBook(Book book) { + private void tryToDeleteBooks(List books) { + final int size = books.size(); + if (size == 0) { + return; + } final ZLResource dialogResource = ZLResource.resource("dialog"); final ZLResource buttonResource = dialogResource.getResource("button"); - final ZLResource boxResource = dialogResource.getResource("deleteBookBox"); + final ZLResource boxResource = dialogResource.getResource( + size == 1 ? "deleteBookBox" : "deleteMultipleBookBox" + ); + final String title = size == 1 + ? books.get(0).getTitle() + : boxResource.getResource("title").getValue(); + final String message = + boxResource.getResource("message").getValue(size).replaceAll("%s", String.valueOf(size)); new AlertDialog.Builder(this) - .setTitle(book.getTitle()) - .setMessage(boxResource.getResource("message").getValue()) + .setTitle(title) + .setMessage(message) .setIcon(0) - .setPositiveButton(buttonResource.getResource("yes").getValue(), new BookDeleter(book)) + .setPositiveButton(buttonResource.getResource("yes").getValue(), new BookDeleter(books)) .setNegativeButton(buttonResource.getResource("no").getValue(), null) .create().show(); } + private void tryToDeleteBook(Book book) { + tryToDeleteBooks(Collections.singletonList(book)); + } + private void startBookSearch(final String pattern) { BookSearchPatternOption.setValue(pattern); diff --git a/src/org/geometerplus/android/fbreader/synchroniser/SynchroniserService.java b/src/org/geometerplus/android/fbreader/synchroniser/SynchroniserService.java index a08cda022..828fce009 100644 --- a/src/org/geometerplus/android/fbreader/synchroniser/SynchroniserService.java +++ b/src/org/geometerplus/android/fbreader/synchroniser/SynchroniserService.java @@ -216,7 +216,8 @@ public class SynchroniserService extends Service implements IBookCollection.List return SyncStatus.HashNotComputed; } else if (myActualHashesFromServer.contains(hash)) { return SyncStatus.AlreadyUploaded; - } else if (myDeletedHashesFromServer.contains(hash)) { + } else if (myDeletedHashesFromServer.contains(hash) && + !book.labels().contains(Book.SYNC_TOSYNC_LABEL)) { return SyncStatus.ToBeDeleted; } else if (book.labels().contains(Book.SYNC_FAILURE_LABEL)) { return SyncStatus.FailedPreviuousTime; diff --git a/src/org/geometerplus/fbreader/library/SyncLabelTree.java b/src/org/geometerplus/fbreader/library/SyncLabelTree.java index b869d6b53..85bc14a26 100644 --- a/src/org/geometerplus/fbreader/library/SyncLabelTree.java +++ b/src/org/geometerplus/fbreader/library/SyncLabelTree.java @@ -25,12 +25,12 @@ import org.geometerplus.fbreader.book.Book; import org.geometerplus.fbreader.book.Filter; public class SyncLabelTree extends FilteredTree { - private final String myLabel; + public final String Label; private final ZLResource myResource; SyncLabelTree(SyncTree parent, String label, Filter filter, ZLResource resource) { super(parent, filter, -1); - myLabel = label; + Label = label; myResource = resource; } @@ -51,7 +51,7 @@ public class SyncLabelTree extends FilteredTree { @Override protected String getStringId() { - return "@SyncLabelTree " + myLabel; + return "@SyncLabelTree " + Label; } @Override