mirror of
				https://github.com/MinimalBible/MinimalBible-Legacy
				synced 2025-11-03 18:00:34 -05:00 
			
		
		
		
	Compare commits
	
		
			16 Commits
		
	
	
		
			Rx/Retrola
			...
			master-old
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 3d19e751d9 | |||
| 2eeb8829f2 | |||
| 597b8b29cc | |||
| 26e754a6d8 | |||
| 1c15767d10 | |||
| db5adbd091 | |||
| b19b740c43 | |||
| 969adad9b0 | |||
| 018fe29a75 | |||
| f5800388d3 | |||
| 8c71d4372e | |||
| 348a6da9a3 | |||
| 8e54fdb86d | |||
| d260f98377 | |||
| 3649468e7f | |||
| d9f6eaa339 | 
@ -2,6 +2,11 @@ language: android
 | 
				
			|||||||
env:
 | 
					env:
 | 
				
			||||||
  matrix:
 | 
					  matrix:
 | 
				
			||||||
    - ANDROID_SDKS=android-19,sysimg-19 ANDROID_TARGET=android-19 ANDROID_ABI=armeabi-v7a
 | 
					    - ANDROID_SDKS=android-19,sysimg-19 ANDROID_TARGET=android-19 ANDROID_ABI=armeabi-v7a
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					android:
 | 
				
			||||||
 | 
					  components:
 | 
				
			||||||
 | 
					    - build-tools-20.0.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
before_install:
 | 
					before_install:
 | 
				
			||||||
  - echo no | android create avd --force -n test -t $ANDROID_TARGET --abi $ANDROID_ABI
 | 
					  - echo no | android create avd --force -n test -t $ANDROID_TARGET --abi $ANDROID_ABI
 | 
				
			||||||
  - emulator -avd test -no-skin -no-audio -no-window &
 | 
					  - emulator -avd test -no-skin -no-audio -no-window &
 | 
				
			||||||
 | 
				
			|||||||
@ -1,5 +1,6 @@
 | 
				
			|||||||
apply plugin: 'android'
 | 
					apply plugin: 'android'
 | 
				
			||||||
apply plugin: 'android-apt'
 | 
					apply plugin: 'android-apt'
 | 
				
			||||||
 | 
					//apply plugin: 'retrolambda'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
