1
0
Fork 0
mirror of https://github.com/geometer/FBReaderJ.git synced 2025-10-06 03:50:19 +02:00

Merge branch 'master' into tapzones

This commit is contained in:
Nikolay Pultsin 2011-03-11 23:50:18 +00:00
commit 72b375496a
52 changed files with 833 additions and 426 deletions

View file

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="org.geometerplus.zlibrary.ui.android" android:versionCode="9913" android:versionName="0.99.13" android:installLocation="auto"> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="org.geometerplus.zlibrary.ui.android" android:versionCode="9915" android:versionName="0.99.15" android:installLocation="auto">
<uses-sdk android:minSdkVersion="4" /> <uses-sdk android:minSdkVersion="4" />
<supports-screens android:smallScreens="true" android:normalScreens="true" android:largeScreens="true" android:anyDensity="true" /> <supports-screens android:smallScreens="true" android:normalScreens="true" android:largeScreens="true" android:anyDensity="true" />
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
@ -145,7 +145,14 @@
</activity> </activity>
<activity android:name="org.geometerplus.android.fbreader.network.NetworkCatalogActivity" android:process=":networkLibrary" android:configChanges="orientation|keyboardHidden" /> <activity android:name="org.geometerplus.android.fbreader.network.NetworkCatalogActivity" android:process=":networkLibrary" android:configChanges="orientation|keyboardHidden" />
<service android:name="org.geometerplus.android.fbreader.network.ItemsLoadingService" android:process=":networkLibrary" /> <service android:name="org.geometerplus.android.fbreader.network.ItemsLoadingService" android:process=":networkLibrary" />
<activity android:name="org.geometerplus.android.fbreader.network.NetworkBookInfoActivity" android:process=":networkLibrary" android:configChanges="orientation|keyboardHidden" /> <activity android:name="org.geometerplus.android.fbreader.network.NetworkBookInfoActivity" android:process=":networkLibrary" android:configChanges="orientation|keyboardHidden">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:host="*" android:scheme="fbreader" />
</intent-filter>
</activity>
<receiver android:name="org.geometerplus.android.fbreader.network.BookDownloaderCallback" android:process=":networkLibrary" /> <receiver android:name="org.geometerplus.android.fbreader.network.BookDownloaderCallback" android:process=":networkLibrary" />
<service android:name="org.geometerplus.android.fbreader.network.LibraryInitializationService" android:process=":networkLibrary" /> <service android:name="org.geometerplus.android.fbreader.network.LibraryInitializationService" android:process=":networkLibrary" />
</application> </application>

View file

@ -145,7 +145,14 @@
</activity> </activity>
<activity android:name="org.geometerplus.android.fbreader.network.NetworkCatalogActivity" android:process=":networkLibrary" android:configChanges="orientation|keyboardHidden" /> <activity android:name="org.geometerplus.android.fbreader.network.NetworkCatalogActivity" android:process=":networkLibrary" android:configChanges="orientation|keyboardHidden" />
<service android:name="org.geometerplus.android.fbreader.network.ItemsLoadingService" android:process=":networkLibrary" /> <service android:name="org.geometerplus.android.fbreader.network.ItemsLoadingService" android:process=":networkLibrary" />
<activity android:name="org.geometerplus.android.fbreader.network.NetworkBookInfoActivity" android:process=":networkLibrary" android:configChanges="orientation|keyboardHidden" /> <activity android:name="org.geometerplus.android.fbreader.network.NetworkBookInfoActivity" android:process=":networkLibrary" android:configChanges="orientation|keyboardHidden">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:host="*" android:scheme="fbreader" />
</intent-filter>
</activity>
<receiver android:name="org.geometerplus.android.fbreader.network.BookDownloaderCallback" android:process=":networkLibrary" /> <receiver android:name="org.geometerplus.android.fbreader.network.BookDownloaderCallback" android:process=":networkLibrary" />
<service android:name="org.geometerplus.android.fbreader.network.LibraryInitializationService" android:process=":networkLibrary" /> <service android:name="org.geometerplus.android.fbreader.network.LibraryInitializationService" android:process=":networkLibrary" />
</application> </application>

View file

@ -1,4 +1,5 @@
===== 0.99.14 (Mar ??, 2011) ===== ===== 0.99.14 (Mar 11, 2011) =====
* New application icon
* Thai localization (by Samphan Pojanasophanakul) * Thai localization (by Samphan Pojanasophanakul)
* Fixed TTF font style detection * Fixed TTF font style detection
* opds:// URLs support has been implemented * opds:// URLs support has been implemented
@ -6,6 +7,10 @@
* Ignore case comparison for zip entry names * Ignore case comparison for zip entry names
* Fixed custom OPDS link search * Fixed custom OPDS link search
* Periodical update of custom links information has been added * Periodical update of custom links information has been added
* Epub rendering issues (like unexpected paragraph ends) were fixed
* Multi-body fb2 file processing has been fixed
* 'Cancel menu' preferences section
* LitRes: several views for purchased books
===== 0.99.13 (Feb 13, 2011) ===== ===== 0.99.13 (Feb 13, 2011) =====
* Fixed book/position forgetting bug * Fixed book/position forgetting bug

View file

@ -1 +1 @@
0.99.13 0.99.15

View file

@ -527,6 +527,17 @@
<node name="summaryOff" value="Navigace klávesami prochází pouze hypertextové odkazy"/> <node name="summaryOff" value="Navigace klávesami prochází pouze hypertextové odkazy"/>
</node> </node>
</node> </node>
<node name="cancelMenu" value="Cancel menu" toBeTranslated="true">
<node name="summary" value="Back button action list" toBeTranslated="true"/>
<node name="previousBook" value="Previous book" toBeTranslated="true">
<node name="summaryOn" value="Show 'return to previous book' item" toBeTranslated="true"/>
<node name="summaryOff" value="Don't show 'return to previous book' item" toBeTranslated="true"/>
</node>
<node name="positions" value="Last 3 positions" toBeTranslated="true">
<node name="summaryOn" value="Show items for last 3 positions in the book" toBeTranslated="true"/>
<node name="summaryOff" value="Don't show items for last 3 positions in the book" toBeTranslated="true"/>
</node>
</node>
</node> </node>
<node name="OptionsDialog"> <node name="OptionsDialog">
<node name="tab"> <node name="tab">

View file

@ -528,6 +528,17 @@
<node name="summaryOff" value="Key navigation visits hyperlinks only" toBeTranslated="true"/> <node name="summaryOff" value="Key navigation visits hyperlinks only" toBeTranslated="true"/>
</node> </node>
</node> </node>
<node name="cancelMenu" value="Cancel menu" toBeTranslated="true">
<node name="summary" value="Back button action list" toBeTranslated="true"/>
<node name="previousBook" value="Previous book" toBeTranslated="true">
<node name="summaryOn" value="Show 'return to previous book' item" toBeTranslated="true"/>
<node name="summaryOff" value="Don't show 'return to previous book' item" toBeTranslated="true"/>
</node>
<node name="positions" value="Last 3 positions" toBeTranslated="true">
<node name="summaryOn" value="Show items for last 3 positions in the book" toBeTranslated="true"/>
<node name="summaryOff" value="Don't show items for last 3 positions in the book" toBeTranslated="true"/>
</node>
</node>
</node> </node>
<node name="OptionsDialog"> <node name="OptionsDialog">
<node name="tab"> <node name="tab">

View file

@ -540,6 +540,17 @@
<node name="summaryOff" value="Key navigation visits hyperlinks only"/> <node name="summaryOff" value="Key navigation visits hyperlinks only"/>
</node> </node>
</node> </node>
<node name="cancelMenu" value="Cancel menu">
<node name="summary" value="Back button action list"/>
<node name="previousBook" value="Previous book">
<node name="summaryOn" value="Show 'return to previous book' item"/>
<node name="summaryOff" value="Don't show 'return to previous book' item"/>
</node>
<node name="positions" value="Last 3 positions">
<node name="summaryOn" value="Show items for last 3 positions in the book"/>
<node name="summaryOff" value="Don't show items for last 3 positions in the book"/>
</node>
</node>
</node> </node>
<node name="OptionsDialog"> <node name="OptionsDialog">
<node name="tab"> <node name="tab">

View file

@ -530,6 +530,17 @@
<node name="summaryOff" value="La navigation par touches visite les liens hypertexts uniquement"/> <node name="summaryOff" value="La navigation par touches visite les liens hypertexts uniquement"/>
</node> </node>
</node> </node>
<node name="cancelMenu" value="Cancel menu" toBeTranslated="true">
<node name="summary" value="Back button action list" toBeTranslated="true"/>
<node name="previousBook" value="Previous book" toBeTranslated="true">
<node name="summaryOn" value="Show 'return to previous book' item" toBeTranslated="true"/>
<node name="summaryOff" value="Don't show 'return to previous book' item" toBeTranslated="true"/>
</node>
<node name="positions" value="Last 3 positions" toBeTranslated="true">
<node name="summaryOn" value="Show items for last 3 positions in the book" toBeTranslated="true"/>
<node name="summaryOff" value="Don't show items for last 3 positions in the book" toBeTranslated="true"/>
</node>
</node>
</node> </node>
<node name="OptionsDialog"> <node name="OptionsDialog">
<node name="tab"> <node name="tab">

View file

@ -527,6 +527,17 @@
<node name="summaryOff" value="A tecla de navegación percorre só as ligazóns"/> <node name="summaryOff" value="A tecla de navegación percorre só as ligazóns"/>
</node> </node>
</node> </node>
<node name="cancelMenu" value="Cancel menu" toBeTranslated="true">
<node name="summary" value="Back button action list" toBeTranslated="true"/>
<node name="previousBook" value="Previous book" toBeTranslated="true">
<node name="summaryOn" value="Show 'return to previous book' item" toBeTranslated="true"/>
<node name="summaryOff" value="Don't show 'return to previous book' item" toBeTranslated="true"/>
</node>
<node name="positions" value="Last 3 positions" toBeTranslated="true">
<node name="summaryOn" value="Show items for last 3 positions in the book" toBeTranslated="true"/>
<node name="summaryOff" value="Don't show items for last 3 positions in the book" toBeTranslated="true"/>
</node>
</node>
</node> </node>
<node name="OptionsDialog"> <node name="OptionsDialog">
<node name="tab"> <node name="tab">

View file

@ -527,6 +527,17 @@
<node name="summaryOff" value="A gombnyomásos navigáció linkről linkre ugrik"/> <node name="summaryOff" value="A gombnyomásos navigáció linkről linkre ugrik"/>
</node> </node>
</node> </node>
<node name="cancelMenu" value="Cancel menu" toBeTranslated="true">
<node name="summary" value="Back button action list" toBeTranslated="true"/>
<node name="previousBook" value="Previous book" toBeTranslated="true">
<node name="summaryOn" value="Show 'return to previous book' item" toBeTranslated="true"/>
<node name="summaryOff" value="Don't show 'return to previous book' item" toBeTranslated="true"/>
</node>
<node name="positions" value="Last 3 positions" toBeTranslated="true">
<node name="summaryOn" value="Show items for last 3 positions in the book" toBeTranslated="true"/>
<node name="summaryOff" value="Don't show items for last 3 positions in the book" toBeTranslated="true"/>
</node>
</node>
</node> </node>
<node name="OptionsDialog"> <node name="OptionsDialog">
<node name="tab"> <node name="tab">

View file

@ -527,6 +527,17 @@
<node name="summaryOff" value="Key navigation visits hyperlinks only" toBeTranslated="true"/> <node name="summaryOff" value="Key navigation visits hyperlinks only" toBeTranslated="true"/>
</node> </node>
</node> </node>
<node name="cancelMenu" value="Cancel menu" toBeTranslated="true">
<node name="summary" value="Back button action list" toBeTranslated="true"/>
<node name="previousBook" value="Previous book" toBeTranslated="true">
<node name="summaryOn" value="Show 'return to previous book' item" toBeTranslated="true"/>
<node name="summaryOff" value="Don't show 'return to previous book' item" toBeTranslated="true"/>
</node>
<node name="positions" value="Last 3 positions" toBeTranslated="true">
<node name="summaryOn" value="Show items for last 3 positions in the book" toBeTranslated="true"/>
<node name="summaryOff" value="Don't show items for last 3 positions in the book" toBeTranslated="true"/>
</node>
</node>
</node> </node>
<node name="OptionsDialog"> <node name="OptionsDialog">
<node name="tab"> <node name="tab">

View file

@ -527,6 +527,17 @@
<node name="summaryOff" value="Key navigation visits hyperlinks only" toBeTranslated="true"/> <node name="summaryOff" value="Key navigation visits hyperlinks only" toBeTranslated="true"/>
</node> </node>
</node> </node>
<node name="cancelMenu" value="Cancel menu" toBeTranslated="true">
<node name="summary" value="Back button action list" toBeTranslated="true"/>
<node name="previousBook" value="Previous book" toBeTranslated="true">
<node name="summaryOn" value="Show 'return to previous book' item" toBeTranslated="true"/>
<node name="summaryOff" value="Don't show 'return to previous book' item" toBeTranslated="true"/>
</node>
<node name="positions" value="Last 3 positions" toBeTranslated="true">
<node name="summaryOn" value="Show items for last 3 positions in the book" toBeTranslated="true"/>
<node name="summaryOff" value="Don't show items for last 3 positions in the book" toBeTranslated="true"/>
</node>
</node>
</node> </node>
<node name="OptionsDialog"> <node name="OptionsDialog">
<node name="tab"> <node name="tab">

