Add the BibleViewer activity back

And with that, I am fully back up-to-date
This commit is contained in:
Bradlee Speice 2014-07-09 21:55:56 -04:00
parent 949f35f312
commit 60ea2a6097
13 changed files with 501 additions and 0 deletions

View File

@ -11,6 +11,10 @@
<activity <activity
android:name=".activity.downloader.DownloadActivity" android:name=".activity.downloader.DownloadActivity"
android:label="@string/app_name" > android:label="@string/app_name" >
</activity>
<activity android:name=".activity.viewer.BibleViewer"
android:label="@string/app_name" >
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />

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

View File

@ -1,5 +1,6 @@
package org.bspeice.minimalbible.activity.downloader; package org.bspeice.minimalbible.activity.downloader;
import org.bspeice.minimalbible.Injector;
import org.bspeice.minimalbible.MinimalBibleModules; import org.bspeice.minimalbible.MinimalBibleModules;
import org.bspeice.minimalbible.activity.downloader.manager.BookDownloadManager; import org.bspeice.minimalbible.activity.downloader.manager.BookDownloadManager;
import org.bspeice.minimalbible.activity.downloader.manager.BookDownloadThread; import org.bspeice.minimalbible.activity.downloader.manager.BookDownloadThread;
@ -49,6 +50,11 @@ public class DownloadActivityModules {
return activity; return activity;
} }
@Provides @Singleton
Injector provideActivityInjector() {
return activity;
}
@Provides @Singleton @Provides @Singleton
BookDownloadManager provideBookDownloadManager() { BookDownloadManager provideBookDownloadManager() {
return new BookDownloadManager(activity); return new BookDownloadManager(activity);

View File

@ -0,0 +1,159 @@
package org.bspeice.minimalbible.activity.viewer;
import android.content.Intent;
import android.os.Bundle;
import android.os.Looper;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBar;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import org.bspeice.minimalbible.Injector;
import org.bspeice.minimalbible.MinimalBible;
import org.bspeice.minimalbible.R;
import org.bspeice.minimalbible.activity.BaseActivity;
import org.bspeice.minimalbible.activity.BaseNavigationDrawerFragment;
import org.bspeice.minimalbible.activity.downloader.DownloadActivity;
import org.bspeice.minimalbible.activity.downloader.DownloadActivityModules;
import org.crosswire.jsword.book.Book;
import javax.inject.Inject;
import dagger.ObjectGraph;
import rx.android.schedulers.AndroidSchedulers;
import rx.functions.Action1;
public class BibleViewer extends BaseActivity implements
BaseNavigationDrawerFragment.NavigationDrawerCallbacks,
Injector {
@Inject BookManager bookManager;
private ObjectGraph bvObjectGraph;
/**
* Build a scoped object graph for anything used by the DownloadActivity
*/
private void buildObjGraph() {
if (bvObjectGraph == null) {
bvObjectGraph = MinimalBible.get(this)
.plus(new BibleViewerModules());
}
bvObjectGraph.inject(this);
}
@Override
public void inject(Object o) {
buildObjGraph();
bvObjectGraph.inject(o);
}
/**
* Fragment managing the behaviors, interactions and presentation of the
* navigation drawer.
*/
private ViewerNavDrawerFragment mNavigationDrawerFragment;
/**
* Used to store the last screen title. For use in
* {@link #restoreActionBar()}.
*/
private CharSequence mTitle;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.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);
mNavigationDrawerFragment = (ViewerNavDrawerFragment) getSupportFragmentManager()
.findFragmentById(R.id.navigation_drawer);
mTitle = getTitle();
// Set up the drawer.
mNavigationDrawerFragment.setUp(R.id.navigation_drawer,
(DrawerLayout) findViewById(R.id.drawer_layout));
}
@Override
public void onNavigationDrawerItemSelected(int position) {
// Handle a navigation movement
}
public void setActionBarTitle(String title) {
ActionBar actionBar = getSupportActionBar();
mTitle = title;
actionBar.setTitle(title);
}
public void restoreActionBar() {
ActionBar actionBar = getSupportActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
actionBar.setDisplayShowTitleEnabled(true);
actionBar.setTitle(mTitle);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
if (!mNavigationDrawerFragment.isDrawerOpen()) {
// Only show items in the action bar relevant to this screen
// if the drawer is not showing. Otherwise, let the drawer
// decide what to show in the action bar.
getMenuInflater().inflate(R.menu.main, menu);
restoreActionBar();
return true;
}
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
} else if (id == R.id.action_downloads) {
startActivity(new Intent(this, DownloadActivity.class));
}
return super.onOptionsItemSelected(item);
}
private void displayMainBook(Book b) {
Log.d("BibleViewer", "Initializing main book: " + b.getName());
Log.d("MainThread?", Boolean.toString(Looper.myLooper() == Looper.getMainLooper()));
FragmentManager fragmentManager = getSupportFragmentManager();
Fragment f = BookFragment.newInstance(b.getName(), this);
fragmentManager.beginTransaction()
.replace(R.id.container, f)
.commit();
}
}

