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"?>
<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" />
<supports-screens android:smallScreens="true" android:normalScreens="true" android:largeScreens="true" android:anyDensity="true" />
<uses-permission android:name="android.permission.INTERNET" />
@ -145,7 +145,14 @@
</activity>
<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" />
<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" />
<service android:name="org.geometerplus.android.fbreader.network.LibraryInitializationService" android:process=":networkLibrary" />
</application>

View file

@ -145,7 +145,14 @@
</activity>
<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" />
<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" />
<service android:name="org.geometerplus.android.fbreader.network.LibraryInitializationService" android:process=":networkLibrary" />
</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)
* Fixed TTF font style detection
* opds:// URLs support has been implemented
@ -6,6 +7,10 @@
* Ignore case comparison for zip entry names
* Fixed custom OPDS link search
* 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) =====
* 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>
</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 name="OptionsDialog">
<node name="tab">

View file

@ -528,6 +528,17 @@
<node name="summaryOff" value="Key navigation visits hyperlinks only" toBeTranslated="true"/>
</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 name="OptionsDialog">
<node name="tab">

View file

@ -540,6 +540,17 @@
<node name="summaryOff" value="Key navigation visits hyperlinks only"/>
</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 name="OptionsDialog">
<node name="tab">

View file

@ -530,6 +530,17 @@
<node name="summaryOff" value="La navigation par touches visite les liens hypertexts uniquement"/>
</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 name="OptionsDialog">
<node name="tab">

View file

@ -527,6 +527,17 @@
<node name="summaryOff" value="A tecla de navegación percorre só as ligazóns"/>
</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 name="OptionsDialog">
<node name="tab">

View file

@ -527,6 +527,17 @@
<node name="summaryOff" value="A gombnyomásos navigáció linkről linkre ugrik"/>
</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 name="OptionsDialog">
<node name="tab">

View file

@ -527,6 +527,17 @@
<node name="summaryOff" value="Key navigation visits hyperlinks only" toBeTranslated="true"/>
</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 name="OptionsDialog">
<node name="tab">

View file

@ -527,6 +527,17 @@
<node name="summaryOff" value="Key navigation visits hyperlinks only" toBeTranslated="true"/>
</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 name="OptionsDialog">
<node name="tab">

View file

@ -526,6 +526,17 @@
<node name="summaryOff" value="При перемещении с помощью кнопок помечать только гиперссылки"/>
</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 name="OptionsDialog">
<node name="tab">

View file

@ -527,6 +527,17 @@
<node name="summaryOff" value="ตัวเลือกคำเลือกได้เฉพาะลิ้งค์ข้อความ"/>
</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 name="OptionsDialog">
<node name="tab">

View file

@ -527,6 +527,17 @@
<node name="summaryOff" value="Key navigation visits hyperlinks only" toBeTranslated="true"/>
</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 name="OptionsDialog">
<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>
</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 name="OptionsDialog">
<node name="tab">

View file

@ -527,6 +527,17 @@
<node name="summaryOff" value="导航键仅访问超链接词句"/>
</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 name="OptionsDialog">
<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());
setListAdapter(adapter);
getListView().setOnCreateContextMenuListener(adapter);
System.err.println("SELECTED: " + adapter.getFirstSelectedItemIndex());
setSelection(adapter.getFirstSelectedItemIndex());
}
}

View file