View file

@ -526,6 +526,17 @@
<node name="summaryOff" value="При перемещении с помощью кнопок помечать только гиперссылки"/> <node name="summaryOff" value="При перемещении с помощью кнопок помечать только гиперссылки"/>
</node> </node>
</node> </node>
<node name="cancelMenu" value="Меню выхода из программы">
<node name="summary" value="Список действий при нажатии на кнопку 'Назад'"/>
<node name="previousBook" value="Предыдущая книга">
<node name="summaryOn" value="Показать пункт меню для возврата к предыдущей книге"/>
<node name="summaryOff" value="Не нужна возможность возврата к предыдущей книге"/>
</node>
<node name="positions" value="Возврат по ссылкам">
<node name="summaryOn" value="Показывать пункты меню для последних 3 позиций в книге"/>
<node name="summaryOff" value="Не нужна возможность возврата по ссылкам"/>
</node>
</node>
</node> </node>
<node name="OptionsDialog"> <node name="OptionsDialog">
<node name="tab"> <node name="tab">

View file

@ -527,6 +527,17 @@
<node name="summaryOff" value="ตัวเลือกคำเลือกได้เฉพาะลิ้งค์ข้อความ"/> <node name="summaryOff" value="ตัวเลือกคำเลือกได้เฉพาะลิ้งค์ข้อความ"/>
</node> </node>
</node> </node>
<node name="cancelMenu" value="Cancel menu" toBeTranslated="true">
<node name="summary" value="Back button action list" toBeTranslated="true"/>
<node name="previousBook" value="Previous book" toBeTranslated="true">
<node name="summaryOn" value="Show 'return to previous book' item" toBeTranslated="true"/>
<node name="summaryOff" value="Don't show 'return to previous book' item" toBeTranslated="true"/>
</node>
<node name="positions" value="Last 3 positions" toBeTranslated="true">
<node name="summaryOn" value="Show items for last 3 positions in the book" toBeTranslated="true"/>
<node name="summaryOff" value="Don't show items for last 3 positions in the book" toBeTranslated="true"/>
</node>
</node>
</node> </node>
<node name="OptionsDialog"> <node name="OptionsDialog">
<node name="tab"> <node name="tab">

View file

@ -527,6 +527,17 @@
<node name="summaryOff" value="Key navigation visits hyperlinks only" toBeTranslated="true"/> <node name="summaryOff" value="Key navigation visits hyperlinks only" toBeTranslated="true"/>
</node> </node>
</node> </node>
<node name="cancelMenu" value="Cancel menu" toBeTranslated="true">
<node name="summary" value="Back button action list" toBeTranslated="true"/>
<node name="previousBook" value="Previous book" toBeTranslated="true">
<node name="summaryOn" value="Show 'return to previous book' item" toBeTranslated="true"/>
<node name="summaryOff" value="Don't show 'return to previous book' item" toBeTranslated="true"/>
</node>
<node name="positions" value="Last 3 positions" toBeTranslated="true">
<node name="summaryOn" value="Show items for last 3 positions in the book" toBeTranslated="true"/>
<node name="summaryOff" value="Don't show items for last 3 positions in the book" toBeTranslated="true"/>
</node>
</node>
</node> </node>
<node name="OptionsDialog"> <node name="OptionsDialog">
<node name="tab"> <node name="tab">

View file

@ -527,6 +527,17 @@
<node name="summaryOff" value="Phím điều hướng chỉ tác động lên siêu liên kết"/> <node name="summaryOff" value="Phím điều hướng chỉ tác động lên siêu liên kết"/>
</node> </node>
</node> </node>
<node name="cancelMenu" value="Cancel menu" toBeTranslated="true">
<node name="summary" value="Back button action list" toBeTranslated="true"/>
<node name="previousBook" value="Previous book" toBeTranslated="true">
<node name="summaryOn" value="Show 'return to previous book' item" toBeTranslated="true"/>
<node name="summaryOff" value="Don't show 'return to previous book' item" toBeTranslated="true"/>
</node>
<node name="positions" value="Last 3 positions" toBeTranslated="true">
<node name="summaryOn" value="Show items for last 3 positions in the book" toBeTranslated="true"/>
<node name="summaryOff" value="Don't show items for last 3 positions in the book" toBeTranslated="true"/>
</node>
</node>
</node> </node>
<node name="OptionsDialog"> <node name="OptionsDialog">
<node name="tab"> <node name="tab">

View file

@ -527,6 +527,17 @@
<node name="summaryOff" value="导航键仅访问超链接词句"/> <node name="summaryOff" value="导航键仅访问超链接词句"/>
</node> </node>
</node> </node>
<node name="cancelMenu" value="Cancel menu" toBeTranslated="true">
<node name="summary" value="Back button action list" toBeTranslated="true"/>
<node name="previousBook" value="Previous book" toBeTranslated="true">
<node name="summaryOn" value="Show 'return to previous book' item" toBeTranslated="true"/>
<node name="summaryOff" value="Don't show 'return to previous book' item" toBeTranslated="true"/>
</node>
<node name="positions" value="Last 3 positions" toBeTranslated="true">
<node name="summaryOn" value="Show items for last 3 positions in the book" toBeTranslated="true"/>
<node name="summaryOff" value="Don't show items for last 3 positions in the book" toBeTranslated="true"/>
</node>
</node>
</node> </node>
<node name="OptionsDialog"> <node name="OptionsDialog">
<node name="tab"> <node name="tab">

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 5.3 KiB

Before After
Before After

View file

@ -107,7 +107,6 @@ public class LibraryTreeActivity extends LibraryBaseActivity {
final LibraryAdapter adapter = new LibraryAdapter(tree.subTrees()); final LibraryAdapter adapter = new LibraryAdapter(tree.subTrees());
setListAdapter(adapter); setListAdapter(adapter);
getListView().setOnCreateContextMenuListener(adapter); getListView().setOnCreateContextMenuListener(adapter);
System.err.println("SELECTED: " + adapter.getFirstSelectedItemIndex());
setSelection(adapter.getFirstSelectedItemIndex()); setSelection(adapter.getFirstSelectedItemIndex());
} }
} }

View file