buildscript {
 | 
					buildscript {
 | 
				
			||||||
    repositories {
 | 
					    repositories {
 | 
				
			||||||
@ -17,20 +18,15 @@ repositories {
 | 
				
			|||||||
dependencies {
 | 
					dependencies {
 | 
				
			||||||
    compile project(path: ':jsword-minimalbible', configuration: 'buildJSword')
 | 
					    compile project(path: ':jsword-minimalbible', configuration: 'buildJSword')
 | 
				
			||||||
    compile project(':appcompat_v7')
 | 
					    compile project(':appcompat_v7')
 | 
				
			||||||
 | 
					 | 
				
			||||||
    apt 'com.squareup.dagger:dagger-compiler:1.2.0'
 | 
					    apt 'com.squareup.dagger:dagger-compiler:1.2.0'
 | 
				
			||||||
    compile 'com.squareup.dagger:dagger:1.2.0'
 | 
					    compile 'com.squareup.dagger:dagger:1.2.0'
 | 
				
			||||||
 | 
					 | 
				
			||||||
    apt 'com.jakewharton:butterknife:5.0.1'
 | 
					    apt 'com.jakewharton:butterknife:5.0.1'
 | 
				
			||||||
    compile 'com.jakewharton:butterknife:5.0.1'
 | 
					    compile 'com.jakewharton:butterknife:5.0.1'
 | 
				
			||||||
 | 
					 | 
				
			||||||
    compile 'de.devland.esperandro:esperandro-api:1.1.2'
 | 
					    compile 'de.devland.esperandro:esperandro-api:1.1.2'
 | 
				
			||||||
    apt 'de.devland.esperandro:esperandro:1.1.2'
 | 
					    apt 'de.devland.esperandro:esperandro:1.1.2'
 | 
				
			||||||
 | 
					 | 
				
			||||||
    // compile 'com.f2prateek.dart:dart:1.1.0'
 | 
					    // compile 'com.f2prateek.dart:dart:1.1.0'
 | 
				
			||||||
 | 
					 | 
				
			||||||
    compile 'com.readystatesoftware.systembartint:systembartint:1.0.3'
 | 
					    compile 'com.readystatesoftware.systembartint:systembartint:1.0.3'
 | 
				
			||||||
    compile 'de.greenrobot:eventbus:2.2.0'
 | 
					    compile 'com.netflix.rxjava:rxjava-android:0.19.0'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Handled by appcompat
 | 
					    // Handled by appcompat
 | 
				
			||||||
    // compile 'com.google.android:support-v4:r7'
 | 
					    // compile 'com.google.android:support-v4:r7'
 | 
				
			||||||
@ -43,11 +39,10 @@ dependencies {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
android {
 | 
					android {
 | 
				
			||||||
    compileSdkVersion 19
 | 
					    compileSdkVersion 19
 | 
				
			||||||
    buildToolsVersion "19.0.3"
 | 
					    buildToolsVersion '20'
 | 
				
			||||||
 | 
					 | 
				
			||||||
    sourceSets {
 | 
					    sourceSets {
 | 
				
			||||||
        main {
 | 
					        main {
 | 
				
			||||||
            manifest.srcFile 'AndroidManifest.xml'
 | 
					            manifest.srcFile 'src/main/AndroidManifest.xml'
 | 
				
			||||||
            java.srcDirs = ['src/main/java']
 | 
					            java.srcDirs = ['src/main/java']
 | 
				
			||||||
            resources.srcDirs = ['src/main/res']
 | 
					            resources.srcDirs = ['src/main/res']
 | 
				
			||||||
            aidl.srcDirs = ['src']
 | 
					            aidl.srcDirs = ['src']
 | 
				
			||||||
@ -57,7 +52,12 @@ android {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Move the tests to tests/java, tests/res, etc...
 | 
					        // Move the tests to tests/java, tests/res, etc...
 | 
				
			||||||
        androidTest.setRoot('src/test')
 | 
					        androidTest {
 | 
				
			||||||
 | 
					            manifest.srcFile 'src/test/AndroidManifest.xml'
 | 
				
			||||||
 | 
					            java.srcDirs = ['src/test/java']
 | 
				
			||||||
 | 
					            resources.srcDirs = ['src/test/res']
 | 
				
			||||||
 | 
					            assets.srcDirs = ['src/test/assets']
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Move the build types to build-types/<type>
 | 
					        // Move the build types to build-types/<type>
 | 
				
			||||||
        // For instance, build-types/debug/java, build-types/debug/AndroidManifest.xml, ...
 | 
					        // For instance, build-types/debug/java, build-types/debug/AndroidManifest.xml, ...
 | 
				
			||||||
@ -68,7 +68,6 @@ android {
 | 
				
			|||||||
        debug.setRoot('build-types/debug')
 | 
					        debug.setRoot('build-types/debug')
 | 
				
			||||||
        release.setRoot('build-types/release')
 | 
					        release.setRoot('build-types/release')
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					 | 
				
			||||||
    packagingOptions {
 | 
					    packagingOptions {
 | 
				
			||||||
        exclude 'META-INF/LICENSE.txt'
 | 
					        exclude 'META-INF/LICENSE.txt'
 | 
				
			||||||
        exclude 'LICENSE.txt'
 | 
					        exclude 'LICENSE.txt'
 | 
				
			||||||
@ -78,7 +77,6 @@ android {
 | 
				
			|||||||
        exclude 'META-INF/NOTICE'
 | 
					        exclude 'META-INF/NOTICE'
 | 
				
			||||||
        exclude 'META-INF/services/javax.annotation.processing.Processor'
 | 
					        exclude 'META-INF/services/javax.annotation.processing.Processor'
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					 | 
				
			||||||
    lintOptions {
 | 
					    lintOptions {
 | 
				
			||||||
        abortOnError false
 | 
					        abortOnError false
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
@ -6,7 +6,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    <uses-sdk
 | 
					    <uses-sdk
 | 
				
			||||||
        android:minSdkVersion="8"
 | 
					        android:minSdkVersion="8"
 | 
				
			||||||
        android:targetSdkVersion="19" />
 | 
					        android:targetSdkVersion="20" />
 | 
				
			||||||
    <uses-permission android:name="android.permission.INTERNET"/>
 | 
					    <uses-permission android:name="android.permission.INTERNET"/>
 | 
				
			||||||
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
 | 
					    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										11
									
								
								MinimalBible/src/main/assets/book.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								MinimalBible/src/main/assets/book.html
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,11 @@
 | 
				
			|||||||
 | 
					<html>
 | 
				
			||||||
 | 
					    <body>
 | 
				
			||||||
 | 
					        <div id="content" />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        <script type="text/javascript">
 | 
				
			||||||
 | 
					            function set_content(content) {
 | 
				
			||||||
 | 
					                document.getElementById("content").innerHTML = content;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        </script>
 | 
				
			||||||
 | 
					    </body>
 | 
				
			||||||
 | 
					</html>
 | 
				
			||||||
@ -2,6 +2,11 @@ package org.bspeice.minimalbible;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import android.app.Application;
 | 
					import android.app.Application;
 | 
				
			||||||
import android.content.Context;
 | 
					import android.content.Context;
 | 
				
			||||||
 | 
					import android.util.Log;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import org.crosswire.jsword.book.sword.SwordBookPath;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.io.File;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import dagger.ObjectGraph;
 | 
					import dagger.ObjectGraph;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -18,6 +23,8 @@ public class MinimalBible extends Application {
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
	private static MinimalBible instance;
 | 
						private static MinimalBible instance;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private String TAG = "MinimalBible";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Create the application, and persist the application Context
 | 
					     * Create the application, and persist the application Context
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
@ -51,6 +58,7 @@ public class MinimalBible extends Application {
 | 
				
			|||||||
    public void onCreate() {
 | 
					    public void onCreate() {
 | 
				
			||||||
        //TODO: Is this necessary?
 | 
					        //TODO: Is this necessary?
 | 
				
			||||||
        inject(this);
 | 
					        inject(this);
 | 
				
			||||||
 | 
					        setJswordHome();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
@ -67,4 +75,24 @@ public class MinimalBible extends Application {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
        return graph;
 | 
					        return graph;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public void plusObjGraph(Object... modules) {
 | 
				
			||||||
 | 
					        graph = graph.plus(modules);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Notify jSword that it needs to store files in the Android internal directory
 | 
				
			||||||
 | 
					     * NOTE: Android will uninstall these files if you uninstall MinimalBible.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    @SuppressWarnings("null")
 | 
				
			||||||
 | 
					    private void setJswordHome() {
 | 
				
			||||||
 | 
					        // We need to set the download directory for jSword to stick with
 | 
				
			||||||
 | 
					        // Android.
 | 
				
			||||||
 | 
					        String home = MinimalBible.getAppContext().getFilesDir().toString();
 | 
				
			||||||
 | 
					        Log.d(TAG, "Setting jsword.home to: " + home);
 | 
				
			||||||
 | 
					        System.setProperty("jsword.home", home);
 | 
				
			||||||
 | 
					        System.setProperty("sword.home", home);
 | 
				
			||||||
 | 
					        SwordBookPath.setDownloadDir(new File(home));
 | 
				
			||||||
 | 
					        Log.d(TAG, "Sword download path: " + SwordBookPath.getSwordDownloadDir());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -1,6 +1,7 @@
 | 
				
			|||||||
package org.bspeice.minimalbible.activities;
 | 
					package org.bspeice.minimalbible.activities;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import org.bspeice.minimalbible.activities.downloader.ActivityDownloaderModule;
 | 
					import org.bspeice.minimalbible.activities.downloader.ActivityDownloaderModule;
 | 
				
			||||||
 | 
					import org.bspeice.minimalbible.activities.viewer.ActivityViewerModule;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import dagger.Module;
 | 
					import dagger.Module;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -9,7 +10,8 @@ import dagger.Module;
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
@Module(
 | 
					@Module(
 | 
				
			||||||
    includes = {
 | 
					    includes = {
 | 
				
			||||||
        ActivityDownloaderModule.class
 | 
					        ActivityDownloaderModule.class,
 | 
				
			||||||
 | 
					        ActivityViewerModule.class
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
public class ActivityModules {
 | 
					public class ActivityModules {
 | 
				
			||||||
 | 
				
			|||||||
@ -17,7 +17,7 @@ public class BaseFragment extends Fragment {
 | 
				
			|||||||
     * @param context The {@link android.app.Activity} we are displaying in
 | 
					     * @param context The {@link android.app.Activity} we are displaying in
 | 
				
			||||||
     * @param view The {@link android.view.View} we need to calculate the offset for.
 | 
					     * @param view The {@link android.view.View} we need to calculate the offset for.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public static void setInsets(Activity context, View view) {
 | 
					    protected static void setInsets(Activity context, View view) {
 | 
				
			||||||
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) return;
 | 
					        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) return;
 | 
				
			||||||
        SystemBarTintManager tintManager = new SystemBarTintManager(context);
 | 
					        SystemBarTintManager tintManager = new SystemBarTintManager(context);
 | 
				
			||||||
        SystemBarTintManager.SystemBarConfig config = tintManager.getConfig();
 | 
					        SystemBarTintManager.SystemBarConfig config = tintManager.getConfig();
 | 
				
			||||||
 | 
				
			|||||||
@ -3,15 +3,11 @@ package org.bspeice.minimalbible.activities.downloader;
 | 
				
			|||||||
import org.bspeice.minimalbible.MinimalBible;
 | 
					import org.bspeice.minimalbible.MinimalBible;
 | 
				
			||||||
import org.bspeice.minimalbible.activities.downloader.manager.BookDownloadManager;
 | 
					import org.bspeice.minimalbible.activities.downloader.manager.BookDownloadManager;
 | 
				
			||||||
import org.bspeice.minimalbible.activities.downloader.manager.BookDownloadThread;
 | 
					import org.bspeice.minimalbible.activities.downloader.manager.BookDownloadThread;
 | 
				
			||||||
import org.bspeice.minimalbible.activities.downloader.manager.BookRefreshTask;
 | 
					 | 
				
			||||||
import org.bspeice.minimalbible.activities.downloader.manager.DownloadManager;
 | 
					 | 
				
			||||||
import org.bspeice.minimalbible.activities.downloader.manager.InstalledManager;
 | 
					 | 
				
			||||||
import org.bspeice.minimalbible.activities.downloader.manager.RefreshManager;
 | 
					import org.bspeice.minimalbible.activities.downloader.manager.RefreshManager;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import dagger.Module;
 | 
					import dagger.Module;
 | 
				
			||||||
import dagger.Provides;
 | 
					import dagger.Provides;
 | 
				
			||||||
import de.devland.esperandro.Esperandro;
 | 
					import de.devland.esperandro.Esperandro;
 | 
				
			||||||
import de.greenrobot.event.EventBus;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Module mappings for the classes under the Download Activity
 | 
					 * Module mappings for the classes under the Download Activity
 | 
				
			||||||
@ -19,22 +15,14 @@ import de.greenrobot.event.EventBus;
 | 
				
			|||||||
@Module(
 | 
					@Module(
 | 
				
			||||||
        injects = {
 | 
					        injects = {
 | 
				
			||||||
            BookListFragment.class,
 | 
					            BookListFragment.class,
 | 
				
			||||||
            DownloadManager.class,
 | 
					 | 
				
			||||||
            BookRefreshTask.class,
 | 
					 | 
				
			||||||
            BookItemHolder.class,
 | 
					            BookItemHolder.class,
 | 
				
			||||||
            BookDownloadManager.class,
 | 
					            BookDownloadManager.class,
 | 
				
			||||||
            BookDownloadThread.class,
 | 
					            BookDownloadThread.class,
 | 
				
			||||||
            RefreshManager.class,
 | 
					            RefreshManager.class
 | 
				
			||||||
            InstalledManager.class
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
public class ActivityDownloaderModule {
 | 
					public class ActivityDownloaderModule {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Provides
 | 
					 | 
				
			||||||
    EventBus provideBus() {
 | 
					 | 
				
			||||||
        return new EventBus();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Provides //@Singleton
 | 
					    @Provides //@Singleton
 | 
				
			||||||
    DownloadPrefs provideDownloadPrefs() {
 | 
					    DownloadPrefs provideDownloadPrefs() {
 | 
				
			||||||
        return Esperandro.getPreferences(DownloadPrefs.class, MinimalBible.getAppContext());
 | 
					        return Esperandro.getPreferences(DownloadPrefs.class, MinimalBible.getAppContext());
 | 
				
			||||||
 | 
				
			|||||||
@ -11,17 +11,18 @@ import org.bspeice.minimalbible.MinimalBible;
 | 
				
			|||||||
import org.bspeice.minimalbible.R;
 | 
					import org.bspeice.minimalbible.R;
 | 
				
			||||||
import org.bspeice.minimalbible.activities.downloader.manager.BookDownloadManager;
 | 
					import org.bspeice.minimalbible.activities.downloader.manager.BookDownloadManager;
 | 
				
			||||||
import org.bspeice.minimalbible.activities.downloader.manager.DLProgressEvent;
 | 
					import org.bspeice.minimalbible.activities.downloader.manager.DLProgressEvent;
 | 
				
			||||||
import org.bspeice.minimalbible.activities.downloader.manager.DownloadManager;
 | 
					 | 
				
			||||||
import org.bspeice.minimalbible.activities.downloader.manager.InstalledManager;
 | 
					import org.bspeice.minimalbible.activities.downloader.manager.InstalledManager;
 | 
				
			||||||
import org.crosswire.jsword.book.Book;
 | 
					import org.crosswire.jsword.book.Book;
 | 
				
			||||||
import org.crosswire.jsword.book.BookException;
 | 
					 | 
				
			||||||
import org.crosswire.jsword.book.Books;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
import javax.inject.Inject;
 | 
					import javax.inject.Inject;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import butterknife.ButterKnife;
 | 
					import butterknife.ButterKnife;
 | 
				
			||||||
import butterknife.InjectView;
 | 
					import butterknife.InjectView;
 | 
				
			||||||
import butterknife.OnClick;
 | 
					import butterknife.OnClick;
 | 
				
			||||||
 | 
					import rx.Subscription;
 | 
				
			||||||
 | 
					import rx.android.schedulers.AndroidSchedulers;
 | 
				
			||||||
 | 
					import rx.functions.Action1;
 | 
				
			||||||
 | 
					import rx.functions.Func1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
* Created by bspeice on 5/20/14.
 | 
					* Created by bspeice on 5/20/14.
 | 
				
			||||||
@ -36,11 +37,11 @@ public class BookItemHolder {
 | 
				
			|||||||
    @InjectView(R.id.download_ibtn_download) ImageButton isDownloaded;
 | 
					    @InjectView(R.id.download_ibtn_download) ImageButton isDownloaded;
 | 
				
			||||||
    @InjectView(R.id.download_prg_download) ProgressWheel downloadProgress;
 | 
					    @InjectView(R.id.download_prg_download) ProgressWheel downloadProgress;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Inject DownloadManager downloadManager;
 | 
					 | 
				
			||||||
    @Inject BookDownloadManager bookDownloadManager;
 | 
					    @Inject BookDownloadManager bookDownloadManager;
 | 
				
			||||||
    @Inject InstalledManager installedManager;
 | 
					    @Inject InstalledManager installedManager;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Book b;
 | 
					    private final Book b;
 | 
				
			||||||
 | 
					    private Subscription subscription;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public BookItemHolder(View v, Book b) {
 | 
					    public BookItemHolder(View v, Book b) {
 | 
				
			||||||
        ButterKnife.inject(this, v);
 | 
					        ButterKnife.inject(this, v);
 | 
				
			||||||
@ -57,7 +58,21 @@ public class BookItemHolder {
 | 
				
			|||||||
        } else if (installedManager.isInstalled(b)) {
 | 
					        } else if (installedManager.isInstalled(b)) {
 | 
				
			||||||
            displayInstalled();
 | 
					            displayInstalled();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        downloadManager.getDownloadBus().register(this);
 | 
					        //TODO: Refactor
 | 
				
			||||||
 | 
					        subscription = bookDownloadManager.getDownloadEvents()
 | 
				
			||||||
 | 
					                .observeOn(AndroidSchedulers.mainThread())
 | 
				
			||||||
 | 
					                .filter(new Func1<DLProgressEvent, Boolean>() {
 | 
				
			||||||
 | 
					                    @Override
 | 
				
			||||||
 | 
					                    public Boolean call(DLProgressEvent event) {
 | 
				
			||||||
 | 
					                        return event.getB().getInitials().equals(b.getInitials());
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                })
 | 
				
			||||||
 | 
					                .subscribe(new Action1<DLProgressEvent>() {
 | 
				
			||||||
 | 
					                    @Override
 | 
				
			||||||
 | 
					                    public void call(DLProgressEvent event) {
 | 
				
			||||||
 | 
					                        BookItemHolder.this.displayProgress((int) event.toCircular());
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private void displayInstalled() {
 | 
					    private void displayInstalled() {
 | 
				
			||||||
@ -75,12 +90,6 @@ public class BookItemHolder {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public void onEventMainThread(DLProgressEvent event) {
 | 
					 | 
				
			||||||
        if (event.getB().getOsisID().equals(b.getOsisID())) {
 | 
					 | 
				
			||||||
            displayProgress((int) event.toCircular());
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Display the current progress of this download
 | 
					     * Display the current progress of this download
 | 
				
			||||||
     * @param progress The progress out of 360 (degrees of a circle)
 | 
					     * @param progress The progress out of 360 (degrees of a circle)
 | 
				
			||||||
@ -119,6 +128,7 @@ public class BookItemHolder {
 | 
				
			|||||||
            downloadProgress.setProgress(progress);
 | 
					            downloadProgress.setProgress(progress);
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            // Download complete
 | 
					            // Download complete
 | 
				
			||||||
 | 
					            subscription.unsubscribe();
 | 
				
			||||||
            RelativeLayout.LayoutParams acronymParams =
 | 
					            RelativeLayout.LayoutParams acronymParams =
 | 
				
			||||||
                    (RelativeLayout.LayoutParams)acronym.getLayoutParams();
 | 
					                    (RelativeLayout.LayoutParams)acronym.getLayoutParams();
 | 
				
			||||||
            acronymParams.addRule(RelativeLayout.LEFT_OF, isDownloaded.getId());
 | 
					            acronymParams.addRule(RelativeLayout.LEFT_OF, isDownloaded.getId());
 | 
				
			||||||
@ -134,6 +144,6 @@ public class BookItemHolder {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public void onScrollOffscreen() {
 | 
					    public void onScrollOffscreen() {
 | 
				
			||||||
        downloadManager.getDownloadBus().unregister(this);
 | 
					        subscription.unsubscribe();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -15,9 +15,9 @@ import java.util.List;
 | 
				
			|||||||
 * Adapter to inflate list_download_items.xml
 | 
					 * Adapter to inflate list_download_items.xml
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
public class BookListAdapter extends BaseAdapter implements AbsListView.RecyclerListener {
 | 
					public class BookListAdapter extends BaseAdapter implements AbsListView.RecyclerListener {
 | 
				
			||||||
    private List<Book> bookList;
 | 
					    private final List<Book> bookList;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private LayoutInflater inflater;
 | 
					    private final LayoutInflater inflater;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public BookListAdapter(LayoutInflater inflater, List<Book> bookList) {
 | 
					    public BookListAdapter(LayoutInflater inflater, List<Book> bookList) {
 | 
				
			||||||
        this.bookList = bookList;
 | 
					        this.bookList = bookList;
 | 
				
			||||||
 | 
				
			|||||||
@ -5,7 +5,6 @@ import android.app.AlertDialog;
 | 
				
			|||||||
import android.app.ProgressDialog;
 | 
					import android.app.ProgressDialog;
 | 
				
			||||||
import android.content.DialogInterface;
 | 
					import android.content.DialogInterface;
 | 
				
			||||||
import android.os.Bundle;
 | 
					import android.os.Bundle;
 | 
				
			||||||
import android.util.Log;
 | 
					 | 
				
			||||||
import android.view.LayoutInflater;
 | 
					import android.view.LayoutInflater;
 | 
				
			||||||
import android.view.View;
 | 
					import android.view.View;
 | 
				
			||||||
import android.view.ViewGroup;
 | 
					import android.view.ViewGroup;
 | 
				
			||||||
@ -15,22 +14,22 @@ import android.widget.Toast;
 | 
				
			|||||||
import org.bspeice.minimalbible.MinimalBible;
 | 
					import org.bspeice.minimalbible.MinimalBible;
 | 
				
			||||||
import org.bspeice.minimalbible.R;
 | 
					import org.bspeice.minimalbible.R;
 | 
				
			||||||
import org.bspeice.minimalbible.activities.BaseFragment;
 | 
					import org.bspeice.minimalbible.activities.BaseFragment;
 | 
				
			||||||
import org.bspeice.minimalbible.activities.downloader.manager.DownloadManager;
 | 
					 | 
				
			||||||
import org.bspeice.minimalbible.activities.downloader.manager.EventBookList;
 | 
					 | 
				
			||||||
import org.bspeice.minimalbible.activities.downloader.manager.RefreshManager;
 | 
					import org.bspeice.minimalbible.activities.downloader.manager.RefreshManager;
 | 
				
			||||||
import org.crosswire.jsword.book.Book;
 | 
					import org.crosswire.jsword.book.Book;
 | 
				
			||||||
import org.crosswire.jsword.book.BookCategory;
 | 
					import org.crosswire.jsword.book.BookCategory;
 | 
				
			||||||
import org.crosswire.jsword.book.BookComparators;
 | 
					import org.crosswire.jsword.book.BookComparators;
 | 
				
			||||||
import org.crosswire.jsword.book.BookFilter;
 | 
					 | 
				
			||||||
import org.crosswire.jsword.book.FilterUtil;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
import java.util.Collections;
 | 
					 | 
				
			||||||
import java.util.List;
 | 
					import java.util.List;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import javax.inject.Inject;
 | 
					import javax.inject.Inject;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import butterknife.ButterKnife;
 | 
					import butterknife.ButterKnife;
 | 
				
			||||||
import butterknife.InjectView;
 | 
					import butterknife.InjectView;
 | 
				
			||||||
 | 
					import rx.Observable;
 | 
				
			||||||
 | 
					import rx.android.schedulers.AndroidSchedulers;
 | 
				
			||||||
 | 
					import rx.functions.Action1;
 | 
				
			||||||
 | 
					import rx.functions.Func1;
 | 
				
			||||||
 | 
					import rx.functions.Func2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * A placeholder fragment containing a simple view.
 | 
					 * A placeholder fragment containing a simple view.
 | 
				
			||||||
@ -41,19 +40,17 @@ public class BookListFragment extends BaseFragment {
 | 
				
			|||||||
     * The fragment argument representing the section number for this fragment.
 | 
					     * The fragment argument representing the section number for this fragment.
 | 
				
			||||||
     * Not a candidate for Dart (yet) because I would have to write a Parcelable around it.
 | 
					     * Not a candidate for Dart (yet) because I would have to write a Parcelable around it.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    private static final String ARG_BOOK_CATEGORY = "book_category";
 | 
					    protected static final String ARG_BOOK_CATEGORY = "book_category";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private final String TAG = "BookListFragment";
 | 
					    private final String TAG = "BookListFragment";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @InjectView(R.id.lst_download_available)
 | 
					    @InjectView(R.id.lst_download_available)
 | 
				
			||||||
    ListView downloadsAvailable;
 | 
					    ListView downloadsAvailable;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Inject DownloadManager downloadManager;
 | 
					 | 
				
			||||||
    @Inject RefreshManager refreshManager;
 | 
					    @Inject RefreshManager refreshManager;
 | 
				
			||||||
 | 
					    @Inject protected DownloadPrefs downloadPrefs;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Inject DownloadPrefs downloadPrefs;
 | 
						protected ProgressDialog refreshDialog;
 | 
				
			||||||
 | 
					 | 
				
			||||||
	private ProgressDialog refreshDialog;
 | 
					 | 
				
			||||||
    private LayoutInflater inflater;
 | 
					    private LayoutInflater inflater;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
@ -96,7 +93,7 @@ public class BookListFragment extends BaseFragment {
 | 
				
			|||||||
     * Trigger the functionality to display a list of modules. Prompts user if downloading
 | 
					     * Trigger the functionality to display a list of modules. Prompts user if downloading
 | 
				
			||||||
     * from the internet is allowable.
 | 
					     * from the internet is allowable.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
 	public void displayModules() {
 | 
					 	protected void displayModules() {
 | 
				
			||||||
		boolean dialogDisplayed = downloadPrefs.hasShownDownloadDialog();
 | 
							boolean dialogDisplayed = downloadPrefs.hasShownDownloadDialog();
 | 
				
			||||||
		
 | 
							
 | 
				
			||||||
		if (!dialogDisplayed) {
 | 
							if (!dialogDisplayed) {
 | 
				
			||||||
@ -118,50 +115,47 @@ public class BookListFragment extends BaseFragment {
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
	private void refreshModules() {
 | 
						private void refreshModules() {
 | 
				
			||||||
        // Check if the downloadManager has already refreshed everything
 | 
					        // Check if the downloadManager has already refreshed everything
 | 
				
			||||||
		List<Book> bookList = refreshManager.getBookList();
 | 
							if (!refreshManager.isRefreshComplete()) {
 | 
				
			||||||
		if (bookList == null) {
 | 
					 | 
				
			||||||
            // downloadManager is in progress of refreshing
 | 
					            // downloadManager is in progress of refreshing
 | 
				
			||||||
            downloadManager.getDownloadBus().register(this);
 | 
					 | 
				
			||||||
            refreshDialog = new ProgressDialog(getActivity());
 | 
					            refreshDialog = new ProgressDialog(getActivity());
 | 
				
			||||||
            refreshDialog.setMessage("Refreshing available modules...");
 | 
					            refreshDialog.setMessage("Refreshing available modules...");
 | 
				
			||||||
            refreshDialog.setCancelable(false);
 | 
					            refreshDialog.setCancelable(false);
 | 
				
			||||||
            refreshDialog.show();
 | 
					            refreshDialog.show();
 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            displayBooks(bookList);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					        // Listen for the books!
 | 
				
			||||||
     * Used by GreenRobot for notifying us that the book refresh is complete
 | 
					        refreshManager.getAvailableModulesFlattened()
 | 
				
			||||||
     */
 | 
					                .filter(new Func1<Book, Boolean>() {
 | 
				
			||||||
    @SuppressWarnings("unused")
 | 
					                    @Override
 | 
				
			||||||
	public void onEventMainThread(EventBookList event) {
 | 
					                    public Boolean call(Book book) {
 | 
				
			||||||
 | 
					                        return book.getBookCategory() ==
 | 
				
			||||||
 | 
					                                BookCategory.fromString(BookListFragment.this.getArguments()
 | 
				
			||||||
 | 
					                                        .getString(ARG_BOOK_CATEGORY));
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                })
 | 
				
			||||||
 | 
					                // Repack all the books
 | 
				
			||||||
 | 
					                .toSortedList(new Func2<Book, Book, Integer>() {
 | 
				
			||||||
 | 
					                    @Override
 | 
				
			||||||
 | 
					                    public Integer call(Book book1, Book book2) {
 | 
				
			||||||
 | 
					                        return BookComparators.getInitialComparator().compare(book1, book2);
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                })
 | 
				
			||||||
 | 
					                .observeOn(AndroidSchedulers.mainThread())
 | 
				
			||||||
 | 
					                .subscribe(new Action1<List<Book>>() {
 | 
				
			||||||
 | 
					                    @Override
 | 
				
			||||||
 | 
					                    public void call(List<Book> books) {
 | 
				
			||||||
 | 
					                        downloadsAvailable.setAdapter(new BookListAdapter(inflater, books));
 | 
				
			||||||
 | 
					                        if (BookListFragment.this.getActivity() != null) {
 | 
				
			||||||
 | 
					                            // On a screen rotate, getActivity() will be null. But, the activity will
 | 
				
			||||||
 | 
					                            // already have been set up correctly, so we don't need to worry about it.
 | 
				
			||||||
 | 
					                            // If not null, we need to set it up now.
 | 
				
			||||||
 | 
					                            setInsets(BookListFragment.this.getActivity(), downloadsAvailable);
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
                        if (refreshDialog != null) {
 | 
					                        if (refreshDialog != null) {
 | 
				
			||||||
                            refreshDialog.cancel();
 | 
					                            refreshDialog.cancel();
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
		displayBooks(event.getBookList());
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Do the hard work of creating the Adapter and displaying books.
 | 
					 | 
				
			||||||
     * @param bookList The (unfiltered) list of {link org.crosswire.jsword.Book}s to display
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    public void displayBooks(List<Book> bookList) {
 | 
					 | 
				
			||||||
        try {
 | 
					 | 
				
			||||||
            // TODO: Should the filter be applied earlier in the process?
 | 
					 | 
				
			||||||
            List<Book> displayList;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            BookCategory c = BookCategory.fromString(getArguments().getString(ARG_BOOK_CATEGORY));
 | 
					 | 
				
			||||||
            BookFilter f = FilterUtil.filterFromCategory(c);
 | 
					 | 
				
			||||||
            displayList = FilterUtil.applyFilter(bookList, f);
 | 
					 | 
				
			||||||
            Collections.sort(displayList, BookComparators.getInitialComparator());
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            downloadsAvailable.setAdapter(new BookListAdapter(inflater, displayList));
 | 
					 | 
				
			||||||
            setInsets(getActivity(), downloadsAvailable);
 | 
					 | 
				
			||||||
        } catch (FilterUtil.InvalidFilterCategoryMappingException e) {
 | 
					 | 
				
			||||||
            // To be honest, there should be no reason you end up here.
 | 
					 | 
				
			||||||
            Log.e(TAG, e.getMessage());
 | 
					 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private class DownloadDialogListener implements
 | 
						private class DownloadDialogListener implements
 | 
				
			||||||
 | 
				
			|||||||
@ -1,10 +1,5 @@
 | 
				
			|||||||
package org.bspeice.minimalbible.activities.downloader;
 | 
					package org.bspeice.minimalbible.activities.downloader;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import org.bspeice.minimalbible.R;
 | 
					 | 
				
			||||||
import org.bspeice.minimalbible.activities.BaseActivity;
 | 
					 | 
				
			||||||
import org.bspeice.minimalbible.activities.BaseNavigationDrawerFragment;
 | 
					 | 
				
			||||||
import org.bspeice.minimalbible.activities.downloader.manager.DownloadManager;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import android.os.Bundle;
 | 
					import android.os.Bundle;
 | 
				
			||||||
import android.support.v4.app.FragmentManager;
 | 
					import android.support.v4.app.FragmentManager;
 | 
				
			||||||
import android.support.v4.widget.DrawerLayout;
 | 
					import android.support.v4.widget.DrawerLayout;
 | 
				
			||||||
@ -12,6 +7,11 @@ import android.support.v7.app.ActionBar;
 | 
				
			|||||||
import android.view.Menu;
 | 
					import android.view.Menu;
 | 
				
			||||||
import android.view.MenuItem;
 | 
					import android.view.MenuItem;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import org.bspeice.minimalbible.R;
 | 
				
			||||||
 | 
					import org.bspeice.minimalbible.activities.BaseActivity;
 | 
				
			||||||
 | 
					import org.bspeice.minimalbible.activities.BaseNavigationDrawerFragment;
 | 
				
			||||||
 | 
					import org.bspeice.minimalbible.activities.downloader.manager.DownloadManager;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public class DownloadActivity extends BaseActivity implements
 | 
					public class DownloadActivity extends BaseActivity implements
 | 
				
			||||||
		BaseNavigationDrawerFragment.NavigationDrawerCallbacks {
 | 
							BaseNavigationDrawerFragment.NavigationDrawerCallbacks {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -19,7 +19,7 @@ import javax.inject.Inject;
 | 
				
			|||||||
import javax.inject.Provider;
 | 
					import javax.inject.Provider;
 | 
				
			||||||
import javax.inject.Singleton;
 | 
					import javax.inject.Singleton;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import de.greenrobot.event.EventBus;
 | 
					import rx.subjects.PublishSubject;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Wrapper to convert JSword progress events to MinimalBible EventBus-based
 | 
					 * Wrapper to convert JSword progress events to MinimalBible EventBus-based
 | 
				
			||||||
@ -32,18 +32,18 @@ public class BookDownloadManager implements WorkListener, BooksListener {
 | 
				
			|||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Mapping of Job ID to the EventBus we should trigger progress on
 | 
					     * Mapping of Job ID to the EventBus we should trigger progress on
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    private Map<String, Book> bookMappings;
 | 
					    private final Map<String, Book> bookMappings;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Cached copy of downloads in progress so views displaying this info can get it quickly.
 | 
					     * Cached copy of downloads in progress so views displaying this info can get it quickly.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    private Map<Book, DLProgressEvent> inProgressDownloads;
 | 
					    private final Map<Book, DLProgressEvent> inProgressDownloads;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private final PublishSubject<DLProgressEvent> downloadEvents = PublishSubject.create();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Inject
 | 
					    @Inject
 | 
				
			||||||
    Provider<BookDownloadThread> dlThreadProvider;
 | 
					    Provider<BookDownloadThread> dlThreadProvider;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Inject DownloadManager downloadManager;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public BookDownloadManager() {
 | 
					    public BookDownloadManager() {
 | 
				
			||||||
        bookMappings = new HashMap<String, Book>();
 | 
					        bookMappings = new HashMap<String, Book>();
 | 
				
			||||||
        inProgressDownloads = new HashMap<Book, DLProgressEvent>();
 | 
					        inProgressDownloads = new HashMap<Book, DLProgressEvent>();
 | 
				
			||||||
@ -56,6 +56,7 @@ public class BookDownloadManager implements WorkListener, BooksListener {
 | 
				
			|||||||
        BookDownloadThread dlThread = dlThreadProvider.get();
 | 
					        BookDownloadThread dlThread = dlThreadProvider.get();
 | 
				
			||||||
        dlThread.downloadBook(b);
 | 
					        dlThread.downloadBook(b);
 | 
				
			||||||
        addJob(BookDownloadThread.getJobId(b), b);
 | 
					        addJob(BookDownloadThread.getJobId(b), b);
 | 
				
			||||||
 | 
					        downloadEvents.onNext(new DLProgressEvent(DLProgressEvent.PROGRESS_BEGINNING, b));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public void addJob(String jobId, Book b) {
 | 
					    public void addJob(String jobId, Book b) {
 | 
				
			||||||
@ -66,20 +67,20 @@ public class BookDownloadManager implements WorkListener, BooksListener {
 | 
				
			|||||||
    public void workProgressed(WorkEvent ev) {
 | 
					    public void workProgressed(WorkEvent ev) {
 | 
				
			||||||
        Progress job = ev.getJob();
 | 
					        Progress job = ev.getJob();
 | 
				
			||||||
        Log.d("BookDownloadManager", "Download in progress: " + job.getJobID() + " - " + job.getJobName() + " " + job.getWorkDone() + "/" + job.getTotalWork());
 | 
					        Log.d("BookDownloadManager", "Download in progress: " + job.getJobID() + " - " + job.getJobName() + " " + job.getWorkDone() + "/" + job.getTotalWork());
 | 
				
			||||||
        EventBus downloadBus = downloadManager.getDownloadBus();
 | 
					 | 
				
			||||||
        if (bookMappings.containsKey(job.getJobID())) {
 | 
					        if (bookMappings.containsKey(job.getJobID())) {
 | 
				
			||||||
            Book b = bookMappings.get(job.getJobID());
 | 
					            Book b = bookMappings.get(job.getJobID());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (job.getWorkDone() == job.getTotalWork()) {
 | 
					            if (job.getWorkDone() == job.getTotalWork()) {
 | 
				
			||||||
                // Download is complete
 | 
					                // Download is complete
 | 
				
			||||||
                inProgressDownloads.remove(bookMappings.get(job.getJobID()));
 | 
					                inProgressDownloads.remove(bookMappings.get(job.getJobID()));
 | 
				
			||||||
                downloadBus.post(new DLProgressEvent(DLProgressEvent.PROGRESS_COMPLETE, b));
 | 
					                bookMappings.remove(job.getJobID());
 | 
				
			||||||
 | 
					                downloadEvents.onNext(new DLProgressEvent(DLProgressEvent.PROGRESS_COMPLETE, b));
 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
                // Track the ongoing download
 | 
					                // Track the ongoing download
 | 
				
			||||||
                DLProgressEvent event = new DLProgressEvent(job.getWorkDone(),
 | 
					                DLProgressEvent event = new DLProgressEvent(job.getWorkDone(),
 | 
				
			||||||
                        job.getTotalWork(), b);
 | 
					                        job.getTotalWork(), b);
 | 
				
			||||||
                inProgressDownloads.put(b, event);
 | 
					                inProgressDownloads.put(b, event);
 | 
				
			||||||
                downloadBus.post(event);
 | 
					                downloadEvents.onNext(event);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -97,6 +98,10 @@ public class BookDownloadManager implements WorkListener, BooksListener {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public PublishSubject<DLProgressEvent> getDownloadEvents() {
 | 
				
			||||||
 | 
					        return downloadEvents;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public void workStateChanged(WorkEvent ev) {
 | 
					    public void workStateChanged(WorkEvent ev) {
 | 
				
			||||||
        Log.d("BookDownloadManager", ev.toString());
 | 
					        Log.d("BookDownloadManager", ev.toString());
 | 
				
			||||||
@ -114,8 +119,7 @@ public class BookDownloadManager implements WorkListener, BooksListener {
 | 
				
			|||||||
        // Not sure why, but the inProgressDownloads might not have our book,
 | 
					        // Not sure why, but the inProgressDownloads might not have our book,
 | 
				
			||||||
        // so we always trigger the PROGRESS_COMPLETE event.
 | 
					        // so we always trigger the PROGRESS_COMPLETE event.
 | 
				
			||||||
        // TODO: Make sure all books get to the inProgressDownloads
 | 
					        // TODO: Make sure all books get to the inProgressDownloads
 | 
				
			||||||
        downloadManager.getDownloadBus()
 | 
					        downloadEvents.onNext(new DLProgressEvent(DLProgressEvent.PROGRESS_COMPLETE, b));
 | 
				
			||||||
                .post(new DLProgressEvent(DLProgressEvent.PROGRESS_COMPLETE, b));
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
 | 
				
			|||||||
@ -9,6 +9,9 @@ import org.crosswire.jsword.book.install.Installer;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import javax.inject.Inject;
 | 
					import javax.inject.Inject;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import rx.functions.Action1;
 | 
				
			||||||
 | 
					import rx.schedulers.Schedulers;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Thread that handles downloading a book
 | 
					 * Thread that handles downloading a book
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
@ -18,8 +21,9 @@ public class BookDownloadThread {
 | 
				
			|||||||
    private final String TAG = "BookDownloadThread";
 | 
					    private final String TAG = "BookDownloadThread";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Inject
 | 
					    @Inject
 | 
				
			||||||
    DownloadManager downloadManager;
 | 
					    BookDownloadManager bookDownloadManager;
 | 
				
			||||||
    @Inject RefreshManager refreshManager;
 | 
					    @Inject
 | 
				
			||||||
 | 
					    RefreshManager refreshManager;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public BookDownloadThread() {
 | 
					    public BookDownloadThread() {
 | 
				
			||||||
        MinimalBible.getApplication().inject(this);
 | 
					        MinimalBible.getApplication().inject(this);
 | 
				
			||||||
@ -29,31 +33,32 @@ public class BookDownloadThread {
 | 
				
			|||||||
        // So, the JobManager can't be injected, but we'll make do
 | 
					        // So, the JobManager can't be injected, but we'll make do
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // First, look up where the Book came from
 | 
					        // First, look up where the Book came from
 | 
				
			||||||
        final Installer i = refreshManager.installerFromBook(b);
 | 
					        refreshManager.installerFromBook(b)
 | 
				
			||||||
 | 
					                .subscribeOn(Schedulers.io())
 | 
				
			||||||
        final Thread worker = new Thread() {
 | 
					                .subscribe(new Action1<Installer>() {
 | 
				
			||||||
                    @Override
 | 
					                    @Override
 | 
				
			||||||
            public void run() {
 | 
					                    public void call(Installer installer) {
 | 
				
			||||||
                        try {
 | 
					                        try {
 | 
				
			||||||
                    i.install(b);
 | 
					                            installer.install(b);
 | 
				
			||||||
                        } catch (InstallException e) {
 | 
					                        } catch (InstallException e) {
 | 
				
			||||||
                            Log.d(TAG, e.getMessage());
 | 
					                            Log.d(TAG, e.getMessage());
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        };
 | 
					 | 
				
			||||||
        worker.start();
 | 
					 | 
				
			||||||
        // The worker automatically communicates with the JobManager for its progress.
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        downloadManager.getDownloadBus().post(new DLProgressEvent(DLProgressEvent.PROGRESS_BEGINNING, b));
 | 
					                        bookDownloadManager.getDownloadEvents()
 | 
				
			||||||
 | 
					                                .onNext(new DLProgressEvent(DLProgressEvent.PROGRESS_BEGINNING, b));
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Build what the installer creates the job name as.
 | 
					     * Build what the installer creates the job name as.
 | 
				
			||||||
     * Likely prone to be brittle.
 | 
					     * Likely prone to be brittle.
 | 
				
			||||||
     * TODO: Make sure to test that this is an accurate job name
 | 
					     * TODO: Make sure to test that this is an accurate job name
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
     * @param b The book to predict the download job name of
 | 
					     * @param b The book to predict the download job name of
 | 
				
			||||||
     * @return The name of the job that will/is download/ing this book
 | 
					     * @return The name of the job that will/is download/ing this book
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public static String getJobId(Book b) {
 | 
					    public static String getJobId(Book b) {
 | 
				
			||||||
        return "INSTALL_BOOK-" + b.getInitials();
 | 
					        return "INSTALL_BOOK-" + b.getInitials();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
@ -1,86 +0,0 @@
 | 
				
			|||||||
package org.bspeice.minimalbible.activities.downloader.manager;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import android.content.Context;
 | 
					 | 
				
			||||||
import android.net.ConnectivityManager;
 | 
					 | 
				
			||||||
import android.net.NetworkInfo;
 | 
					 | 
				
			||||||
import android.os.AsyncTask;
 | 
					 | 
				
			||||||
import android.util.Log;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import org.bspeice.minimalbible.MinimalBible;
 | 
					 | 
				
			||||||
import org.bspeice.minimalbible.activities.downloader.DownloadPrefs;
 | 
					 | 
				
			||||||
import org.crosswire.jsword.book.Book;
 | 
					 | 
				
			||||||
import org.crosswire.jsword.book.install.InstallException;
 | 
					 | 
				
			||||||
import org.crosswire.jsword.book.install.Installer;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import java.util.HashMap;
 | 
					 | 
				
			||||||
import java.util.List;
 | 
					 | 
				
			||||||
import java.util.Map;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import javax.inject.Inject;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
public class BookRefreshTask extends AsyncTask<Installer, Integer, List<Book>> {
 | 
					 | 
				
			||||||
	private static final String TAG = "EventBookRefreshTask";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // If last refresh was before the below, force an internet refresh
 | 
					 | 
				
			||||||
    private final Long refreshAfter = System.currentTimeMillis() - 604800000L; // 1 Week in millis
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Inject DownloadPrefs downloadPrefs;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Inject DownloadManager downloadManager;
 | 
					 | 
				
			||||||
    @Inject InstalledManager installedManager;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	public BookRefreshTask() {
 | 
					 | 
				
			||||||
        MinimalBible.getApplication().inject(this);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	@Override
 | 
					 | 
				
			||||||
	protected List<Book> doInBackground(Installer... params) {
 | 
					 | 
				
			||||||
        Map<Installer, List<Book>> bookList = new HashMap<Installer, List<Book>>();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		int index = 0;
 | 
					 | 
				
			||||||
		for (Installer i : params) {
 | 
					 | 
				
			||||||
			if (doRefresh()) {
 | 
					 | 
				
			||||||
				try {
 | 
					 | 
				
			||||||
					i.reloadBookList();
 | 
					 | 
				
			||||||
                    downloadPrefs.downloadRefreshedOn(System.currentTimeMillis());
 | 
					 | 
				
			||||||
				} catch (InstallException e) {
 | 
					 | 
				
			||||||
					Log.e(TAG,
 | 
					 | 
				
			||||||
							"Error downloading books from installer: "
 | 
					 | 
				
			||||||
									+ i.toString(), e);
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
            bookList.put(i, i.getBooks());
 | 
					 | 
				
			||||||
			publishProgress(++index, params.length);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
        //TODO: Filter duplicates
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        installedManager.initialize();
 | 
					 | 
				
			||||||
        EventBookList event = new EventBookList(bookList);
 | 
					 | 
				
			||||||
        downloadManager.getDownloadBus().post(event);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return event.getBookList();
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	private boolean doRefresh() {
 | 
					 | 
				
			||||||
		// Check if we should refresh over the internet, or use the local copy
 | 
					 | 
				
			||||||
		// TODO: Discover if we need to refresh over Internet, or use a cached
 | 
					 | 
				
			||||||
		// copy - likely something time-based, also check network state.
 | 
					 | 
				
			||||||
		// Fun fact - jSword handles the caching for us.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return (isWifi() && downloadEnabled() && needsRefresh());
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private boolean isWifi() {
 | 
					 | 
				
			||||||
        ConnectivityManager mgr = (ConnectivityManager)MinimalBible.getAppContext().getSystemService(Context.CONNECTIVITY_SERVICE);
 | 
					 | 
				
			||||||
        NetworkInfo networkInfo = mgr.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
 | 
					 | 
				
			||||||
        return networkInfo.isConnected();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private boolean downloadEnabled() {
 | 
					 | 
				
			||||||
        return downloadPrefs.hasEnabledDownload();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private boolean needsRefresh() {
 | 
					 | 
				
			||||||
        return (downloadPrefs.downloadRefreshedOn() > refreshAfter);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -6,8 +6,8 @@ import org.crosswire.jsword.book.Book;
 | 
				
			|||||||
 * Used for notifying that a book's download progress is ongoing
 | 
					 * Used for notifying that a book's download progress is ongoing
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
public class DLProgressEvent {
 | 
					public class DLProgressEvent {
 | 
				
			||||||
    private int progress;
 | 
					    private final int progress;
 | 
				
			||||||
    private Book b;
 | 
					    private final Book b;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public static final int PROGRESS_COMPLETE = 100;
 | 
					    public static final int PROGRESS_COMPLETE = 100;
 | 
				
			||||||
    public static final int PROGRESS_BEGINNING = 0;
 | 
					    public static final int PROGRESS_BEGINNING = 0;
 | 
				
			||||||
 | 
				
			|||||||
@ -14,19 +14,12 @@ import java.util.Map;
 | 
				
			|||||||
import javax.inject.Inject;
 | 
					import javax.inject.Inject;
 | 
				
			||||||
import javax.inject.Singleton;
 | 
					import javax.inject.Singleton;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import de.greenrobot.event.EventBus;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// TODO: Listen to BookInstall events?
 | 
					// TODO: Listen to BookInstall events?
 | 
				
			||||||
@Singleton
 | 
					@Singleton
 | 
				
			||||||
public class DownloadManager {
 | 
					public class DownloadManager {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private final String TAG = "DownloadManager";
 | 
						private final String TAG = "DownloadManager";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Inject
 | 
					 | 
				
			||||||
    protected EventBus downloadBus;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	public static final BookCategory[] VALID_CATEGORIES = { BookCategory.BIBLE,
 | 
						public static final BookCategory[] VALID_CATEGORIES = { BookCategory.BIBLE,
 | 
				
			||||||
			BookCategory.COMMENTARY, BookCategory.DICTIONARY,
 | 
								BookCategory.COMMENTARY, BookCategory.DICTIONARY,
 | 
				
			||||||
			BookCategory.MAPS };
 | 
								BookCategory.MAPS };
 | 
				
			||||||
@ -34,8 +27,8 @@ public class DownloadManager {
 | 
				
			|||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Set up the DownloadManager, and notify jSword of where it should store files at
 | 
					     * Set up the DownloadManager, and notify jSword of where it should store files at
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
 | 
					    @Inject
 | 
				
			||||||
	public DownloadManager() {
 | 
						public DownloadManager() {
 | 
				
			||||||
        MinimalBible.getApplication().inject(this);
 | 
					 | 
				
			||||||
		setDownloadDir();
 | 
							setDownloadDir();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -47,15 +40,6 @@ public class DownloadManager {
 | 
				
			|||||||
		return new InstallManager().getInstallers();
 | 
							return new InstallManager().getInstallers();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Helper method to transform the installers map to an array
 | 
					 | 
				
			||||||
     * @return Array with all available {@link org.crosswire.jsword.book.install.Installer} objects
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
	public Installer[] getInstallersArray() {
 | 
					 | 
				
			||||||
		Map<String, Installer> installers = getInstallers();
 | 
					 | 
				
			||||||
		return installers.values().toArray(new Installer[installers.size()]);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Notify jSword that it needs to store files in the Android internal directory
 | 
					     * Notify jSword that it needs to store files in the Android internal directory
 | 
				
			||||||
     * NOTE: Android will uninstall these files if you uninstall MinimalBible.
 | 
					     * NOTE: Android will uninstall these files if you uninstall MinimalBible.
 | 
				
			||||||
@ -71,14 +55,4 @@ public class DownloadManager {
 | 
				
			|||||||
        SwordBookPath.setDownloadDir(new File(home));
 | 
					        SwordBookPath.setDownloadDir(new File(home));
 | 
				
			||||||
        Log.d(TAG, "Sword download path: " + SwordBookPath.getSwordDownloadDir());
 | 
					        Log.d(TAG, "Sword download path: " + SwordBookPath.getSwordDownloadDir());
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Get the current download bus
 | 
					 | 
				
			||||||
     * Used to broker refresh events, and ongoing download events
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
	public EventBus getDownloadBus() {
 | 
					 | 
				
			||||||
		return this.downloadBus;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -1,33 +0,0 @@
 | 
				
			|||||||
package org.bspeice.minimalbible.activities.downloader.manager;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import java.util.ArrayList;
 | 
					 | 
				
			||||||
import java.util.List;
 | 
					 | 
				
			||||||
import java.util.Map;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import org.crosswire.jsword.book.Book;
 | 
					 | 
				
			||||||
import org.crosswire.jsword.book.install.Installer;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * POJO class for {@link de.greenrobot.event.EventBus} to broadcast whenever
 | 
					 | 
				
			||||||
 * we've finished updating the book list.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
public class EventBookList {
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
	private Map<Installer, List<Book>> bookMapping;
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
	public EventBookList(Map<Installer, List<Book>> bookList) {
 | 
					 | 
				
			||||||
		this.bookMapping = bookList;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	public Map<Installer, List<Book>> getInstallerMapping() {
 | 
					 | 
				
			||||||
		return bookMapping;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public List<Book> getBookList() {
 | 
					 | 
				
			||||||
        List<Book> bookList = new ArrayList<Book>();
 | 
					 | 
				
			||||||
        for (Installer i: bookMapping.keySet()) {
 | 
					 | 
				
			||||||
            bookList.addAll(bookMapping.get(i));
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        return bookList;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -19,10 +19,11 @@ import javax.inject.Singleton;
 | 
				
			|||||||
@Singleton
 | 
					@Singleton
 | 
				
			||||||
public class InstalledManager implements BooksListener {
 | 
					public class InstalledManager implements BooksListener {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Inject DownloadManager downloadManager;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private Books installedBooks;
 | 
					    private Books installedBooks;
 | 
				
			||||||
    private List<Book> installedBooksList;
 | 
					    private List<Book> installedBooksList;
 | 
				
			||||||
 | 
					    private String TAG = "InstalledManager";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Inject InstalledManager() {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Register our manager to receive events on Book install
 | 
					     * Register our manager to receive events on Book install
 | 
				
			||||||
@ -30,6 +31,7 @@ public class InstalledManager implements BooksListener {
 | 
				
			|||||||
     * so we don't put it in the constructor.
 | 
					     * so we don't put it in the constructor.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public void initialize() {
 | 
					    public void initialize() {
 | 
				
			||||||
 | 
					        //TODO: Move this to a true async, rather than separate initialize() function
 | 
				
			||||||
        installedBooks = Books.installed();
 | 
					        installedBooks = Books.installed();
 | 
				
			||||||
        installedBooksList = installedBooks.getBooks();
 | 
					        installedBooksList = installedBooks.getBooks();
 | 
				
			||||||
        installedBooks.addBooksListener(this);
 | 
					        installedBooks.addBooksListener(this);
 | 
				
			||||||
@ -44,6 +46,7 @@ public class InstalledManager implements BooksListener {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public void bookAdded(BooksEvent booksEvent) {
 | 
					    public void bookAdded(BooksEvent booksEvent) {
 | 
				
			||||||
 | 
					        Log.d(TAG, "Book added: " + booksEvent.getBook().toString());
 | 
				
			||||||
        Book b = booksEvent.getBook();
 | 
					        Book b = booksEvent.getBook();
 | 
				
			||||||
        if (!installedBooksList.contains(b)) {
 | 
					        if (!installedBooksList.contains(b)) {
 | 
				
			||||||
            installedBooksList.add(b);
 | 
					            installedBooksList.add(b);
 | 
				
			||||||
@ -52,6 +55,7 @@ public class InstalledManager implements BooksListener {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public void bookRemoved(BooksEvent booksEvent) {
 | 
					    public void bookRemoved(BooksEvent booksEvent) {
 | 
				
			||||||
 | 
					        Log.d(TAG, "Book removed: " + booksEvent.getBook().toString());
 | 
				
			||||||
        Book b = booksEvent.getBook();
 | 
					        Book b = booksEvent.getBook();
 | 
				
			||||||
        if (installedBooksList.contains(b)) {
 | 
					        if (installedBooksList.contains(b)) {
 | 
				
			||||||
            installedBooksList.remove(b);
 | 
					            installedBooksList.remove(b);
 | 
				
			||||||
@ -59,10 +63,19 @@ public class InstalledManager implements BooksListener {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public void removeBook(Book b) {
 | 
					    public void removeBook(Book b) {
 | 
				
			||||||
 | 
					        if (installedBooks == null) {
 | 
				
			||||||
 | 
					            initialize();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        // Not sure why we need to call this multiple times, but...
 | 
				
			||||||
 | 
					        while (Books.installed().getBooks().contains(b)) {
 | 
				
			||||||
            try {
 | 
					            try {
 | 
				
			||||||
            installedBooks.removeBook(b);
 | 
					                // This worked in the past, but isn't now...
 | 
				
			||||||
 | 
					                // installedBooks.remove(b);
 | 
				
			||||||
 | 
					                Book realBook = installedBooks.getBook(b.getInitials());
 | 
				
			||||||
 | 
					                b.getDriver().delete(realBook);
 | 
				
			||||||
            } catch (BookException e) {
 | 
					            } catch (BookException e) {
 | 
				
			||||||
                Log.e("InstalledManager", "Unable to remove book (already uninstalled?): " + e.getLocalizedMessage());
 | 
					                Log.e("InstalledManager", "Unable to remove book (already uninstalled?): " + e.getLocalizedMessage());
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -8,11 +8,17 @@ import java.util.ArrayList;
 | 
				
			|||||||
import java.util.HashMap;
 | 
					import java.util.HashMap;
 | 
				
			||||||
import java.util.List;
 | 
					import java.util.List;
 | 
				
			||||||
import java.util.Map;
 | 
					import java.util.Map;
 | 
				
			||||||
 | 
					import java.util.concurrent.atomic.AtomicBoolean;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import javax.inject.Inject;
 | 
					import javax.inject.Inject;
 | 
				
			||||||
import javax.inject.Singleton;
 | 
					import javax.inject.Singleton;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import de.greenrobot.event.EventBus;
 | 
					import rx.Observable;
 | 
				
			||||||
 | 
					import rx.functions.Action0;
 | 
				
			||||||
 | 
					import rx.functions.Action1;
 | 
				
			||||||
 | 
					import rx.functions.Func1;
 | 
				
			||||||
 | 
					import rx.functions.Func2;
 | 
				
			||||||
 | 
					import rx.schedulers.Schedulers;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Handle refreshing the list of books available as needed
 | 
					 * Handle refreshing the list of books available as needed
 | 
				
			||||||
@ -21,35 +27,74 @@ import de.greenrobot.event.EventBus;
 | 
				
			|||||||
public class RefreshManager {
 | 
					public class RefreshManager {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Inject DownloadManager downloadManager;
 | 
					    @Inject DownloadManager downloadManager;
 | 
				
			||||||
 | 
					    @Inject InstalledManager installedManager;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Cached copy of modules that are available so we don't refresh for everyone who requests it.
 | 
					     * Cached copy of modules that are available so we don't refresh for everyone who requests it.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    private Map<Installer, List<Book>> availableModules;
 | 
					    private Observable<Map<Installer, List<Book>>> availableModules;
 | 
				
			||||||
 | 
					    private final AtomicBoolean refreshComplete = new AtomicBoolean();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public RefreshManager() {
 | 
					    public RefreshManager() {
 | 
				
			||||||
        MinimalBible.getApplication().inject(this);
 | 
					        MinimalBible.getApplication().inject(this);
 | 
				
			||||||
        availableModules = new HashMap<Installer, List<Book>>();
 | 
					 | 
				
			||||||
        refreshModules();
 | 
					        refreshModules();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Do the work of kicking off the AsyncTask to refresh books, and make sure we know
 | 
					     * Do the work of kicking off the AsyncTask to refresh books, and make sure we know
 | 
				
			||||||
     * when it's done.
 | 
					     * when it's done.
 | 
				
			||||||
 | 
					     * TODO: Should I have a better way of scheduling than Schedulers.io()?
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    private void refreshModules() {
 | 
					    private void refreshModules() {
 | 
				
			||||||
        EventBus refreshBus = downloadManager.getDownloadBus();
 | 
					        if (availableModules == null) {
 | 
				
			||||||
        refreshBus.register(this);
 | 
					            availableModules = Observable.from(downloadManager.getInstallers().values())
 | 
				
			||||||
        new BookRefreshTask().execute(downloadManager.getInstallersArray());
 | 
					                    .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>>();
 | 
				
			||||||
 | 
					                            map.put(installer, installer.getBooks());
 | 
				
			||||||
 | 
					                            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);
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    });
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    public Observable<Map<Installer, List<Book>>> getAvailableModules() {
 | 
				
			||||||
     * When book refresh is done, cache the list so we can give that to someone else
 | 
					        return availableModules;
 | 
				
			||||||
     * @param event A POJO wrapper around the Book list
 | 
					    }
 | 
				
			||||||
     */
 | 
					
 | 
				
			||||||
    @SuppressWarnings("unused")
 | 
					    public Observable<Book> getAvailableModulesFlattened() {
 | 
				
			||||||
    public void onEvent(EventBookList event) {
 | 
					        return availableModules
 | 
				
			||||||
        this.availableModules = event.getInstallerMapping();
 | 
					                // 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);
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
@ -57,15 +102,18 @@ public class RefreshManager {
 | 
				
			|||||||
     * @return The cached book list, or null
 | 
					     * @return The cached book list, or null
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public List<Book> getBookList() {
 | 
					    public List<Book> getBookList() {
 | 
				
			||||||
        if (availableModules.values().size() == 0) {
 | 
					        List<Book> availableList = new ArrayList<Book>();
 | 
				
			||||||
            return null;
 | 
					        availableModules.reduce(availableList,
 | 
				
			||||||
        } else {
 | 
					                new Func2<List<Book>, Map<Installer, List<Book>>, List<Book>>() {
 | 
				
			||||||
            List<Book> bookList = new ArrayList<Book>();
 | 
					            @Override
 | 
				
			||||||
            for (List<Book> l : availableModules.values()) {
 | 
					            public List<Book> call(List<Book> books, Map<Installer, List<Book>> installerListMap) {
 | 
				
			||||||
                bookList.addAll(l);
 | 
					                for (List<Book> l : installerListMap.values()) {
 | 
				
			||||||
 | 
					                    books.addAll(l);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            return bookList;
 | 
					                return books;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					        return availableList;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
@ -73,12 +121,28 @@ public class RefreshManager {
 | 
				
			|||||||
     * @param b The book to search for
 | 
					     * @param b The book to search for
 | 
				
			||||||
     * @return The Installer that should be used for this book.
 | 
					     * @return The Installer that should be used for this book.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public Installer installerFromBook(Book b) {
 | 
					    public Observable<Installer> installerFromBook(final Book b) {
 | 
				
			||||||
        for (Map.Entry<Installer, List<Book>> entry : availableModules.entrySet()) {
 | 
					        return availableModules.filter(new Func1<Map<Installer, List<Book>>, Boolean>() {
 | 
				
			||||||
            if (entry.getValue().contains(b)) {
 | 
					            @Override
 | 
				
			||||||
                return entry.getKey();
 | 
					            public Boolean call(Map<Installer, List<Book>> installerListMap) {
 | 
				
			||||||
 | 
					                for (List<Book> element : installerListMap.values()) {
 | 
				
			||||||
 | 
					                    if (element.contains(b)) {
 | 
				
			||||||
 | 
					                        return true;
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
        return null;
 | 
					                return false;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					        .first()
 | 
				
			||||||
 | 
					        .map(new Func1<Map<Installer, List<Book>>, Installer>() {
 | 
				
			||||||
 | 
					            @Override
 | 
				
			||||||
 | 
					            public Installer call(Map<Installer, List<Book>> element) {
 | 
				
			||||||
 | 
					                return element.entrySet().iterator().next().getKey();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public boolean isRefreshComplete() {
 | 
				
			||||||
 | 
					        return refreshComplete.get();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -0,0 +1,15 @@
 | 
				
			|||||||
 | 
					package org.bspeice.minimalbible.activities.viewer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import dagger.Module;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Created by bspeice on 6/18/14.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					@Module(
 | 
				
			||||||
 | 
					        injects = {
 | 
				
			||||||
 | 
					                BibleViewer.class,
 | 
				
			||||||
 | 
					                BookFragment.class
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					public class ActivityViewerModule {
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -1,27 +1,33 @@
 | 
				
			|||||||
package org.bspeice.minimalbible.activities.viewer;
 | 
					package org.bspeice.minimalbible.activities.viewer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import android.app.Activity;
 | 
					 | 
				
			||||||
import android.content.Intent;
 | 
					import android.content.Intent;
 | 
				
			||||||
import android.os.Bundle;
 | 
					import android.os.Bundle;
 | 
				
			||||||
 | 
					import android.os.Looper;
 | 
				
			||||||
import android.support.v4.app.Fragment;
 | 
					import android.support.v4.app.Fragment;
 | 
				
			||||||
import android.support.v4.app.FragmentManager;
 | 
					import android.support.v4.app.FragmentManager;
 | 
				
			||||||
import android.support.v4.widget.DrawerLayout;
 | 
					import android.support.v4.widget.DrawerLayout;
 | 
				
			||||||
import android.support.v7.app.ActionBar;
 | 
					import android.support.v7.app.ActionBar;
 | 
				
			||||||
import android.view.LayoutInflater;
 | 
					import android.util.Log;
 | 
				
			||||||
import android.view.Menu;
 | 
					import android.view.Menu;
 | 
				
			||||||
import android.view.MenuItem;
 | 
					import android.view.MenuItem;
 | 
				
			||||||
import android.view.View;
 | 
					 | 
				
			||||||
import android.view.ViewGroup;
 | 
					 | 
				
			||||||
import android.widget.TextView;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import org.bspeice.minimalbible.MinimalBible;
 | 
				
			||||||
import org.bspeice.minimalbible.R;
 | 
					import org.bspeice.minimalbible.R;
 | 
				
			||||||
import org.bspeice.minimalbible.activities.BaseActivity;
 | 
					import org.bspeice.minimalbible.activities.BaseActivity;
 | 
				
			||||||
import org.bspeice.minimalbible.activities.BaseNavigationDrawerFragment;
 | 
					import org.bspeice.minimalbible.activities.BaseNavigationDrawerFragment;
 | 
				
			||||||
import org.bspeice.minimalbible.activities.downloader.DownloadActivity;
 | 
					import org.bspeice.minimalbible.activities.downloader.DownloadActivity;
 | 
				
			||||||
 | 
					import org.crosswire.jsword.book.Book;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import javax.inject.Inject;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import rx.android.schedulers.AndroidSchedulers;
 | 
				
			||||||
 | 
					import rx.functions.Action1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public class BibleViewer extends BaseActivity implements
 | 
					public class BibleViewer extends BaseActivity implements
 | 
				
			||||||
		BaseNavigationDrawerFragment.NavigationDrawerCallbacks {
 | 
							BaseNavigationDrawerFragment.NavigationDrawerCallbacks {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Inject BookManager bookManager;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/**
 | 
						/**
 | 
				
			||||||
	 * Fragment managing the behaviors, interactions and presentation of the
 | 
						 * Fragment managing the behaviors, interactions and presentation of the
 | 
				
			||||||
	 * navigation drawer.
 | 
						 * navigation drawer.
 | 
				
			||||||
@ -37,6 +43,31 @@ public class BibleViewer extends BaseActivity implements
 | 
				
			|||||||
	@Override
 | 
						@Override
 | 
				
			||||||
	protected void onCreate(Bundle savedInstanceState) {
 | 
						protected void onCreate(Bundle savedInstanceState) {
 | 
				
			||||||
		super.onCreate(savedInstanceState);
 | 
							super.onCreate(savedInstanceState);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        MinimalBible.getApplication().inject(this);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // If no books are installed, we need to download one first.
 | 
				
			||||||
 | 
					        int count = bookManager.getInstalledBooks()
 | 
				
			||||||
 | 
					                .count()
 | 
				
			||||||
 | 
					                .toBlocking()
 | 
				
			||||||
 | 
					                .last();
 | 
				
			||||||
 | 
					        if (count <= 0) {
 | 
				
			||||||
 | 
					            Intent i = new Intent(this, DownloadActivity.class);
 | 
				
			||||||
 | 
					            startActivityForResult(i, 0);
 | 
				
			||||||
 | 
					            finish();
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            bookManager.getInstalledBooks()
 | 
				
			||||||
 | 
					                    .first()
 | 
				
			||||||
 | 
					                    .subscribeOn(AndroidSchedulers.mainThread())
 | 
				
			||||||
 | 
					                    .subscribe(new Action1<Book>() {
 | 
				
			||||||
 | 
					                        @Override
 | 
				
			||||||
 | 
					                        public void call(Book book) {
 | 
				
			||||||
 | 
					                            Log.d("BibleViewer", "Subscribed to display book: " + book.getName());
 | 
				
			||||||
 | 
					                            displayMainBook(book);
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    });
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		setContentView(R.layout.activity_bible_viewer);
 | 
							setContentView(R.layout.activity_bible_viewer);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		mNavigationDrawerFragment = (ViewerNavDrawerFragment) getSupportFragmentManager()
 | 
							mNavigationDrawerFragment = (ViewerNavDrawerFragment) getSupportFragmentManager()
 | 
				
			||||||
@ -50,26 +81,13 @@ public class BibleViewer extends BaseActivity implements
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	@Override
 | 
						@Override
 | 
				
			||||||
	public void onNavigationDrawerItemSelected(int position) {
 | 
						public void onNavigationDrawerItemSelected(int position) {
 | 
				
			||||||
		// update the main content by replacing fragments
 | 
							// Handle a navigation movement
 | 
				
			||||||
		FragmentManager fragmentManager = getSupportFragmentManager();
 | 
					 | 
				
			||||||
		fragmentManager
 | 
					 | 
				
			||||||
				.beginTransaction()
 | 
					 | 
				
			||||||
				.replace(R.id.container,
 | 
					 | 
				
			||||||
						PlaceholderFragment.newInstance(position + 1)).commit();
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public void onSectionAttached(int number) {
 | 
					    public void setActionBarTitle(String title) {
 | 
				
			||||||
		switch (number) {
 | 
					        ActionBar actionBar = getSupportActionBar();
 | 
				
			||||||
		case 1:
 | 
					        mTitle = title;
 | 
				
			||||||
			mTitle = getString(R.string.title_section1);
 | 
					        actionBar.setTitle(title);
 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
		case 2:
 | 
					 | 
				
			||||||
			mTitle = getString(R.string.title_section2);
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
		case 3:
 | 
					 | 
				
			||||||
			mTitle = getString(R.string.title_section3);
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public void restoreActionBar() {
 | 
						public void restoreActionBar() {
 | 
				
			||||||
@ -106,48 +124,13 @@ public class BibleViewer extends BaseActivity implements
 | 
				
			|||||||
		return super.onOptionsItemSelected(item);
 | 
							return super.onOptionsItemSelected(item);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/**
 | 
					    private void displayMainBook(Book b) {
 | 
				
			||||||
	 * A placeholder fragment containing a simple view.
 | 
					        Log.d("BibleViewer", "Initializing main book: " + b.getName());
 | 
				
			||||||
	 */
 | 
					        Log.d("MainThread?", Boolean.toString(Looper.myLooper() == Looper.getMainLooper()));
 | 
				
			||||||
	public static class PlaceholderFragment extends Fragment {
 | 
					        FragmentManager fragmentManager = getSupportFragmentManager();
 | 
				
			||||||
		/**
 | 
					        Fragment f = BookFragment.newInstance(b.getName());
 | 
				
			||||||
		 * The fragment argument representing the section number for this
 | 
					        fragmentManager.beginTransaction()
 | 
				
			||||||
		 * fragment.
 | 
					                .replace(R.id.container, f)
 | 
				
			||||||
		 */
 | 
					                .commit();
 | 
				
			||||||
		private static final String ARG_SECTION_NUMBER = "section_number";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		/**
 | 
					 | 
				
			||||||
		 * Returns a new instance of this fragment for the given section number.
 | 
					 | 
				
			||||||
		 */
 | 
					 | 
				
			||||||
		public static PlaceholderFragment newInstance(int sectionNumber) {
 | 
					 | 
				
			||||||
			PlaceholderFragment fragment = new PlaceholderFragment();
 | 
					 | 
				
			||||||
			Bundle args = new Bundle();
 | 
					 | 
				
			||||||
			args.putInt(ARG_SECTION_NUMBER, sectionNumber);
 | 
					 | 
				
			||||||
			fragment.setArguments(args);
 | 
					 | 
				
			||||||
			return fragment;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public PlaceholderFragment() {
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		@Override
 | 
					 | 
				
			||||||
		public View onCreateView(LayoutInflater inflater, ViewGroup container,
 | 
					 | 
				
			||||||
				Bundle savedInstanceState) {
 | 
					 | 
				
			||||||
			View rootView = inflater.inflate(R.layout.fragment_main, container,
 | 
					 | 
				
			||||||
					false);
 | 
					 | 
				
			||||||
			TextView textView = (TextView) rootView
 | 
					 | 
				
			||||||
					.findViewById(R.id.section_label);
 | 
					 | 
				
			||||||
			textView.setText(Integer.toString(getArguments().getInt(
 | 
					 | 
				
			||||||
					ARG_SECTION_NUMBER)));
 | 
					 | 
				
			||||||
			return rootView;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		@Override
 | 
					 | 
				
			||||||
		public void onAttach(Activity activity) {
 | 
					 | 
				
			||||||
			super.onAttach(activity);
 | 
					 | 
				
			||||||
			((BibleViewer) activity).onSectionAttached(getArguments().getInt(
 | 
					 | 
				
			||||||
					ARG_SECTION_NUMBER));
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
				
			|||||||
@ -0,0 +1,140 @@
 | 
				
			|||||||
 | 
					package org.bspeice.minimalbible.activities.viewer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import android.app.Activity;
 | 
				
			||||||
 | 
					import android.os.Bundle;
 | 
				
			||||||
 | 
					import android.util.Log;
 | 
				
			||||||
 | 
					import android.view.LayoutInflater;
 | 
				
			||||||
 | 
					import android.view.View;
 | 
				
			||||||
 | 
					import android.view.ViewGroup;
 | 
				
			||||||
 | 
					import android.webkit.WebView;
 | 
				
			||||||
 | 
					import android.webkit.WebViewClient;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import org.bspeice.minimalbible.MinimalBible;
 | 
				
			||||||
 | 
					import org.bspeice.minimalbible.R;
 | 
				
			||||||
 | 
					import org.bspeice.minimalbible.activities.BaseFragment;
 | 
				
			||||||
 | 
					import org.crosswire.jsword.book.Book;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.util.List;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import javax.inject.Inject;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import butterknife.ButterKnife;
 | 
				
			||||||
 | 
					import butterknife.InjectView;
 | 
				
			||||||
 | 
					import rx.android.schedulers.AndroidSchedulers;
 | 
				
			||||||
 | 
					import rx.functions.Action1;
 | 
				
			||||||
 | 
					import rx.functions.Func1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * A placeholder fragment containing a simple view.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					public class BookFragment extends BaseFragment {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Inject BookManager bookManager;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @InjectView(R.id.book_content)
 | 
				
			||||||
 | 
					    WebView mainContent;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private static final String ARG_BOOK_NAME = "book_name";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private Book mBook;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Returns a new instance of this fragment for the given section number.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public static BookFragment newInstance(String bookName) {
 | 
				
			||||||
 | 
					        BookFragment fragment = new BookFragment();
 | 
				
			||||||
 | 
					        Bundle args = new Bundle();
 | 
				
			||||||
 | 
					        args.putString(ARG_BOOK_NAME, bookName);
 | 
				
			||||||
 | 
					        fragment.setArguments(args);
 | 
				
			||||||
 | 
					        return fragment;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public BookFragment() {
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public void onCreate(Bundle state) {
 | 
				
			||||||
 | 
					        super.onCreate(state);
 | 
				
			||||||
 | 
					        MinimalBible.getApplication().inject(this);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public View onCreateView(LayoutInflater inflater, ViewGroup container,
 | 
				
			||||||
 | 
					            Bundle savedInstanceState) {
 | 
				
			||||||
 | 
					        View rootView = inflater.inflate(R.layout.fragment_viewer_main, container,
 | 
				
			||||||
 | 
					                false);
 | 
				
			||||||
 | 
					        ButterKnife.inject(this, rootView);
 | 
				
			||||||
 | 
					        mainContent.getSettings().setJavaScriptEnabled(true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // TODO: Load initial text from SharedPreferences
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // And due to Observable async, we can kick off fetching the actual book asynchronously!
 | 
				
			||||||
 | 
					        bookManager.getInstalledBooks()
 | 
				
			||||||
 | 
					                .first(new Func1<Book, Boolean>() {
 | 
				
			||||||
 | 
					                    @Override
 | 
				
			||||||
 | 
					                    public Boolean call(Book book) {
 | 
				
			||||||
 | 
					                        String mBookName = getArguments().getString(ARG_BOOK_NAME);
 | 
				
			||||||
 | 
					                        return book.getName().equals(mBookName);
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                })
 | 
				
			||||||
 | 
					                .observeOn(AndroidSchedulers.mainThread())
 | 
				
			||||||
 | 
					                .subscribe(new Action1<Book>() {
 | 
				
			||||||
 | 
					                    @Override
 | 
				
			||||||
 | 
					                    public void call(Book book) {
 | 
				
			||||||
 | 
					                        BookFragment.this.mBook = book;
 | 
				
			||||||
 | 
					                        displayBook(book);
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }, new Action1<Throwable>() {
 | 
				
			||||||
 | 
					                    @Override
 | 
				
			||||||
 | 
					                    public void call(Throwable throwable) {
 | 
				
			||||||
 | 
					                        Log.d("BookFragment", "No books installed?");
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return rootView;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // TODO: Remove?
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public void onAttach(Activity activity) {
 | 
				
			||||||
 | 
					        super.onAttach(activity);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private void displayBook(Book b) {
 | 
				
			||||||
 | 
					        Log.d("BookFragment", b.getName());
 | 
				
			||||||
 | 
					        ((BibleViewer)getActivity()).setActionBarTitle(b.getInitials());
 | 
				
			||||||
 | 
					        mainContent.loadUrl(getString(R.string.content_page));
 | 
				
			||||||
 | 
					        mainContent.setWebViewClient(new WebViewClient(){
 | 
				
			||||||
 | 
					            @Override
 | 
				
			||||||
 | 
					            public void onPageFinished(WebView view, String url) {
 | 
				
			||||||
 | 
					                super.onPageFinished(view, url);
 | 
				
			||||||
 | 
					                invokeJavascript("set_content", BookFragment.this.mBook.getName());
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private void invokeJavascript(String function, Object arg) {
 | 
				
			||||||
 | 
					        mainContent.loadUrl("javascript:" + function + "('" + arg.toString() + "')");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private void invokeJavascript(String function, List<Object> args) {
 | 
				
			||||||
 | 
					        mainContent.loadUrl("javascript:" + function + "(" + joinString(",", args.toArray()) + ")");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Convenience from http://stackoverflow.com/a/17795110/1454178
 | 
				
			||||||
 | 
					    public static String joinString(String join, Object... strings) {
 | 
				
			||||||
 | 
					        if (strings == null || strings.length == 0) {
 | 
				
			||||||
 | 
					            return "";
 | 
				
			||||||
 | 
					        } else if (strings.length == 1) {
 | 
				
			||||||
 | 
					            return strings[0].toString();
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            StringBuilder sb = new StringBuilder();
 | 
				
			||||||
 | 
					            sb.append(strings[0]);
 | 
				
			||||||
 | 
					            for (int i = 1; i < strings.length; i++) {
 | 
				
			||||||
 | 
					                sb.append(join).append(strings[i].toString());
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            return sb.toString();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,50 @@
 | 
				
			|||||||
 | 
					package org.bspeice.minimalbible.activities.viewer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import org.crosswire.jsword.book.Book;
 | 
				
			||||||
 | 
					import org.crosswire.jsword.book.Books;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import javax.inject.Inject;
 | 
				
			||||||
 | 
					import javax.inject.Singleton;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import rx.Observable;
 | 
				
			||||||
 | 
					import rx.functions.Action0;
 | 
				
			||||||
 | 
					import rx.functions.Action1;
 | 
				
			||||||
 | 
					import rx.schedulers.Schedulers;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Created by bspeice on 6/18/14.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					@Singleton
 | 
				
			||||||
 | 
					public class BookManager {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private Observable<Book> installedBooks;
 | 
				
			||||||
 | 
					    private Boolean refreshComplete;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Inject
 | 
				
			||||||
 | 
					    BookManager() {
 | 
				
			||||||
 | 
					        installedBooks = Observable.from(Books.installed().getBooks())
 | 
				
			||||||
 | 
					            .cache();
 | 
				
			||||||
 | 
					        installedBooks.subscribeOn(Schedulers.io())
 | 
				
			||||||
 | 
					                .subscribe(new Action1<Book>() {
 | 
				
			||||||
 | 
					            @Override
 | 
				
			||||||
 | 
					            public void call(Book book) {}
 | 
				
			||||||
 | 
					        }, new Action1<Throwable>() {
 | 
				
			||||||
 | 
					            @Override
 | 
				
			||||||
 | 
					            public void call(Throwable throwable) {}
 | 
				
			||||||
 | 
					        }, new Action0() {
 | 
				
			||||||
 | 
					            @Override
 | 
				
			||||||
 | 
					            public void call() {
 | 
				
			||||||
 | 
					                BookManager.this.refreshComplete = true;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public Observable<Book> getInstalledBooks() {
 | 
				
			||||||
 | 
					        return installedBooks;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public Boolean isRefreshComplete() {
 | 
				
			||||||
 | 
					        return refreshComplete;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -1,16 +0,0 @@
 | 
				
			|||||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 | 
					 | 
				
			||||||
    xmlns:tools="http://schemas.android.com/tools"
 | 
					 | 
				
			||||||
    android:layout_width="match_parent"
 | 
					 | 
				
			||||||
    android:layout_height="match_parent"
 | 
					 | 
				
			||||||
    android:paddingBottom="@dimen/activity_vertical_margin"
 | 
					 | 
				
			||||||
    android:paddingLeft="@dimen/activity_horizontal_margin"
 | 
					 | 
				
			||||||
    android:paddingRight="@dimen/activity_horizontal_margin"
 | 
					 | 
				
			||||||
    android:paddingTop="@dimen/activity_vertical_margin"
 | 
					 | 
				
			||||||
    tools:context="org.bspeice.minimalbible.MainActivity$PlaceholderFragment" >
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    <TextView
 | 
					 | 
				
			||||||
        android:id="@+id/section_label"
 | 
					 | 
				
			||||||
        android:layout_width="wrap_content"
 | 
					 | 
				
			||||||
        android:layout_height="wrap_content" />
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
</RelativeLayout>
 | 
					 | 
				
			||||||
@ -3,6 +3,7 @@
 | 
				
			|||||||
    android:id="@+id/list_nav_drawer"
 | 
					    android:id="@+id/list_nav_drawer"
 | 
				
			||||||
    android:layout_width="match_parent"
 | 
					    android:layout_width="match_parent"
 | 
				
			||||||
    android:layout_height="match_parent"
 | 
					    android:layout_height="match_parent"
 | 
				
			||||||
 | 
					    android:background="#cccccc"
 | 
				
			||||||
    android:choiceMode="singleChoice"
 | 
					    android:choiceMode="singleChoice"
 | 
				
			||||||
    android:divider="@android:color/transparent"
 | 
					    android:divider="@android:color/transparent"
 | 
				
			||||||
    android:dividerHeight="0dp"
 | 
					    android:dividerHeight="0dp"
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										12
									
								
								MinimalBible/src/main/res/layout/fragment_viewer_main.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								MinimalBible/src/main/res/layout/fragment_viewer_main.xml
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,12 @@
 | 
				
			|||||||
 | 
					<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 | 
				
			||||||
 | 
					    xmlns:tools="http://schemas.android.com/tools"
 | 
				
			||||||
 | 
					    android:layout_width="match_parent"
 | 
				
			||||||
 | 
					    android:layout_height="match_parent"
 | 
				
			||||||
 | 
					    tools:context="org.bspeice.minimalbible.MainActivity$PlaceholderFragment" >
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <WebView
 | 
				
			||||||
 | 
					        android:id="@+id/book_content"
 | 
				
			||||||
 | 
					        android:layout_width="fill_parent"
 | 
				
			||||||
 | 
					        android:layout_height="fill_parent" />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					</RelativeLayout>
 | 
				
			||||||
@ -3,10 +3,6 @@
 | 
				
			|||||||
    xmlns:tools="http://schemas.android.com/tools"
 | 
					    xmlns:tools="http://schemas.android.com/tools"
 | 
				
			||||||
    tools:context="org.bspeice.minimalbible.MainActivity" >
 | 
					    tools:context="org.bspeice.minimalbible.MainActivity" >
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    <item
 | 
					 | 
				
			||||||
        android:id="@+id/action_example"
 | 
					 | 
				
			||||||
        android:title="@string/action_example"
 | 
					 | 
				
			||||||
        app:showAsAction="withText|ifRoom"/>
 | 
					 | 
				
			||||||
    <item
 | 
					    <item
 | 
				
			||||||
        android:id="@+id/action_settings"
 | 
					        android:id="@+id/action_settings"
 | 
				
			||||||
        android:orderInCategory="100"
 | 
					        android:orderInCategory="100"
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										4
									
								
								MinimalBible/src/main/res/values/html_strings.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								MinimalBible/src/main/res/values/html_strings.xml
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,4 @@
 | 
				
			|||||||
 | 
					<?xml version="1.0" encoding="utf-8"?>
 | 
				
			||||||
 | 
					<resources>
 | 
				
			||||||
 | 
					    <string name="content_page">file:///android_asset/book.html</string>
 | 
				
			||||||
 | 
					</resources>
 | 
				
			||||||
							
								
								
									
										19
									
								
								MinimalBible/src/test/AndroidManifest.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								MinimalBible/src/test/AndroidManifest.xml
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,19 @@
 | 
				
			|||||||
 | 
					<manifest xmlns:android="http://schemas.android.com/apk/res/android"
 | 
				
			||||||
 | 
					    package="org.bspeice.minimalbible">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <uses-sdk
 | 
				
			||||||
 | 
					        android:minSdkVersion="8"
 | 
				
			||||||
 | 
					        android:targetSdkVersion="20" />
 | 
				
			||||||
 | 
					    <uses-permission android:name="android.permission.INTERNET"/>
 | 
				
			||||||
 | 
					    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <application
 | 
				
			||||||
 | 
					        android:allowBackup="true"
 | 
				
			||||||
 | 
					        android:icon="@drawable/ic_launcher"
 | 
				
			||||||
 | 
					        android:label="@string/app_name"
 | 
				
			||||||
 | 
					        android:theme="@style/AppTheme"
 | 
				
			||||||
 | 
					        android:name="org.bspeice.minimalbible.test.MinimalBibleTest" >
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    </application>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					</manifest>
 | 
				
			||||||
@ -1,119 +0,0 @@
 | 
				
			|||||||
package org.bspeice.minimalbible.test;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import android.test.InstrumentationTestCase;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import org.bspeice.minimalbible.MinimalBible;
 | 
					 | 
				
			||||||
import org.bspeice.minimalbible.MinimalBibleModules;
 | 
					 | 
				
			||||||
import org.bspeice.minimalbible.activities.downloader.manager.BookDownloadThread;
 | 
					 | 
				
			||||||
import org.bspeice.minimalbible.activities.downloader.manager.DLProgressEvent;
 | 
					 | 
				
			||||||
import org.bspeice.minimalbible.activities.downloader.manager.DownloadManager;
 | 
					 | 
				
			||||||
import org.bspeice.minimalbible.activities.downloader.manager.InstalledManager;
 | 
					 | 
				
			||||||
import org.bspeice.minimalbible.activities.downloader.manager.RefreshManager;
 | 
					 | 
				
			||||||
import org.crosswire.jsword.book.Book;
 | 
					 | 
				
			||||||
import org.crosswire.jsword.book.BookException;
 | 
					 | 
				
			||||||
import org.crosswire.jsword.book.Books;
 | 
					 | 
				
			||||||
import org.crosswire.jsword.book.install.Installer;
 | 
					 | 
				
			||||||
import org.crosswire.jsword.passage.NoSuchKeyException;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import java.util.concurrent.Callable;
 | 
					 | 
				
			||||||
import java.util.concurrent.CountDownLatch;
 | 
					 | 
				
			||||||
import java.util.concurrent.TimeUnit;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import javax.inject.Inject;
 | 
					 | 
				
			||||||
import javax.inject.Provider;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import dagger.Module;
 | 
					 | 
				
			||||||
import dagger.ObjectGraph;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import static com.jayway.awaitility.Awaitility.*;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Tests for the Download activity
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
public class DownloadActivityTest extends InstrumentationTestCase {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Module(addsTo = MinimalBibleModules.class,
 | 
					 | 
				
			||||||
            injects = DownloadActivityTest.class)
 | 
					 | 
				
			||||||
    public static class DownloadActivityTestModule {}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Inject DownloadManager dm;
 | 
					 | 
				
			||||||
    @Inject InstalledManager im;
 | 
					 | 
				
			||||||
    @Inject Provider<BookDownloadThread> bookDownloadThreadProvider;
 | 
					 | 
				
			||||||
    @Inject RefreshManager rm;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public void setUp() {
 | 
					 | 
				
			||||||
        MinimalBible application = MinimalBible.getApplication();
 | 
					 | 
				
			||||||
        ObjectGraph graph = application.getObjGraph();
 | 
					 | 
				
			||||||
        ObjectGraph plusGraph = graph.plus(DownloadActivityTestModule.class);
 | 
					 | 
				
			||||||
        plusGraph.inject(this);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public void testBasicAssertion() {
 | 
					 | 
				
			||||||
        assertEquals(true, true);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * When we start a download, make sure a progress event of 0 is triggered.
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    public void testInitialProgressEventOnDownload() throws InterruptedException {
 | 
					 | 
				
			||||||
        final CountDownLatch signal = new CountDownLatch(1);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // Need to make sure we've refreshed the refreshmanager first
 | 
					 | 
				
			||||||
        Installer i = (Installer) dm.getInstallers().values().toArray()[0];
 | 
					 | 
				
			||||||
        final Book testBook = i.getBooks().get(0);
 | 
					 | 
				
			||||||
        await().atMost(30, TimeUnit.SECONDS).until(new Callable<Boolean>() {
 | 
					 | 
				
			||||||
            @Override
 | 
					 | 
				
			||||||
            public Boolean call() throws Exception {
 | 
					 | 
				
			||||||
                return rm.installerFromBook(testBook) != null;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // And wait for the actual download
 | 
					 | 
				
			||||||
        dm.getDownloadBus().register(new Object() {
 | 
					 | 
				
			||||||
            public void onEvent(DLProgressEvent event) {
 | 
					 | 
				
			||||||
                if (event.getProgress() == 0) {
 | 
					 | 
				
			||||||
                    signal.countDown();
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        BookDownloadThread thread = bookDownloadThreadProvider.get();
 | 
					 | 
				
			||||||
        thread.downloadBook(testBook);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        signal.await(10, TimeUnit.SECONDS);
 | 
					 | 
				
			||||||
        if (signal.getCount() != 0) {
 | 
					 | 
				
			||||||
            fail("Event did not trigger!");
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Test that we can successfully download and remove a book
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    public void testInstallAndRemoveBook() {
 | 
					 | 
				
			||||||
        // Install a book
 | 
					 | 
				
			||||||
        Installer i = (Installer) dm.getInstallers().values().toArray()[0];
 | 
					 | 
				
			||||||
        final Book testBook = i.getBooks().get(0);
 | 
					 | 
				
			||||||
        await().atMost(30, TimeUnit.SECONDS).until(new Callable<Boolean>() {
 | 
					 | 
				
			||||||
            @Override
 | 
					 | 
				
			||||||
            public Boolean call() throws Exception {
 | 
					 | 
				
			||||||
                return Books.installed().getBooks().contains(testBook);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // Validate that we can actually do something with the book
 | 
					 | 
				
			||||||
        // TODO: Validate that the book exists on the filesystem too
 | 
					 | 
				
			||||||
        try {
 | 
					 | 
				
			||||||
            assertNotNull(testBook.getRawText(testBook.getKey("Gen 1:1")));
 | 
					 | 
				
			||||||
        } catch (BookException e) {
 | 
					 | 
				
			||||||
            fail(e.getMessage());
 | 
					 | 
				
			||||||
        } catch (NoSuchKeyException e) {
 | 
					 | 
				
			||||||
            fail(e.getMessage());
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // Remove the book and make sure it's gone
 | 
					 | 
				
			||||||
        // TODO: Validate that the book is off the filesystem
 | 
					 | 
				
			||||||
        im.removeBook(testBook);
 | 
					 | 
				
			||||||
        assertFalse(Books.installed().getBooks().contains(testBook));
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -0,0 +1,20 @@
 | 
				
			|||||||
 | 
					package org.bspeice.minimalbible.test;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import org.bspeice.minimalbible.MinimalBible;
 | 
				
			||||||
 | 
					import org.bspeice.minimalbible.MinimalBibleModules;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import dagger.Module;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Master module for MinimalBible
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					@Module(
 | 
				
			||||||
 | 
					    injects = {
 | 
				
			||||||
 | 
					        MinimalBible.class
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    includes = {
 | 
				
			||||||
 | 
					            MinimalBibleModules.class
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					public class MinimalBibleModulesTest {
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,75 @@
 | 
				
			|||||||
 | 
					package org.bspeice.minimalbible.test;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import android.content.Context;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import org.bspeice.minimalbible.MinimalBible;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import dagger.ObjectGraph;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public class MinimalBibleTest extends MinimalBible {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * The graph used by Dagger to track dependencies
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    private ObjectGraph graph;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * A singleton reference to the Application currently being run.
 | 
				
			||||||
 | 
					     * Used mostly so we have a fixed point to get the App Context from
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
						private static MinimalBibleTest instance;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private String TAG = "MinimalBibleTest";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Create the application, and persist the application Context
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
						public MinimalBibleTest() {
 | 
				
			||||||
 | 
							instance = this;		
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Get the Application Context. Please note, all attempts to get the App Context should come
 | 
				
			||||||
 | 
					     * through here, and please be sure that the Application won't satisfy what you need.
 | 
				
			||||||
 | 
					     * @return The Application Context
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
						public static Context getAppContext() {
 | 
				
			||||||
 | 
					        return instance;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Get the Application, rather than just the Application Context. You likely should be using
 | 
				
			||||||
 | 
					     * this, rather than {@link #getAppContext()}
 | 
				
			||||||
 | 
					     * @return The MinimalBible {@link android.app.Application} object
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public static MinimalBibleTest getApplication() {
 | 
				
			||||||
 | 
					        return instance;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Create the {@link android.app.Application}. Responsible for building and
 | 
				
			||||||
 | 
					     * holding on to the master ObjectGraph.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public void onCreate() {
 | 
				
			||||||
 | 
					        super.onCreate();
 | 
				
			||||||
 | 
					        //TODO: Is this necessary?
 | 
				
			||||||
 | 
					        inject(this);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Inject a Dagger object
 | 
				
			||||||
 | 
					     * @param o The object to be injected
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public void inject(Object o) {
 | 
				
			||||||
 | 
					        getObjGraph().inject(o);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public ObjectGraph getObjGraph() {
 | 
				
			||||||
 | 
					        if (graph == null) {
 | 
				
			||||||
 | 
					            graph = ObjectGraph.create(MinimalBibleModulesTest.class);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return graph;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,117 @@
 | 
				
			|||||||
 | 
					package org.bspeice.minimalbible.test.activities.downloader;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import android.os.Bundle;
 | 
				
			||||||
 | 
					import android.os.Handler;
 | 
				
			||||||
 | 
					import android.os.Looper;
 | 
				
			||||||
 | 
					import android.support.v4.app.Fragment;
 | 
				
			||||||
 | 
					import android.support.v4.app.FragmentManager;
 | 
				
			||||||
 | 
					import android.test.ActivityInstrumentationTestCase2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import org.bspeice.minimalbible.MinimalBible;
 | 
				
			||||||
 | 
					import org.bspeice.minimalbible.activities.downloader.BookListFragment;
 | 
				
			||||||
 | 
					import org.bspeice.minimalbible.activities.downloader.DownloadActivity;
 | 
				
			||||||
 | 
					import org.bspeice.minimalbible.activities.downloader.DownloadPrefs;
 | 
				
			||||||
 | 
					import org.bspeice.minimalbible.test.MinimalBibleModulesTest;
 | 
				
			||||||
 | 
					import org.crosswire.jsword.book.BookCategory;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.util.concurrent.CountDownLatch;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import dagger.Module;
 | 
				
			||||||
 | 
					import de.devland.esperandro.Esperandro;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Created by bspeice on 6/23/14.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					public class BookListFragmentTest extends ActivityInstrumentationTestCase2<DownloadActivity> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Module(injects = TestDialogDisplayedIfFirstTimeFragment.class,
 | 
				
			||||||
 | 
					            addsTo = MinimalBibleModulesTest.class
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					    protected static class BookListFragmentTestModule{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public BookListFragmentTest() {
 | 
				
			||||||
 | 
					        super(DownloadActivity.class);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    FragmentManager mFragmentManager;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public void setUp() throws Exception {
 | 
				
			||||||
 | 
					        super.setUp();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        mFragmentManager = getActivity().getSupportFragmentManager();
 | 
				
			||||||
 | 
					        assertNotNull(mFragmentManager);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public <F extends Fragment> F startFragment(F fragment) {
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            mFragmentManager.beginTransaction()
 | 
				
			||||||
 | 
					                    .replace(android.R.id.content, fragment)
 | 
				
			||||||
 | 
					                    .commit();
 | 
				
			||||||
 | 
					        } catch (Exception e) {
 | 
				
			||||||
 | 
					            e.printStackTrace();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        final CountDownLatch signal = new CountDownLatch(1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        new Handler(Looper.getMainLooper()).post(new Runnable() {
 | 
				
			||||||
 | 
					            @Override
 | 
				
			||||||
 | 
					            public void run() {
 | 
				
			||||||
 | 
					                mFragmentManager.executePendingTransactions();
 | 
				
			||||||
 | 
					                signal.countDown();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            signal.await();
 | 
				
			||||||
 | 
					        } catch (InterruptedException e) {
 | 
				
			||||||
 | 
					            e.printStackTrace();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return (F)(mFragmentManager.findFragmentById(android.R.id.content));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected class TestDialogDisplayedIfFirstTimeFragment extends BookListFragment {
 | 
				
			||||||
 | 
					        /**
 | 
				
			||||||
 | 
					         * If the refresh dialog is blank after calling display, it must be showing the warning
 | 
				
			||||||
 | 
					         * @return Whether the warning dialog is showing
 | 
				
			||||||
 | 
					         */
 | 
				
			||||||
 | 
					        public boolean callDisplayModules(DownloadPrefs prefs) {
 | 
				
			||||||
 | 
					            // Inject the new preferences...
 | 
				
			||||||
 | 
					            this.downloadPrefs = prefs;
 | 
				
			||||||
 | 
					            displayModules();
 | 
				
			||||||
 | 
					            return (refreshDialog == null);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public void setArgs(BookCategory c) {
 | 
				
			||||||
 | 
					            Bundle args = new Bundle();
 | 
				
			||||||
 | 
					            args.putString(ARG_BOOK_CATEGORY, c.toString());
 | 
				
			||||||
 | 
					            this.setArguments(args);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public void testDialogDisplayedIfFirstTime() {
 | 
				
			||||||
 | 
					        ((MinimalBible)getActivity().getApplication()).plusObjGraph(BookListFragmentTestModule.class);
 | 
				
			||||||
 | 
					        TestDialogDisplayedIfFirstTimeFragment f = new TestDialogDisplayedIfFirstTimeFragment();
 | 
				
			||||||
 | 
					        f.setArgs(BookCategory.BIBLE);
 | 
				
			||||||
 | 
					        startFragment(f);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        DownloadPrefs prefs = Esperandro.getPreferences(DownloadPrefs.class, getActivity());
 | 
				
			||||||
 | 
					        prefs.hasShownDownloadDialog(false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        assertNotNull(f);
 | 
				
			||||||
 | 
					        assertTrue(f.callDisplayModules(Esperandro.getPreferences(DownloadPrefs.class, getActivity())));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public void testRefreshDisplayedAfterFirstTime() {
 | 
				
			||||||
 | 
					        ((MinimalBible)getActivity().getApplication()).plusObjGraph(BookListFragmentTestModule.class);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        TestDialogDisplayedIfFirstTimeFragment f = new TestDialogDisplayedIfFirstTimeFragment();
 | 
				
			||||||
 | 
					        f.setArgs(BookCategory.BIBLE);
 | 
				
			||||||
 | 
					        startFragment(f);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        DownloadPrefs prefs = Esperandro.getPreferences(DownloadPrefs.class, getActivity());
 | 
				
			||||||
 | 
					        prefs.hasShownDownloadDialog(true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        assertNotNull(f);
 | 
				
			||||||
 | 
					        assertFalse(f.callDisplayModules(Esperandro.getPreferences(DownloadPrefs.class, getActivity())));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -6,7 +6,7 @@ dependencies {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
android {
 | 
					android {
 | 
				
			||||||
    compileSdkVersion 19
 | 
					    compileSdkVersion 19
 | 
				
			||||||
    buildToolsVersion "19.0.3"
 | 
					    buildToolsVersion "20"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    sourceSets {
 | 
					    sourceSets {
 | 
				
			||||||
        main {
 | 
					        main {
 | 
				
			||||||
 | 
				
			|||||||
@ -4,6 +4,6 @@ buildscript {
 | 
				
			|||||||
        mavenCentral()
 | 
					        mavenCentral()
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    dependencies {
 | 
					    dependencies {
 | 
				
			||||||
        classpath 'com.android.tools.build:gradle:0.9.+'
 | 
					        classpath 'com.android.tools.build:gradle:0.12.+'
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										4
									
								
								gradle/wrapper/gradle-wrapper.properties
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								gradle/wrapper/gradle-wrapper.properties
									
									
									
									
										vendored
									
									
								
							@ -1,6 +1,6 @@
 | 
				
			|||||||
#Mon May 05 23:06:48 EDT 2014
 | 
					#Fri Jun 27 21:15:50 EDT 2014
 | 
				
			||||||
distributionBase=GRADLE_USER_HOME
 | 
					distributionBase=GRADLE_USER_HOME
 | 
				
			||||||
distributionPath=wrapper/dists
 | 
					distributionPath=wrapper/dists
 | 
				
			||||||
zipStoreBase=GRADLE_USER_HOME
 | 
					zipStoreBase=GRADLE_USER_HOME
 | 
				
			||||||
zipStorePath=wrapper/dists
 | 
					zipStorePath=wrapper/dists
 | 
				
			||||||
distributionUrl=http\://services.gradle.org/distributions/gradle-1.11-all.zip
 | 
					distributionUrl=http\://services.gradle.org/distributions/gradle-1.12-all.zip
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user