View File

@ -0,0 +1,15 @@
package org.bspeice.minimalbible.activity.viewer;
import dagger.Module;
/**
* Created by bspeice on 6/18/14.
*/
@Module(
injects = {
BibleViewer.class,
BookFragment.class
}
)
public class BibleViewerModules {
}

View File

@ -0,0 +1,142 @@
package org.bspeice.minimalbible.activity.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.Injector;
import org.bspeice.minimalbible.MinimalBible;
import org.bspeice.minimalbible.R;
import org.bspeice.minimalbible.activity.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, Injector injector) {
BookFragment fragment = new BookFragment();
injector.inject(fragment);
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);
((Injector)getActivity()).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();
}
}
}

View File

@ -0,0 +1,50 @@
package org.bspeice.minimalbible.activity.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;
}
}

View File

@ -0,0 +1,38 @@
package org.bspeice.minimalbible.activity.viewer;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import org.bspeice.minimalbible.R;
import org.bspeice.minimalbible.activity.BaseNavigationDrawerFragment;
public class ViewerNavDrawerFragment extends BaseNavigationDrawerFragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
mDrawerListView = (ListView) inflater.inflate(
R.layout.fragment_navigation_drawer, container, false);
mDrawerListView
.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
selectItem(position);
}
});
mDrawerListView.setAdapter(new ArrayAdapter<String>(getActionBar()
.getThemedContext(), android.R.layout.simple_list_item_1,
android.R.id.text1, new String[] {
getString(R.string.title_section1),
getString(R.string.title_section2),
getString(R.string.title_section3)}));
mDrawerListView.setItemChecked(mCurrentSelectedPosition, true);
return mDrawerListView;
}
}

View File

@ -0,0 +1,42 @@
<!-- A DrawerLayout is intended to be used as the top-level content view using match_parent for both width and height to consume the full space available. -->
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="org.bspeice.minimalbible.activities.viewer.BibleViewer" >
<!--
As the main content view, the view below consumes the entire
space available using match_parent in both dimensions.
-->
<FrameLayout
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:clipToPadding="false" />
<!--
android:layout_gravity="start" tells DrawerLayout to treat
this as a sliding drawer on the left side for left-to-right
languages and on the right side for right-to-left languages.
If you're not building against API 17 or higher, use
android:layout_gravity="left" instead.
-->
<!--
The drawer is given a fixed width in dp and extends the full height of
the container.
-->
<fragment
android:id="@+id/navigation_drawer"
android:name="org.bspeice.minimalbible.activity.viewer.ViewerNavDrawerFragment"
android:layout_width="@dimen/navigation_drawer_width"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:clipToPadding="false"
android:layout_gravity="start" />
</android.support.v4.widget.DrawerLayout>

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

View File

@ -0,0 +1,17 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context="org.bspeice.minimalbible.MainActivity" >
<item
android:id="@+id/action_settings"
android:orderInCategory="100"
android:title="@string/action_settings"
app:showAsAction="never"/>
<item
android:id="@+id/action_downloads"
android:orderInCategory="100"
android:title="@string/activity_downloader" />
</menu>

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="content_page">file:///android_asset/book.html</string>
</resources>

View File

@ -9,5 +9,6 @@
<string name="navigation_drawer_close">Close navigation drawer</string> <string name="navigation_drawer_close">Close navigation drawer</string>
<string name="action_example">Example action</string> <string name="action_example">Example action</string>
<string name="action_settings">Settings</string> <string name="action_settings">Settings</string>
<string name="activity_downloader">Downloads</string>
</resources> </resources>