@ -187,7 +187,6 @@ abstract class NetworkBaseActivity extends ListActivity implements NetworkView.E
@Override @Override
public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo) { public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo) {
System.err.println("onCreateContextMenu -1");
if (menuInfo != null) { if (menuInfo != null) {
final int position = ((AdapterView.AdapterContextMenuInfo)menuInfo).position; final int position = ((AdapterView.AdapterContextMenuInfo)menuInfo).position;
final NetworkTree tree = (NetworkTree)getListAdapter().getItem(position); final NetworkTree tree = (NetworkTree)getListAdapter().getItem(position);

View file

@ -225,15 +225,28 @@ class NetworkBookActions extends NetworkTreeActions {
if (tree instanceof NetworkAuthorTree || tree instanceof NetworkSeriesTree) { if (tree instanceof NetworkAuthorTree || tree instanceof NetworkSeriesTree) {
switch (actionCode) { switch (actionCode) {
case SHOW_BOOKS_ITEM_ID: case SHOW_BOOKS_ITEM_ID:
NetworkView.Instance().openTree(activity, tree); Util.openTree(activity, tree);
return true; return true;
} }
return false; return false;
} else if (tree instanceof NetworkBookTree) {
return runActionStatic(activity, ((NetworkBookTree)tree), actionCode);
} else {
return false;
} }
return runAction(activity, ((NetworkBookTree) tree).Book, actionCode);
} }
static boolean runAction(Activity activity, NetworkBookItem book, int actionCode) { static boolean runActionStatic(Activity activity, NetworkBookTree tree, int actionCode) {
switch (actionCode) {
case SHOW_BOOK_ACTIVITY_ITEM_ID:
Util.openTree(activity, tree);
return true;
default:
return runActionStatic(activity, tree.Book, actionCode);
}
}
static boolean runActionStatic(Activity activity, NetworkBookItem book, int actionCode) {
switch (actionCode) { switch (actionCode) {
case DOWNLOAD_BOOK_ITEM_ID: case DOWNLOAD_BOOK_ITEM_ID:
doDownloadBook(activity, book, false); doDownloadBook(activity, book, false);
@ -259,9 +272,6 @@ class NetworkBookActions extends NetworkTreeActions {
case BUY_IN_BROWSER_ITEM_ID: case BUY_IN_BROWSER_ITEM_ID:
doBuyInBrowser(activity, book); doBuyInBrowser(activity, book);
return true; return true;
case SHOW_BOOK_ACTIVITY_ITEM_ID:
NetworkView.Instance().showBookInfoActivity(activity, book);
return true;
case ADD_BOOK_TO_BASKET: case ADD_BOOK_TO_BASKET:
book.Link.basket().add(book); book.Link.basket().add(book);
return true; return true;

View file

@ -43,7 +43,9 @@ import org.geometerplus.zlibrary.core.image.ZLLoadableImage;
import org.geometerplus.zlibrary.ui.android.image.ZLAndroidImageManager; import org.geometerplus.zlibrary.ui.android.image.ZLAndroidImageManager;
import org.geometerplus.zlibrary.ui.android.image.ZLAndroidImageData; import org.geometerplus.zlibrary.ui.android.image.ZLAndroidImageData;
import org.geometerplus.fbreader.network.*; import org.geometerplus.fbreader.network.NetworkTree;
import org.geometerplus.fbreader.network.NetworkBookItem;
import org.geometerplus.fbreader.network.tree.NetworkBookTree;
public class NetworkBookInfoActivity extends Activity implements NetworkView.EventListener { public class NetworkBookInfoActivity extends Activity implements NetworkView.EventListener {
private NetworkBookItem myBook; private NetworkBookItem myBook;
@ -56,33 +58,46 @@ public class NetworkBookInfoActivity extends Activity implements NetworkView.Eve
protected void onCreate(Bundle icicle) { protected void onCreate(Bundle icicle) {
super.onCreate(icicle); super.onCreate(icicle);
if (!NetworkView.Instance().isInitialized()) {
finish();
return;
}
myBook = NetworkView.Instance().getBookInfoItem();
if (myBook == null) {
finish();
return;
}
myConnection = new BookDownloaderServiceConnection();
bindService(
new Intent(getApplicationContext(), BookDownloaderService.class),
myConnection,
BIND_AUTO_CREATE
);
setTitle(myBook.Title);
myMainView = getLayoutInflater().inflate(R.layout.network_book, null, false); myMainView = getLayoutInflater().inflate(R.layout.network_book, null, false);
setContentView(myMainView); setContentView(myMainView);
myMainView.setOnCreateContextMenuListener(this); myMainView.setOnCreateContextMenuListener(this);
}
setupDescription(); @Override
setupInfo(); protected void onResume() {
setupCover(); super.onResume();
setupButtons();
if (!NetworkView.Instance().isInitialized()) {
if (NetworkInitializer.Instance == null) {
new NetworkInitializer(null);
NetworkInitializer.Instance.start();
} else {
NetworkInitializer.Instance.setActivity(null);
}
}
if (myBook == null) {
final NetworkTree tree = Util.getTreeFromIntent(getIntent());
if (!(tree instanceof NetworkBookTree)) {
finish();
return;
}
myBook = ((NetworkBookTree)tree).Book;
myConnection = new BookDownloaderServiceConnection();
bindService(
new Intent(getApplicationContext(), BookDownloaderService.class),
myConnection,
BIND_AUTO_CREATE
);
setTitle(myBook.Title);
setupDescription();
setupInfo();
setupCover();
setupButtons();
}
} }
View getMainView() { View getMainView() {
@ -99,6 +114,9 @@ public class NetworkBookInfoActivity extends Activity implements NetworkView.Eve
@Override @Override
public void onDestroy() { public void onDestroy() {
if (!NetworkView.Instance().isInitialized() && NetworkInitializer.Instance != null) {
NetworkInitializer.Instance.setActivity(null);
}
if (myConnection != null) { if (myConnection != null) {
unbindService(myConnection); unbindService(myConnection);
myConnection = null; myConnection = null;
@ -108,22 +126,20 @@ public class NetworkBookInfoActivity extends Activity implements NetworkView.Eve
@Override @Override
public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo) { public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo) {
new RefillAccountActions().buildContextMenu(this, menu, myBook.Link); NetworkView.Instance().getTopUpActions().buildContextMenu(this, menu, myBook.Link);
} }
@Override @Override
public boolean onContextItemSelected(MenuItem item) { public boolean onContextItemSelected(MenuItem item) {
new RefillAccountActions().runAction(this, myBook.Link, item.getItemId()); RefillAccountActions.runAction(this, myBook.Link, item.getItemId());
return true; return true;
} }
private final void setupDescription() { private final void setupDescription() {
setTextFromResource(R.id.network_book_description_title, "description"); setTextFromResource(R.id.network_book_description_title, "description");
final String description; String description = myBook.Summary;
if (myBook.Summary != null) { if (description == null) {
description = myBook.Summary;
} else {
description = myResource.getResource("noDescription").getValue(); description = myResource.getResource("noDescription").getValue();
} }
setTextById(R.id.network_book_description, description); setTextById(R.id.network_book_description, description);
@ -155,7 +171,7 @@ public class NetworkBookInfoActivity extends Activity implements NetworkView.Eve
if (myBook.Authors.size() > 0) { if (myBook.Authors.size() > 0) {
findViewById(R.id.network_book_authors).setVisibility(View.VISIBLE); findViewById(R.id.network_book_authors).setVisibility(View.VISIBLE);
final StringBuilder authorsText = new StringBuilder(); final StringBuilder authorsText = new StringBuilder();
for (NetworkBookItem.AuthorData author: myBook.Authors) { for (NetworkBookItem.AuthorData author : myBook.Authors) {
if (authorsText.length() > 0) { if (authorsText.length() > 0) {
authorsText.append(", "); authorsText.append(", ");
} }
@ -183,7 +199,7 @@ public class NetworkBookInfoActivity extends Activity implements NetworkView.Eve
if (myBook.Tags.size() > 0) { if (myBook.Tags.size() > 0) {
findViewById(R.id.network_book_tags).setVisibility(View.VISIBLE); findViewById(R.id.network_book_tags).setVisibility(View.VISIBLE);
final StringBuilder tagsText = new StringBuilder(); final StringBuilder tagsText = new StringBuilder();
for (String tag: myBook.Tags) { for (String tag : myBook.Tags) {
if (tagsText.length() > 0) { if (tagsText.length() > 0) {
tagsText.append(", "); tagsText.append(", ");
} }
@ -278,7 +294,7 @@ public class NetworkBookInfoActivity extends Activity implements NetworkView.Eve
button.setVisibility(View.VISIBLE); button.setVisibility(View.VISIBLE);
button.setOnClickListener(new View.OnClickListener() { button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) { public void onClick(View v) {
NetworkBookActions.runAction(NetworkBookInfoActivity.this, myBook, a.Id); NetworkBookActions.runActionStatic(NetworkBookInfoActivity.this, myBook, a.Id);
NetworkBookInfoActivity.this.updateView(); NetworkBookInfoActivity.this.updateView();
} }
}); });

View file

@ -69,18 +69,20 @@ class NetworkCatalogActions extends NetworkTreeActions {
if (tree instanceof NetworkCatalogRootTree) { if (tree instanceof NetworkCatalogRootTree) {
return tree.getName(); return tree.getName();
} }
return tree.getName() + " - " + ((NetworkCatalogTree) tree).Item.Link.getSiteName(); return tree.getName() + " - " + ((NetworkCatalogTree)tree).Item.Link.getSiteName();
} }
@Override @Override
public void buildContextMenu(Activity activity, ContextMenu menu, NetworkTree tree) { public void buildContextMenu(Activity activity, ContextMenu menu, NetworkTree tree) {
final NetworkCatalogTree catalogTree = (NetworkCatalogTree)tree; final NetworkCatalogItem item = ((NetworkCatalogTree)tree).Item;
final NetworkCatalogItem item = catalogTree.Item; final NetworkURLCatalogItem urlItem =
item instanceof NetworkURLCatalogItem ? (NetworkURLCatalogItem)item : null;
menu.setHeaderTitle(tree.getName()); menu.setHeaderTitle(tree.getName());
boolean hasItems = false; boolean hasItems = false;
final String catalogUrl = item.URLByType.get(NetworkCatalogItem.URL_CATALOG); final String catalogUrl =
urlItem != null ? urlItem.URLByType.get(NetworkURLCatalogItem.URL_CATALOG) : null;
if (catalogUrl != null && if (catalogUrl != null &&
(!(item instanceof BasketItem) || item.Link.basket().bookIds().size() > 0)) { (!(item instanceof BasketItem) || item.Link.basket().bookIds().size() > 0)) {
addMenuItem(menu, OPEN_CATALOG_ITEM_ID, "openCatalog"); addMenuItem(menu, OPEN_CATALOG_ITEM_ID, "openCatalog");
@ -107,13 +109,13 @@ class NetworkCatalogActions extends NetworkTreeActions {
} }
} }
} }
INetworkLink link = catalogTree.Item.Link; INetworkLink link = item.Link;
if (link instanceof ICustomNetworkLink) { if (link instanceof ICustomNetworkLink) {
addMenuItem(menu, CUSTOM_CATALOG_EDIT, "editCustomCatalog"); addMenuItem(menu, CUSTOM_CATALOG_EDIT, "editCustomCatalog");
addMenuItem(menu, CUSTOM_CATALOG_REMOVE, "removeCustomCatalog"); addMenuItem(menu, CUSTOM_CATALOG_REMOVE, "removeCustomCatalog");
} }
} else { } else {
if (item.URLByType.get(NetworkCatalogItem.URL_HTML_PAGE) != null) { if (urlItem != null && urlItem.URLByType.get(NetworkURLCatalogItem.URL_HTML_PAGE) != null) {
addMenuItem(menu, OPEN_IN_BROWSER_ITEM_ID, "openInBrowser"); addMenuItem(menu, OPEN_IN_BROWSER_ITEM_ID, "openInBrowser");
hasItems = true; hasItems = true;
} }
@ -127,16 +129,19 @@ class NetworkCatalogActions extends NetworkTreeActions {
@Override @Override
public int getDefaultActionCode(NetworkBaseActivity activity, NetworkTree tree) { public int getDefaultActionCode(NetworkBaseActivity activity, NetworkTree tree) {
final NetworkCatalogTree catalogTree = (NetworkCatalogTree) tree; final NetworkCatalogItem item = ((NetworkCatalogTree)tree).Item;
final NetworkCatalogItem item = catalogTree.Item; if (!(item instanceof NetworkURLCatalogItem)) {
if (item.URLByType.get(NetworkCatalogItem.URL_CATALOG) != null) {
return OPEN_CATALOG_ITEM_ID; return OPEN_CATALOG_ITEM_ID;
} }
if (item.URLByType.get(NetworkCatalogItem.URL_HTML_PAGE) != null) { final NetworkURLCatalogItem urlItem = (NetworkURLCatalogItem)item;
if (urlItem.URLByType.get(NetworkURLCatalogItem.URL_CATALOG) != null) {
return OPEN_CATALOG_ITEM_ID;
}
if (urlItem.URLByType.get(NetworkURLCatalogItem.URL_HTML_PAGE) != null) {
return OPEN_IN_BROWSER_ITEM_ID; return OPEN_IN_BROWSER_ITEM_ID;
} }
if (item.getVisibility() == ZLBoolean3.B3_UNDEFINED && if (urlItem.getVisibility() == ZLBoolean3.B3_UNDEFINED &&
item.Link.authenticationManager() != null) { urlItem.Link.authenticationManager() != null) {
return SIGNIN_ITEM_ID; return SIGNIN_ITEM_ID;
} }
return TREE_NO_ACTION; return TREE_NO_ACTION;
@ -166,14 +171,14 @@ class NetworkCatalogActions extends NetworkTreeActions {
@Override @Override
public boolean prepareOptionsMenu(NetworkBaseActivity activity, Menu menu, NetworkTree tree) { public boolean prepareOptionsMenu(NetworkBaseActivity activity, Menu menu, NetworkTree tree) {
final NetworkCatalogTree catalogTree = (NetworkCatalogTree) tree; final NetworkCatalogItem item = ((NetworkCatalogTree)tree).Item;
final NetworkCatalogItem item = catalogTree.Item; final NetworkURLCatalogItem urlItem =
item instanceof NetworkURLCatalogItem ? (NetworkURLCatalogItem)item : null;
final boolean isLoading =
NetworkView.Instance().containsItemsLoadingRunnable(tree.getUniqueKey());
prepareOptionsItem(menu, RELOAD_ITEM_ID, prepareOptionsItem(menu, RELOAD_ITEM_ID,
item.URLByType.get(NetworkCatalogItem.URL_CATALOG) != null && !isLoading); urlItem != null &&
urlItem.URLByType.get(NetworkURLCatalogItem.URL_CATALOG) != null &&
!NetworkView.Instance().containsItemsLoadingRunnable(tree.getUniqueKey()));
boolean signIn = false; boolean signIn = false;
boolean signOut = false; boolean signOut = false;
@ -204,14 +209,14 @@ class NetworkCatalogActions extends NetworkTreeActions {
} }
private boolean consumeByVisibility(final NetworkBaseActivity activity, final NetworkTree tree, final int actionCode) { private boolean consumeByVisibility(final NetworkBaseActivity activity, final NetworkTree tree, final int actionCode) {
final NetworkCatalogTree catalogTree = (NetworkCatalogTree) tree; final NetworkCatalogItem item = ((NetworkCatalogTree)tree).Item;
switch (catalogTree.Item.getVisibility()) { switch (item.getVisibility()) {
case B3_TRUE: case B3_TRUE:
return false; return false;
case B3_UNDEFINED: case B3_UNDEFINED:
AuthenticationDialog.show(activity, ((NetworkCatalogTree)tree).Item.Link, new Runnable() { AuthenticationDialog.show(activity, ((NetworkCatalogTree)tree).Item.Link, new Runnable() {
public void run() { public void run() {
if (catalogTree.Item.getVisibility() != ZLBoolean3.B3_TRUE) { if (item.getVisibility() != ZLBoolean3.B3_TRUE) {
return; return;
} }
if (actionCode != SIGNIN_ITEM_ID) { if (actionCode != SIGNIN_ITEM_ID) {
@ -229,11 +234,12 @@ class NetworkCatalogActions extends NetworkTreeActions {
if (consumeByVisibility(activity, tree, actionCode)) { if (consumeByVisibility(activity, tree, actionCode)) {
return true; return true;
} }
final NetworkCatalogTree catalogTree = (NetworkCatalogTree)tree; final NetworkCatalogTree catalogTree = (NetworkCatalogTree)tree;
final NetworkCatalogItem item = catalogTree.Item;
switch (actionCode) { switch (actionCode) {
case OPEN_CATALOG_ITEM_ID: case OPEN_CATALOG_ITEM_ID:
{ {
final NetworkCatalogItem item = catalogTree.Item;
if (item instanceof BasketItem && item.Link.basket().bookIds().size() == 0) { if (item instanceof BasketItem && item.Link.basket().bookIds().size() == 0) {
UIUtil.showErrorMessage(activity, "emptyBasket"); UIUtil.showErrorMessage(activity, "emptyBasket");
} else { } else {
@ -242,41 +248,43 @@ class NetworkCatalogActions extends NetworkTreeActions {
return true; return true;
} }
case OPEN_IN_BROWSER_ITEM_ID: case OPEN_IN_BROWSER_ITEM_ID:
Util.openInBrowser( if (item instanceof NetworkURLCatalogItem) {
activity, Util.openInBrowser(
catalogTree.Item.URLByType.get(NetworkCatalogItem.URL_HTML_PAGE) activity,
); ((NetworkURLCatalogItem)item).URLByType.get(NetworkURLCatalogItem.URL_HTML_PAGE)
);
}
return true; return true;
case RELOAD_ITEM_ID: case RELOAD_ITEM_ID:
doReloadCatalog(activity, catalogTree); doReloadCatalog(activity, catalogTree);
return true; return true;
case SIGNIN_ITEM_ID: case SIGNIN_ITEM_ID:
AuthenticationDialog.show(activity, catalogTree.Item.Link, null); AuthenticationDialog.show(activity, item.Link, null);
return true; return true;
case SIGNUP_ITEM_ID: case SIGNUP_ITEM_ID:
Util.runRegistrationDialog(activity, catalogTree.Item.Link); Util.runRegistrationDialog(activity, item.Link);
return true; return true;
case SIGNOUT_ITEM_ID: case SIGNOUT_ITEM_ID:
doSignOut(activity, catalogTree); doSignOut(activity, catalogTree);
return true; return true;
case REFILL_ACCOUNT_ITEM_ID: case REFILL_ACCOUNT_ITEM_ID:
new RefillAccountActions().runStandalone(activity, catalogTree.Item.Link); new RefillAccountActions().runStandalone(activity, item.Link);
return true; return true;
case CUSTOM_CATALOG_EDIT: case CUSTOM_CATALOG_EDIT:
{ {
final Intent intent = new Intent(activity, AddCustomCatalogActivity.class); final Intent intent = new Intent(activity, AddCustomCatalogActivity.class);
NetworkLibraryActivity.addLinkToIntent( NetworkLibraryActivity.addLinkToIntent(
intent, intent,
(ICustomNetworkLink)catalogTree.Item.Link (ICustomNetworkLink)item.Link
); );
activity.startActivity(intent); activity.startActivity(intent);
return true; return true;
} }
case CUSTOM_CATALOG_REMOVE: case CUSTOM_CATALOG_REMOVE:
removeCustomLink((ICustomNetworkLink)catalogTree.Item.Link); removeCustomLink((ICustomNetworkLink)item.Link);
return true; return true;
case BASKET_CLEAR: case BASKET_CLEAR:
catalogTree.Item.Link.basket().clear(); item.Link.basket().clear();
return true; return true;
case BASKET_BUY_ALL_BOOKS: case BASKET_BUY_ALL_BOOKS:
return true; return true;
@ -411,7 +419,7 @@ class NetworkCatalogActions extends NetworkTreeActions {
if (tree.Item.supportsResumeLoading()) { if (tree.Item.supportsResumeLoading()) {
resumeNotLoad = true; resumeNotLoad = true;
} else { } else {
NetworkView.Instance().openTree(activity, tree); Util.openTree(activity, tree);
return; return;
} }
} else { } else {
@ -439,7 +447,7 @@ class NetworkCatalogActions extends NetworkTreeActions {
); );
processExtraData(activity, tree.Item.extraData(), new Runnable() { processExtraData(activity, tree.Item.extraData(), new Runnable() {
public void run() { public void run() {
NetworkView.Instance().openTree(activity, tree); Util.openTree(activity, tree);
} }
}); });
} }

View file

@ -33,8 +33,6 @@ import org.geometerplus.fbreader.network.tree.*;
import org.geometerplus.fbreader.tree.FBTree; import org.geometerplus.fbreader.tree.FBTree;
public class NetworkCatalogActivity extends NetworkBaseActivity implements UserRegistrationConstants { public class NetworkCatalogActivity extends NetworkBaseActivity implements UserRegistrationConstants {
public static final String CATALOG_KEY_KEY = "org.geometerplus.android.fbreader.network.CatalogKey";
private NetworkTree myTree; private NetworkTree myTree;
private volatile boolean myInProgress; private volatile boolean myInProgress;
@ -50,17 +48,14 @@ public class NetworkCatalogActivity extends NetworkBaseActivity implements UserR
return; return;
} }
final Intent intent = getIntent(); myTree = Util.getTreeFromIntent(getIntent());
final NetworkLibrary library = NetworkLibrary.Instance();
final NetworkTree.Key key = (NetworkTree.Key)intent.getSerializableExtra(CATALOG_KEY_KEY);
myTree = library.getTreeByKey(key);
if (myTree == null) { if (myTree == null) {
throw new RuntimeException("Tree not found for key " + key); finish();
return;
} }
networkView.setOpenedActivity(key, this); networkView.setOpenedActivity(myTree.getUniqueKey(), this);
setListAdapter(new CatalogAdapter()); setListAdapter(new CatalogAdapter());
getListView().invalidateViews(); getListView().invalidateViews();

View file

@ -0,0 +1,118 @@
/*
* Copyright (C) 2010-2011 Geometer Plus <contact@geometerplus.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
package org.geometerplus.android.fbreader.network;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Handler;
import android.os.Message;
import org.geometerplus.zlibrary.core.resources.ZLResource;
import org.geometerplus.zlibrary.core.network.ZLNetworkException;
import org.geometerplus.android.util.UIUtil;
class NetworkInitializer extends Handler {
static NetworkInitializer Instance;
private Activity myActivity;
public NetworkInitializer(Activity activity) {
Instance = this;
setActivity(activity);
}
public void setActivity(Activity activity) {
myActivity = activity;
}
final DialogInterface.OnClickListener myListener = new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
if (which == DialogInterface.BUTTON_POSITIVE) {
NetworkInitializer.this.start();
} else if (myActivity != null) {
myActivity.finish();
}
}
};
// run this method only if myActivity != null
private void runInitialization() {
UIUtil.wait("loadingNetworkLibrary", new Runnable() {
public void run() {
String error = null;
try {
NetworkView.Instance().initialize();
if (myActivity instanceof NetworkLibraryActivity) {
((NetworkLibraryActivity)myActivity).processSavedIntent();
}
} catch (ZLNetworkException e) {
error = e.getMessage();
}
NetworkInitializer.this.end(error);
}
}, myActivity);
}
private void showTryAgainDialog(Activity activity, String error) {
final ZLResource dialogResource = ZLResource.resource("dialog");
final ZLResource boxResource = dialogResource.getResource("networkError");
final ZLResource buttonResource = dialogResource.getResource("button");
new AlertDialog.Builder(activity)
.setTitle(boxResource.getResource("title").getValue())
.setMessage(error)
.setIcon(0)
.setPositiveButton(buttonResource.getResource("tryAgain").getValue(), myListener)
.setNegativeButton(buttonResource.getResource("cancel").getValue(), myListener)
.setOnCancelListener(new DialogInterface.OnCancelListener() {
public void onCancel(DialogInterface dialog) {
myListener.onClick(dialog, DialogInterface.BUTTON_NEGATIVE);
}
})
.create().show();
}
@Override
public void handleMessage(Message message) {
if (myActivity == null) {
return;
} else if (message.what == 0) {
runInitialization(); // run initialization process
} else if (message.obj == null) {
if (myActivity instanceof NetworkLibraryActivity) {
final NetworkLibraryActivity a = (NetworkLibraryActivity)myActivity;
a.startService(new Intent(a.getApplicationContext(), LibraryInitializationService.class));
a.prepareView(); // initialization is complete successfully
}
} else {
showTryAgainDialog(myActivity, (String)message.obj); // handle initialization error
}
}
public void start() {
sendEmptyMessage(0);
}
private void end(String error) {
sendMessage(obtainMessage(1, error));
}
}

View file

@ -95,10 +95,16 @@ public class NetworkLibraryActivity extends NetworkBaseActivity {
processIntent(intent); processIntent(intent);
} }
void processSavedIntent() {
if (myIntent != null) {
processIntent(myIntent);
myIntent = null;
}
}
private void processIntent(Intent intent) { private void processIntent(Intent intent) {
if (ADD_CATALOG.equals(intent.getAction())) { if (ADD_CATALOG.equals(intent.getAction())) {
final ICustomNetworkLink link = getLinkFromIntent(intent); final ICustomNetworkLink link = getLinkFromIntent(intent);
System.err.println("LINK = " + link);
if (link != null) { if (link != null) {
runOnUiThread(new Runnable() { runOnUiThread(new Runnable() {
public void run() { public void run() {
@ -113,7 +119,7 @@ public class NetworkLibraryActivity extends NetworkBaseActivity {
} }
} }
private void prepareView() { void prepareView() {
if (myTree == null) { if (myTree == null) {
myTree = NetworkLibrary.Instance().getRootTree(); myTree = NetworkLibrary.Instance().getRootTree();
setListAdapter(new LibraryAdapter()); setListAdapter(new LibraryAdapter());
@ -121,17 +127,15 @@ public class NetworkLibraryActivity extends NetworkBaseActivity {
} }
} }
private static Initializator myInitializator;
@Override @Override
public void onResume() { public void onResume() {
super.onResume(); super.onResume();
if (!NetworkView.Instance().isInitialized()) { if (!NetworkView.Instance().isInitialized()) {
if (myInitializator == null) { if (NetworkInitializer.Instance == null) {
myInitializator = new Initializator(this); new NetworkInitializer(this);
myInitializator.start(); NetworkInitializer.Instance.start();
} else { } else {
myInitializator.setActivity(this); NetworkInitializer.Instance.setActivity(this);
} }
} else { } else {
prepareView(); prepareView();
@ -144,96 +148,12 @@ public class NetworkLibraryActivity extends NetworkBaseActivity {
@Override @Override
public void onDestroy() { public void onDestroy() {
if (!NetworkView.Instance().isInitialized() if (!NetworkView.Instance().isInitialized() && NetworkInitializer.Instance != null) {
&& myInitializator != null) { NetworkInitializer.Instance.setActivity(null);
myInitializator.setActivity(null);
} }
super.onDestroy(); super.onDestroy();
} }
private static class Initializator extends Handler {
private NetworkLibraryActivity myActivity;
public Initializator(NetworkLibraryActivity activity) {
myActivity = activity;
}
public void setActivity(NetworkLibraryActivity activity) {
myActivity = activity;
}
final DialogInterface.OnClickListener myListener = new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
if (which == DialogInterface.BUTTON_POSITIVE) {
Initializator.this.start();
} else if (myActivity != null) {
myActivity.finish();
}
}
};
// run this method only if myActivity != null
private void runInitialization() {
UIUtil.wait("loadingNetworkLibrary", new Runnable() {
public void run() {
String error = null;
try {
NetworkView.Instance().initialize();
if (myActivity.myIntent != null) {
myActivity.processIntent(myActivity.myIntent);
myActivity.myIntent = null;
}
} catch (ZLNetworkException e) {
error = e.getMessage();
}
Initializator.this.end(error);
}
}, myActivity);
}
// run this method only if myActivity != null
private void processResults(String error) {
final ZLResource dialogResource = ZLResource.resource("dialog");
final ZLResource boxResource = dialogResource.getResource("networkError");
final ZLResource buttonResource = dialogResource.getResource("button");
new AlertDialog.Builder(myActivity)
.setTitle(boxResource.getResource("title").getValue())
.setMessage(error)
.setIcon(0)
.setPositiveButton(buttonResource.getResource("tryAgain").getValue(), myListener)
.setNegativeButton(buttonResource.getResource("cancel").getValue(), myListener)
.setOnCancelListener(new DialogInterface.OnCancelListener() {
public void onCancel(DialogInterface dialog) {
myListener.onClick(dialog, DialogInterface.BUTTON_NEGATIVE);
}
})
.create().show();
}
@Override
public void handleMessage(Message message) {
if (myActivity == null) {
return;
} else if (message.what == 0) {
runInitialization(); // run initialization process
} else if (message.obj == null) {
myActivity.startService(new Intent(myActivity.getApplicationContext(), LibraryInitializationService.class));
myActivity.prepareView(); // initialization is complete successfully
} else {
processResults((String) message.obj); // handle initialization error
}
}
public void start() {
sendEmptyMessage(0);
}
private void end(String error) {
sendMessage(obtainMessage(1, error));
}
}
private final class LibraryAdapter extends BaseAdapter { private final class LibraryAdapter extends BaseAdapter {
public final int getCount() { public final int getCount() {
if (!NetworkView.Instance().isInitialized()) { if (!NetworkView.Instance().isInitialized()) {
@ -279,9 +199,13 @@ public class NetworkLibraryActivity extends NetworkBaseActivity {
} }
private static boolean searchIsInProgress() { private static boolean searchIsInProgress() {
return NetworkView.Instance().containsItemsLoadingRunnable( final NetworkView nView = NetworkView.Instance();
NetworkLibrary.Instance().getSearchItemTree().getUniqueKey() return
); nView != null &&
nView.isInitialized() &&
nView.containsItemsLoadingRunnable(
NetworkLibrary.Instance().getSearchItemTree().getUniqueKey()
);
} }
@Override @Override

View file

@ -172,6 +172,6 @@ public class NetworkSearchActivity extends Activity {
tree.getUniqueKey(), tree.getUniqueKey(),
new SearchRunnable(handler, pattern) new SearchRunnable(handler, pattern)
); );
NetworkView.Instance().openTree(this, tree); Util.openTree(this, tree);
} }
} }

View file

@ -96,7 +96,7 @@ class NetworkView {
} }
public NetworkTreeActions getActions(NetworkTree tree) { public NetworkTreeActions getActions(NetworkTree tree) {
for (NetworkTreeActions actions: myActions) { for (NetworkTreeActions actions : myActions) {
if (actions.canHandleTree(tree)) { if (actions.canHandleTree(tree)) {
return actions; return actions;
} }
@ -109,9 +109,6 @@ class NetworkView {
*/ */
public boolean createOptionsMenu(Menu menu, NetworkTree tree) { public boolean createOptionsMenu(Menu menu, NetworkTree tree) {
if (!isInitialized()) {
return false;
}
final NetworkTreeActions actions = getActions(tree); final NetworkTreeActions actions = getActions(tree);
if (actions != null) { if (actions != null) {
return actions.createOptionsMenu(menu, tree); return actions.createOptionsMenu(menu, tree);
@ -120,9 +117,6 @@ class NetworkView {
} }
public boolean prepareOptionsMenu(NetworkBaseActivity activity, Menu menu, NetworkTree tree) { public boolean prepareOptionsMenu(NetworkBaseActivity activity, Menu menu, NetworkTree tree) {
if (!isInitialized()) {
return false;
}
final NetworkTreeActions actions = getActions(tree); final NetworkTreeActions actions = getActions(tree);
if (actions != null) { if (actions != null) {
return actions.prepareOptionsMenu(activity, menu, tree); return actions.prepareOptionsMenu(activity, menu, tree);
@ -131,9 +125,6 @@ class NetworkView {
} }
public boolean runOptionsMenu(NetworkBaseActivity activity, MenuItem item, NetworkTree tree) { public boolean runOptionsMenu(NetworkBaseActivity activity, MenuItem item, NetworkTree tree) {
if (!isInitialized()) {
return false;
}
final NetworkTreeActions actions = getActions(tree); final NetworkTreeActions actions = getActions(tree);
if (actions != null) { if (actions != null) {
return actions.runAction(activity, tree, item.getItemId()); return actions.runAction(activity, tree, item.getItemId());
@ -186,7 +177,7 @@ class NetworkView {
public void tryResumeLoading(NetworkBaseActivity activity, NetworkCatalogTree tree, Runnable expandRunnable) { public void tryResumeLoading(NetworkBaseActivity activity, NetworkCatalogTree tree, Runnable expandRunnable) {
final ItemsLoadingRunnable runnable = getItemsLoadingRunnable(tree.getUniqueKey()); final ItemsLoadingRunnable runnable = getItemsLoadingRunnable(tree.getUniqueKey());
if (runnable != null && runnable.tryResumeLoading()) { if (runnable != null && runnable.tryResumeLoading()) {
openTree(activity, tree); Util.openTree(activity, tree);
return; return;
} }
if (runnable == null) { if (runnable == null) {
@ -248,24 +239,6 @@ class NetworkView {
} }
/*
* Starting BookInfo activity
*/
private NetworkBookItem myBookInfoItem;
public void showBookInfoActivity(Context context, NetworkBookItem book) {
myBookInfoItem = book;
context.startActivity(
new Intent(context.getApplicationContext(), NetworkBookInfoActivity.class)
);
}
NetworkBookItem getBookInfoItem() {
return myBookInfoItem;
}
/* /*
* Opening Catalogs & managing opened catalogs stack * Opening Catalogs & managing opened catalogs stack
*/ */
@ -273,13 +246,6 @@ class NetworkView {
private final HashMap<NetworkTree.Key,NetworkCatalogActivity> myOpenedActivities = private final HashMap<NetworkTree.Key,NetworkCatalogActivity> myOpenedActivities =
new HashMap<NetworkTree.Key,NetworkCatalogActivity>(); new HashMap<NetworkTree.Key,NetworkCatalogActivity>();
public void openTree(Context context, NetworkTree tree) {
context.startActivity(
new Intent(context.getApplicationContext(), NetworkCatalogActivity.class)
.putExtra(NetworkCatalogActivity.CATALOG_KEY_KEY, tree.getUniqueKey())
);
}
void setOpenedActivity(NetworkTree.Key key, NetworkCatalogActivity activity) { void setOpenedActivity(NetworkTree.Key key, NetworkCatalogActivity activity) {
if (activity == null) { if (activity == null) {
myOpenedActivities.remove(key); myOpenedActivities.remove(key);

View file

@ -44,7 +44,7 @@ class RefillAccountActions extends NetworkTreeActions {
buildContextMenu(activity, menu, ((TopUpTree)tree).Item.Link); buildContextMenu(activity, menu, ((TopUpTree)tree).Item.Link);
} }
public void buildContextMenu(Activity activity, ContextMenu menu, INetworkLink link) { void buildContextMenu(Activity activity, ContextMenu menu, INetworkLink link) {
menu.setHeaderTitle(getTitleValue("refillTitle")); menu.setHeaderTitle(getTitleValue("refillTitle"));
if (Util.isSmsAccountRefillingSupported(activity, link)) { if (Util.isSmsAccountRefillingSupported(activity, link)) {
@ -93,7 +93,7 @@ class RefillAccountActions extends NetworkTreeActions {
return runAction(activity, link, actionCode); return runAction(activity, link, actionCode);
} }
public boolean runAction(Activity activity, INetworkLink link, int actionCode) { static boolean runAction(Activity activity, INetworkLink link, int actionCode) {
Runnable refillRunnable = null; Runnable refillRunnable = null;
switch (actionCode) { switch (actionCode) {
case REFILL_VIA_SMS_ITEM_ID: case REFILL_VIA_SMS_ITEM_ID:
@ -111,7 +111,7 @@ class RefillAccountActions extends NetworkTreeActions {
return true; return true;
} }
private Runnable browserRefillRunnable(final Activity activity, final INetworkLink link) { private static Runnable browserRefillRunnable(final Activity activity, final INetworkLink link) {
return new Runnable() { return new Runnable() {
public void run() { public void run() {
Util.openInBrowser( Util.openInBrowser(
@ -122,7 +122,7 @@ class RefillAccountActions extends NetworkTreeActions {
}; };
} }
private Runnable smsRefillRunnable(final Activity activity, final INetworkLink link) { private static Runnable smsRefillRunnable(final Activity activity, final INetworkLink link) {
return new Runnable() { return new Runnable() {
public void run() { public void run() {
Util.runSmsDialog(activity, link); Util.runSmsDialog(activity, link);
@ -130,7 +130,7 @@ class RefillAccountActions extends NetworkTreeActions {
}; };
} }
private void doRefill(final Activity activity, final INetworkLink link, final Runnable refiller) { private static void doRefill(final Activity activity, final INetworkLink link, final Runnable refiller) {
final NetworkAuthenticationManager mgr = link.authenticationManager(); final NetworkAuthenticationManager mgr = link.authenticationManager();
if (mgr.mayBeAuthorised(false)) { if (mgr.mayBeAuthorised(false)) {
refiller.run(); refiller.run();

View file

@ -29,9 +29,9 @@ import android.net.Uri;
import org.geometerplus.zlibrary.core.network.ZLNetworkException; import org.geometerplus.zlibrary.core.network.ZLNetworkException;
import org.geometerplus.fbreader.network.NetworkLibrary; import org.geometerplus.fbreader.network.*;
import org.geometerplus.fbreader.network.INetworkLink;
import org.geometerplus.fbreader.network.authentication.NetworkAuthenticationManager; import org.geometerplus.fbreader.network.authentication.NetworkAuthenticationManager;
import org.geometerplus.fbreader.network.tree.NetworkBookTree;
import org.geometerplus.android.util.PackageUtil; import org.geometerplus.android.util.PackageUtil;
@ -126,4 +126,21 @@ abstract class Util implements UserRegistrationConstants {
context.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url))); context.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url)));
} }
} }
private static final String TREE_KEY_KEY = "org.geometerplus.android.fbreader.network.TreeKey";
static void openTree(Context context, NetworkTree tree) {
final Class<?> clz = tree instanceof NetworkBookTree
? NetworkBookInfoActivity.class : NetworkCatalogActivity.class;
context.startActivity(
new Intent(context.getApplicationContext(), clz)
.putExtra(TREE_KEY_KEY, tree.getUniqueKey())
);
}
public static NetworkTree getTreeFromIntent(Intent intent) {
final NetworkLibrary library = NetworkLibrary.Instance();
final NetworkTree.Key key = (NetworkTree.Key)intent.getSerializableExtra(TREE_KEY_KEY);
return library.getTreeByKey(key);
}
} }

View file

@ -382,5 +382,9 @@ public class PreferenceActivity extends ZLPreferenceActivity {
"navigateOverAllWords" "navigateOverAllWords"
)); ));
dictionaryScreen.addOption(fbReader.DictionaryTappingActionOption, "tappingAction"); dictionaryScreen.addOption(fbReader.DictionaryTappingActionOption, "tappingAction");
final Screen cancelMenuScreen = createPreferenceScreen("cancelMenu");
cancelMenuScreen.addOption(fbReader.ShowPreviousBookInCancelMenuOption, "previousBook");
cancelMenuScreen.addOption(fbReader.ShowPositionsInCancelMenuOption, "positions");
} }
} }

View file

@ -77,7 +77,7 @@ public class BookReader {
flushTextBufferToParagraph(); flushTextBufferToParagraph();
myCurrentTextModel.addControl(kind, start); myCurrentTextModel.addControl(kind, start);
} }
if (!start && (myHyperlinkReference.length() != 0) && (kind == myHyperlinkKind)) { if (!start && myHyperlinkReference.length() != 0 && kind == myHyperlinkKind) {
myHyperlinkReference = ""; myHyperlinkReference = "";
} }
} }
@ -113,6 +113,7 @@ public class BookReader {
} }
public final void beginParagraph(byte kind) { public final void beginParagraph(byte kind) {
endParagraph();
final ZLTextWritableModel textModel = myCurrentTextModel; final ZLTextWritableModel textModel = myCurrentTextModel;
if (textModel != null) { if (textModel != null) {
textModel.createParagraph(kind); textModel.createParagraph(kind);
@ -138,9 +139,9 @@ public class BookReader {
private final void insertEndParagraph(byte kind) { private final void insertEndParagraph(byte kind) {
final ZLTextWritableModel textModel = myCurrentTextModel; final ZLTextWritableModel textModel = myCurrentTextModel;
if ((textModel != null) && mySectionContainsRegularContents) { if (textModel != null && mySectionContainsRegularContents) {
int size = textModel.getParagraphsNumber(); int size = textModel.getParagraphsNumber();
if ((size > 0) && (textModel.getParagraph(size-1).getKind() != kind)) { if (size > 0 && textModel.getParagraph(size - 1).getKind() != kind) {
textModel.createParagraph(kind); textModel.createParagraph(kind);
mySectionContainsRegularContents = false; mySectionContainsRegularContents = false;
} }
@ -189,9 +190,19 @@ public class BookReader {
} }
public final void addData(char[] data, int offset, int length, boolean direct) { public final void addData(char[] data, int offset, int length, boolean direct) {
if (!myTextParagraphExists || (length == 0)) { if (!myTextParagraphExists || length == 0) {
return; return;
} }
if (!myInsideTitle && !mySectionContainsRegularContents) {
while (length > 0 && Character.isWhitespace(data[offset])) {
--length;
++offset;
}
if (length == 0) {
return;
}
}
myTextParagraphIsNonEmpty = true; myTextParagraphIsNonEmpty = true;
if (direct && (myTextBufferLength == 0) && !myInsideTitle) { if (direct && (myTextBufferLength == 0) && !myInsideTitle) {
@ -302,6 +313,10 @@ public class BookReader {
} }
} }
public final boolean hasContentsData() {
return myContentsBuffer.length() > 0;
}
public final void beginContentsParagraph(int referenceNumber) { public final void beginContentsParagraph(int referenceNumber) {
beginContentsParagraph(Model.BookTextModel, referenceNumber); beginContentsParagraph(Model.BookTextModel, referenceNumber);
} }

View file

@ -89,6 +89,11 @@ public final class FBReaderApp extends ZLApplication {
final ZLStringOption ColorProfileOption = final ZLStringOption ColorProfileOption =
new ZLStringOption("Options", "ColorProfile", ColorProfile.DAY); new ZLStringOption("Options", "ColorProfile", ColorProfile.DAY);
public final ZLBooleanOption ShowPreviousBookInCancelMenuOption =
new ZLBooleanOption("CancelMenu", "previousBook", false);
public final ZLBooleanOption ShowPositionsInCancelMenuOption =
new ZLBooleanOption("CancelMenu", "positions", true);
private final ZLKeyBindings myBindings = new ZLKeyBindings("Keys"); private final ZLKeyBindings myBindings = new ZLKeyBindings("Keys");
public final FBView BookTextView; public final FBView BookTextView;
@ -324,15 +329,19 @@ public final class FBReaderApp extends ZLApplication {
public List<CancelActionDescription> getCancelActionsList() { public List<CancelActionDescription> getCancelActionsList() {
myCancelActionsList.clear(); myCancelActionsList.clear();
final Book previousBook = Library.getPreviousBook(); if (ShowPreviousBookInCancelMenuOption.getValue()) {
if (previousBook != null) { final Book previousBook = Library.getPreviousBook();
myCancelActionsList.add(new CancelActionDescription( if (previousBook != null) {
CancelActionType.previousBook, previousBook.getTitle() myCancelActionsList.add(new CancelActionDescription(
)); CancelActionType.previousBook, previousBook.getTitle()
));
}
} }
if (Model != null && Model.Book != null) { if (ShowPositionsInCancelMenuOption.getValue()) {
for (Bookmark bookmark : Bookmark.invisibleBookmarks(Model.Book)) { if (Model != null && Model.Book != null) {
myCancelActionsList.add(new BookmarkDescription(bookmark)); for (Bookmark bookmark : Bookmark.invisibleBookmarks(Model.Book)) {
myCancelActionsList.add(new BookmarkDescription(bookmark));
}
} }
} }
myCancelActionsList.add(new CancelActionDescription( myCancelActionsList.add(new CancelActionDescription(

View file

@ -171,6 +171,13 @@ public final class FB2Reader extends ZLXMLReaderAdapter {
case FB2Tag.BODY: case FB2Tag.BODY:
myBookReader.popKind(); myBookReader.popKind();
myReadMainText = false; myReadMainText = false;
if (myReadMainText) {
myBookReader.insertEndOfSectionParagraph();
}
if (mySectionDepth > 0) {
myBookReader.endContentsParagraph();
mySectionDepth = 0;
}
myBookReader.unsetCurrentTextModel(); myBookReader.unsetCurrentTextModel();
break; break;
@ -308,16 +315,24 @@ public final class FB2Reader extends ZLXMLReaderAdapter {
myBookReader.pushKind(FBTextKind.TITLE); myBookReader.pushKind(FBTextKind.TITLE);
} else { } else {
myBookReader.pushKind(FBTextKind.SECTION_TITLE); myBookReader.pushKind(FBTextKind.SECTION_TITLE);
myInsideTitle = true; if (!myBookReader.hasContentsData()) {
myBookReader.enterTitle(); myInsideTitle = true;
myBookReader.enterTitle();
}
} }
break; break;
case FB2Tag.BODY: case FB2Tag.BODY:
++myBodyCounter; ++myBodyCounter;
myParagraphsBeforeBodyNumber = myBookReader.Model.BookTextModel.getParagraphsNumber(); myParagraphsBeforeBodyNumber = myBookReader.Model.BookTextModel.getParagraphsNumber();
if ((myBodyCounter == 1) || (attributes.getValue("name") == null)) { final String name = attributes.getValue("name");
if (myBodyCounter == 1 || !"notes".equals(name)) {
myBookReader.setMainTextModel(); myBookReader.setMainTextModel();
if (name != null) {
myBookReader.beginContentsParagraph();
myBookReader.addContentsData(name.toCharArray());
++mySectionDepth;
}
myReadMainText = true; myReadMainText = true;
} }
myBookReader.pushKind(FBTextKind.REGULAR); myBookReader.pushKind(FBTextKind.REGULAR);

View file

@ -32,9 +32,15 @@ class XHTMLTagParagraphWithControlAction extends XHTMLTagAction {
protected void doAtStart(XHTMLReader reader, ZLStringMap xmlattributes) { protected void doAtStart(XHTMLReader reader, ZLStringMap xmlattributes) {
final BookReader modelReader = reader.getModelReader(); final BookReader modelReader = reader.getModelReader();
if ((myControl == FBTextKind.TITLE) && switch (myControl) {
(modelReader.Model.BookTextModel.getParagraphsNumber() > 1)) { case FBTextKind.TITLE:
modelReader.insertEndOfSectionParagraph(); case FBTextKind.H1:
case FBTextKind.H2:
if (modelReader.Model.BookTextModel.getParagraphsNumber() > 1) {
modelReader.insertEndOfSectionParagraph();
}
modelReader.enterTitle();
break;
} }
modelReader.pushKind(myControl); modelReader.pushKind(myControl);
modelReader.beginParagraph(); modelReader.beginParagraph();
@ -44,6 +50,13 @@ class XHTMLTagParagraphWithControlAction extends XHTMLTagAction {
final BookReader modelReader = reader.getModelReader(); final BookReader modelReader = reader.getModelReader();
modelReader.endParagraph(); modelReader.endParagraph();
modelReader.popKind(); modelReader.popKind();
switch (myControl) {
case FBTextKind.TITLE:
case FBTextKind.H1:
case FBTextKind.H2:
modelReader.exitTitle();
break;
}
} }
} }
/* /*

View file

@ -35,11 +35,11 @@ public final class NetworkBookItem extends NetworkItem {
* Creates new AuthorData instance. * Creates new AuthorData instance.
* *
* @param displayName author's name. Must be not <code>null</code>. * @param displayName author's name. Must be not <code>null</code>.
* @param sortKey string that defines sorting order of book's authors. Must be not <code>null</code>. * @param sortKey string that defines sorting order of book's authors.
*/ */
public AuthorData(String displayName, String sortKey) { public AuthorData(String displayName, String sortKey) {
DisplayName = displayName.intern(); DisplayName = displayName.intern();
SortKey = sortKey.intern(); SortKey = sortKey != null ? sortKey.intern() : DisplayName.toLowerCase().intern();
} }
public int compareTo(AuthorData data) { public int compareTo(AuthorData data) {

View file

@ -23,19 +23,23 @@ import java.util.*;
import org.geometerplus.zlibrary.core.util.ZLBoolean3; import org.geometerplus.zlibrary.core.util.ZLBoolean3;
import org.geometerplus.zlibrary.core.network.ZLNetworkException; import org.geometerplus.zlibrary.core.network.ZLNetworkException;
import org.geometerplus.zlibrary.core.network.ZLNetworkManager;
import org.geometerplus.zlibrary.core.network.ZLNetworkRequest;
import org.geometerplus.fbreader.network.authentication.NetworkAuthenticationManager; import org.geometerplus.fbreader.network.authentication.NetworkAuthenticationManager;
public abstract class NetworkCatalogItem extends NetworkItem { public abstract class NetworkCatalogItem extends NetworkItem {
// bit mask for flags parameter
public static final int FLAG_SHOW_AUTHOR = 1 << 0;
public static final int FLAG_GROUP_BY_AUTHOR = 1 << 1;
public static final int FLAG_GROUP_BY_SERIES = 1 << 2;
public static final int FLAG_GROUP_MORE_THAN_1_BOOK_BY_SERIES = 1 << 3;
// catalog types: public static final int FLAGS_DEFAULT =
public static enum CatalogType { FLAG_SHOW_AUTHOR |
OTHER, FLAG_GROUP_MORE_THAN_1_BOOK_BY_SERIES;
BY_AUTHOR, public static final int FLAGS_GROUP =
BY_SERIES FLAG_GROUP_BY_AUTHOR |
} FLAG_GROUP_BY_SERIES |
FLAG_GROUP_MORE_THAN_1_BOOK_BY_SERIES;
// catalog accessibility types: // catalog accessibility types:
public static enum Accessibility { public static enum Accessibility {
@ -45,27 +49,8 @@ public abstract class NetworkCatalogItem extends NetworkItem {
HAS_BOOKS HAS_BOOKS
} }
// URL type values:
public static final int URL_NONE = 0;
public static final int URL_CATALOG = 1;
public static final int URL_HTML_PAGE = 2;
private final Accessibility myAccessibility; private final Accessibility myAccessibility;
private final CatalogType myCatalogType; public final int Flags;
public final TreeMap<Integer, String> URLByType;
/**
* Creates new NetworkCatalogItem instance with <code>Accessibility.ALWAYS</code> accessibility and <code>CatalogType.OTHER</code> type.
*
* @param link corresponding NetworkLink object. Must be not <code>null</code>.
* @param title title of this library item. Must be not <code>null</code>.
* @param summary description of this library item. Can be <code>null</code>.
* @param cover cover url. Can be <code>null</code>.
* @param urlByType map contains URLs and their types. Must be not <code>null</code>.
*/
public NetworkCatalogItem(INetworkLink link, String title, String summary, String cover, Map<Integer,String> urlByType) {
this(link, title, summary, cover, urlByType, Accessibility.ALWAYS, CatalogType.OTHER);
}
/** /**
* Creates new NetworkCatalogItem instance with specified accessibility and type. * Creates new NetworkCatalogItem instance with specified accessibility and type.
@ -74,16 +59,14 @@ public abstract class NetworkCatalogItem extends NetworkItem {
* @param title title of this library item. Must be not <code>null</code>. * @param title title of this library item. Must be not <code>null</code>.
* @param summary description of this library item. Can be <code>null</code>. * @param summary description of this library item. Can be <code>null</code>.
* @param cover cover url. Can be <code>null</code>. * @param cover cover url. Can be <code>null</code>.
* @param urlByType map contains URLs and their types. Must be not <code>null</code>.
* @param accessibility value defines when this library item will be accessible * @param accessibility value defines when this library item will be accessible
* in the network library view. * in the network library view.
* @param catalogType value defines type of this catalog. * @param flags describes how to show book items inside this catalog
*/ */
public NetworkCatalogItem(INetworkLink link, String title, String summary, String cover, Map<Integer, String> urlByType, Accessibility accessibility, CatalogType catalogType) { public NetworkCatalogItem(INetworkLink link, String title, String summary, String cover, Accessibility accessibility, int flags) {
super(link, title, summary, cover); super(link, title, summary, cover);
myAccessibility = accessibility; myAccessibility = accessibility;
myCatalogType = catalogType; Flags = flags;
URLByType = new TreeMap<Integer, String>(urlByType);
} }
public Map<String,String> extraData() { public Map<String,String> extraData() {
@ -109,10 +92,6 @@ public abstract class NetworkCatalogItem extends NetworkItem {
public void onDisplayItem() { public void onDisplayItem() {
} }
public final CatalogType getCatalogType() {
return myCatalogType;
}
public ZLBoolean3 getVisibility() { public ZLBoolean3 getVisibility() {
final NetworkAuthenticationManager mgr = Link.authenticationManager(); final NetworkAuthenticationManager mgr = Link.authenticationManager();
switch (myAccessibility) { switch (myAccessibility) {
@ -140,35 +119,5 @@ public abstract class NetworkCatalogItem extends NetworkItem {
} }
} }
/** public abstract String getStringId();
* Performs all necessary operations with NetworkOperationData and NetworkRequest
* to complete loading children items.
*
* @param data Network operation data instance
* @param networkRequest initial network request
*
* @throws ZLNetworkException when network operation couldn't be completed
*/
protected final void doLoadChildren(NetworkOperationData data,
ZLNetworkRequest networkRequest) throws ZLNetworkException {
while (networkRequest != null) {
ZLNetworkManager.Instance().perform(networkRequest);
if (data.Listener.confirmInterrupt()) {
return;
}
networkRequest = data.resume();
}
}
/**
* Override this method if result of the request depends not only from URL
* (e.g. result of the POST request depends from the URL and the body of the request).
*
* @return unique String for corresponding network request, for which:
* {@code item1.getFullRequestString().equals(item2.getFullRequestString())}
* iff network requests for items {@code item1} and {@code item2} are the same.
*/
public String getFullRequestString() {
return URLByType.get(URL_CATALOG);
}
} }

View file

@ -408,6 +408,9 @@ public class NetworkLibrary {
} }
public NetworkTree getTreeByKey(NetworkTree.Key key) { public NetworkTree getTreeByKey(NetworkTree.Key key) {
if (key == null) {
return null;
}
if (key.Parent == null) { if (key.Parent == null) {
return key.equals(myRootTree.getUniqueKey()) ? myRootTree : null; return key.equals(myRootTree.getUniqueKey()) ? myRootTree : null;
} }

View file

@ -0,0 +1,109 @@
/*
* Copyright (C) 2010-2011 Geometer Plus <contact@geometerplus.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
package org.geometerplus.fbreader.network;
import java.util.*;
import org.geometerplus.zlibrary.core.util.ZLBoolean3;
import org.geometerplus.zlibrary.core.network.ZLNetworkException;
import org.geometerplus.zlibrary.core.network.ZLNetworkManager;
import org.geometerplus.zlibrary.core.network.ZLNetworkRequest;
import org.geometerplus.fbreader.network.authentication.NetworkAuthenticationManager;
public abstract class NetworkURLCatalogItem extends NetworkCatalogItem {
// URL type values:
public static final int URL_NONE = 0;
public static final int URL_CATALOG = 1;
public static final int URL_HTML_PAGE = 2;
public final TreeMap<Integer,String> URLByType;
/**
* Creates new NetworkURLCatalogItem instance with <code>Accessibility.ALWAYS</code> accessibility and <code>FLAGS_DEFAULT</code> flags.
*
* @param link corresponding NetworkLink object. Must be not <code>null</code>.
* @param title title of this library item. Must be not <code>null</code>.
* @param summary description of this library item. Can be <code>null</code>.
* @param cover cover url. Can be <code>null</code>.
* @param urlByType map contains URLs and their types. Must be not <code>null</code>.
*/
public NetworkURLCatalogItem(INetworkLink link, String title, String summary, String cover, Map<Integer,String> urlByType) {
this(link, title, summary, cover, urlByType, Accessibility.ALWAYS, FLAGS_DEFAULT);
}
/**
* Creates new NetworkURLCatalogItem instance with specified accessibility and type.
*
* @param link corresponding NetworkLink object. Must be not <code>null</code>.
* @param title title of this library item. Must be not <code>null</code>.
* @param summary description of this library item. Can be <code>null</code>.
* @param cover cover url. Can be <code>null</code>.
* @param urlByType map contains URLs and their types. Must be not <code>null</code>.
* @param accessibility value defines when this library item will be accessible
* in the network library view.
* @param flags value defines how to show book items in this catalog.
*/
public NetworkURLCatalogItem(INetworkLink link, String title, String summary, String cover, Map<Integer, String> urlByType, Accessibility accessibility, int flags) {
super(link, title, summary, cover, accessibility, flags);
URLByType = new TreeMap<Integer,String>(urlByType);
}
/**
* Performs all necessary operations with NetworkOperationData and NetworkRequest
* to complete loading children items.
*
* @param data Network operation data instance
* @param networkRequest initial network request
*
* @throws ZLNetworkException when network operation couldn't be completed
*/
protected final void doLoadChildren(NetworkOperationData data,
ZLNetworkRequest networkRequest) throws ZLNetworkException {
while (networkRequest != null) {
ZLNetworkManager.Instance().perform(networkRequest);
if (data.Listener.confirmInterrupt()) {
return;
}
networkRequest = data.resume();
}
}
/**
* Override this method if result of the request depends not only from URL
* (e.g. result of the POST request depends from the URL and the body of the request).
*
* @return unique String for corresponding network request, for which:
* {@code item1.getFullRequestString().equals(item2.getFullRequestString())}
* iff network requests for items {@code item1} and {@code item2} are the same.
*/
//public String getFullRequestString() {
// return URLByType.get(URL_CATALOG);
//}
@Override
public String getStringId() {
String id = URLByType.get(URL_CATALOG);
if (id == null) {
id = URLByType.get(URL_HTML_PAGE);
}
return id != null ? id : String.valueOf(hashCode());
}
}

View file

@ -29,8 +29,8 @@ import org.geometerplus.fbreader.network.*;
abstract class SortedCatalogItem extends NetworkCatalogItem { abstract class SortedCatalogItem extends NetworkCatalogItem {
private final List<NetworkItem> myChildren = new LinkedList<NetworkItem>(); private final List<NetworkItem> myChildren = new LinkedList<NetworkItem>();
private SortedCatalogItem(NetworkCatalogItem parent, ZLResource resource, List<NetworkItem> children) { private SortedCatalogItem(NetworkCatalogItem parent, ZLResource resource, List<NetworkItem> children, int flags) {
super(parent.Link, resource.getValue(), resource.getResource("summary").getValue(), "", parent.URLByType); super(parent.Link, resource.getValue(), resource.getResource("summary").getValue(), "", Accessibility.ALWAYS, flags);
for (NetworkItem child : children) { for (NetworkItem child : children) {
if (accepts(child)) { if (accepts(child)) {
myChildren.add(child); myChildren.add(child);
@ -51,8 +51,8 @@ abstract class SortedCatalogItem extends NetworkCatalogItem {
return item instanceof NetworkBookItem; return item instanceof NetworkBookItem;
} }
public SortedCatalogItem(NetworkCatalogItem parent, String resourceKey, List<NetworkItem> children) { public SortedCatalogItem(NetworkCatalogItem parent, String resourceKey, List<NetworkItem> children, int flags) {
this(parent, ZLResource.resource("networkView").getResource(resourceKey), children); this(parent, ZLResource.resource("networkView").getResource(resourceKey), children, flags);
} }
@Override @Override
@ -70,18 +70,23 @@ abstract class SortedCatalogItem extends NetworkCatalogItem {
class ByAuthorCatalogItem extends SortedCatalogItem { class ByAuthorCatalogItem extends SortedCatalogItem {
ByAuthorCatalogItem(NetworkCatalogItem parent, List<NetworkItem> children) { ByAuthorCatalogItem(NetworkCatalogItem parent, List<NetworkItem> children) {
super(parent, "byAuthor", children); super(parent, "byAuthor", children, FLAG_GROUP_BY_AUTHOR);
} }
@Override @Override
protected Comparator<NetworkItem> getComparator() { protected Comparator<NetworkItem> getComparator() {
return new NetworkBookItemComparator(); return new NetworkBookItemComparator();
} }
@Override
public String getStringId() {
return "@ByAuthor";
}
} }
class ByTitleCatalogItem extends SortedCatalogItem { class ByTitleCatalogItem extends SortedCatalogItem {
ByTitleCatalogItem(NetworkCatalogItem parent, List<NetworkItem> children) { ByTitleCatalogItem(NetworkCatalogItem parent, List<NetworkItem> children) {
super(parent, "byTitle", children); super(parent, "byTitle", children, FLAG_SHOW_AUTHOR);
} }
@Override @Override
@ -92,11 +97,16 @@ class ByTitleCatalogItem extends SortedCatalogItem {
} }
}; };
} }
@Override
public String getStringId() {
return "@ByTitle";
}
} }
class ByDateCatalogItem extends SortedCatalogItem { class ByDateCatalogItem extends SortedCatalogItem {
ByDateCatalogItem(NetworkCatalogItem parent, List<NetworkItem> children) { ByDateCatalogItem(NetworkCatalogItem parent, List<NetworkItem> children) {
super(parent, "byDate", children); super(parent, "byDate", children, FLAG_SHOW_AUTHOR);
} }
@Override @Override
@ -107,11 +117,16 @@ class ByDateCatalogItem extends SortedCatalogItem {
} }
}; };
} }
@Override
public String getStringId() {
return "@ByDate";
}
} }
class BySeriesCatalogItem extends SortedCatalogItem { class BySeriesCatalogItem extends SortedCatalogItem {
BySeriesCatalogItem(NetworkCatalogItem parent, List<NetworkItem> children) { BySeriesCatalogItem(NetworkCatalogItem parent, List<NetworkItem> children) {
super(parent, "bySeries", children); super(parent, "bySeries", children, FLAG_SHOW_AUTHOR | FLAG_GROUP_BY_SERIES);
} }
@Override @Override
@ -135,13 +150,18 @@ class BySeriesCatalogItem extends SortedCatalogItem {
item instanceof NetworkBookItem && item instanceof NetworkBookItem &&
((NetworkBookItem)item).SeriesTitle != null; ((NetworkBookItem)item).SeriesTitle != null;
} }
@Override
public String getStringId() {
return "@BySeries";
}
} }
public class LitResBookshelfItem extends NetworkCatalogItem { public class LitResBookshelfItem extends NetworkURLCatalogItem {
private boolean myForceReload; private boolean myForceReload;
public LitResBookshelfItem(INetworkLink link, String title, String summary, String cover, Map<Integer, String> urlByType, Accessibility accessibility) { public LitResBookshelfItem(INetworkLink link, String title, String summary, String cover, Map<Integer, String> urlByType, Accessibility accessibility) {
super(link, title, summary, cover, urlByType, accessibility, CatalogType.OTHER); super(link, title, summary, cover, urlByType, accessibility, FLAGS_DEFAULT);
} }
@Override @Override
@ -174,7 +194,7 @@ public class LitResBookshelfItem extends NetworkCatalogItem {
listener.onNewItem(Link, item); listener.onNewItem(Link, item);
} }
} else { } else {
listener.onNewItem(Link, new ByDateCatalogItem(this, children)); //listener.onNewItem(Link, new ByDateCatalogItem(this, children));
listener.onNewItem(Link, new ByAuthorCatalogItem(this, children)); listener.onNewItem(Link, new ByAuthorCatalogItem(this, children));
listener.onNewItem(Link, new ByTitleCatalogItem(this, children)); listener.onNewItem(Link, new ByTitleCatalogItem(this, children));
final BySeriesCatalogItem bySeries = new BySeriesCatalogItem(this, children); final BySeriesCatalogItem bySeries = new BySeriesCatalogItem(this, children);

View file

@ -31,7 +31,7 @@ import org.geometerplus.fbreader.network.opds.OPDSNetworkLink;
public class LitResRecommendationsItem extends OPDSCatalogItem { public class LitResRecommendationsItem extends OPDSCatalogItem {
public LitResRecommendationsItem(INetworkLink link, String title, String summary, String cover, Map<Integer,String> urlByType, Accessibility accessibility) { public LitResRecommendationsItem(INetworkLink link, String title, String summary, String cover, Map<Integer,String> urlByType, Accessibility accessibility) {
super(link, title, summary, cover, urlByType, accessibility, CatalogType.BY_SERIES); super(link, title, summary, cover, urlByType, accessibility, FLAGS_DEFAULT & ~FLAGS_GROUP);
} }
@Override @Override

View file

@ -52,7 +52,6 @@ class LitResXMLReader extends LitResAuthenticationXMLReader {
private LinkedList<NetworkBookItem.AuthorData> myAuthors = new LinkedList<NetworkBookItem.AuthorData>(); private LinkedList<NetworkBookItem.AuthorData> myAuthors = new LinkedList<NetworkBookItem.AuthorData>();
private LinkedList<String> myTags = new LinkedList<String>(); private LinkedList<String> myTags = new LinkedList<String>();
private HashMap<Integer, String> myURLByType = new HashMap<Integer, String>(); // TODO: remove
private LinkedList<BookReference> myReferences = new LinkedList<BookReference>(); private LinkedList<BookReference> myReferences = new LinkedList<BookReference>();
public LitResXMLReader(INetworkLink link, List<NetworkItem> books) { public LitResXMLReader(INetworkLink link, List<NetworkItem> books) {
@ -122,11 +121,6 @@ class LitResXMLReader extends LitResAuthenticationXMLReader {
myBookId = attributes.getValue("hub_id"); myBookId = attributes.getValue("hub_id");
myCover = attributes.getValue("cover_preview"); myCover = attributes.getValue("cover_preview");
final String url = attributes.getValue("url");
if (url != null) {
myURLByType.put(NetworkCatalogItem.URL_HTML_PAGE, url);
}
myReferences.add(new BookReference( myReferences.add(new BookReference(
"https://robot.litres.ru/pages/catalit_download_book/?art=" + myBookId, "https://robot.litres.ru/pages/catalit_download_book/?art=" + myBookId,
BookReference.Format.FB2_ZIP, BookReference.Format.FB2_ZIP,
@ -238,7 +232,6 @@ class LitResXMLReader extends LitResAuthenticationXMLReader {
myIndexInSeries = 0; myIndexInSeries = 0;
myAuthors.clear(); myAuthors.clear();
myTags.clear(); myTags.clear();
myURLByType.clear();
myReferences.clear(); myReferences.clear();
myState = CATALOG; myState = CATALOG;
} }

View file

@ -30,7 +30,7 @@ import org.geometerplus.fbreader.network.opds.OPDSCatalogItem;
public class BasketItem extends OPDSCatalogItem { public class BasketItem extends OPDSCatalogItem {
BasketItem(OPDSNetworkLink link, String title, String summary, String cover, Map<Integer,String> urlByType, Accessibility accessibility) { BasketItem(OPDSNetworkLink link, String title, String summary, String cover, Map<Integer,String> urlByType, Accessibility accessibility) {
super(link, title, summary, cover, urlByType, accessibility, CatalogType.BY_SERIES); super(link, title, summary, cover, urlByType, accessibility, FLAGS_DEFAULT & ~FLAGS_GROUP);
link.setSupportsBasket(); link.setSupportsBasket();
} }

View file

@ -375,7 +375,7 @@ class NetworkOPDSFeedReader implements OPDSFeedReader, OPDSConstants, MimeTypes
boolean urlIsAlternate = false; boolean urlIsAlternate = false;
String htmlURL = null; String htmlURL = null;
String litresRel = null; String litresRel = null;
NetworkCatalogItem.CatalogType catalogType = NetworkCatalogItem.CatalogType.OTHER; int catalogType = NetworkCatalogItem.FLAGS_DEFAULT;
for (ATOMLink link : entry.Links) { for (ATOMLink link : entry.Links) {
final String href = ZLNetworkUtil.url(myBaseURL, link.getHref()); final String href = ZLNetworkUtil.url(myBaseURL, link.getHref());
final String type = ZLNetworkUtil.filterMimeType(link.getType()); final String type = ZLNetworkUtil.filterMimeType(link.getType());
@ -396,9 +396,9 @@ class NetworkOPDSFeedReader implements OPDSFeedReader, OPDSConstants, MimeTypes
url = href; url = href;
urlIsAlternate = false; urlIsAlternate = false;
if (REL_CATALOG_AUTHOR.equals(rel)) { if (REL_CATALOG_AUTHOR.equals(rel)) {
catalogType = NetworkCatalogItem.CatalogType.BY_AUTHOR; catalogType &= ~NetworkCatalogItem.FLAG_SHOW_AUTHOR;
} else if (REL_CATALOG_SERIES.equals(rel)) { } else if (REL_CATALOG_SERIES.equals(rel)) {
catalogType = NetworkCatalogItem.CatalogType.BY_SERIES; catalogType &= ~NetworkCatalogItem.FLAGS_GROUP;
} }
} }
} else if (MIME_TEXT_HTML.equals(type)) { } else if (MIME_TEXT_HTML.equals(type)) {
@ -431,12 +431,12 @@ class NetworkOPDSFeedReader implements OPDSFeedReader, OPDSConstants, MimeTypes
annotation = null; annotation = null;
} }
HashMap<Integer, String> urlMap = new HashMap<Integer, String>(); HashMap<Integer,String> urlMap = new HashMap<Integer,String>();
if (url != null) { if (url != null) {
urlMap.put(NetworkCatalogItem.URL_CATALOG, url); urlMap.put(NetworkURLCatalogItem.URL_CATALOG, url);
} }
if (htmlURL != null) { if (htmlURL != null) {
urlMap.put(NetworkCatalogItem.URL_HTML_PAGE, htmlURL); urlMap.put(NetworkURLCatalogItem.URL_HTML_PAGE, htmlURL);
} }
if (litresRel != null) { if (litresRel != null) {
if (REL_BOOKSHELF.equals(litresRel)) { if (REL_BOOKSHELF.equals(litresRel)) {

View file

@ -26,7 +26,7 @@ import org.geometerplus.zlibrary.core.network.ZLNetworkRequest;
import org.geometerplus.fbreader.network.*; import org.geometerplus.fbreader.network.*;
public class OPDSCatalogItem extends NetworkCatalogItem { public class OPDSCatalogItem extends NetworkURLCatalogItem {
static class State extends NetworkOperationData { static class State extends NetworkOperationData {
public String LastLoadedId; public String LastLoadedId;
public final HashSet<String> LoadedIds = new HashSet<String>(); public final HashSet<String> LoadedIds = new HashSet<String>();
@ -43,8 +43,8 @@ public class OPDSCatalogItem extends NetworkCatalogItem {
myExtraData = extraData; myExtraData = extraData;
} }
public OPDSCatalogItem(INetworkLink link, String title, String summary, String cover, Map<Integer, String> urlByType, Accessibility accessibility, CatalogType catalogType) { public OPDSCatalogItem(INetworkLink link, String title, String summary, String cover, Map<Integer, String> urlByType, Accessibility accessibility, int flags) {
super(link, title, summary, cover, urlByType, accessibility, catalogType); super(link, title, summary, cover, urlByType, accessibility, flags);
myExtraData = null; myExtraData = null;
} }

View file

@ -37,7 +37,7 @@ import org.geometerplus.fbreader.network.*;
import org.geometerplus.fbreader.network.atom.ATOMUpdated; import org.geometerplus.fbreader.network.atom.ATOMUpdated;
public class OPDSLinkReader { public class OPDSLinkReader {
static final String CATALOGS_URL = "http://data.fbreader.org/catalogs/generic-1.2.xml"; static final String CATALOGS_URL = "http://data.fbreader.org/catalogs/generic-1.3.xml";
public static final int CACHE_LOAD = 0; public static final int CACHE_LOAD = 0;
public static final int CACHE_UPDATE = 1; public static final int CACHE_UPDATE = 1;

View file

@ -290,28 +290,10 @@ class OPDSLinkXMLReader extends OPDSXMLReader implements OPDSConstants, MimeType
} }
return false; return false;
} else if (tag == FBREADER_REWRITING_RULE) { } else if (tag == FBREADER_REWRITING_RULE) {
final String type = attributes.getValue("type"); ((LinkReader)myFeedReader).addUrlRewritingRule(new URLRewritingRule(attributes));
final String apply = attributes.getValue("apply");
final String name = attributes.getValue("name");
final String value = attributes.getValue("value");
final int typeValue;
if (type == "addUrlParameter") {
typeValue = URLRewritingRule.ADD_URL_PARAMETER;
} else {
return false;
}
final int applyValue;
if (apply == "external") {
applyValue = URLRewritingRule.APPLY_EXTERNAL;
} else if (apply == "internal") {
applyValue = URLRewritingRule.APPLY_INTERNAL;
} else {
applyValue = URLRewritingRule.APPLY_ALWAYS;
}
((LinkReader) myFeedReader).addUrlRewritingRule(new URLRewritingRule(typeValue, applyValue, name, value));
return false; return false;
} else if (tag == FBREADER_STABLE_IDENTIFIERS) { } else if (tag == FBREADER_STABLE_IDENTIFIERS) {
((LinkReader) myFeedReader).setHasStableIdentifiers(true); ((LinkReader)myFeedReader).setHasStableIdentifiers(true);
return false; return false;
} else if (tag == FBREADER_EXTRA) { } else if (tag == FBREADER_EXTRA) {
final String name = attributes.getValue("name"); final String name = attributes.getValue("name");

View file

@ -27,7 +27,6 @@ import java.io.IOException;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import org.geometerplus.zlibrary.core.util.ZLMiscUtil; import org.geometerplus.zlibrary.core.util.ZLMiscUtil;
import org.geometerplus.zlibrary.core.util.ZLNetworkUtil;
import org.geometerplus.zlibrary.core.network.ZLNetworkException; import org.geometerplus.zlibrary.core.network.ZLNetworkException;
import org.geometerplus.zlibrary.core.network.ZLNetworkRequest; import org.geometerplus.zlibrary.core.network.ZLNetworkRequest;
@ -135,7 +134,7 @@ public class OPDSNetworkLink extends AbstractNetworkLink {
public NetworkCatalogItem libraryItem() { public NetworkCatalogItem libraryItem() {
TreeMap<Integer,String> urlMap = new TreeMap<Integer,String>(); TreeMap<Integer,String> urlMap = new TreeMap<Integer,String>();
urlMap.put(NetworkCatalogItem.URL_CATALOG, getUrlInfo(URL_MAIN).URL); urlMap.put(NetworkURLCatalogItem.URL_CATALOG, getUrlInfo(URL_MAIN).URL);
return new OPDSCatalogItem(this, getTitle(), getSummary(), getUrlInfo(URL_ICON).URL, urlMap, myExtraData); return new OPDSCatalogItem(this, getTitle(), getSummary(), getUrlInfo(URL_ICON).URL, urlMap, myExtraData);
} }
@ -144,17 +143,11 @@ public class OPDSNetworkLink extends AbstractNetworkLink {
} }
public String rewriteUrl(String url, boolean isUrlExternal) { public String rewriteUrl(String url, boolean isUrlExternal) {
final int apply = isUrlExternal
? URLRewritingRule.APPLY_EXTERNAL : URLRewritingRule.APPLY_INTERNAL;
for (URLRewritingRule rule: myUrlRewritingRules) { for (URLRewritingRule rule: myUrlRewritingRules) {
if (rule.Apply != URLRewritingRule.APPLY_ALWAYS) { if ((rule.whereToApply() & apply) != 0) {
if ((rule.Apply == URLRewritingRule.APPLY_EXTERNAL && !isUrlExternal) url = rule.apply(url);
|| (rule.Apply == URLRewritingRule.APPLY_INTERNAL && isUrlExternal)) {
continue;
}
}
switch (rule.Type) {
case URLRewritingRule.ADD_URL_PARAMETER:
url = ZLNetworkUtil.appendParameter(url, rule.Name, rule.Value);
break;
} }
} }
return url; return url;

View file

@ -19,40 +19,89 @@
package org.geometerplus.fbreader.network.opds; package org.geometerplus.fbreader.network.opds;
import java.util.HashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.geometerplus.zlibrary.core.util.ZLMiscUtil; import org.geometerplus.zlibrary.core.util.ZLMiscUtil;
import org.geometerplus.zlibrary.core.util.ZLNetworkUtil;
import org.geometerplus.zlibrary.core.xml.ZLStringMap;
class URLRewritingRule { class URLRewritingRule {
// rule types: // rule types:
public static final int ADD_URL_PARAMETER = 0; public static final int ADD_URL_PARAMETER = 0;
public static final int REWRITE = 1;
public static final int UNKNOWN = 2;
// apply values: // apply values:
public static final int APPLY_ALWAYS = 0;
public static final int APPLY_EXTERNAL = 1; public static final int APPLY_EXTERNAL = 1;
public static final int APPLY_INTERNAL = 2; public static final int APPLY_INTERNAL = 2;
public static final int APPLY_ALWAYS = APPLY_EXTERNAL | APPLY_INTERNAL;
private int myType = UNKNOWN;
private int myApply = APPLY_ALWAYS;
public final int Type; private final HashMap<String,String> myParameters = new HashMap<String,String>();
public final int Apply;
public final String Name;
public final String Value;
public URLRewritingRule(int type, int apply, String name, String value) { public URLRewritingRule(ZLStringMap map) {
Type = type; for (int i = map.getSize() - 1; i >= 0; --i) {
Apply = apply; final String key = map.getKey(i);
Name = name; final String value = map.getValue(key);
Value = value; if ("type".equals(key)) {
if ("addUrlParameter".equals(value)) {
myType = ADD_URL_PARAMETER;
} else if ("rewrite".equals(value)) {
myType = REWRITE;
}
} else if ("apply".equals(key)) {
if ("internal".equals(value)) {
myApply = APPLY_INTERNAL;
} else if ("external".equals(value)) {
myApply = APPLY_EXTERNAL;
}
} else {
myParameters.put(key, value);
}
}
} }
@Override public int whereToApply() {
public String toString() { return myApply;
return "Rule: {type=" + Type
+ "; apply=" + Apply
+ "; name=" + Name
+ "; value=" + Value
+ "}";
} }
public String apply(String url) {
switch (myType) {
default:
return url;
case ADD_URL_PARAMETER:
{
final String name = myParameters.get("name");
final String value = myParameters.get("value");
if (name == null || value == null) {
return url;
}
return ZLNetworkUtil.appendParameter(url, name, value);
}
case REWRITE:
{
/*
final String pattern = myParameters.get("pattern");
final String replacement = myParameters.get("replacement");
if (pattern == null || replacement == null) {
return url;
}
final Matcher matcher = Pattern.compile(pattern).matcher(url);
if (matcher.matches()) {
for (int i = matcher.groupCount(); i >= 1; --i) {
url = replacement.replace("%" + i, matcher.group(1));
}
}
*/
return url;
}
}
}
/*
@Override @Override
public boolean equals(Object o) { public boolean equals(Object o) {
if (this == o) { if (this == o) {
@ -70,4 +119,5 @@ class URLRewritingRule {
} }
return true; return true;
} }
*/
} }

View file

@ -170,6 +170,6 @@ public class NetworkCatalogTree extends NetworkTree {
@Override @Override
protected String getStringId() { protected String getStringId() {
return Item.getFullRequestString(); return Item.getStringId();
} }
} }

View file

@ -24,7 +24,6 @@ import org.geometerplus.zlibrary.core.util.ZLBoolean3;
import org.geometerplus.fbreader.network.*; import org.geometerplus.fbreader.network.*;
public class NetworkTreeFactory { public class NetworkTreeFactory {
public static NetworkTree createNetworkTree(NetworkCatalogTree parent, NetworkItem item) { public static NetworkTree createNetworkTree(NetworkCatalogTree parent, NetworkItem item) {
return createNetworkTree(parent, item, -1); return createNetworkTree(parent, item, -1);
} }
@ -50,36 +49,75 @@ public class NetworkTreeFactory {
throw new RuntimeException("Unable to insert NetworkBookItem to the middle of the catalog"); throw new RuntimeException("Unable to insert NetworkBookItem to the middle of the catalog");
} }
final NetworkCatalogItem.CatalogType catalogType = parent.Item.getCatalogType(); final NetworkBookItem book = (NetworkBookItem)item;
final boolean showAuthors = catalogType != NetworkCatalogItem.CatalogType.BY_AUTHOR; final int flags = parent.Item.Flags;
final boolean showAuthors = (flags & NetworkCatalogItem.FLAG_SHOW_AUTHOR) != 0;
NetworkBookItem book = (NetworkBookItem) item; switch (flags & NetworkCatalogItem.FLAGS_GROUP) {
String seriesTitle = book.SeriesTitle; default:
if (seriesTitle == null || catalogType == NetworkCatalogItem.CatalogType.BY_SERIES) { return new NetworkBookTree(parent, book, position, showAuthors);
return new NetworkBookTree(parent, (NetworkBookItem) item, position, showAuthors); case NetworkCatalogItem.FLAG_GROUP_BY_SERIES:
} if (book.SeriesTitle == null) {
return new NetworkBookTree(parent, book, position, showAuthors);
if (position > 0) { } else {
final NetworkTree previous = (NetworkTree) parent.subTrees().get(position - 1); final NetworkTree previous = position > 0
if (previous instanceof NetworkSeriesTree) { ? (NetworkTree)parent.subTrees().get(position - 1) : null;
final NetworkSeriesTree seriesTree = (NetworkSeriesTree) previous; NetworkSeriesTree seriesTree = null;
if (seriesTitle.equals(seriesTree.SeriesTitle)) { if (previous instanceof NetworkSeriesTree) {
seriesTree.invalidateChildren(); // call to update secondString seriesTree = (NetworkSeriesTree)previous;
if (!book.SeriesTitle.equals(seriesTree.SeriesTitle)) {
seriesTree = null;
}
}
if (seriesTree == null) {
seriesTree = new NetworkSeriesTree(
parent, book.SeriesTitle, position, showAuthors
);
}
return new NetworkBookTree(seriesTree, book, showAuthors); return new NetworkBookTree(seriesTree, book, showAuthors);
} }
} else if (previous instanceof NetworkBookTree) { case NetworkCatalogItem.FLAG_GROUP_MORE_THAN_1_BOOK_BY_SERIES:
final NetworkBookTree bookTree = (NetworkBookTree) previous; if (position > 0 && book.SeriesTitle != null) {
final NetworkBookItem previousBook = bookTree.Book; final NetworkTree previous =
if (seriesTitle.equals(previousBook.SeriesTitle)) { (NetworkTree)parent.subTrees().get(position - 1);
bookTree.removeSelf(); if (previous instanceof NetworkSeriesTree) {
final NetworkSeriesTree seriesTree = new NetworkSeriesTree(parent, seriesTitle, --position, showAuthors); final NetworkSeriesTree seriesTree = (NetworkSeriesTree)previous;
new NetworkBookTree(seriesTree, previousBook, showAuthors); if (book.SeriesTitle.equals(seriesTree.SeriesTitle)) {
return new NetworkBookTree(seriesTree, book, showAuthors); return new NetworkBookTree(seriesTree, book, showAuthors);
}
} else /* if (previous instanceof NetworkBookTree) */ {
final NetworkBookItem previousBook = ((NetworkBookTree)previous).Book;
if (book.SeriesTitle.equals(previousBook.SeriesTitle)) {
previous.removeSelf();
final NetworkSeriesTree seriesTree = new NetworkSeriesTree(
parent, book.SeriesTitle, position - 1, showAuthors
);
new NetworkBookTree(seriesTree, previousBook, showAuthors);
return new NetworkBookTree(seriesTree, book, showAuthors);
}
}
}
return new NetworkBookTree(parent, book, position, showAuthors);
case NetworkCatalogItem.FLAG_GROUP_BY_AUTHOR:
if (book.Authors.isEmpty()) {
return new NetworkBookTree(parent, book, position, showAuthors);
} else {
final NetworkBookItem.AuthorData author = book.Authors.get(0);
final NetworkTree previous = position > 0
? (NetworkTree)parent.subTrees().get(position - 1) : null;
NetworkAuthorTree authorTree = null;
if (previous instanceof NetworkAuthorTree) {
authorTree = (NetworkAuthorTree)previous;
if (!author.equals(authorTree.Author)) {
authorTree = null;
}
}
if (authorTree == null) {
authorTree = new NetworkAuthorTree(parent, author);
}
return new NetworkBookTree(authorTree, book, showAuthors);
} }
}
} }
return new NetworkBookTree(parent, book, position, showAuthors);
} else if (item instanceof TopUpItem) { } else if (item instanceof TopUpItem) {
return new TopUpTree(parent, (TopUpItem)item); return new TopUpTree(parent, (TopUpItem)item);
} }

View file

@ -67,7 +67,7 @@ public class SearchItemTree extends NetworkTree {
if (!(currentNode instanceof NetworkAuthorTree)) { if (!(currentNode instanceof NetworkAuthorTree)) {
throw new RuntimeException("That's impossible!!!"); throw new RuntimeException("That's impossible!!!");
} }
NetworkAuthorTree child = (NetworkAuthorTree) currentNode; NetworkAuthorTree child = (NetworkAuthorTree)currentNode;
if (!child.Author.equals(author)) { if (!child.Author.equals(author)) {
throw new RuntimeException("That's impossible!!!"); throw new RuntimeException("That's impossible!!!");
} }