mirror of
https://github.com/MinimalBible/MinimalBible
synced 2025-07-01 22:05:57 -04:00
RefreshManager going functional!
This commit is contained in:
@ -18,6 +18,7 @@ import org.bspeice.minimalbible.activity.downloader.manager.RefreshManager;
|
||||
import org.crosswire.jsword.book.Book;
|
||||
import org.crosswire.jsword.book.BookCategory;
|
||||
import org.crosswire.jsword.book.BookComparators;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@ -41,15 +42,12 @@ public class BookListFragment extends BaseFragment {
|
||||
*/
|
||||
protected static final String ARG_BOOK_CATEGORY = "book_category";
|
||||
|
||||
private final String TAG = "BookListFragment";
|
||||
|
||||
@Inject
|
||||
protected DownloadPrefs downloadPrefs;
|
||||
protected ProgressDialog refreshDialog;
|
||||
@InjectView(R.id.lst_download_available)
|
||||
ListView downloadsAvailable;
|
||||
|
||||
@Inject RefreshManager refreshManager;
|
||||
@Inject protected DownloadPrefs downloadPrefs;
|
||||
|
||||
protected ProgressDialog refreshDialog;
|
||||
private LayoutInflater inflater;
|
||||
|
||||
/**
|
||||
@ -114,7 +112,7 @@ public class BookListFragment extends BaseFragment {
|
||||
*/
|
||||
private void refreshModules() {
|
||||
// Check if the downloadManager has already refreshed everything
|
||||
if (!refreshManager.isRefreshComplete()) {
|
||||
if (!refreshManager.getRefreshComplete().get()) {
|
||||
// downloadManager is in progress of refreshing
|
||||
refreshDialog = new ProgressDialog(getActivity());
|
||||
refreshDialog.setMessage("Refreshing available modules...");
|
||||
@ -123,7 +121,7 @@ public class BookListFragment extends BaseFragment {
|
||||
}
|
||||
|
||||
// Listen for the books!
|
||||
refreshManager.getAvailableModulesFlattened()
|
||||
refreshManager.getAvailableModulesFlat()
|
||||
.filter(new Func1<Book, Boolean>() {
|
||||
@Override
|
||||
public Boolean call(Book book) {
|
||||
@ -162,7 +160,7 @@ public class BookListFragment extends BaseFragment {
|
||||
private class DownloadDialogListener implements
|
||||
DialogInterface.OnClickListener {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
public void onClick(@NotNull DialogInterface dialog, int which) {
|
||||
downloadPrefs.hasShownDownloadDialog(true);
|
||||
|
||||
switch (which) {
|
||||
|
@ -40,6 +40,7 @@ import de.devland.esperandro.Esperandro;
|
||||
addsTo = MinimalBibleModules.class,
|
||||
library = true
|
||||
)
|
||||
@SuppressWarnings("unused")
|
||||
public class DownloadActivityModules {
|
||||
DownloadActivity activity;
|
||||
|
||||
@ -65,7 +66,7 @@ public class DownloadActivityModules {
|
||||
/**
|
||||
* Provide the context for the DownloadActivity. We name it so that we don't have to
|
||||
* \@Provides a specific class, but can keep track of what exactly we mean by "Context"
|
||||
* @return
|
||||
* @return The DownloadActivity Context
|
||||
*/
|
||||
@Provides @Singleton @Named("DownloadActivityContext")
|
||||
Context provideActivityContext() {
|
||||
@ -105,7 +106,7 @@ public class DownloadActivityModules {
|
||||
}
|
||||
|
||||
@Provides @Singleton
|
||||
RefreshManager provideRefreshManager() {
|
||||
return new RefreshManager(activity);
|
||||
RefreshManager provideRefreshManager(Collection<Installer> installers) {
|
||||
return new RefreshManager(installers);
|
||||
}
|
||||
}
|
||||
|
@ -32,20 +32,15 @@ import rx.subjects.PublishSubject;
|
||||
//TODO: Install indexes for Bibles
|
||||
@Singleton
|
||||
public class BookDownloadManager implements WorkListener, BooksListener {
|
||||
private String TAG = "BookDownloadManager";
|
||||
|
||||
/**
|
||||
* Mapping of Job ID to the EventBus we should trigger progress on
|
||||
*/
|
||||
private final Map<String, Book> bookMappings;
|
||||
|
||||
/**
|
||||
* Cached copy of downloads in progress so views displaying this info can get it quickly.
|
||||
*/
|
||||
private final Map<Book, DLProgressEvent> inProgressDownloads;
|
||||
|
||||
private final PublishSubject<DLProgressEvent> downloadEvents = PublishSubject.create();
|
||||
|
||||
@Inject Books installedBooks;
|
||||
@Inject RefreshManager refreshManager;
|
||||
|
||||
@ -58,6 +53,18 @@ public class BookDownloadManager implements WorkListener, BooksListener {
|
||||
installedBooks.addBooksListener(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build what the installer creates the job name as.
|
||||
* Likely prone to be brittle.
|
||||
*
|
||||
* @param b The book to predict the download job name of
|
||||
* @return The name of the job that will/is download/ing this book
|
||||
*/
|
||||
|
||||
public static String getJobId(Book b) {
|
||||
return "INSTALL_BOOK-" + b.getInitials();
|
||||
}
|
||||
|
||||
public void installBook(Book b) {
|
||||
downloadBook(b);
|
||||
addJob(getJobId(b), b);
|
||||
@ -74,32 +81,19 @@ public class BookDownloadManager implements WorkListener, BooksListener {
|
||||
// First, look up where the Book came from
|
||||
Observable.just(refreshManager.installerFromBook(b))
|
||||
.subscribeOn(Schedulers.io())
|
||||
.subscribe(new Action1<Installer>() {
|
||||
.subscribe(new Action1<Observable<Installer>>() {
|
||||
@Override
|
||||
public void call(Installer installer) {
|
||||
public void call(Observable<Installer> installerObservable) {
|
||||
try {
|
||||
installer.install(b);
|
||||
installerObservable.toBlocking().first().install(b);
|
||||
} catch (InstallException e) {
|
||||
Log.d(TAG, e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
getDownloadEvents()
|
||||
.onNext(new DLProgressEvent(DLProgressEvent.PROGRESS_BEGINNING, b));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Build what the installer creates the job name as.
|
||||
* Likely prone to be brittle.
|
||||
* TODO: Make sure to test that this is an accurate job name
|
||||
*
|
||||
* @param b The book to predict the download job name of
|
||||
* @return The name of the job that will/is download/ing this book
|
||||
*/
|
||||
|
||||
public static String getJobId(Book b) {
|
||||
return "INSTALL_BOOK-" + b.getInitials();
|
||||
getDownloadEvents()
|
||||
.onNext(new DLProgressEvent(DLProgressEvent.PROGRESS_BEGINNING, b));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,137 +0,0 @@
|
||||
package org.bspeice.minimalbible.activity.downloader.manager;
|
||||
|
||||
import org.bspeice.minimalbible.Injector;
|
||||
import org.crosswire.jsword.book.Book;
|
||||
import org.crosswire.jsword.book.install.InstallException;
|
||||
import org.crosswire.jsword.book.install.Installer;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import rx.Observable;
|
||||
import rx.functions.Action0;
|
||||
import rx.functions.Action1;
|
||||
import rx.functions.Func1;
|
||||
import rx.schedulers.Schedulers;
|
||||
|
||||
/**
|
||||
* Handle refreshing the list of books available as needed
|
||||
* Note that we don't refactor this class out since we need somewhere
|
||||
* to track whether the refresh is done.
|
||||
*/
|
||||
@Singleton
|
||||
public class RefreshManager {
|
||||
|
||||
/**
|
||||
* Cached copy of modules that are available so we don't refresh for everyone who requests it.
|
||||
*/
|
||||
private Observable<Map<Installer, List<Book>>> availableModules;
|
||||
private final AtomicBoolean refreshComplete = new AtomicBoolean();
|
||||
|
||||
@Inject
|
||||
Collection<Installer> installers;
|
||||
|
||||
@Inject
|
||||
public RefreshManager(Injector injector) {
|
||||
injector.inject(this);
|
||||
refreshModules();
|
||||
}
|
||||
|
||||
/**
|
||||
* Do the work of kicking off the AsyncTask to refresh books, and make sure we know
|
||||
* when it's done.
|
||||
* NOTE: This code assigns its own thread. This is because we are called privately, and
|
||||
* don't want to expose this method. I don't like hiding the side effects like this, but
|
||||
* in this case I'm making an exception.
|
||||
* TODO: Need logic for when to do reloadBookList() vs. getBooks()
|
||||
*/
|
||||
private Observable<Map<Installer, List<Book>>> refreshModules() {
|
||||
if (availableModules == null) {
|
||||
availableModules = Observable.from(installers)
|
||||
.map(new Func1<Installer, Map<Installer, List<Book>>>() {
|
||||
@Override
|
||||
public Map<Installer, List<Book>> call(Installer installer) {
|
||||
Map<Installer, List<Book>> map = new HashMap<Installer, List<Book>>();
|
||||
try {
|
||||
installer.reloadBookList();
|
||||
map.put(installer, installer.getBooks());
|
||||
} catch (InstallException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return map;
|
||||
}
|
||||
}).subscribeOn(Schedulers.io())
|
||||
.cache();
|
||||
|
||||
// Set refresh complete when it is.
|
||||
availableModules.observeOn(Schedulers.io())
|
||||
.subscribe(new Action1<Map<Installer, List<Book>>>() {
|
||||
@Override
|
||||
public void call(Map<Installer, List<Book>> onNext) {}
|
||||
}, new Action1<Throwable>() {
|
||||
@Override
|
||||
public void call(Throwable onError) {}
|
||||
}, new Action0() {
|
||||
@Override
|
||||
public void call() {
|
||||
refreshComplete.set(true);
|
||||
}
|
||||
});
|
||||
}
|
||||
return availableModules;
|
||||
}
|
||||
|
||||
public Observable<Book> getAvailableModulesFlattened() {
|
||||
return availableModules
|
||||
// First flatten the Map to its lists
|
||||
.flatMap(new Func1<Map<Installer, List<Book>>, Observable<? extends List<Book>>>() {
|
||||
@Override
|
||||
public Observable<? extends List<Book>> call(Map<Installer, List<Book>> books) {
|
||||
return Observable.from(books.values());
|
||||
}
|
||||
})
|
||||
// Then flatten the lists
|
||||
.flatMap(new Func1<List<Book>, Observable<? extends Book>>() {
|
||||
@Override
|
||||
public Observable<? extends Book> call(List<Book> t1) {
|
||||
return Observable.from(t1);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Find the installer that a Book comes from.
|
||||
* TODO: Should this be @link{Observable} so we don't have to block?
|
||||
* @param b The book to search for
|
||||
* @return The Installer that should be used for this book.
|
||||
*/
|
||||
public Installer installerFromBook(final Book b) {
|
||||
Map<Installer, List<Book>> element = availableModules
|
||||
.filter(new Func1<Map<Installer, List<Book>>, Boolean>() {
|
||||
@Override
|
||||
public Boolean call(Map<Installer, List<Book>> installerListMap) {
|
||||
for (List<Book> element : installerListMap.values()) {
|
||||
if (element.contains(b)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
})
|
||||
.toBlocking()
|
||||
.first();
|
||||
return element.entrySet().iterator().next().getKey();
|
||||
}
|
||||
|
||||
public boolean isRefreshComplete() {
|
||||
return refreshComplete.get();
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user