1
0
Fork 0
mirror of https://github.com/geometer/FBReaderJ.git synced 2025-10-05 10:49:24 +02:00

new synchronisation-related actions in library menus

This commit is contained in:
Nikolay Pultsin 2014-07-27 22:10:55 +01:00
parent 0a7aa5fc29
commit 05fd7f181f
4 changed files with 126 additions and 54 deletions

View file

@ -53,10 +53,8 @@
<node name="fileTreeLibrary" value="FBReader library">
<node name="summary" value="FBReader books directory"/>
</node>
<node name="menu">
<node name="localSearch" value="Search"/>
<node name="rescan" value="Rescan"/>
</node>
<node name="localSearch" value="Search"/>
<node name="rescan" value="Rescan"/>
<node name="openBook" value="Open book"/>
<node name="showBookInfo" value="Book info"/>
<node name="shareBook" value="Share book"/>
@ -66,6 +64,8 @@
<node name="removeFromRecents" value="Remove from recent list"/>
<node name="markAsRead" value="Mark as read"/>
<node name="markAsUnread" value="Mark as unread"/>
<node name="deleteAll" value="Delete all"/>
<node name="syncAgain" value="Synchronise again"/>
</node>
<node name="networkLibrary" value="FBReader network library">
<node name="byAuthor" value="By author">
@ -849,6 +849,10 @@
<node name="deleteBookBox">
<node name="message" value="The book file will be removed irreversibly. Are you sure?"/>
</node>
<node name="deleteMultipleBookBox">
<node name="title" value="Delete books"/>
<node name="message" value="%s book files will be removed irreversibly. Are you sure?"/>
</node>
<node name="redownloadFileBox">
<node name="message" value="File already exists. Redownload?"/>
</node>

View file

@ -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<LibraryTree> 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<LibraryTree> 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<LibraryTree> implements MenuIt
final ZLResource resource = LibraryTree.resource();
final List<String> 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<LibraryTree> 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<LibraryTree> 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<LibraryTree> 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<Book> books = new LinkedList<Book>();
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<LibraryTree> implements MenuIt
// Book deletion
//
private class BookDeleter implements DialogInterface.OnClickListener {
private final Book myBook;
private final List<Book> myBooks;
BookDeleter(Book book) {
myBook = book;
BookDeleter(List<Book> books) {
myBooks = new ArrayList<Book>(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<Book> 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);

View file

@ -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;

View file

@ -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