@ -187,7 +187,6 @@ abstract class NetworkBaseActivity extends ListActivity implements NetworkView.E
@Override
public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo) {
System.err.println("onCreateContextMenu -1");
if (menuInfo != null) {
final int position = ((AdapterView.AdapterContextMenuInfo)menuInfo).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) {
switch (actionCode) {
case SHOW_BOOKS_ITEM_ID:
NetworkView.Instance().openTree(activity, tree);
Util.openTree(activity, tree);
return true;
}
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) {
case DOWNLOAD_BOOK_ITEM_ID:
doDownloadBook(activity, book, false);
@ -259,9 +272,6 @@ class NetworkBookActions extends NetworkTreeActions {
case BUY_IN_BROWSER_ITEM_ID:
doBuyInBrowser(activity, book);
return true;
case SHOW_BOOK_ACTIVITY_ITEM_ID:
NetworkView.Instance().showBookInfoActivity(activity, book);
return true;
case ADD_BOOK_TO_BASKET:
book.Link.basket().add(book);
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.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 {
private NetworkBookItem myBook;
@ -56,33 +58,46 @@ public class NetworkBookInfoActivity extends Activity implements NetworkView.Eve
protected void onCreate(Bundle 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);
setContentView(myMainView);
myMainView.setOnCreateContextMenuListener(this);
}
setupDescription();
setupInfo();
setupCover();
setupButtons();
@Override
protected void onResume() {
super.onResume();
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() {
@ -99,6 +114,9 @@ public class NetworkBookInfoActivity extends Activity implements NetworkView.Eve
@Override
public void onDestroy() {
if (!NetworkView.Instance().isInitialized() && NetworkInitializer.Instance != null) {
NetworkInitializer.Instance.setActivity(null);
}
if (myConnection != null) {
unbindService(myConnection);
myConnection = null;
@ -108,22 +126,20 @@ public class NetworkBookInfoActivity extends Activity implements NetworkView.Eve
@Override
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
public boolean onContextItemSelected(MenuItem item) {
new RefillAccountActions().runAction(this, myBook.Link, item.getItemId());
RefillAccountActions.runAction(this, myBook.Link, item.getItemId());
return true;
}
private final void setupDescription() {
setTextFromResource(R.id.network_book_description_title, "description");
final String description;
if (myBook.Summary != null) {
description = myBook.Summary;
} else {
String description = myBook.Summary;
if (description == null) {
description = myResource.getResource("noDescription").getValue();
}
setTextById(R.id.network_book_description, description);
@ -155,7 +171,7 @@ public class NetworkBookInfoActivity extends Activity implements NetworkView.Eve
if (myBook.Authors.size() > 0) {
findViewById(R.id.network_book_authors).setVisibility(View.VISIBLE);
final StringBuilder authorsText = new StringBuilder();
for (NetworkBookItem.AuthorData author: myBook.Authors) {
for (NetworkBookItem.AuthorData author : myBook.Authors) {
if (authorsText.length() > 0) {
authorsText.append(", ");
}
@ -183,7 +199,7 @@ public class NetworkBookInfoActivity extends Activity implements NetworkView.Eve
if (myBook.Tags.size() > 0) {
findViewById(R.id.network_book_tags).setVisibility(View.VISIBLE);
final StringBuilder tagsText = new StringBuilder();
for (String tag: myBook.Tags) {
for (String tag : myBook.Tags) {
if (tagsText.length() > 0) {
tagsText.append(", ");
}
@ -278,7 +294,7 @@ public class NetworkBookInfoActivity extends Activity implements NetworkView.Eve
button.setVisibility(View.VISIBLE);
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
NetworkBookActions.runAction(NetworkBookInfoActivity.this, myBook, a.Id);
NetworkBookActions.runActionStatic(NetworkBookInfoActivity.this, myBook, a.Id);
NetworkBookInfoActivity.this.updateView();
}
});

View file

@ -69,18 +69,20 @@ class NetworkCatalogActions extends NetworkTreeActions {
if (tree instanceof NetworkCatalogRootTree) {
return tree.getName();
}
return tree.getName() + " - " + ((NetworkCatalogTree) tree).Item.Link.getSiteName();
return tree.getName() + " - " + ((NetworkCatalogTree)tree).Item.Link.getSiteName();
}
@Override
public void buildContextMenu(Activity activity, ContextMenu menu, NetworkTree tree) {
final NetworkCatalogTree catalogTree = (NetworkCatalogTree)tree;
final NetworkCatalogItem item = catalogTree.Item;
final NetworkCatalogItem item = ((NetworkCatalogTree)tree).Item;
final NetworkURLCatalogItem urlItem =
item instanceof NetworkURLCatalogItem ? (NetworkURLCatalogItem)item : null;
menu.setHeaderTitle(tree.getName());
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 &&
(!(item instanceof BasketItem) || item.Link.basket().bookIds().size() > 0)) {
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) {
addMenuItem(menu, CUSTOM_CATALOG_EDIT, "editCustomCatalog");
addMenuItem(menu, CUSTOM_CATALOG_REMOVE, "removeCustomCatalog");
}
} 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");
hasItems = true;
}
@ -127,16 +129,19 @@ class NetworkCatalogActions extends NetworkTreeActions {
@Override
public int getDefaultActionCode(NetworkBaseActivity activity, NetworkTree tree) {
final NetworkCatalogTree catalogTree = (NetworkCatalogTree) tree;
final NetworkCatalogItem item = catalogTree.Item;
if (item.URLByType.get(NetworkCatalogItem.URL_CATALOG) != null) {
final NetworkCatalogItem item = ((NetworkCatalogTree)tree).Item;
if (!(item instanceof NetworkURLCatalogItem)) {
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;
}
if (item.getVisibility() == ZLBoolean3.B3_UNDEFINED &&
item.Link.authenticationManager() != null) {
if (urlItem.getVisibility() == ZLBoolean3.B3_UNDEFINED &&
urlItem.Link.authenticationManager() != null) {
return SIGNIN_ITEM_ID;
}
return TREE_NO_ACTION;
@ -166,14 +171,14 @@ class NetworkCatalogActions extends NetworkTreeActions {
@Override
public boolean prepareOptionsMenu(NetworkBaseActivity activity, Menu menu, NetworkTree tree) {
final NetworkCatalogTree catalogTree = (NetworkCatalogTree) tree;
final NetworkCatalogItem item = catalogTree.Item;
final boolean isLoading =
NetworkView.Instance().containsItemsLoadingRunnable(tree.getUniqueKey());
final NetworkCatalogItem item = ((NetworkCatalogTree)tree).Item;
final NetworkURLCatalogItem urlItem =
item instanceof NetworkURLCatalogItem ? (NetworkURLCatalogItem)item : null;
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 signOut = false;
@ -204,14 +209,14 @@ class NetworkCatalogActions extends NetworkTreeActions {
}
private boolean consumeByVisibility(final NetworkBaseActivity activity, final NetworkTree tree, final int actionCode) {
final NetworkCatalogTree catalogTree = (NetworkCatalogTree) tree;
switch (catalogTree.Item.getVisibility()) {
final NetworkCatalogItem item = ((NetworkCatalogTree)tree).Item;
switch (item.getVisibility()) {
case B3_TRUE:
return false;
case B3_UNDEFINED:
AuthenticationDialog.show(activity, ((NetworkCatalogTree)tree).Item.Link, new Runnable() {
public void run() {
if (catalogTree.Item.getVisibility() != ZLBoolean3.B3_TRUE) {
if (item.getVisibility() != ZLBoolean3.B3_TRUE) {
return;
}
if (actionCode != SIGNIN_ITEM_ID) {
@ -229,11 +234,12 @@ class NetworkCatalogActions extends NetworkTreeActions {
if (consumeByVisibility(activity, tree, actionCode)) {
return true;
}
final NetworkCatalogTree catalogTree = (NetworkCatalogTree)tree;
final NetworkCatalogItem item = catalogTree.Item;
switch (actionCode) {
case OPEN_CATALOG_ITEM_ID:
{
final NetworkCatalogItem item = catalogTree.Item;
if (item instanceof BasketItem && item.Link.basket().bookIds().size() == 0) {
UIUtil.showErrorMessage(activity, "emptyBasket");
} else {
@ -242,41 +248,43 @@ class NetworkCatalogActions extends NetworkTreeActions {
return true;
}
case OPEN_IN_BROWSER_ITEM_ID:
Util.openInBrowser(
activity,
catalogTree.Item.URLByType.get(NetworkCatalogItem.URL_HTML_PAGE)
);
if (item instanceof NetworkURLCatalogItem) {
Util.openInBrowser(
activity,
((NetworkURLCatalogItem)item).URLByType.get(NetworkURLCatalogItem.URL_HTML_PAGE)
);
}
return true;
case RELOAD_ITEM_ID:
doReloadCatalog(activity, catalogTree);
return true;
case SIGNIN_ITEM_ID:
AuthenticationDialog.show(activity, catalogTree.Item.Link, null);
AuthenticationDialog.show(activity, item.Link, null);
return true;
case SIGNUP_ITEM_ID:
Util.runRegistrationDialog(activity, catalogTree.Item.Link);
Util.runRegistrationDialog(activity, item.Link);
return true;
case SIGNOUT_ITEM_ID:
doSignOut(activity, catalogTree);
return true;
case REFILL_ACCOUNT_ITEM_ID:
new RefillAccountActions().runStandalone(activity, catalogTree.Item.Link);
new RefillAccountActions().runStandalone(activity, item.Link);
return true;
case CUSTOM_CATALOG_EDIT:
{
final Intent intent = new Intent(activity, AddCustomCatalogActivity.class);
NetworkLibraryActivity.addLinkToIntent(
intent,
(ICustomNetworkLink)catalogTree.Item.Link
(ICustomNetworkLink)item.Link
);
activity.startActivity(intent);
return true;
}
case CUSTOM_CATALOG_REMOVE:
removeCustomLink((ICustomNetworkLink)catalogTree.Item.Link);
removeCustomLink((ICustomNetworkLink)item.Link);
return true;
case BASKET_CLEAR:
catalogTree.Item.Link.basket().clear();
item.Link.basket().clear();
return true;
case BASKET_BUY_ALL_BOOKS:
return true;
@ -411,7 +419,7 @@ class NetworkCatalogActions extends NetworkTreeActions {
if (tree.Item.supportsResumeLoading()) {
resumeNotLoad = true;
} else {
NetworkView.Instance().openTree(activity, tree);
Util.openTree(activity, tree);
return;
}
} else {
@ -439,7 +447,7 @@ class NetworkCatalogActions extends NetworkTreeActions {
);
processExtraData(activity, tree.Item.extraData(), new Runnable() {
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;
public class NetworkCatalogActivity extends NetworkBaseActivity implements UserRegistrationConstants {
public static final String CATALOG_KEY_KEY = "org.geometerplus.android.fbreader.network.CatalogKey";
private NetworkTree myTree;
private volatile boolean myInProgress;
@ -50,17 +48,14 @@ public class NetworkCatalogActivity extends NetworkBaseActivity implements UserR
return;
}
final Intent intent = getIntent();
final NetworkLibrary library = NetworkLibrary.Instance();
final NetworkTree.Key key = (NetworkTree.Key)intent.getSerializableExtra(CATALOG_KEY_KEY);
myTree = library.getTreeByKey(key);
myTree = Util.getTreeFromIntent(getIntent());
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());
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);
}
void processSavedIntent() {
if (myIntent != null) {
processIntent(myIntent);
myIntent = null;
}
}
private void processIntent(Intent intent) {
if (ADD_CATALOG.equals(intent.getAction())) {
final ICustomNetworkLink link = getLinkFromIntent(intent);
System.err.println("LINK = " + link);
if (link != null) {
runOnUiThread(new Runnable() {
public void run() {
@ -113,7 +119,7 @@ public class NetworkLibraryActivity extends NetworkBaseActivity {
}
}
private void prepareView() {
void prepareView() {
if (myTree == null) {
myTree = NetworkLibrary.Instance().getRootTree();
setListAdapter(new LibraryAdapter());
@ -121,17 +127,15 @@ public class NetworkLibraryActivity extends NetworkBaseActivity {
}
}
private static Initializator myInitializator;
@Override
public void onResume() {
super.onResume();
if (!NetworkView.Instance().isInitialized()) {
if (myInitializator == null) {
myInitializator = new Initializator(this);
myInitializator.start();
if (NetworkInitializer.Instance == null) {
new NetworkInitializer(this);
NetworkInitializer.Instance.start();
} else {
myInitializator.setActivity(this);
NetworkInitializer.Instance.setActivity(this);
}
} else {
prepareView();
@ -144,96 +148,12 @@ public class NetworkLibraryActivity extends NetworkBaseActivity {
@Override
public void onDestroy() {
if (!NetworkView.Instance().isInitialized()
&& myInitializator != null) {
myInitializator.setActivity(null);
if (!NetworkView.Instance().isInitialized() && NetworkInitializer.Instance != null) {
NetworkInitializer.Instance.setActivity(null);
}
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 {
public final int getCount() {
if (!NetworkView.Instance().isInitialized()) {
@ -279,9 +199,13 @@ public class NetworkLibraryActivity extends NetworkBaseActivity {
}
private static boolean searchIsInProgress() {
return NetworkView.Instance().containsItemsLoadingRunnable(
NetworkLibrary.Instance().getSearchItemTree().getUniqueKey()
);
final NetworkView nView = NetworkView.Instance();
return
nView != null &&
nView.isInitialized() &&
nView.containsItemsLoadingRunnable(
NetworkLibrary.Instance().getSearchItemTree().getUniqueKey()
);
}
@Override

View file

@ -172,6 +172,6 @@ public class NetworkSearchActivity extends Activity {
tree.getUniqueKey(),
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) {
for (NetworkTreeActions actions: myActions) {
for (NetworkTreeActions actions : myActions) {
if (actions.canHandleTree(tree)) {
return actions;
}
@ -109,9 +109,6 @@ class NetworkView {
*/
public boolean createOptionsMenu(Menu menu, NetworkTree tree) {
if (!isInitialized()) {
return false;
}
final NetworkTreeActions actions = getActions(tree);
if (actions != null) {
return actions.createOptionsMenu(menu, tree);
@ -120,9 +117,6 @@ class NetworkView {
}
public boolean prepareOptionsMenu(NetworkBaseActivity activity, Menu menu, NetworkTree tree) {
if (!isInitialized()) {
return false;
}
final NetworkTreeActions actions = getActions(tree);
if (actions != null) {
return actions.prepareOptionsMenu(activity, menu, tree);
@ -131,9 +125,6 @@ class NetworkView {
}
public boolean runOptionsMenu(NetworkBaseActivity activity, MenuItem item, NetworkTree tree) {
if (!isInitialized()) {
return false;
}
final NetworkTreeActions actions = getActions(tree);
if (actions != null) {
return actions.runAction(activity, tree, item.getItemId());
@ -186,7 +177,7 @@ class NetworkView {
public void tryResumeLoading(NetworkBaseActivity activity, NetworkCatalogTree tree, Runnable expandRunnable) {
final ItemsLoadingRunnable runnable = getItemsLoadingRunnable(tree.getUniqueKey());
if (runnable != null && runnable.tryResumeLoading()) {
openTree(activity, tree);
Util.openTree(activity, tree);
return;
}
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
*/
@ -273,13 +246,6 @@ class NetworkView {
private final HashMap<NetworkTree.Key,NetworkCatalogActivity> myOpenedActivities =
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) {
if (activity == null) {
myOpenedActivities.remove(key);

View file

@ -44,7 +44,7 @@ class RefillAccountActions extends NetworkTreeActions {
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"));
if (Util.isSmsAccountRefillingSupported(activity, link)) {
@ -93,7 +93,7 @@ class RefillAccountActions extends NetworkTreeActions {
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;
switch (actionCode) {
case REFILL_VIA_SMS_ITEM_ID:
@ -111,7 +111,7 @@ class RefillAccountActions extends NetworkTreeActions {
return true;
}
private Runnable browserRefillRunnable(final Activity activity, final INetworkLink link) {
private static Runnable browserRefillRunnable(final Activity activity, final INetworkLink link) {
return new Runnable() {
public void run() {
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() {
public void run() {
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();
if (mgr.mayBeAuthorised(false)) {
refiller.run();

View file

@ -29,9 +29,9 @@ import android.net.Uri;
import org.geometerplus.zlibrary.core.network.ZLNetworkException;
import org.geometerplus.fbreader.network.NetworkLibrary;
import org.geometerplus.fbreader.network.INetworkLink;
import org.geometerplus.fbreader.network.*;
import org.geometerplus.fbreader.network.authentication.NetworkAuthenticationManager;
import org.geometerplus.fbreader.network.tree.NetworkBookTree;
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)));
}
}
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"
));
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();
myCurrentTextModel.addControl(kind, start);
}
if (!start && (myHyperlinkReference.length() != 0) && (kind == myHyperlinkKind)) {
if (!start && myHyperlinkReference.length() != 0 && kind == myHyperlinkKind) {
myHyperlinkReference = "";
}
}
@ -113,6 +113,7 @@ public class BookReader {
}
public final void beginParagraph(byte kind) {
endParagraph();
final ZLTextWritableModel textModel = myCurrentTextModel;
if (textModel != null) {
textModel.createParagraph(kind);
@ -138,9 +139,9 @@ public class BookReader {
private final void insertEndParagraph(byte kind) {
final ZLTextWritableModel textModel = myCurrentTextModel;
if ((textModel != null) && mySectionContainsRegularContents) {
if (textModel != null && mySectionContainsRegularContents) {
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);
mySectionContainsRegularContents = false;
}
@ -189,9 +190,19 @@ public class BookReader {
}
public final void addData(char[] data, int offset, int length, boolean direct) {
if (!myTextParagraphExists || (length == 0)) {
if (!myTextParagraphExists || length == 0) {
return;
}
if (!myInsideTitle && !mySectionContainsRegularContents) {
while (length > 0 && Character.isWhitespace(data[offset])) {
--length;
++offset;
}
if (length == 0) {
return;
}
}
myTextParagraphIsNonEmpty = true;
if (direct && (myTextBufferLength == 0) && !myInsideTitle) {
@ -301,6 +312,10 @@ public class BookReader {
myContentsBuffer.append(data, offset, length);
}
}
public final boolean hasContentsData() {
return myContentsBuffer.length() > 0;
}
public final void beginContentsParagraph(int referenceNumber) {
beginContentsParagraph(Model.BookTextModel, referenceNumber);

View file

@ -89,6 +89,11 @@ public final class FBReaderApp extends ZLApplication {
final ZLStringOption ColorProfileOption =
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");
public final FBView BookTextView;
@ -324,15 +329,19 @@ public final class FBReaderApp extends ZLApplication {
public List<CancelActionDescription> getCancelActionsList() {
myCancelActionsList.clear();
final Book previousBook = Library.getPreviousBook();
if (previousBook != null) {
myCancelActionsList.add(new CancelActionDescription(
CancelActionType.previousBook, previousBook.getTitle()
));
if (ShowPreviousBookInCancelMenuOption.getValue()) {
final Book previousBook = Library.getPreviousBook();
if (previousBook != null) {
myCancelActionsList.add(new CancelActionDescription(
CancelActionType.previousBook, previousBook.getTitle()
));
}
}
if (Model != null && Model.Book != null) {
for (Bookmark bookmark : Bookmark.invisibleBookmarks(Model.Book)) {
myCancelActionsList.add(new BookmarkDescription(bookmark));
if (ShowPositionsInCancelMenuOption.getValue()) {
if (Model != null && Model.Book != null) {
for (Bookmark bookmark : Bookmark.invisibleBookmarks(Model.Book)) {
myCancelActionsList.add(new BookmarkDescription(bookmark));
}
}
}
myCancelActionsList.add(new CancelActionDescription(

View file

@ -171,6 +171,13 @@ public final class FB2Reader extends ZLXMLReaderAdapter {
case FB2Tag.BODY:
myBookReader.popKind();
myReadMainText = false;
if (myReadMainText) {
myBookReader.insertEndOfSectionParagraph();
}
if (mySectionDepth > 0) {
myBookReader.endContentsParagraph();
mySectionDepth = 0;
}
myBookReader.unsetCurrentTextModel();
break;
@ -308,16 +315,24 @@ public final class FB2Reader extends ZLXMLReaderAdapter {
myBookReader.pushKind(FBTextKind.TITLE);
} else {
myBookReader.pushKind(FBTextKind.SECTION_TITLE);
myInsideTitle = true;
myBookReader.enterTitle();
if (!myBookReader.hasContentsData()) {
myInsideTitle = true;
myBookReader.enterTitle();
}
}
break;
case FB2Tag.BODY:
++myBodyCounter;
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();
if (name != null) {
myBookReader.beginContentsParagraph();
myBookReader.addContentsData(name.toCharArray());
++mySectionDepth;
}
myReadMainText = true;
}
myBookReader.pushKind(FBTextKind.REGULAR);

View file

@ -32,9 +32,15 @@ class XHTMLTagParagraphWithControlAction extends XHTMLTagAction {
protected void doAtStart(XHTMLReader reader, ZLStringMap xmlattributes) {
final BookReader modelReader = reader.getModelReader();
if ((myControl == FBTextKind.TITLE) &&
(modelReader.Model.BookTextModel.getParagraphsNumber() > 1)) {
modelReader.insertEndOfSectionParagraph();
switch (myControl) {
case FBTextKind.TITLE:
case FBTextKind.H1:
case FBTextKind.H2:
if (modelReader.Model.BookTextModel.getParagraphsNumber() > 1) {
modelReader.insertEndOfSectionParagraph();
}
modelReader.enterTitle();
break;
}
modelReader.pushKind(myControl);
modelReader.beginParagraph();
@ -44,6 +50,13 @@ class XHTMLTagParagraphWithControlAction extends XHTMLTagAction {
final BookReader modelReader = reader.getModelReader();
modelReader.endParagraph();
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.
*
* @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) {
DisplayName = displayName.intern();
SortKey = sortKey.intern();
SortKey = sortKey != null ? sortKey.intern() : DisplayName.toLowerCase().intern();
}
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.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 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 enum CatalogType {
OTHER,
BY_AUTHOR,
BY_SERIES
}
public static final int FLAGS_DEFAULT =
FLAG_SHOW_AUTHOR |
FLAG_GROUP_MORE_THAN_1_BOOK_BY_SERIES;
public static final int FLAGS_GROUP =
FLAG_GROUP_BY_AUTHOR |
FLAG_GROUP_BY_SERIES |
FLAG_GROUP_MORE_THAN_1_BOOK_BY_SERIES;
// catalog accessibility types:
public static enum Accessibility {
@ -45,27 +49,8 @@ public abstract class NetworkCatalogItem extends NetworkItem {
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 CatalogType myCatalogType;
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);
}
public final int Flags;
/**
* 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 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 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);
myAccessibility = accessibility;
myCatalogType = catalogType;
URLByType = new TreeMap<Integer, String>(urlByType);
Flags = flags;
}
public Map<String,String> extraData() {
@ -109,10 +92,6 @@ public abstract class NetworkCatalogItem extends NetworkItem {
public void onDisplayItem() {
}
public final CatalogType getCatalogType() {
return myCatalogType;
}
public ZLBoolean3 getVisibility() {
final NetworkAuthenticationManager mgr = Link.authenticationManager();
switch (myAccessibility) {
@ -140,35 +119,5 @@ public abstract class NetworkCatalogItem extends NetworkItem {
}
}
/**
* 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);
}
public abstract String getStringId();
}

View file

@ -408,6 +408,9 @@ public class NetworkLibrary {
}
public NetworkTree getTreeByKey(NetworkTree.Key key) {
if (key == null) {
return null;
}
if (key.Parent == 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 {
private final List<NetworkItem> myChildren = new LinkedList<NetworkItem>();
private SortedCatalogItem(NetworkCatalogItem parent, ZLResource resource, List<NetworkItem> children) {
super(parent.Link, resource.getValue(), resource.getResource("summary").getValue(), "", parent.URLByType);
private SortedCatalogItem(NetworkCatalogItem parent, ZLResource resource, List<NetworkItem> children, int flags) {
super(parent.Link, resource.getValue(), resource.getResource("summary").getValue(), "", Accessibility.ALWAYS, flags);
for (NetworkItem child : children) {
if (accepts(child)) {
myChildren.add(child);
@ -51,8 +51,8 @@ abstract class SortedCatalogItem extends NetworkCatalogItem {
return item instanceof NetworkBookItem;
}
public SortedCatalogItem(NetworkCatalogItem parent, String resourceKey, List<NetworkItem> children) {
this(parent, ZLResource.resource("networkView").getResource(resourceKey), children);
public SortedCatalogItem(NetworkCatalogItem parent, String resourceKey, List<NetworkItem> children, int flags) {
this(parent, ZLResource.resource("networkView").getResource(resourceKey), children, flags);
}
@Override
@ -70,18 +70,23 @@ abstract class SortedCatalogItem extends NetworkCatalogItem {
class ByAuthorCatalogItem extends SortedCatalogItem {
ByAuthorCatalogItem(NetworkCatalogItem parent, List<NetworkItem> children) {
super(parent, "byAuthor", children);
super(parent, "byAuthor", children, FLAG_GROUP_BY_AUTHOR);
}
@Override
protected Comparator<NetworkItem> getComparator() {
return new NetworkBookItemComparator();
}
@Override
public String getStringId() {
return "@ByAuthor";
}
}
class ByTitleCatalogItem extends SortedCatalogItem {
ByTitleCatalogItem(NetworkCatalogItem parent, List<NetworkItem> children) {
super(parent, "byTitle", children);
super(parent, "byTitle", children, FLAG_SHOW_AUTHOR);
}
@Override
@ -92,11 +97,16 @@ class ByTitleCatalogItem extends SortedCatalogItem {
}
};
}
@Override
public String getStringId() {
return "@ByTitle";
}
}
class ByDateCatalogItem extends SortedCatalogItem {
ByDateCatalogItem(NetworkCatalogItem parent, List<NetworkItem> children) {
super(parent, "byDate", children);
super(parent, "byDate", children, FLAG_SHOW_AUTHOR);
}
@Override
@ -107,11 +117,16 @@ class ByDateCatalogItem extends SortedCatalogItem {
}
};
}
@Override
public String getStringId() {
return "@ByDate";
}
}
class BySeriesCatalogItem extends SortedCatalogItem {
BySeriesCatalogItem(NetworkCatalogItem parent, List<NetworkItem> children) {
super(parent, "bySeries", children);
super(parent, "bySeries", children, FLAG_SHOW_AUTHOR | FLAG_GROUP_BY_SERIES);
}
@Override
@ -135,13 +150,18 @@ class BySeriesCatalogItem extends SortedCatalogItem {
item instanceof NetworkBookItem &&
((NetworkBookItem)item).SeriesTitle != null;
}
@Override
public String getStringId() {
return "@BySeries";
}
}
public class LitResBookshelfItem extends NetworkCatalogItem {
public class LitResBookshelfItem extends NetworkURLCatalogItem {
private boolean myForceReload;
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
@ -174,7 +194,7 @@ public class LitResBookshelfItem extends NetworkCatalogItem {
listener.onNewItem(Link, item);
}
} 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 ByTitleCatalogItem(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 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

View file

@ -52,7 +52,6 @@ class LitResXMLReader extends LitResAuthenticationXMLReader {
private LinkedList<NetworkBookItem.AuthorData> myAuthors = new LinkedList<NetworkBookItem.AuthorData>();
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>();
public LitResXMLReader(INetworkLink link, List<NetworkItem> books) {
@ -122,11 +121,6 @@ class LitResXMLReader extends LitResAuthenticationXMLReader {
myBookId = attributes.getValue("hub_id");
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(
"https://robot.litres.ru/pages/catalit_download_book/?art=" + myBookId,
BookReference.Format.FB2_ZIP,
@ -238,7 +232,6 @@ class LitResXMLReader extends LitResAuthenticationXMLReader {
myIndexInSeries = 0;
myAuthors.clear();
myTags.clear();
myURLByType.clear();
myReferences.clear();
myState = CATALOG;
}

View file

@ -30,7 +30,7 @@ import org.geometerplus.fbreader.network.opds.OPDSCatalogItem;
public class BasketItem extends OPDSCatalogItem {
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();
}

View file

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

View file

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

View file

@ -37,7 +37,7 @@ import org.geometerplus.fbreader.network.*;
import org.geometerplus.fbreader.network.atom.ATOMUpdated;
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_UPDATE = 1;

View file

@ -290,28 +290,10 @@ class OPDSLinkXMLReader extends OPDSXMLReader implements OPDSConstants, MimeType
}
return false;
} else if (tag == FBREADER_REWRITING_RULE) {
final String type = attributes.getValue("type");
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));
((LinkReader)myFeedReader).addUrlRewritingRule(new URLRewritingRule(attributes));
return false;
} else if (tag == FBREADER_STABLE_IDENTIFIERS) {
((LinkReader) myFeedReader).setHasStableIdentifiers(true);
((LinkReader)myFeedReader).setHasStableIdentifiers(true);
return false;
} else if (tag == FBREADER_EXTRA) {
final String name = attributes.getValue("name");

View file

@ -27,7 +27,6 @@ import java.io.IOException;
import java.io.UnsupportedEncodingException;
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.ZLNetworkRequest;
@ -135,7 +134,7 @@ public class OPDSNetworkLink extends AbstractNetworkLink {
public NetworkCatalogItem libraryItem() {
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);
}
@ -144,17 +143,11 @@ public class OPDSNetworkLink extends AbstractNetworkLink {
}
public String rewriteUrl(String url, boolean isUrlExternal) {
final int apply = isUrlExternal
? URLRewritingRule.APPLY_EXTERNAL : URLRewritingRule.APPLY_INTERNAL;
for (URLRewritingRule rule: myUrlRewritingRules) {
if (rule.Apply != URLRewritingRule.APPLY_ALWAYS) {
if ((rule.Apply == URLRewritingRule.APPLY_EXTERNAL && !isUrlExternal)
|| (rule.Apply == URLRewritingRule.APPLY_INTERNAL && isUrlExternal)) {
continue;
}
}
switch (rule.Type) {
case URLRewritingRule.ADD_URL_PARAMETER:
url = ZLNetworkUtil.appendParameter(url, rule.Name, rule.Value);
break;
if ((rule.whereToApply() & apply) != 0) {
url = rule.apply(url);
}
}
return url;

View file

@ -19,40 +19,89 @@
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.ZLNetworkUtil;
import org.geometerplus.zlibrary.core.xml.ZLStringMap;
class URLRewritingRule {
// rule types:
public static final int ADD_URL_PARAMETER = 0;
public static final int REWRITE = 1;
public static final int UNKNOWN = 2;
// apply values:
public static final int APPLY_ALWAYS = 0;
public static final int APPLY_EXTERNAL = 1;
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;
public final int Apply;
public final String Name;
public final String Value;
private final HashMap<String,String> myParameters = new HashMap<String,String>();
public URLRewritingRule(int type, int apply, String name, String value) {
Type = type;
Apply = apply;
Name = name;
Value = value;
public URLRewritingRule(ZLStringMap map) {
for (int i = map.getSize() - 1; i >= 0; --i) {
final String key = map.getKey(i);
final String value = map.getValue(key);
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 String toString() {
return "Rule: {type=" + Type
+ "; apply=" + Apply
+ "; name=" + Name
+ "; value=" + Value
+ "}";
public int whereToApply() {
return myApply;
}
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
public boolean equals(Object o) {
if (this == o) {
@ -70,4 +119,5 @@ class URLRewritingRule {
}
return true;
}
*/
}

View file

@ -170,6 +170,6 @@ public class NetworkCatalogTree extends NetworkTree {
@Override
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.*;
public class NetworkTreeFactory {
public static NetworkTree createNetworkTree(NetworkCatalogTree parent, NetworkItem item) {
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");
}
final NetworkCatalogItem.CatalogType catalogType = parent.Item.getCatalogType();
final boolean showAuthors = catalogType != NetworkCatalogItem.CatalogType.BY_AUTHOR;
final NetworkBookItem book = (NetworkBookItem)item;
final int flags = parent.Item.Flags;
final boolean showAuthors = (flags & NetworkCatalogItem.FLAG_SHOW_AUTHOR) != 0;
NetworkBookItem book = (NetworkBookItem) item;
String seriesTitle = book.SeriesTitle;
if (seriesTitle == null || catalogType == NetworkCatalogItem.CatalogType.BY_SERIES) {
return new NetworkBookTree(parent, (NetworkBookItem) item, position, showAuthors);
}
if (position > 0) {
final NetworkTree previous = (NetworkTree) parent.subTrees().get(position - 1);
if (previous instanceof NetworkSeriesTree) {
final NetworkSeriesTree seriesTree = (NetworkSeriesTree) previous;
if (seriesTitle.equals(seriesTree.SeriesTitle)) {
seriesTree.invalidateChildren(); // call to update secondString
switch (flags & NetworkCatalogItem.FLAGS_GROUP) {
default:
return new NetworkBookTree(parent, book, position, showAuthors);
case NetworkCatalogItem.FLAG_GROUP_BY_SERIES:
if (book.SeriesTitle == null) {
return new NetworkBookTree(parent, book, position, showAuthors);
} else {
final NetworkTree previous = position > 0
? (NetworkTree)parent.subTrees().get(position - 1) : null;
NetworkSeriesTree seriesTree = null;
if (previous instanceof NetworkSeriesTree) {
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);
}
} else if (previous instanceof NetworkBookTree) {
final NetworkBookTree bookTree = (NetworkBookTree) previous;
final NetworkBookItem previousBook = bookTree.Book;
if (seriesTitle.equals(previousBook.SeriesTitle)) {
bookTree.removeSelf();
final NetworkSeriesTree seriesTree = new NetworkSeriesTree(parent, seriesTitle, --position, showAuthors);
new NetworkBookTree(seriesTree, previousBook, showAuthors);
return new NetworkBookTree(seriesTree, book, showAuthors);
case NetworkCatalogItem.FLAG_GROUP_MORE_THAN_1_BOOK_BY_SERIES:
if (position > 0 && book.SeriesTitle != null) {
final NetworkTree previous =
(NetworkTree)parent.subTrees().get(position - 1);
if (previous instanceof NetworkSeriesTree) {
final NetworkSeriesTree seriesTree = (NetworkSeriesTree)previous;
if (book.SeriesTitle.equals(seriesTree.SeriesTitle)) {
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) {
return new TopUpTree(parent, (TopUpItem)item);
}

View file

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