diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index c30317de6..4b7a628fc 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -131,9 +131,18 @@
-
+
+
+
+
+
+
+
+
+
+
diff --git a/AndroidManifest.xml.pattern b/AndroidManifest.xml.pattern
index b86275398..482ff9aca 100644
--- a/AndroidManifest.xml.pattern
+++ b/AndroidManifest.xml.pattern
@@ -131,9 +131,18 @@
-
+
+
+
+
+
+
+
+
+
+
diff --git a/ChangeLog b/ChangeLog
index 897575fef..bd1047a2e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,11 @@
-===== 0.99.14 (??? ??, 2011) =====
+===== 0.99.14 (Mar ??, 2011) =====
* Thai localization (by Samphan Pojanasophanakul)
* Fixed TTF font style detection
+* opds:// URLs support has been implemented
+* Unexpected search call has been fixed
+* Ignore case comparison for zip entry names
+* Fixed custom OPDS link search
+* Periodical update of custom links information has been added
===== 0.99.13 (Feb 13, 2011) =====
* Fixed book/position forgetting bug
diff --git a/TODO.CustomCatalog b/TODO.CustomCatalog
new file mode 100644
index 000000000..47360a95c
--- /dev/null
+++ b/TODO.CustomCatalog
@@ -0,0 +1 @@
+* start FBReader in new task
diff --git a/TODO.network b/TODO.network
index 088b8dd55..131e829d9 100644
--- a/TODO.network
+++ b/TODO.network
@@ -1,3 +1,27 @@
+DONE show 'empty basket' message without opening of catalog
+* update basket view if basket content is changed
+* basket summary
+DONE show recommendation item if basket is not empty
+* new actions in main menu: clear; buy all
+* update recommendations list after each basket updating/purchasing
+* update recommendations list visibility after each basket updating/purchasing
+* remove book from basket on purchasing
+
+* search item behaviour like search item in local library
+* separate search for each catalog (if search URL is presented)
+* menu search button should be available for all catalog levels
+
+* float point numbers as series index
+* replace AuthenticationCatalog by AuthenticationActivity
+* 'recently visited catalogs' item
+* load search URL for catalogs from these catalogs, not from our generic file
+DONE show library name in network book activity
+
+* litres: credit card top up
+* litres: terminal (?) top up
+* litres: similar books link
+
+------------------------------
NP: оповещение об изменениях в namespace'ах происходит после того,
как был обработан тег, объявляющий эти namespace'ы... Нужно сделать:
@@ -5,22 +29,8 @@ NP: оповещение об изменениях в namespace'ах проис
2) вызов namespaceMapChangedHandler после вызова endElementHandler
3) вызов namespaceMapChangedHandler для пустых тегов
-** Записать изменения в ChangeLog
-
-DONE Network library: Объединять книги по сериям
- ** в сериях книги нужно сортировать по индексу
- NP: а где это происходит???
-
-DONE Возможность открывать локальные файлы из всяких файл-менеджеров
-DONE На этой странице есть ссылка на epub-файл "для ПК". http://www.zone4iphone.ru/index.php?p_id=7&b_id=18413
- Проверить скачивание книги браузером и возможность чтения из папки, куда файл был скачан.
- DONE добавлять в библиотеку (сделать таблицу добавленных вручную книг)
-
------------------------------
-** пополнение счета в litres с помощью sms
- ** сделать как "подкаталог" для элемента "пополнить счет"
-
** восстановление пароля (use default e-mail)
** сделать отдельную ветку (?) для скачанных samples
** (?) удалять sample при покупке/скачивании полного варианта
@@ -57,5 +67,4 @@ DELAYED что делать, когда мало памяти???
-----------------------------
другое:
-DONE layout для китайских текстов
* поддержка hufdic в mobipocket
diff --git a/assets/resources/application/cs.xml b/assets/resources/application/cs.xml
index a3eba2f15..7a7f4d190 100644
--- a/assets/resources/application/cs.xml
+++ b/assets/resources/application/cs.xml
@@ -47,6 +47,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
@@ -57,6 +69,8 @@
+
+
@@ -109,6 +123,7 @@
+
@@ -559,10 +574,6 @@
-
-
-
-
@@ -576,7 +587,7 @@
-
+
@@ -610,6 +621,8 @@
+
+
diff --git a/assets/resources/application/de.xml b/assets/resources/application/de.xml
index a5f4ef6ae..2a27a143a 100644
--- a/assets/resources/application/de.xml
+++ b/assets/resources/application/de.xml
@@ -48,6 +48,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
@@ -58,6 +70,8 @@
+
+
@@ -110,6 +124,7 @@
+
@@ -560,10 +575,6 @@
-
-
-
-
@@ -577,7 +588,7 @@
-
+
@@ -611,6 +622,8 @@
+
+
diff --git a/assets/resources/application/en.xml b/assets/resources/application/en.xml
index 3bbcc3115..ef99c9fd1 100644
--- a/assets/resources/application/en.xml
+++ b/assets/resources/application/en.xml
@@ -46,6 +46,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
@@ -56,6 +68,8 @@
+
+
@@ -66,6 +80,8 @@
+
+
@@ -97,6 +113,8 @@
+
+
@@ -108,6 +126,7 @@
+
@@ -568,10 +587,6 @@
-
-
-
-
@@ -585,7 +600,7 @@
-
+
@@ -619,6 +634,8 @@
+
+
diff --git a/assets/resources/application/fr.xml b/assets/resources/application/fr.xml
index f9bd3390f..d3a53d408 100644
--- a/assets/resources/application/fr.xml
+++ b/assets/resources/application/fr.xml
@@ -50,6 +50,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
@@ -60,6 +72,8 @@
+
+
@@ -112,6 +126,7 @@
+
@@ -562,10 +577,6 @@
-
-
-
-
@@ -579,7 +590,7 @@
-
+
@@ -613,6 +624,8 @@
+
+
diff --git a/assets/resources/application/gl.xml b/assets/resources/application/gl.xml
index 9fabc7324..9692dba8d 100644
--- a/assets/resources/application/gl.xml
+++ b/assets/resources/application/gl.xml
@@ -47,6 +47,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
@@ -57,6 +69,8 @@
+
+
@@ -109,6 +123,7 @@
+
@@ -559,10 +574,6 @@
-
-
-
-
@@ -576,7 +587,7 @@
-
+
@@ -610,6 +621,8 @@
+
+
diff --git a/assets/resources/application/hu.xml b/assets/resources/application/hu.xml
index 9a514b903..2728284d9 100644
--- a/assets/resources/application/hu.xml
+++ b/assets/resources/application/hu.xml
@@ -47,6 +47,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
@@ -57,6 +69,8 @@
+
+
@@ -109,6 +123,7 @@
+
@@ -559,10 +574,6 @@
-
-
-
-
@@ -576,7 +587,7 @@
-
+
@@ -610,6 +621,8 @@
+
+
diff --git a/assets/resources/application/it.xml b/assets/resources/application/it.xml
index 677225789..1a886d7d4 100644
--- a/assets/resources/application/it.xml
+++ b/assets/resources/application/it.xml
@@ -47,6 +47,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
@@ -57,6 +69,8 @@
+
+
@@ -109,6 +123,7 @@
+
@@ -559,10 +574,6 @@
-
-
-
-
@@ -576,7 +587,7 @@
-
+
@@ -610,6 +621,8 @@
+
+
diff --git a/assets/resources/application/nl.xml b/assets/resources/application/nl.xml
index 937e00481..eb64c7c63 100644
--- a/assets/resources/application/nl.xml
+++ b/assets/resources/application/nl.xml
@@ -47,6 +47,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
@@ -57,6 +69,8 @@
+
+
@@ -109,6 +123,7 @@
+
@@ -559,10 +574,6 @@
-
-
-
-
@@ -576,7 +587,7 @@
-
+
@@ -610,6 +621,8 @@
+
+
diff --git a/assets/resources/application/ru.xml b/assets/resources/application/ru.xml
index b6b34d4da..e6e5b7b36 100644
--- a/assets/resources/application/ru.xml
+++ b/assets/resources/application/ru.xml
@@ -46,6 +46,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
@@ -56,6 +68,8 @@
+
+
@@ -108,6 +122,7 @@
+
@@ -558,10 +573,6 @@
-
-
-
-
@@ -575,7 +586,7 @@
-
+
@@ -609,6 +620,8 @@
+
+
diff --git a/assets/resources/application/th.xml b/assets/resources/application/th.xml
index bcb0e5941..315cbb2e2 100644
--- a/assets/resources/application/th.xml
+++ b/assets/resources/application/th.xml
@@ -47,6 +47,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
@@ -57,6 +69,8 @@
+
+
@@ -109,6 +123,7 @@
+
@@ -237,12 +252,12 @@
-
-
+
+
-
-
-
+
+
+
@@ -559,10 +574,6 @@
-
-
-
-
@@ -576,7 +587,7 @@
-
+
@@ -610,6 +621,8 @@
+
+
diff --git a/assets/resources/application/uk.xml b/assets/resources/application/uk.xml
index cd76fe5b3..69b79ffa3 100644
--- a/assets/resources/application/uk.xml
+++ b/assets/resources/application/uk.xml
@@ -47,6 +47,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
@@ -57,6 +69,8 @@
+
+
@@ -109,6 +123,7 @@
+
@@ -559,10 +574,6 @@
-
-
-
-
@@ -576,7 +587,7 @@
-
+
@@ -610,6 +621,8 @@
+
+
diff --git a/assets/resources/application/vi.xml b/assets/resources/application/vi.xml
index c4ecfcbbf..aaa724007 100644
--- a/assets/resources/application/vi.xml
+++ b/assets/resources/application/vi.xml
@@ -47,6 +47,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
@@ -57,6 +69,8 @@
+
+
@@ -109,6 +123,7 @@
+
@@ -559,10 +574,6 @@
-
-
-
-
@@ -576,7 +587,7 @@
-
+
@@ -610,6 +621,8 @@
+
+
diff --git a/assets/resources/application/zh.xml b/assets/resources/application/zh.xml
index 67be67fbd..f58b8e38f 100644
--- a/assets/resources/application/zh.xml
+++ b/assets/resources/application/zh.xml
@@ -47,6 +47,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
@@ -57,6 +69,8 @@
+
+
@@ -109,6 +123,7 @@
+
@@ -559,10 +574,6 @@
-
-
-
-
@@ -576,7 +587,7 @@
-
+
@@ -610,6 +621,8 @@
+
+
diff --git a/assets/resources/zlibrary/th.xml b/assets/resources/zlibrary/th.xml
index 21594c60b..16a07e026 100644
--- a/assets/resources/zlibrary/th.xml
+++ b/assets/resources/zlibrary/th.xml
@@ -75,7 +75,7 @@
-
+
diff --git a/icons/library/ic_list_library_wallet.png b/icons/library/ic_list_library_wallet.png
deleted file mode 100644
index 020dbc4ba..000000000
Binary files a/icons/library/ic_list_library_wallet.png and /dev/null differ
diff --git a/res/layout/network_custom_catalog_dialog.xml b/res/layout/add_custom_catalog.xml
similarity index 60%
rename from res/layout/network_custom_catalog_dialog.xml
rename to res/layout/add_custom_catalog.xml
index 29d9592be..40823bcfa 100644
--- a/res/layout/network_custom_catalog_dialog.xml
+++ b/res/layout/add_custom_catalog.xml
@@ -1,6 +1,5 @@
@@ -12,124 +11,124 @@
android:orientation="vertical"
>
+
+
+
+
diff --git a/res/layout/network_book.xml b/res/layout/network_book.xml
index 82f540d0d..034318973 100644
--- a/res/layout/network_book.xml
+++ b/res/layout/network_book.xml
@@ -101,116 +101,12 @@
android:paddingRight="10dp"
android:paddingTop="10dp"
>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
myFileHeaders = new LinkedHashMap();
+ private final LinkedHashMap myFileHeaders = new LinkedHashMap() {
+ @Override
+ public LocalFileHeader get(Object key) {
+ return super.get(((String)key).toLowerCase());
+ }
+
+ @Override
+ public LocalFileHeader put(String key, LocalFileHeader value) {
+ return super.put(key.toLowerCase(), value);
+ }
+ };
private boolean myAllFilesAreRead;
@@ -50,7 +60,7 @@ public final class ZipFile {
}
if (header.FileName != null) {
myFileHeaders.put(header.FileName, header);
- if (header.FileName.equals(fileToFind)) {
+ if (header.FileName.equalsIgnoreCase(fileToFind)) {
return true;
}
}
diff --git a/src/org/geometerplus/android/fbreader/BookInfoActivity.java b/src/org/geometerplus/android/fbreader/BookInfoActivity.java
index 0c67650d5..3e00616e5 100644
--- a/src/org/geometerplus/android/fbreader/BookInfoActivity.java
+++ b/src/org/geometerplus/android/fbreader/BookInfoActivity.java
@@ -149,7 +149,7 @@ public class BookInfoActivity extends Activity {
}
private void setupInfoPair(int id, String key, CharSequence value) {
- LinearLayout layout = (LinearLayout)findViewById(id);
+ final LinearLayout layout = (LinearLayout)findViewById(id);
if (value == null || value.length() == 0) {
layout.setVisibility(View.GONE);
return;
diff --git a/src/org/geometerplus/android/fbreader/CancelActivity.java b/src/org/geometerplus/android/fbreader/CancelActivity.java
index b207e23a0..7582233c2 100644
--- a/src/org/geometerplus/android/fbreader/CancelActivity.java
+++ b/src/org/geometerplus/android/fbreader/CancelActivity.java
@@ -77,12 +77,12 @@ public class CancelActivity extends ListActivity {
if (summary != null) {
summaryView.setVisibility(View.VISIBLE);
summaryView.setText(summary);
- titleView.setLayoutParams(new LinearLayout.LayoutParams(
+ titleView.setLayoutParams(new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.FILL_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT
));
} else {
summaryView.setVisibility(View.GONE);
- titleView.setLayoutParams(new LinearLayout.LayoutParams(
+ titleView.setLayoutParams(new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.FILL_PARENT, LinearLayout.LayoutParams.FILL_PARENT
));
}
diff --git a/src/org/geometerplus/android/fbreader/FBReader.java b/src/org/geometerplus/android/fbreader/FBReader.java
index c2300ecac..e3b86637d 100644
--- a/src/org/geometerplus/android/fbreader/FBReader.java
+++ b/src/org/geometerplus/android/fbreader/FBReader.java
@@ -20,6 +20,7 @@
package org.geometerplus.android.fbreader;
import android.app.SearchManager;
+import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
@@ -27,7 +28,6 @@ import android.os.Handler;
import android.os.Message;
import android.view.Menu;
import android.view.WindowManager;
-import android.view.Window;
import android.widget.RelativeLayout;
import org.geometerplus.zlibrary.core.filesystem.ZLFile;
@@ -152,6 +152,7 @@ public final class FBReader extends ZLAndroidActivity {
}
};
UIUtil.wait("search", runnable, this);
+ startActivity(new Intent(this, getClass()));
} else {
super.onNewIntent(intent);
}
diff --git a/src/org/geometerplus/android/fbreader/SQLiteBooksDatabase.java b/src/org/geometerplus/android/fbreader/SQLiteBooksDatabase.java
index 1cf0de390..036dc517f 100644
--- a/src/org/geometerplus/android/fbreader/SQLiteBooksDatabase.java
+++ b/src/org/geometerplus/android/fbreader/SQLiteBooksDatabase.java
@@ -37,6 +37,7 @@ import org.geometerplus.zlibrary.text.view.ZLTextFixedPosition;
import org.geometerplus.fbreader.library.*;
import org.geometerplus.android.util.UIUtil;
+import org.geometerplus.android.util.SQLiteUtil;
public final class SQLiteBooksDatabase extends BooksDatabase {
private final String myInstanceId;
@@ -107,29 +108,6 @@ public final class SQLiteBooksDatabase extends BooksDatabase {
}, context);
}
- private static void bindString(SQLiteStatement statement, int index, String value) {
- if (value != null) {
- statement.bindString(index, value);
- } else {
- statement.bindNull(index);
- }
- }
-
- private static void bindDate(SQLiteStatement statement, int index, Date value) {
- if (value != null) {
- statement.bindLong(index, value.getTime());
- } else {
- statement.bindNull(index);
- }
- }
-
- private static Date getDate(Cursor cursor, int index) {
- if (cursor.isNull(index)) {
- return null;
- }
- return new Date(cursor.getLong(index));
- }
-
@Override
protected Book loadBook(long bookId) {
Book book = null;
@@ -278,8 +256,8 @@ public final class SQLiteBooksDatabase extends BooksDatabase {
);
}
myUpdateBookInfoStatement.bindLong(1, fileId);
- bindString(myUpdateBookInfoStatement, 2, encoding);
- bindString(myUpdateBookInfoStatement, 3, language);
+ SQLiteUtil.bindString(myUpdateBookInfoStatement, 2, encoding);
+ SQLiteUtil.bindString(myUpdateBookInfoStatement, 3, language);
myUpdateBookInfoStatement.bindString(4, title);
myUpdateBookInfoStatement.bindLong(5, bookId);
myUpdateBookInfoStatement.execute();
@@ -292,8 +270,8 @@ public final class SQLiteBooksDatabase extends BooksDatabase {
"INSERT OR IGNORE INTO Books (encoding,language,title,file_id) VALUES (?,?,?,?)"
);
}
- bindString(myInsertBookInfoStatement, 1, encoding);
- bindString(myInsertBookInfoStatement, 2, language);
+ SQLiteUtil.bindString(myInsertBookInfoStatement, 1, encoding);
+ SQLiteUtil.bindString(myInsertBookInfoStatement, 2, language);
myInsertBookInfoStatement.bindString(3, title);
final FileInfoSet infoSet = new FileInfoSet(file);
myInsertBookInfoStatement.bindLong(4, infoSet.getId(file));
@@ -709,9 +687,9 @@ public final class SQLiteBooksDatabase extends BooksDatabase {
cursor.getLong(1),
cursor.getString(2),
cursor.getString(3),
- getDate(cursor, 4),
- getDate(cursor, 5),
- getDate(cursor, 6),
+ SQLiteUtil.getDate(cursor, 4),
+ SQLiteUtil.getDate(cursor, 5),
+ SQLiteUtil.getDate(cursor, 6),
(int)cursor.getLong(7),
cursor.getString(8),
(int)cursor.getLong(9),
@@ -737,9 +715,9 @@ public final class SQLiteBooksDatabase extends BooksDatabase {
cursor.getLong(1),
cursor.getString(2),
cursor.getString(3),
- getDate(cursor, 4),
- getDate(cursor, 5),
- getDate(cursor, 6),
+ SQLiteUtil.getDate(cursor, 4),
+ SQLiteUtil.getDate(cursor, 5),
+ SQLiteUtil.getDate(cursor, 6),
(int)cursor.getLong(7),
cursor.getString(8),
(int)cursor.getLong(9),
@@ -775,11 +753,11 @@ public final class SQLiteBooksDatabase extends BooksDatabase {
statement.bindLong(1, bookmark.getBookId());
statement.bindString(2, bookmark.getText());
- bindDate(statement, 3, bookmark.getTime(Bookmark.CREATION));
- bindDate(statement, 4, bookmark.getTime(Bookmark.MODIFICATION));
- bindDate(statement, 5, bookmark.getTime(Bookmark.ACCESS));
+ SQLiteUtil.bindDate(statement, 3, bookmark.getTime(Bookmark.CREATION));
+ SQLiteUtil.bindDate(statement, 4, bookmark.getTime(Bookmark.MODIFICATION));
+ SQLiteUtil.bindDate(statement, 5, bookmark.getTime(Bookmark.ACCESS));
statement.bindLong(6, bookmark.getAccessCount());
- bindString(statement, 7, bookmark.ModelId);
+ SQLiteUtil.bindString(statement, 7, bookmark.ModelId);
statement.bindLong(8, bookmark.ParagraphIndex);
statement.bindLong(9, bookmark.ElementIndex);
statement.bindLong(10, bookmark.CharIndex);
diff --git a/src/org/geometerplus/android/fbreader/image/ImageViewActivity.java b/src/org/geometerplus/android/fbreader/image/ImageViewActivity.java
index 0f91fc5e5..a1c19596a 100644
--- a/src/org/geometerplus/android/fbreader/image/ImageViewActivity.java
+++ b/src/org/geometerplus/android/fbreader/image/ImageViewActivity.java
@@ -53,7 +53,7 @@ public class ImageViewActivity extends Activity {
setContentView(new ImageView());
final Uri uri = getIntent().getData();
- if ("imagefile".equals(uri.getScheme())) {
+ if (ZLFileImage.SCHEME.equals(uri.getScheme())) {
try {
final String[] data = uri.getPath().split("\000");
final ZLFileImage image = new ZLFileImage(
diff --git a/src/org/geometerplus/android/fbreader/network/AddCustomCatalogActivity.java b/src/org/geometerplus/android/fbreader/network/AddCustomCatalogActivity.java
new file mode 100644
index 000000000..0326fac4d
--- /dev/null
+++ b/src/org/geometerplus/android/fbreader/network/AddCustomCatalogActivity.java
@@ -0,0 +1,275 @@
+/*
+ * Copyright (C) 2010-2011 Geometer Plus
+ *
+ * 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 java.util.HashMap;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Bundle;
+import android.view.View;
+import android.view.inputmethod.InputMethodManager;
+import android.widget.Button;
+import android.widget.TextView;
+
+import org.geometerplus.zlibrary.core.resources.ZLResource;
+import org.geometerplus.zlibrary.core.network.ZLNetworkException;
+
+import org.geometerplus.zlibrary.ui.android.R;
+
+import org.geometerplus.fbreader.network.*;
+import org.geometerplus.fbreader.network.opds.OPDSCustomLink;
+
+import org.geometerplus.android.util.UIUtil;
+
+public class AddCustomCatalogActivity extends Activity {
+ private ZLResource myResource;
+ private volatile ICustomNetworkLink myLink;
+
+ @Override
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+ Thread.setDefaultUncaughtExceptionHandler(new org.geometerplus.zlibrary.ui.android.library.UncaughtExceptionHandler(this));
+ setContentView(R.layout.add_custom_catalog);
+
+ myResource = ZLResource.resource("dialog").getResource("CustomCatalogDialog");
+
+ setTitle(myResource.getResource("title").getValue());
+
+ setTextFromResource(R.id.add_custom_catalog_title_label, "catalogTitle");
+ setTextFromResource(R.id.add_custom_catalog_url_label, "catalogUrl");
+ setTextFromResource(R.id.add_custom_catalog_summary_label, "catalogSummary");
+ setTextFromResource(R.id.add_custom_catalog_title_example, "catalogTitleExample");
+ setTextFromResource(R.id.add_custom_catalog_url_example, "catalogUrlExample");
+ setTextFromResource(R.id.add_custom_catalog_summary_example, "catalogSummaryExample");
+
+ setupButton(
+ R.id.add_custom_catalog_ok_button, "ok", new View.OnClickListener() {
+ public void onClick(View view) {
+ final InputMethodManager imm =
+ (InputMethodManager)getSystemService(INPUT_METHOD_SERVICE);
+ imm.hideSoftInputFromWindow(findViewById(R.id.add_custom_catalog_url).getWindowToken(), 0);
+ imm.hideSoftInputFromWindow(findViewById(R.id.add_custom_catalog_title).getWindowToken(), 0);
+ imm.hideSoftInputFromWindow(findViewById(R.id.add_custom_catalog_summary).getWindowToken(), 0);
+ onOkButton();
+ }
+ }
+ );
+ setupButton(
+ R.id.add_custom_catalog_cancel_button, "cancel", new View.OnClickListener() {
+ public void onClick(View view) {
+ finish();
+ }
+ }
+ );
+
+ final Intent intent = getIntent();
+ myLink = NetworkLibraryActivity.getLinkFromIntent(intent);
+ final Uri uri = intent.getData();
+
+ if (myLink != null) {
+ setTextById(R.id.add_custom_catalog_url, myLink.getUrlInfo(INetworkLink.URL_MAIN).URL);
+ setTextById(R.id.add_custom_catalog_title, myLink.getTitle());
+ setTextById(R.id.add_custom_catalog_summary, myLink.getSummary());
+ setExtraFieldsVisibility(true);
+ } else if (uri != null) {
+ loadInfoByUri(uri);
+ } else {
+ setExtraFieldsVisibility(false);
+ }
+ }
+
+ private void onOkButton() {
+ final String textUrl = getTextById(R.id.add_custom_catalog_url);
+ if (isEmptyString(textUrl)) {
+ setErrorByKey("urlIsEmpty");
+ return;
+ }
+
+ final String title = getTextById(R.id.add_custom_catalog_title);
+ final String summary = getTextById(R.id.add_custom_catalog_summary);
+ Uri uri = null;
+ try {
+ uri = Uri.parse(textUrl);
+ if (isEmptyString(uri.getScheme())) {
+ uri = Uri.parse("http://" + textUrl);
+ }
+ if (isEmptyString(uri.getHost())) {
+ setErrorByKey("invalidUrl");
+ return;
+ }
+ } catch (Throwable t) {
+ setErrorByKey("invalidUrl");
+ return;
+ }
+ if (myLink == null) {
+ loadInfoByUri(uri);
+ } else if (isEmptyString(title)) {
+ setErrorByKey("titleIsEmpty");
+ } else {
+ myLink.setTitle(title);
+ myLink.setSummary(summary);
+
+ Intent intent = new Intent(
+ NetworkLibraryActivity.ADD_CATALOG,
+ uri,
+ AddCustomCatalogActivity.this,
+ NetworkLibraryActivity.class
+ ).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
+ NetworkLibraryActivity.addLinkToIntent(intent, myLink);
+ startActivity(intent);
+ finish();
+ }
+ }
+
+ private boolean isEmptyString(String s) {
+ return s == null || s.length() == 0;
+ }
+
+ private void setExtraFieldsVisibility(boolean show) {
+ final int visibility = show ? View.VISIBLE : View.GONE;
+ runOnUiThread(new Runnable() {
+ public void run() {
+ findViewById(R.id.add_custom_catalog_title_group).setVisibility(visibility);
+ findViewById(R.id.add_custom_catalog_summary_group).setVisibility(visibility);
+ }
+ });
+ }
+
+ private void setTextById(int id, String text) {
+ ((TextView)findViewById(id)).setText(text);
+ }
+
+ private String getTextById(int id) {
+ final String text = ((TextView)findViewById(id)).getText().toString();
+ return text != null ? text.trim() : null;
+ }
+
+ private void setupButton(int id, String resourceKey, View.OnClickListener listener) {
+ final Button button = (Button)findViewById(id);
+ button.setText(
+ ZLResource.resource("dialog").getResource("button").getResource(resourceKey).getValue()
+ );
+ button.setOnClickListener(listener);
+ }
+
+ private void setTextFromResource(int id, String resourceKey) {
+ setTextById(id, myResource.getResource(resourceKey).getValue());
+ }
+
+ private void setErrorText(final String errorText) {
+ runOnUiThread(new Runnable() {
+ public void run() {
+ final TextView errorView = (TextView)findViewById(R.id.add_custom_catalog_error);
+ if (errorText != null) {
+ errorView.setText(errorText);
+ errorView.setVisibility(View.VISIBLE);
+ } else {
+ errorView.setVisibility(View.GONE);
+ }
+ }
+ });
+ }
+
+ private void setErrorByKey(final String resourceKey) {
+ setErrorText(myResource.getResource(resourceKey).getValue());
+ }
+
+ private void runErrorDialog(final String errorText) {
+ final DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ switch (which) {
+ case DialogInterface.BUTTON_POSITIVE:
+ setExtraFieldsVisibility(true);
+ break;
+ case DialogInterface.BUTTON_NEUTRAL:
+ break;
+ case DialogInterface.BUTTON_NEGATIVE:
+ AddCustomCatalogActivity.this.finish();
+ break;
+ }
+ }
+ };
+
+ final ZLResource dialogResource = ZLResource.resource("dialog");
+ final ZLResource boxResource = dialogResource.getResource("networkError");
+ final ZLResource buttonResource = dialogResource.getResource("button");
+ new AlertDialog.Builder(this)
+ .setTitle(boxResource.getResource("title").getValue())
+ .setMessage(errorText)
+ .setIcon(0)
+ .setPositiveButton(buttonResource.getResource("continue").getValue(), listener)
+ .setNeutralButton(buttonResource.getResource("editUrl").getValue(), listener)
+ .setNegativeButton(buttonResource.getResource("cancel").getValue(), listener)
+ .create().show();
+ }
+
+ private void loadInfoByUri(Uri uri) {
+ String textUrl = uri.toString();
+ if (isEmptyString(uri.getScheme())) {
+ textUrl = "http://" + textUrl;
+ uri = Uri.parse(textUrl);
+ } else if ("opds".equals(uri.getScheme())) {
+ textUrl = "http" + uri.toString().substring(4);
+ }
+
+ setTextById(R.id.add_custom_catalog_url, textUrl);
+ final String siteName = uri.getHost();
+ if (isEmptyString(siteName)) {
+ setErrorByKey("invalidUrl");
+ return;
+ }
+ final HashMap infos = new HashMap();
+ infos.put(INetworkLink.URL_MAIN, new UrlInfo(textUrl));
+ myLink = new OPDSCustomLink(
+ ICustomNetworkLink.INVALID_ID, siteName, null, null, infos
+ );
+
+ final Runnable loadInfoRunnable = new Runnable() {
+ private String myError;
+
+ public void run() {
+ try {
+ myError = null;
+ myLink.reloadInfo(false);
+ } catch (ZLNetworkException e) {
+ myError = e.getMessage();
+ }
+ runOnUiThread(new Runnable() {
+ public void run() {
+ if (myError == null) {
+ setTextById(R.id.add_custom_catalog_title, myLink.getTitle());
+ setTextById(R.id.add_custom_catalog_summary, myLink.getSummary());
+ setExtraFieldsVisibility(true);
+ } else {
+ runErrorDialog(myError);
+ myLink = null;
+ }
+ }
+ });
+ setErrorText(myError);
+ }
+ };
+ UIUtil.wait("loadingCatalogInfo", loadInfoRunnable, this);
+ }
+}
diff --git a/src/org/geometerplus/android/fbreader/network/AddCustomCatalogItemActions.java b/src/org/geometerplus/android/fbreader/network/AddCustomCatalogItemActions.java
index d8ef4aedf..fb1d6da1f 100644
--- a/src/org/geometerplus/android/fbreader/network/AddCustomCatalogItemActions.java
+++ b/src/org/geometerplus/android/fbreader/network/AddCustomCatalogItemActions.java
@@ -20,14 +20,14 @@
package org.geometerplus.android.fbreader.network;
import android.app.Activity;
+import android.content.Intent;
import android.view.Menu;
import android.view.ContextMenu;
import org.geometerplus.fbreader.network.NetworkTree;
-
+import org.geometerplus.fbreader.network.tree.AddCustomCatalogItemTree;
class AddCustomCatalogItemActions extends NetworkTreeActions {
-
public static final int RUN_ITEM_ID = 0;
@Override
@@ -70,6 +70,6 @@ class AddCustomCatalogItemActions extends NetworkTreeActions {
}
public static void addCustomCatalog(Activity activity) {
- NetworkDialog.show(activity, NetworkDialog.DIALOG_CUSTOM_CATALOG, null, null);
+ activity.startActivity(new Intent(activity, AddCustomCatalogActivity.class));
}
}
diff --git a/src/org/geometerplus/android/fbreader/network/AuthenticationDialog.java b/src/org/geometerplus/android/fbreader/network/AuthenticationDialog.java
index 7e7b1d0cb..5d4bc5dbb 100644
--- a/src/org/geometerplus/android/fbreader/network/AuthenticationDialog.java
+++ b/src/org/geometerplus/android/fbreader/network/AuthenticationDialog.java
@@ -19,44 +19,103 @@
package org.geometerplus.android.fbreader.network;
-import android.app.Dialog;
+import android.app.Activity;
import android.app.AlertDialog;
+import android.app.Dialog;
import android.content.DialogInterface;
+import android.os.Handler;
+import android.os.Message;
import android.view.View;
import android.widget.TextView;
-import org.geometerplus.zlibrary.ui.android.R;
-
+import org.geometerplus.zlibrary.core.resources.ZLResource;
import org.geometerplus.zlibrary.core.network.ZLNetworkException;
+import org.geometerplus.zlibrary.ui.android.R;
+
+import org.geometerplus.fbreader.network.INetworkLink;
+import org.geometerplus.fbreader.network.NetworkLibrary;
import org.geometerplus.fbreader.network.authentication.NetworkAuthenticationManager;
import org.geometerplus.android.util.UIUtil;
+class AuthenticationDialog {
+ private static AuthenticationDialog ourDialog;
-class AuthenticationDialog extends NetworkDialog {
- public AuthenticationDialog() {
- super("AuthenticationDialog");
+ public static AuthenticationDialog getDialog() {
+ if (ourDialog == null) {
+ ourDialog = new AuthenticationDialog();
+ }
+ return ourDialog;
}
- @Override
- protected void clearData() {
+ private class DialogHandler extends Handler {
+ @Override
+ public void handleMessage(Message message) {
+ if (!NetworkView.Instance().isInitialized()) {
+ return;
+ }
+ final NetworkLibrary library = NetworkLibrary.Instance();
+ library.invalidateVisibility();
+ library.synchronize();
+ NetworkView.Instance().fireModelChanged();
+ if (message.what == -1) {
+ myErrorMessage = (String)message.obj;
+ myActivity.showDialog(0);
+ } else if (message.what == 1) {
+ if (myOnSuccessRunnable != null) {
+ myOnSuccessRunnable.run();
+ }
+ }
+ }
+ };
+
+
+ private final ZLResource myResource =
+ ZLResource.resource("dialog").getResource("AuthenticationDialog");
+
+ private INetworkLink myLink;
+ private String myErrorMessage;
+ private Runnable myOnSuccessRunnable;
+ private Activity myActivity;
+
+ private final DialogHandler myHandler = new DialogHandler();
+
+ public static void show(Activity activity, INetworkLink link, Runnable onSuccessRunnable) {
+ getDialog().showInternal(activity, link, onSuccessRunnable);
}
- @Override
- public View createLayout() {
+ private void showInternal(Activity activity, INetworkLink link, Runnable onSuccessRunnable) {
+ myLink = link;
+ myErrorMessage = null;
+ myOnSuccessRunnable = onSuccessRunnable;
+ activity.showDialog(0);
+ }
+
+ private void sendSuccess() {
+ myHandler.sendMessage(myHandler.obtainMessage(1, null));
+ }
+
+ private void sendCancel() {
+ myHandler.sendMessage(myHandler.obtainMessage(0, null));
+ }
+
+ private void sendError(String message) {
+ myHandler.sendMessage(myHandler.obtainMessage(-1, message));
+ }
+
+ private View createLayout() {
final View layout = myActivity.getLayoutInflater().inflate(R.layout.network_authentication_dialog, null);
- ((TextView) layout.findViewById(R.id.network_authentication_login_text)).setText(myResource.getResource("login").getValue());
- ((TextView) layout.findViewById(R.id.network_authentication_password_text)).setText(myResource.getResource("password").getValue());
+ ((TextView)layout.findViewById(R.id.network_authentication_login_text)).setText(myResource.getResource("login").getValue());
+ ((TextView)layout.findViewById(R.id.network_authentication_password_text)).setText(myResource.getResource("password").getValue());
- final TextView registerText = (TextView) layout.findViewById(R.id.network_authentication_register);
+ final TextView registerText = (TextView)layout.findViewById(R.id.network_authentication_register);
registerText.setText(myResource.getResource("register").getValue());
registerText.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
- //final NetworkAuthenticationManager mgr = myLink.authenticationManager();
if (Util.isRegistrationSupported(myActivity, myLink)) {
- myActivity.dismissDialog(NetworkDialog.DIALOG_AUTHENTICATION);
+ myActivity.dismissDialog(0);
Util.runRegistrationDialog(myActivity, myLink);
}
}
@@ -64,15 +123,14 @@ class AuthenticationDialog extends NetworkDialog {
return layout;
}
- @Override
- protected void onPositive(DialogInterface dialog) {
- AlertDialog alert = (AlertDialog) dialog;
- final String login = ((TextView) alert.findViewById(R.id.network_authentication_login)).getText().toString().trim();
- final String password = ((TextView) alert.findViewById(R.id.network_authentication_password)).getText().toString();
+ private void onPositive(DialogInterface dialog) {
+ AlertDialog alert = (AlertDialog)dialog;
+ final String login = ((TextView)alert.findViewById(R.id.network_authentication_login)).getText().toString().trim();
+ final String password = ((TextView)alert.findViewById(R.id.network_authentication_password)).getText().toString();
if (login.length() == 0) {
final String err = myResource.getResource("loginIsEmpty").getValue();
- sendError(true, false, err);
+ sendError(err);
return;
}
@@ -87,37 +145,64 @@ class AuthenticationDialog extends NetworkDialog {
}
} catch (ZLNetworkException e) {
mgr.logOut();
- sendError(true, false, e.getMessage());
+ sendError(e.getMessage());
return;
}
- sendSuccess(false);
+ sendSuccess();
}
};
UIUtil.wait("authentication", runnable, myActivity);
}
- @Override
- protected void onNegative(DialogInterface dialog) {
+ private void onNegative(DialogInterface dialog) {
final NetworkAuthenticationManager mgr = myLink.authenticationManager();
final Runnable runnable = new Runnable() {
public void run() {
if (mgr.mayBeAuthorised(false)) {
mgr.logOut();
- sendCancel(false);
+ sendCancel();
}
}
};
UIUtil.wait("signOut", runnable, myActivity);
}
- @Override
- public void prepareDialogInternal(Dialog dialog) {
+ public final Dialog createDialog(final Activity activity) {
+ myActivity = activity;
+ final DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ if (which == DialogInterface.BUTTON_POSITIVE) {
+ onPositive(dialog);
+ } else {
+ onNegative(dialog);
+ }
+ }
+ };
+
+ final View layout = createLayout();
+ final ZLResource buttonResource = ZLResource.resource("dialog").getResource("button");
+ return new AlertDialog.Builder(activity)
+ .setView(layout)
+ .setTitle(myResource.getResource("title").getValue())
+ .setPositiveButton(buttonResource.getResource("ok").getValue(), listener)
+ .setNegativeButton(buttonResource.getResource("cancel").getValue(), listener)
+ .setOnCancelListener(new DialogInterface.OnCancelListener() {
+ public void onCancel(DialogInterface dialog) {
+ onNegative(dialog);
+ }
+ })
+ .create();
+ }
+
+ public final void prepareDialog(final Activity activity, Dialog dialog) {
+ myActivity = activity;
+
final NetworkAuthenticationManager mgr = myLink.authenticationManager();
- ((TextView) dialog.findViewById(R.id.network_authentication_login)).setText(mgr.UserNameOption.getValue());
- ((TextView) dialog.findViewById(R.id.network_authentication_password)).setText("");
+ ((TextView)dialog.findViewById(R.id.network_authentication_login)).setText(mgr.UserNameOption.getValue());
+ ((TextView)dialog.findViewById(R.id.network_authentication_password)).setText("");
- final TextView error = (TextView) dialog.findViewById(R.id.network_authentication_error);
+ final TextView error = (TextView)dialog.findViewById(R.id.network_authentication_error);
if (myErrorMessage == null) {
error.setVisibility(View.GONE);
error.setText("");
diff --git a/src/org/geometerplus/android/fbreader/network/CustomCatalogDialog.java b/src/org/geometerplus/android/fbreader/network/CustomCatalogDialog.java
deleted file mode 100644
index 944c2122c..000000000
--- a/src/org/geometerplus/android/fbreader/network/CustomCatalogDialog.java
+++ /dev/null
@@ -1,238 +0,0 @@
-/*
- * Copyright (C) 2010-2011 Geometer Plus
- *
- * 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.Dialog;
-import android.app.AlertDialog;
-import android.net.Uri;
-import android.os.Handler;
-import android.os.Message;
-import android.view.View;
-import android.widget.TextView;
-import android.content.DialogInterface;
-
-import org.geometerplus.zlibrary.core.resources.ZLResource;
-import org.geometerplus.zlibrary.core.network.ZLNetworkException;
-
-import org.geometerplus.zlibrary.ui.android.R;
-
-import org.geometerplus.android.util.UIUtil;
-
-import org.geometerplus.fbreader.network.*;
-import org.geometerplus.fbreader.network.opds.OPDSLinkReader;
-
-
-class CustomCatalogDialog extends NetworkDialog {
-
- private String myTitle;
- private String myUrl;
- private String mySummary;
-
- private boolean myLinkWithoutInfo;
-
- public CustomCatalogDialog() {
- super("CustomCatalogDialog");
- }
-
- @Override
- protected void clearData() {
- myTitle = myUrl = mySummary = null;
- myLinkWithoutInfo = false;
- }
-
- @Override
- protected View createLayout() {
- final View layout = myActivity.getLayoutInflater().inflate(R.layout.network_custom_catalog_dialog, null);
-
- ((TextView) layout.findViewById(R.id.network_catalog_title_text)).setText(myResource.getResource("catalogTitle").getValue());
- ((TextView) layout.findViewById(R.id.network_catalog_url_text)).setText(myResource.getResource("catalogUrl").getValue());
- ((TextView) layout.findViewById(R.id.network_catalog_summary_text)).setText(myResource.getResource("catalogSummary").getValue());
- ((TextView) layout.findViewById(R.id.network_catalog_title_example)).setText(myResource.getResource("catalogTitleExample").getValue());
- ((TextView) layout.findViewById(R.id.network_catalog_url_example)).setText(myResource.getResource("catalogUrlExample").getValue());
- ((TextView) layout.findViewById(R.id.network_catalog_summary_example)).setText(myResource.getResource("catalogSummaryExample").getValue());
-
- return layout;
- }
-
- @Override
- protected void onPositive(DialogInterface dialog) {
- AlertDialog alert = (AlertDialog) dialog;
- myTitle = ((TextView) alert.findViewById(R.id.network_catalog_title)).getText().toString().trim();
- myUrl = ((TextView) alert.findViewById(R.id.network_catalog_url)).getText().toString().trim();
- mySummary = ((TextView) alert.findViewById(R.id.network_catalog_summary)).getText().toString().trim();
-
- if (myTitle.length() == 0) {
- myTitle = null;
- if (myLink != null) {
- final String err = myResource.getResource("titleIsEmpty").getValue();
- sendError(true, false, err);
- return;
- }
- }
- if (myUrl.length() == 0) {
- myUrl = null;
- final String err = myResource.getResource("urlIsEmpty").getValue();
- sendError(true, false, err);
- return;
- }
- if (mySummary.length() == 0) {
- mySummary = null;
- }
-
- Uri uri = Uri.parse(myUrl);
- if (uri.getScheme() == null) {
- myUrl = "http://" + myUrl;
- uri = Uri.parse(myUrl);
- }
-
- String siteName = uri.getHost();
- if (siteName == null) {
- final String err = myResource.getResource("invalidUrl").getValue();
- sendError(true, false, err);
- return;
- }
- if (siteName.startsWith("www.")) {
- siteName = siteName.substring(4);
- }
-
- final NetworkLibrary library = NetworkLibrary.Instance();
- if (myLink != null && library.hasCustomLinkTitle(myTitle, myLink)) {
- final String err = myResource.getResource("titleAlreadyExists").getValue();
- sendError(true, false, err);
- return;
- }
- if (library.hasCustomLinkSite(siteName, myLink)) {
- final String err = myResource.getResource("siteAlreadyExists").getValue();
- sendError(true, false, err);
- return;
- }
-
- if (myLink != null) {
- final ICustomNetworkLink link = (ICustomNetworkLink) myLink;
- link.setSiteName(siteName);
- link.setTitle(myTitle);
- link.setSummary(mySummary);
- link.setLink(INetworkLink.URL_MAIN, myUrl);
-
- if (myLinkWithoutInfo) {
- NetworkLibrary.Instance().addCustomLink(link);
- myLinkWithoutInfo = false;
- } else {
- link.saveLink();
- }
- sendSuccess(true);
- return;
- }
-
- myLinkWithoutInfo = true;
- myLink = OPDSLinkReader.createCustomLinkWithoutInfo(siteName, myUrl);
-
- final Handler handler = new Handler() {
- public void handleMessage(Message msg) {
- final String err = (String) msg.obj;
- if (err != null) {
- final DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int which) {
- if (which == DialogInterface.BUTTON_NEGATIVE) {
- sendSuccess(true);
- } else {
- if (which == DialogInterface.BUTTON_NEUTRAL) {
- myLinkWithoutInfo = false;
- myLink = null;
- }
- sendError(true, false, null);
- }
- }
- };
- 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(err)
- .setIcon(0)
- .setPositiveButton(buttonResource.getResource("continue").getValue(), listener)
- .setNeutralButton(buttonResource.getResource("editUrl").getValue(), listener)
- .setNegativeButton(buttonResource.getResource("cancel").getValue(), listener)
- .setOnCancelListener(new DialogInterface.OnCancelListener() {
- public void onCancel(DialogInterface dialog) {
- listener.onClick(dialog, DialogInterface.BUTTON_NEGATIVE);
- }
- })
- .create().show();
- } else {
- sendError(true, false, null);
- }
- }
- };
-
- final Runnable loadInfoRunnable = new Runnable() {
- public void run() {
- String error = null;
- try {
- ((ICustomNetworkLink)myLink).reloadInfo();
- } catch (ZLNetworkException e) {
- error = e.getMessage();
- }
- handler.sendMessage(handler.obtainMessage(0, error));
- }
- };
- UIUtil.wait("loadingCatalogInfo", loadInfoRunnable, myActivity);
- }
-
- @Override
- protected void onNegative(DialogInterface dialog) {
- sendCancel(false);
- }
-
- @Override
- public void prepareDialogInternal(Dialog dialog) {
- if (myLink != null) {
- if (myTitle == null) myTitle = myLink.getTitle();
- if (myUrl == null) myUrl = myLink.getLink(INetworkLink.URL_MAIN);
- if (mySummary == null) mySummary = myLink.getSummary();
- }
- ((TextView) dialog.findViewById(R.id.network_catalog_title)).setText(myTitle);
- ((TextView) dialog.findViewById(R.id.network_catalog_url)).setText(myUrl);
- ((TextView) dialog.findViewById(R.id.network_catalog_summary)).setText(mySummary);
-
- final int examplesVisibility = (myLink == null || myLinkWithoutInfo) ? View.VISIBLE : View.GONE;
- dialog.findViewById(R.id.network_catalog_title_example).setVisibility(examplesVisibility);
- dialog.findViewById(R.id.network_catalog_url_example).setVisibility(examplesVisibility);
- dialog.findViewById(R.id.network_catalog_summary_example).setVisibility(examplesVisibility);
-
- final int groupsVisibility = (myLink != null) ? View.VISIBLE : View.GONE;
- dialog.findViewById(R.id.network_catalog_title_group).setVisibility(groupsVisibility);
- dialog.findViewById(R.id.network_catalog_summary_group).setVisibility(groupsVisibility);
-
- final TextView error = (TextView) dialog.findViewById(R.id.network_catalog_error);
- if (myErrorMessage == null) {
- error.setVisibility(View.GONE);
- error.setText("");
- } else {
- error.setVisibility(View.VISIBLE);
- error.setText(myErrorMessage);
- }
-
- View dlgView = dialog.findViewById(R.id.network_custom_catalog_dialog);
- dlgView.invalidate();
- dlgView.requestLayout();
- }
-}
diff --git a/src/org/geometerplus/android/fbreader/network/ItemsLoadingHandler.java b/src/org/geometerplus/android/fbreader/network/ItemsLoadingHandler.java
index 75e28c3d9..d048538de 100644
--- a/src/org/geometerplus/android/fbreader/network/ItemsLoadingHandler.java
+++ b/src/org/geometerplus/android/fbreader/network/ItemsLoadingHandler.java
@@ -29,7 +29,7 @@ import android.os.Message;
import android.os.Handler;
import org.geometerplus.fbreader.network.INetworkLink;
-import org.geometerplus.fbreader.network.NetworkLibraryItem;
+import org.geometerplus.fbreader.network.NetworkItem;
abstract class ItemsLoadingHandler extends Handler {
@@ -37,20 +37,20 @@ abstract class ItemsLoadingHandler extends Handler {
private static final int WHAT_UPDATE_ITEMS = 0;
private static final int WHAT_FINISHED = 1;
- private final LinkedList myItems = new LinkedList();
- private final HashMap> myUncommitedItems = new HashMap>();
+ private final LinkedList myItems = new LinkedList();
+ private final HashMap> myUncommitedItems = new HashMap>();
private final Object myItemsMonitor = new Object();
private volatile boolean myFinishProcessed;
private final Object myFinishMonitor = new Object();
- public final void addItem(INetworkLink link, NetworkLibraryItem item) {
+ public final void addItem(INetworkLink link, NetworkItem item) {
synchronized (myItemsMonitor) {
myItems.add(item);
- LinkedList uncommited = myUncommitedItems.get(link);
+ LinkedList uncommited = myUncommitedItems.get(link);
if (uncommited == null) {
- uncommited = new LinkedList();
+ uncommited = new LinkedList();
myUncommitedItems.put(link, uncommited);
}
uncommited.add(item);
@@ -59,7 +59,7 @@ abstract class ItemsLoadingHandler extends Handler {
public final void commitItems(INetworkLink link) {
synchronized (myItemsMonitor) {
- LinkedList uncommited = myUncommitedItems.get(link);
+ LinkedList uncommited = myUncommitedItems.get(link);
if (uncommited != null) {
uncommited.clear();
}
@@ -98,9 +98,9 @@ abstract class ItemsLoadingHandler extends Handler {
}
private final void doProcessFinish(String errorMessage, boolean interrupted) {
- HashSet uncommitedItems = new HashSet();
+ HashSet uncommitedItems = new HashSet();
synchronized (myUncommitedItems) {
- for (LinkedList items: myUncommitedItems.values()) {
+ for (LinkedList items: myUncommitedItems.values()) {
uncommitedItems.addAll(items);
}
}
@@ -124,9 +124,9 @@ abstract class ItemsLoadingHandler extends Handler {
// callbacks
- public abstract void onUpdateItems(List items);
+ public abstract void onUpdateItems(List items);
public abstract void afterUpdateItems();
- public abstract void onFinish(String errorMessage, boolean interrupted, Set uncommitedItems);
+ public abstract void onFinish(String errorMessage, boolean interrupted, Set uncommitedItems);
@Override
diff --git a/src/org/geometerplus/android/fbreader/network/ItemsLoadingRunnable.java b/src/org/geometerplus/android/fbreader/network/ItemsLoadingRunnable.java
index ffa82bab1..4c3f4ec9b 100644
--- a/src/org/geometerplus/android/fbreader/network/ItemsLoadingRunnable.java
+++ b/src/org/geometerplus/android/fbreader/network/ItemsLoadingRunnable.java
@@ -26,7 +26,7 @@ import org.geometerplus.zlibrary.core.network.ZLNetworkException;
import org.geometerplus.fbreader.network.INetworkLink;
import org.geometerplus.fbreader.network.NetworkOperationData;
-import org.geometerplus.fbreader.network.NetworkLibraryItem;
+import org.geometerplus.fbreader.network.NetworkItem;
abstract class ItemsLoadingRunnable implements Runnable {
private final ItemsLoadingHandler myHandler;
@@ -99,7 +99,7 @@ abstract class ItemsLoadingRunnable implements Runnable {
doLoading(new NetworkOperationData.OnNewItemListener() {
private long myUpdateTime;
private int myItemsNumber;
- public void onNewItem(INetworkLink link, NetworkLibraryItem item) {
+ public void onNewItem(INetworkLink link, NetworkItem item) {
myHandler.addItem(link, item);
++myItemsNumber;
final long now = System.currentTimeMillis();
diff --git a/src/org/geometerplus/android/fbreader/network/ItemsLoadingService.java b/src/org/geometerplus/android/fbreader/network/ItemsLoadingService.java
index 34ff845ca..2e91b5d4c 100644
--- a/src/org/geometerplus/android/fbreader/network/ItemsLoadingService.java
+++ b/src/org/geometerplus/android/fbreader/network/ItemsLoadingService.java
@@ -25,6 +25,7 @@ import android.os.Message;
import android.app.Service;
import android.content.Intent;
+import org.geometerplus.fbreader.network.NetworkTree;
public class ItemsLoadingService extends Service {
@@ -53,7 +54,7 @@ public class ItemsLoadingService extends Service {
super.onStart(intent, startId);
doStart();
- final String key = intent.getStringExtra(ITEMS_LOADING_RUNNABLE_KEY);
+ final NetworkTree.Key key = (NetworkTree.Key)intent.getSerializableExtra(ITEMS_LOADING_RUNNABLE_KEY);
if (key == null) {
doStop();
return;
diff --git a/src/org/geometerplus/android/fbreader/network/NetworkBaseActivity.java b/src/org/geometerplus/android/fbreader/network/NetworkBaseActivity.java
index 86aadfd71..a7c8b1a80 100644
--- a/src/org/geometerplus/android/fbreader/network/NetworkBaseActivity.java
+++ b/src/org/geometerplus/android/fbreader/network/NetworkBaseActivity.java
@@ -38,11 +38,12 @@ import org.geometerplus.zlibrary.ui.android.image.ZLAndroidImageData;
import org.geometerplus.fbreader.network.NetworkTree;
import org.geometerplus.fbreader.network.tree.NetworkBookTree;
+import org.geometerplus.fbreader.network.tree.AddCustomCatalogItemTree;
+import org.geometerplus.fbreader.network.tree.SearchItemTree;
import org.geometerplus.android.fbreader.tree.ZLAndroidTree;
abstract class NetworkBaseActivity extends ListActivity implements NetworkView.EventListener {
-
protected final ZLResource myResource = ZLResource.resource("networkView");
public BookDownloaderServiceConnection Connection;
@@ -105,6 +106,14 @@ abstract class NetworkBaseActivity extends ListActivity implements NetworkView.E
};
private void setupCover(final ImageView coverView, NetworkTree tree, int width, int height) {
+ if (tree instanceof AddCustomCatalogItemTree) {
+ coverView.setImageResource(R.drawable.ic_list_plus);
+ return;
+ }
+ if (tree instanceof SearchItemTree) {
+ coverView.setImageResource(R.drawable.ic_list_searchresult);
+ return;
+ }
if (tree instanceof ZLAndroidTree) {
coverView.setImageResource(((ZLAndroidTree)tree).getCoverResourceId());
return;
@@ -178,42 +187,31 @@ abstract class NetworkBaseActivity extends ListActivity implements NetworkView.E
@Override
public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo) {
- NetworkTree tree = null;
+ System.err.println("onCreateContextMenu -1");
if (menuInfo != null) {
final int position = ((AdapterView.AdapterContextMenuInfo)menuInfo).position;
- tree = (NetworkTree)getListAdapter().getItem(position);
- } else {
- tree = getDefaultTree();
- }
- if (tree != null) {
- final NetworkTreeActions actions = NetworkView.Instance().getActions(tree);
- if (actions != null) {
- actions.buildContextMenu(this, menu, tree);
+ final NetworkTree tree = (NetworkTree)getListAdapter().getItem(position);
+ if (tree != null) {
+ final NetworkTreeActions actions = NetworkView.Instance().getActions(tree);
+ if (actions != null) {
+ actions.buildContextMenu(this, menu, tree);
+ return;
+ }
}
}
- }
-
- private NetworkTree myDefaultTree;
- protected NetworkTree getDefaultTree() {
- return myDefaultTree;
- }
- protected void setDefaultTree(NetworkTree tree) {
- myDefaultTree = tree;
+ super.onCreateContextMenu(menu, view, menuInfo);
}
@Override
public boolean onContextItemSelected(MenuItem item) {
- NetworkTree tree = null;
if (item != null && item.getMenuInfo() != null) {
final int position = ((AdapterView.AdapterContextMenuInfo)item.getMenuInfo()).position;
- tree = (NetworkTree)getListAdapter().getItem(position);
- } else {
- tree = getDefaultTree();
- }
- if (tree != null) {
- final NetworkTreeActions actions = NetworkView.Instance().getActions(tree);
- if (actions != null && actions.runAction(this, tree, item.getItemId())) {
- return true;
+ final NetworkTree tree = (NetworkTree)getListAdapter().getItem(position);
+ if (tree != null) {
+ final NetworkTreeActions actions = NetworkView.Instance().getActions(tree);
+ if (actions != null && actions.runAction(this, tree, item.getItemId())) {
+ return true;
+ }
}
}
return super.onContextItemSelected(item);
@@ -260,7 +258,7 @@ abstract class NetworkBaseActivity extends ListActivity implements NetworkView.E
if (!NetworkView.Instance().isInitialized()) {
return null;
}
- final NetworkDialog dlg = NetworkDialog.getDialog(id);
+ final AuthenticationDialog dlg = AuthenticationDialog.getDialog();
if (dlg != null) {
return dlg.createDialog(this);
}
@@ -271,10 +269,10 @@ abstract class NetworkBaseActivity extends ListActivity implements NetworkView.E
protected void onPrepareDialog(int id, Dialog dialog) {
super.onPrepareDialog(id, dialog);
- final NetworkDialog dlg = NetworkDialog.getDialog(id);
+ final AuthenticationDialog dlg = AuthenticationDialog.getDialog();
if (dlg != null) {
dlg.prepareDialog(this, dialog);
- }
+ }
}
@Override
diff --git a/src/org/geometerplus/android/fbreader/network/NetworkBookActions.java b/src/org/geometerplus/android/fbreader/network/NetworkBookActions.java
index cff6a0021..bf3c9c68c 100644
--- a/src/org/geometerplus/android/fbreader/network/NetworkBookActions.java
+++ b/src/org/geometerplus/android/fbreader/network/NetworkBookActions.java
@@ -49,8 +49,6 @@ import org.geometerplus.fbreader.network.authentication.NetworkAuthenticationMan
class NetworkBookActions extends NetworkTreeActions {
- private static final String PACKAGE = "org.geometerplus.android.fbreader.network";
-
public static final int DOWNLOAD_BOOK_ITEM_ID = 0;
public static final int DOWNLOAD_DEMO_ITEM_ID = 1;
public static final int READ_BOOK_ITEM_ID = 2;
@@ -60,8 +58,11 @@ class NetworkBookActions extends NetworkTreeActions {
public static final int BUY_DIRECTLY_ITEM_ID = 6;
public static final int BUY_IN_BROWSER_ITEM_ID = 7;
public static final int SHOW_BOOK_ACTIVITY_ITEM_ID = 8;
-
public static final int SHOW_BOOKS_ITEM_ID = 9;
+ public static final int ADD_BOOK_TO_BASKET = 10;
+ public static final int REMOVE_BOOK_FROM_BASKET = 11;
+ public static final int ADD_CATALOG_TO_FAVORITES = 12;
+ public static final int REMOVE_CATALOG_FROM_FAVORITES = 13;
private static boolean useFullReferences(NetworkBookItem book) {
return book.reference(BookReference.Type.DOWNLOAD_FULL) != null ||
@@ -184,6 +185,14 @@ class NetworkBookActions extends NetworkTreeActions {
final String price = ((BuyBookReference) reference).Price;
actions.add(new Action(id, "buy", price));
}
+ final Basket basket = book.Link.basket();
+ if (basket != null) {
+ if (basket.contains(book)) {
+ actions.add(new Action(REMOVE_BOOK_FROM_BASKET, "removeFromBasket"));
+ } else {
+ actions.add(new Action(ADD_BOOK_TO_BASKET, "addToBasket"));
+ }
+ }
}
return actions;
}
@@ -215,28 +224,15 @@ class NetworkBookActions extends NetworkTreeActions {
public boolean runAction(NetworkBaseActivity activity, NetworkTree tree, int actionCode) {
if (tree instanceof NetworkAuthorTree || tree instanceof NetworkSeriesTree) {
switch (actionCode) {
- case SHOW_BOOKS_ITEM_ID:
- showBooks(activity, tree);
- return true;
+ case SHOW_BOOKS_ITEM_ID:
+ NetworkView.Instance().openTree(activity, tree);
+ return true;
}
return false;
}
return runAction(activity, ((NetworkBookTree) tree).Book, actionCode);
}
-
- private void showBooks(NetworkBaseActivity activity, NetworkTree tree) {
- String key = null;
- if (tree instanceof NetworkAuthorTree) {
- key = PACKAGE + ".Authors:" + ((NetworkAuthorTree) tree).Author.DisplayName;
- } else if (tree instanceof NetworkSeriesTree) {
- key = PACKAGE + ".Series:" + ((NetworkSeriesTree) tree).SeriesTitle;
- }
- if (key != null) {
- NetworkView.Instance().openTree(activity, tree, key);
- }
- }
-
static boolean runAction(Activity activity, NetworkBookItem book, int actionCode) {
switch (actionCode) {
case DOWNLOAD_BOOK_ITEM_ID:
@@ -266,6 +262,12 @@ class NetworkBookActions extends NetworkTreeActions {
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;
+ case REMOVE_BOOK_FROM_BASKET:
+ book.Link.basket().remove(book);
+ return true;
}
return false;
}
@@ -308,7 +310,7 @@ class NetworkBookActions extends NetworkTreeActions {
Uri.fromFile(new File(local)),
activity.getApplicationContext(),
FBReader.class
- ).addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
+ ).addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK)
);
}
}
@@ -450,7 +452,7 @@ class NetworkBookActions extends NetworkTreeActions {
}
} catch (ZLNetworkException e) {
}
- NetworkDialog.show(activity, NetworkDialog.DIALOG_AUTHENTICATION, book.Link, buyRunnable);
+ AuthenticationDialog.show(activity, book.Link, buyRunnable);
}
private static void doBuyInBrowser(Activity activity, final NetworkBookItem book) {
diff --git a/src/org/geometerplus/android/fbreader/network/NetworkBookInfoActivity.java b/src/org/geometerplus/android/fbreader/network/NetworkBookInfoActivity.java
index ec29e172e..8efd11417 100644
--- a/src/org/geometerplus/android/fbreader/network/NetworkBookInfoActivity.java
+++ b/src/org/geometerplus/android/fbreader/network/NetworkBookInfoActivity.java
@@ -29,6 +29,7 @@ import android.view.View;
import android.view.ContextMenu;
import android.view.MenuItem;
import android.widget.ImageView;
+import android.widget.LinearLayout;
import android.widget.TextView;
import android.content.Intent;
import android.graphics.Bitmap;
@@ -88,6 +89,14 @@ public class NetworkBookInfoActivity extends Activity implements NetworkView.Eve
return myMainView;
}
+ private void setTextById(int id, CharSequence text) {
+ ((TextView)findViewById(id)).setText(text);
+ }
+
+ private void setTextFromResource(int id, String resourceKey) {
+ setTextById(id, myResource.getResource(resourceKey).getValue());
+ }
+
@Override
public void onDestroy() {
if (myConnection != null) {
@@ -99,7 +108,7 @@ public class NetworkBookInfoActivity extends Activity implements NetworkView.Eve
@Override
public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo) {
- new RefillAccountActions().buildContextMenu(this, menu, new RefillAccountTree(myBook.Link));
+ new RefillAccountActions().buildContextMenu(this, menu, myBook.Link);
}
@Override
@@ -109,29 +118,39 @@ public class NetworkBookInfoActivity extends Activity implements NetworkView.Eve
}
private final void setupDescription() {
- ((TextView) findViewById(R.id.network_book_description_title)).setText(myResource.getResource("description").getValue());
+ setTextFromResource(R.id.network_book_description_title, "description");
- final TextView descriptionView = (TextView) findViewById(R.id.network_book_description);
final String description;
if (myBook.Summary != null) {
description = myBook.Summary;
} else {
description = myResource.getResource("noDescription").getValue();
}
- descriptionView.setText(description);
+ setTextById(R.id.network_book_description, description);
+ }
+
+ private void setPairLabelTextFromResource(int id, String resourceKey) {
+ final LinearLayout layout = (LinearLayout)findViewById(id);
+ ((TextView)layout.findViewById(R.id.book_info_key))
+ .setText(myResource.getResource(resourceKey).getValue());
+ }
+
+ private void setPairValueText(int id, CharSequence text) {
+ final LinearLayout layout = (LinearLayout)findViewById(id);
+ ((TextView)layout.findViewById(R.id.book_info_value)).setText(text);
}
private void setupInfo() {
- ((TextView) findViewById(R.id.network_book_info_title)).setText(myResource.getResource("bookInfo").getValue());
+ setTextFromResource(R.id.network_book_info_title, "bookInfo");
- ((TextView) findViewById(R.id.network_book_title_key)).setText(myResource.getResource("title").getValue());
- ((TextView) findViewById(R.id.network_book_authors_key)).setText(myResource.getResource("authors").getValue());
- ((TextView) findViewById(R.id.network_book_series_key)).setText(myResource.getResource("series").getValue());
- ((TextView) findViewById(R.id.network_book_series_index_key)).setText(myResource.getResource("indexInSeries").getValue());
- ((TextView) findViewById(R.id.network_book_tags_key)).setText(myResource.getResource("tags").getValue());
+ setPairLabelTextFromResource(R.id.network_book_title, "title");
+ setPairLabelTextFromResource(R.id.network_book_authors, "authors");
+ setPairLabelTextFromResource(R.id.network_book_series_title, "series");
+ setPairLabelTextFromResource(R.id.network_book_series_index, "indexInSeries");
+ setPairLabelTextFromResource(R.id.network_book_tags, "tags");
+ setPairLabelTextFromResource(R.id.network_book_catalog, "catalog");
-
- ((TextView) findViewById(R.id.network_book_title_value)).setText(myBook.Title);
+ setPairValueText(R.id.network_book_title, myBook.Title);
if (myBook.Authors.size() > 0) {
findViewById(R.id.network_book_authors).setVisibility(View.VISIBLE);
@@ -142,22 +161,22 @@ public class NetworkBookInfoActivity extends Activity implements NetworkView.Eve
}
authorsText.append(author.DisplayName);
}
- ((TextView) findViewById(R.id.network_book_authors_value)).setText(authorsText);
+ setPairValueText(R.id.network_book_authors, authorsText);
} else {
findViewById(R.id.network_book_authors).setVisibility(View.GONE);
}
if (myBook.SeriesTitle != null) {
- findViewById(R.id.network_book_series).setVisibility(View.VISIBLE);
- ((TextView) findViewById(R.id.network_book_series_value)).setText(myBook.SeriesTitle);
+ findViewById(R.id.network_book_series_title).setVisibility(View.VISIBLE);
+ setPairValueText(R.id.network_book_series_title, myBook.SeriesTitle);
if (myBook.IndexInSeries > 0) {
- ((TextView) findViewById(R.id.network_book_series_index_value)).setText(String.valueOf(myBook.IndexInSeries));
+ setPairValueText(R.id.network_book_series_index, String.valueOf(myBook.IndexInSeries));
findViewById(R.id.network_book_series_index).setVisibility(View.VISIBLE);
} else {
findViewById(R.id.network_book_series_index).setVisibility(View.GONE);
}
} else {
- findViewById(R.id.network_book_series).setVisibility(View.GONE);
+ findViewById(R.id.network_book_series_title).setVisibility(View.GONE);
findViewById(R.id.network_book_series_index).setVisibility(View.GONE);
}
@@ -170,15 +189,17 @@ public class NetworkBookInfoActivity extends Activity implements NetworkView.Eve
}
tagsText.append(tag);
}
- ((TextView) findViewById(R.id.network_book_tags_value)).setText(tagsText);
+ setPairValueText(R.id.network_book_tags, tagsText);
} else {
findViewById(R.id.network_book_tags).setVisibility(View.GONE);
}
+
+ setPairValueText(R.id.network_book_catalog, myBook.Link.getTitle());
}
private final void setupCover() {
final View rootView = findViewById(R.id.network_book_root);
- final ImageView coverView = (ImageView) findViewById(R.id.network_book_cover);
+ final ImageView coverView = (ImageView)findViewById(R.id.network_book_cover);
final DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
@@ -232,9 +253,11 @@ public class NetworkBookInfoActivity extends Activity implements NetworkView.Eve
};
final Set actions = NetworkBookActions.getContextMenuActions(myBook, myConnection);
- final boolean skipSecondButton = actions.size() < buttons.length && (actions.size() % 2) == 1;
+ final boolean skipSecondButton =
+ actions.size() < buttons.length &&
+ actions.size() % 2 == 1;
int buttonNumber = 0;
- for (final NetworkBookActions.Action a: actions) {
+ for (final NetworkBookActions.Action a : actions) {
if (skipSecondButton && buttonNumber == 1) {
++buttonNumber;
}
@@ -250,7 +273,7 @@ public class NetworkBookInfoActivity extends Activity implements NetworkView.Eve
}
final int buttonId = buttons[buttonNumber++];
- TextView button = (TextView) findViewById(buttonId);
+ TextView button = (TextView)findViewById(buttonId);
button.setText(text);
button.setVisibility(View.VISIBLE);
button.setOnClickListener(new View.OnClickListener() {
@@ -305,7 +328,7 @@ public class NetworkBookInfoActivity extends Activity implements NetworkView.Eve
if (!NetworkView.Instance().isInitialized()) {
return null;
}
- final NetworkDialog dlg = NetworkDialog.getDialog(id);
+ final AuthenticationDialog dlg = AuthenticationDialog.getDialog();
if (dlg != null) {
return dlg.createDialog(this);
}
@@ -316,9 +339,9 @@ public class NetworkBookInfoActivity extends Activity implements NetworkView.Eve
protected void onPrepareDialog(int id, Dialog dialog) {
super.onPrepareDialog(id, dialog);
- final NetworkDialog dlg = NetworkDialog.getDialog(id);
+ final AuthenticationDialog dlg = AuthenticationDialog.getDialog();
if (dlg != null) {
dlg.prepareDialog(this, dialog);
- }
+ }
}
}
diff --git a/src/org/geometerplus/android/fbreader/network/NetworkCatalogActions.java b/src/org/geometerplus/android/fbreader/network/NetworkCatalogActions.java
index 2fe1265e6..5343b6642 100644
--- a/src/org/geometerplus/android/fbreader/network/NetworkCatalogActions.java
+++ b/src/org/geometerplus/android/fbreader/network/NetworkCatalogActions.java
@@ -23,12 +23,13 @@ import java.util.*;
import android.app.Activity;
import android.app.AlertDialog;
+import android.content.Intent;
+import android.net.Uri;
import android.os.Message;
import android.os.Handler;
import android.view.Menu;
import android.view.ContextMenu;
-import org.geometerplus.zlibrary.core.resources.ZLResource;
import org.geometerplus.zlibrary.core.util.ZLBoolean3;
import org.geometerplus.zlibrary.core.network.ZLNetworkException;
@@ -39,11 +40,11 @@ import org.geometerplus.fbreader.network.*;
import org.geometerplus.fbreader.network.tree.NetworkTreeFactory;
import org.geometerplus.fbreader.network.tree.NetworkCatalogTree;
import org.geometerplus.fbreader.network.tree.NetworkCatalogRootTree;
+import org.geometerplus.fbreader.network.opds.BasketItem;
import org.geometerplus.fbreader.network.authentication.*;
class NetworkCatalogActions extends NetworkTreeActions {
-
public static final int OPEN_CATALOG_ITEM_ID = 0;
public static final int OPEN_IN_BROWSER_ITEM_ID = 1;
public static final int RELOAD_ITEM_ID = 2;
@@ -55,6 +56,9 @@ class NetworkCatalogActions extends NetworkTreeActions {
public static final int CUSTOM_CATALOG_EDIT = 7;
public static final int CUSTOM_CATALOG_REMOVE = 8;
+ public static final int BASKET_CLEAR = 9;
+ public static final int BASKET_BUY_ALL_BOOKS = 10;
+
@Override
public boolean canHandleTree(NetworkTree tree) {
return tree instanceof NetworkCatalogTree;
@@ -70,14 +74,15 @@ class NetworkCatalogActions extends NetworkTreeActions {
@Override
public void buildContextMenu(Activity activity, ContextMenu menu, NetworkTree tree) {
- final NetworkCatalogTree catalogTree = (NetworkCatalogTree) tree;
+ final NetworkCatalogTree catalogTree = (NetworkCatalogTree)tree;
final NetworkCatalogItem item = catalogTree.Item;
menu.setHeaderTitle(tree.getName());
boolean hasItems = false;
final String catalogUrl = item.URLByType.get(NetworkCatalogItem.URL_CATALOG);
- if (catalogUrl != null) {
+ if (catalogUrl != null &&
+ (!(item instanceof BasketItem) || item.Link.basket().bookIds().size() > 0)) {
addMenuItem(menu, OPEN_CATALOG_ITEM_ID, "openCatalog");
hasItems = true;
}
@@ -152,6 +157,10 @@ class NetworkCatalogActions extends NetworkTreeActions {
addOptionsItem(menu, SIGNUP_ITEM_ID, "signUp");
addOptionsItem(menu, SIGNOUT_ITEM_ID, "signOut", "");
addOptionsItem(menu, REFILL_ACCOUNT_ITEM_ID, "refillAccount");
+ if (((NetworkCatalogTree)tree).Item instanceof BasketItem) {
+ addOptionsItem(menu, BASKET_CLEAR, "clearBasket");
+ addOptionsItem(menu, BASKET_BUY_ALL_BOOKS, "buyAllBooks");
+ }
return true;
}
@@ -160,11 +169,11 @@ class NetworkCatalogActions extends NetworkTreeActions {
final NetworkCatalogTree catalogTree = (NetworkCatalogTree) tree;
final NetworkCatalogItem item = catalogTree.Item;
- final String catalogUrl = item.URLByType.get(NetworkCatalogItem.URL_CATALOG);
- final boolean isLoading = (catalogUrl != null) ?
- NetworkView.Instance().containsItemsLoadingRunnable(catalogUrl) : false;
+ final boolean isLoading =
+ NetworkView.Instance().containsItemsLoadingRunnable(tree.getUniqueKey());
- prepareOptionsItem(menu, RELOAD_ITEM_ID, catalogUrl != null && !isLoading);
+ prepareOptionsItem(menu, RELOAD_ITEM_ID,
+ item.URLByType.get(NetworkCatalogItem.URL_CATALOG) != null && !isLoading);
boolean signIn = false;
boolean signOut = false;
@@ -200,7 +209,7 @@ class NetworkCatalogActions extends NetworkTreeActions {
case B3_TRUE:
return false;
case B3_UNDEFINED:
- NetworkDialog.show(activity, NetworkDialog.DIALOG_AUTHENTICATION, ((NetworkCatalogTree)tree).Item.Link, new Runnable() {
+ AuthenticationDialog.show(activity, ((NetworkCatalogTree)tree).Item.Link, new Runnable() {
public void run() {
if (catalogTree.Item.getVisibility() != ZLBoolean3.B3_TRUE) {
return;
@@ -220,36 +229,56 @@ class NetworkCatalogActions extends NetworkTreeActions {
if (consumeByVisibility(activity, tree, actionCode)) {
return true;
}
+ final NetworkCatalogTree catalogTree = (NetworkCatalogTree)tree;
switch (actionCode) {
case OPEN_CATALOG_ITEM_ID:
- doExpandCatalog(activity, (NetworkCatalogTree)tree);
+ {
+ final NetworkCatalogItem item = catalogTree.Item;
+ if (item instanceof BasketItem && item.Link.basket().bookIds().size() == 0) {
+ UIUtil.showErrorMessage(activity, "emptyBasket");
+ } else {
+ doExpandCatalog(activity, catalogTree);
+ }
return true;
+ }
case OPEN_IN_BROWSER_ITEM_ID:
Util.openInBrowser(
activity,
- ((NetworkCatalogTree)tree).Item.URLByType.get(NetworkCatalogItem.URL_HTML_PAGE)
+ catalogTree.Item.URLByType.get(NetworkCatalogItem.URL_HTML_PAGE)
);
return true;
case RELOAD_ITEM_ID:
- doReloadCatalog(activity, (NetworkCatalogTree)tree);
+ doReloadCatalog(activity, catalogTree);
return true;
case SIGNIN_ITEM_ID:
- NetworkDialog.show(activity, NetworkDialog.DIALOG_AUTHENTICATION, ((NetworkCatalogTree)tree).Item.Link, null);
+ AuthenticationDialog.show(activity, catalogTree.Item.Link, null);
return true;
case SIGNUP_ITEM_ID:
- Util.runRegistrationDialog(activity, ((NetworkCatalogTree)tree).Item.Link);
+ Util.runRegistrationDialog(activity, catalogTree.Item.Link);
return true;
case SIGNOUT_ITEM_ID:
- doSignOut(activity, (NetworkCatalogTree)tree);
+ doSignOut(activity, catalogTree);
return true;
case REFILL_ACCOUNT_ITEM_ID:
- new RefillAccountActions().runStandalone(activity, ((RefillAccountTree)activity.getDefaultTree()).Link);
+ new RefillAccountActions().runStandalone(activity, catalogTree.Item.Link);
return true;
case CUSTOM_CATALOG_EDIT:
- NetworkDialog.show(activity, NetworkDialog.DIALOG_CUSTOM_CATALOG, ((NetworkCatalogTree)tree).Item.Link, null);
+ {
+ final Intent intent = new Intent(activity, AddCustomCatalogActivity.class);
+ NetworkLibraryActivity.addLinkToIntent(
+ intent,
+ (ICustomNetworkLink)catalogTree.Item.Link
+ );
+ activity.startActivity(intent);
return true;
+ }
case CUSTOM_CATALOG_REMOVE:
- removeCustomLink((ICustomNetworkLink)((NetworkCatalogTree)tree).Item.Link);
+ removeCustomLink((ICustomNetworkLink)catalogTree.Item.Link);
+ return true;
+ case BASKET_CLEAR:
+ catalogTree.Item.Link.basket().clear();
+ return true;
+ case BASKET_BUY_ALL_BOOKS:
return true;
}
return false;
@@ -257,18 +286,17 @@ class NetworkCatalogActions extends NetworkTreeActions {
private static class ExpandCatalogHandler extends ItemsLoadingHandler {
-
- private final String myKey;
+ private final NetworkTree.Key myKey;
private final NetworkCatalogTree myTree;
- ExpandCatalogHandler(NetworkCatalogTree tree, String key) {
+ ExpandCatalogHandler(NetworkCatalogTree tree, NetworkTree.Key key) {
myTree = tree;
myKey = key;
}
@Override
- public void onUpdateItems(List items) {
- for (NetworkLibraryItem item: items) {
+ public void onUpdateItems(List items) {
+ for (NetworkItem item: items) {
myTree.ChildrenItems.add(item);
NetworkTreeFactory.createNetworkTree(myTree, item);
}
@@ -283,7 +311,7 @@ class NetworkCatalogActions extends NetworkTreeActions {
@Override
public void onFinish(String errorMessage, boolean interrupted,
- Set uncommitedItems) {
+ Set uncommitedItems) {
if (interrupted &&
(!myTree.Item.supportsResumeLoading() || errorMessage != null)) {
myTree.ChildrenItems.clear();
@@ -304,30 +332,18 @@ class NetworkCatalogActions extends NetworkTreeActions {
}
private void afterUpdateCatalog(String errorMessage, boolean childrenEmpty) {
- final ZLResource dialogResource = ZLResource.resource("dialog");
- ZLResource boxResource = null;
+ if (!NetworkView.Instance().isInitialized()) {
+ return;
+ }
+ final NetworkCatalogActivity activity = NetworkView.Instance().getOpenedActivity(myKey);
+ if (activity == null) {
+ return;
+ }
String msg = null;
if (errorMessage != null) {
- boxResource = dialogResource.getResource("networkError");
- msg = errorMessage;
+ UIUtil.showErrorMessageText(activity, errorMessage);
} else if (childrenEmpty) {
- // TODO: make ListView's empty view instead
- boxResource = dialogResource.getResource("emptyCatalogBox");
- msg = boxResource.getResource("message").getValue();
- }
- if (msg != null) {
- if (NetworkView.Instance().isInitialized()) {
- final NetworkCatalogActivity activity = NetworkView.Instance().getOpenedActivity(myKey);
- if (activity != null) {
- final ZLResource buttonResource = dialogResource.getResource("button");
- new AlertDialog.Builder(activity)
- .setTitle(boxResource.getResource("title").getValue())
- .setMessage(msg)
- .setIcon(0)
- .setPositiveButton(buttonResource.getResource("ok").getValue(), null)
- .create().show();
- }
- }
+ UIUtil.showErrorMessage(activity, "emptyCatalog");
}
}
}
@@ -385,12 +401,9 @@ class NetworkCatalogActions extends NetworkTreeActions {
}
}
- public void doExpandCatalog(final NetworkBaseActivity activity, final NetworkCatalogTree tree) {
- final String url = tree.Item.URLByType.get(NetworkCatalogItem.URL_CATALOG);
- if (url == null) {
- throw new RuntimeException("That's impossible!!!");
- }
- NetworkView.Instance().tryResumeLoading(activity, tree, url, new Runnable() {
+ private void doExpandCatalog(final NetworkBaseActivity activity, final NetworkCatalogTree tree) {
+ final NetworkTree.Key key = tree.getUniqueKey();
+ NetworkView.Instance().tryResumeLoading(activity, tree, new Runnable() {
public void run() {
boolean resumeNotLoad = false;
if (tree.hasChildren()) {
@@ -398,7 +411,7 @@ class NetworkCatalogActions extends NetworkTreeActions {
if (tree.Item.supportsResumeLoading()) {
resumeNotLoad = true;
} else {
- NetworkView.Instance().openTree(activity, tree, url);
+ NetworkView.Instance().openTree(activity, tree);
return;
}
} else {
@@ -408,15 +421,25 @@ class NetworkCatalogActions extends NetworkTreeActions {
}
}
- final ExpandCatalogHandler handler = new ExpandCatalogHandler(tree, url);
+ /* FIXME: if catalog's loading will be very fast
+ * then it is possible that loading message is lost
+ * (see ExpandCatalogHandler.afterUpdateCatalog method).
+ *
+ * For example, this can be fixed via adding method
+ * NetworkView.postCatalogLoadingResult, that will do the following:
+ * 1) If there is activity, then show message
+ * 2) If there is no activity, then save message, and show when activity is created
+ * 3) Remove unused messages (say, by timeout)
+ */
+ final ExpandCatalogHandler handler = new ExpandCatalogHandler(tree, key);
NetworkView.Instance().startItemsLoading(
activity,
- url,
+ key,
new ExpandCatalogRunnable(handler, tree, true, resumeNotLoad)
);
processExtraData(activity, tree.Item.extraData(), new Runnable() {
public void run() {
- NetworkView.Instance().openTree(activity, tree, url);
+ NetworkView.Instance().openTree(activity, tree);
}
});
}
@@ -424,20 +447,17 @@ class NetworkCatalogActions extends NetworkTreeActions {
}
public void doReloadCatalog(NetworkBaseActivity activity, final NetworkCatalogTree tree) {
- final String url = tree.Item.URLByType.get(NetworkCatalogItem.URL_CATALOG);
- if (url == null) {
- throw new RuntimeException("That's impossible!!!");
- }
- if (NetworkView.Instance().containsItemsLoadingRunnable(url)) {
+ final NetworkTree.Key key = tree.getUniqueKey();
+ if (NetworkView.Instance().containsItemsLoadingRunnable(key)) {
return;
}
tree.ChildrenItems.clear();
tree.clear();
NetworkView.Instance().fireModelChangedAsync();
- final ExpandCatalogHandler handler = new ExpandCatalogHandler(tree, url);
+ final ExpandCatalogHandler handler = new ExpandCatalogHandler(tree, key);
NetworkView.Instance().startItemsLoading(
activity,
- url,
+ key,
new ExpandCatalogRunnable(handler, tree, false, false)
);
}
@@ -468,7 +488,6 @@ class NetworkCatalogActions extends NetworkTreeActions {
private void removeCustomLink(ICustomNetworkLink link) {
final NetworkLibrary library = NetworkLibrary.Instance();
library.removeCustomLink(link);
- library.updateChildren();
library.synchronize();
NetworkView.Instance().fireModelChangedAsync();
}
diff --git a/src/org/geometerplus/android/fbreader/network/NetworkCatalogActivity.java b/src/org/geometerplus/android/fbreader/network/NetworkCatalogActivity.java
index b30016e0c..d96eeeb56 100644
--- a/src/org/geometerplus/android/fbreader/network/NetworkCatalogActivity.java
+++ b/src/org/geometerplus/android/fbreader/network/NetworkCatalogActivity.java
@@ -28,17 +28,15 @@ import android.content.Intent;
import org.geometerplus.zlibrary.core.network.ZLNetworkException;
-import org.geometerplus.fbreader.network.NetworkTree;
-import org.geometerplus.fbreader.network.NetworkCatalogItem;
+import org.geometerplus.fbreader.network.*;
import org.geometerplus.fbreader.network.tree.*;
+import org.geometerplus.fbreader.tree.FBTree;
public class NetworkCatalogActivity extends NetworkBaseActivity implements UserRegistrationConstants {
- public static final String CATALOG_LEVEL_KEY = "org.geometerplus.android.fbreader.network.CatalogLevel";
public static final String CATALOG_KEY_KEY = "org.geometerplus.android.fbreader.network.CatalogKey";
private NetworkTree myTree;
- private String myCatalogKey;
- private boolean myInProgress;
+ private volatile boolean myInProgress;
@Override
public void onCreate(Bundle icicle) {
@@ -53,27 +51,49 @@ public class NetworkCatalogActivity extends NetworkBaseActivity implements UserR
}
final Intent intent = getIntent();
- final int level = intent.getIntExtra(CATALOG_LEVEL_KEY, -1);
- if (level == -1) {
- throw new RuntimeException("Catalog's Level was not specified!!!");
+
+ final NetworkLibrary library = NetworkLibrary.Instance();
+ final NetworkTree.Key key = (NetworkTree.Key)intent.getSerializableExtra(CATALOG_KEY_KEY);
+ myTree = library.getTreeByKey(key);
+
+ if (myTree == null) {
+ throw new RuntimeException("Tree not found for key " + key);
}
- myCatalogKey = intent.getStringExtra(CATALOG_KEY_KEY);
- if (myCatalogKey == null) {
- throw new RuntimeException("Catalog's Key was not specified!!!");
- }
-
- myTree = networkView.getOpenedTree(level);
-
- networkView.setOpenedActivity(myCatalogKey, this);
+ networkView.setOpenedActivity(key, this);
setListAdapter(new CatalogAdapter());
getListView().invalidateViews();
setupTitle();
- if (myTree instanceof NetworkCatalogTree &&
- Util.isAccountRefillingSupported(this, ((NetworkCatalogTree)myTree).Item.Link)) {
- setDefaultTree(new RefillAccountTree((NetworkCatalogTree)myTree));
+ }
+
+ @Override
+ public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo) {
+ if (menuInfo == null && myTree instanceof NetworkCatalogTree) {
+ final INetworkLink link = ((NetworkCatalogTree)myTree).Item.Link;
+ if (Util.isAccountRefillingSupported(this, link)) {
+ final RefillAccountActions actions = NetworkView.Instance().getTopUpActions();
+ if (actions != null) {
+ actions.buildContextMenu(this, menu, link);
+ return;
+ }
+ }
}
+ super.onCreateContextMenu(menu, view, menuInfo);
+ }
+
+ @Override
+ public boolean onContextItemSelected(MenuItem item) {
+ if ((item == null || item.getMenuInfo() == null) && myTree instanceof NetworkCatalogTree) {
+ final INetworkLink link = ((NetworkCatalogTree)myTree).Item.Link;
+ if (Util.isAccountRefillingSupported(this, link)) {
+ final RefillAccountActions actions = NetworkView.Instance().getTopUpActions();
+ if (actions != null && actions.runAction(this, link, item.getItemId())) {
+ return true;
+ }
+ }
+ }
+ return super.onContextItemSelected(item);
}
@Override
@@ -112,25 +132,10 @@ public class NetworkCatalogActivity extends NetworkBaseActivity implements UserR
setProgressBarIndeterminateVisibility(myInProgress);
}
- private static String getNetworkTreeKey(NetworkTree tree, boolean recursive) {
- if (tree instanceof NetworkCatalogTree) {
- return ((NetworkCatalogTree) tree).Item.URLByType.get(NetworkCatalogItem.URL_CATALOG);
- } else if (tree instanceof SearchItemTree) {
- return NetworkSearchActivity.SEARCH_RUNNABLE_KEY;
- } else if (recursive && tree.Parent instanceof NetworkTree) {
- if (tree instanceof NetworkAuthorTree
- || tree instanceof NetworkSeriesTree) {
- return getNetworkTreeKey((NetworkTree) tree.Parent, true);
- }
- }
- return null;
- }
-
-
@Override
public void onDestroy() {
- if (myTree != null && myCatalogKey != null && NetworkView.Instance().isInitialized()) {
- NetworkView.Instance().setOpenedActivity(myCatalogKey, null);
+ if (myTree != null && NetworkView.Instance().isInitialized()) {
+ NetworkView.Instance().setOpenedActivity(myTree.getUniqueKey(), null);
}
super.onDestroy();
}
@@ -141,44 +146,15 @@ public class NetworkCatalogActivity extends NetworkBaseActivity implements UserR
}
private final class CatalogAdapter extends BaseAdapter {
-
- private ArrayList mySpecialItems;
-
- public CatalogAdapter() {
- if (myTree instanceof NetworkCatalogRootTree) {
- final NetworkCatalogRootTree rootTree = (NetworkCatalogRootTree)myTree;
- mySpecialItems = new ArrayList();
- if (Util.isAccountRefillingSupported(NetworkCatalogActivity.this, rootTree.Item.Link)) {
- mySpecialItems.add(new RefillAccountTree(rootTree));
- }
- if (mySpecialItems.size() > 0) {
- mySpecialItems.trimToSize();
- } else {
- mySpecialItems = null;
- }
- }
- }
-
public final int getCount() {
- return myTree.subTrees().size() +
- ((mySpecialItems != null && !myInProgress) ? mySpecialItems.size() : 0);
+ return myTree.subTrees().size();
}
public final NetworkTree getItem(int position) {
- if (position < 0) {
+ if (position < 0 || position >= myTree.subTrees().size()) {
return null;
}
- if (position < myTree.subTrees().size()) {
- return (NetworkTree) myTree.subTrees().get(position);
- }
- if (myInProgress) {
- return null;
- }
- position -= myTree.subTrees().size();
- if (mySpecialItems != null && position < mySpecialItems.size()) {
- return mySpecialItems.get(position);
- }
- return null;
+ return (NetworkTree)myTree.subTrees().get(position);
}
public final long getItemId(int position) {
@@ -192,18 +168,26 @@ public class NetworkCatalogActivity extends NetworkBaseActivity implements UserR
void onModelChanged() {
notifyDataSetChanged();
- if (mySpecialItems != null) {
- for (NetworkTree tree: mySpecialItems) {
- tree.invalidateChildren(); // call to update secondString
+ for (FBTree child : myTree.subTrees()) {
+ if (child instanceof TopUpTree) {
+ child.invalidateChildren();
}
}
}
}
+ private static NetworkTree.Key getLoadableNetworkTreeKey(NetworkTree tree) {
+ if ((tree instanceof NetworkAuthorTree || tree instanceof NetworkSeriesTree)
+ && tree.Parent instanceof NetworkTree) {
+ return getLoadableNetworkTreeKey((NetworkTree)tree.Parent);
+ }
+ return tree.getUniqueKey();
+ }
+
@Override
public void onModelChanged() {
final NetworkView networkView = NetworkView.Instance();
- final String key = getNetworkTreeKey(myTree, true);
+ final NetworkTree.Key key = getLoadableNetworkTreeKey(myTree);
myInProgress = key != null && networkView.isInitialized() && networkView.containsItemsLoadingRunnable(key);
getListView().invalidateViews();
@@ -227,9 +211,9 @@ public class NetworkCatalogActivity extends NetworkBaseActivity implements UserR
}
private void doStopLoading() {
- final String key = getNetworkTreeKey(myTree, false);
- if (key != null && NetworkView.Instance().isInitialized()) {
- final ItemsLoadingRunnable runnable = NetworkView.Instance().getItemsLoadingRunnable(key);
+ if (NetworkView.Instance().isInitialized()) {
+ final ItemsLoadingRunnable runnable =
+ NetworkView.Instance().getItemsLoadingRunnable(myTree.getUniqueKey());
if (runnable != null) {
runnable.interruptLoading();
}
diff --git a/src/org/geometerplus/android/fbreader/network/NetworkDialog.java b/src/org/geometerplus/android/fbreader/network/NetworkDialog.java
deleted file mode 100644
index 5a9347a77..000000000
--- a/src/org/geometerplus/android/fbreader/network/NetworkDialog.java
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- * Copyright (C) 2010-2011 Geometer Plus
- *
- * 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 java.util.TreeMap;
-
-import android.app.Activity;
-import android.app.AlertDialog;
-import android.app.Dialog;
-import android.content.DialogInterface;
-import android.os.Handler;
-import android.os.Message;
-import android.view.View;
-
-import org.geometerplus.zlibrary.core.resources.ZLResource;
-
-import org.geometerplus.fbreader.network.INetworkLink;
-import org.geometerplus.fbreader.network.NetworkLibrary;
-
-
-abstract class NetworkDialog {
-
- // dialog identifiers
- public static final int DIALOG_AUTHENTICATION = 0;
- public static final int DIALOG_CUSTOM_CATALOG = 1;
-
- private static final TreeMap ourInstances = new TreeMap();
-
- public static NetworkDialog getDialog(int id) {
- NetworkDialog dlg = ourInstances.get(Integer.valueOf(id));
- if (dlg == null) {
- switch (id) {
- case DIALOG_AUTHENTICATION:
- dlg = new AuthenticationDialog();
- break;
- case DIALOG_CUSTOM_CATALOG:
- dlg = new CustomCatalogDialog();
- break;
- }
- if (dlg != null) {
- dlg.myId = id;
- ourInstances.put(Integer.valueOf(id), dlg);
- }
- }
- return dlg;
- }
-
-
- private class DialogHandler extends Handler {
-
- public Message obtainMessage(int code, boolean invalidateLibrary, String message) {
- return obtainMessage(code, invalidateLibrary ? 1 : 0, 0, message);
- }
-
- @Override
- public void handleMessage(Message message) {
- if (!NetworkView.Instance().isInitialized()) {
- return;
- }
- final NetworkLibrary library = NetworkLibrary.Instance();
- if (message.arg1 != 0) {
- library.invalidateChildren();
- }
- library.invalidateVisibility();
- library.synchronize();
- NetworkView.Instance().fireModelChanged();
- if (message.what < 0) {
- if (message.what == -2) {
- 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((String) message.obj)
- .setIcon(0)
- .setPositiveButton(buttonResource.getResource("ok").getValue(), null)
- .create().show();
- } else {
- myErrorMessage = (String) message.obj;
- myActivity.showDialog(myId);
- return;
- }
- } else if (message.what > 0) {
- if (myOnSuccessRunnable != null) {
- myOnSuccessRunnable.run();
- }
- }
- clearData();
- }
- };
-
-
- protected final ZLResource myResource;
-
- protected int myId;
-
- protected INetworkLink myLink;
- protected String myErrorMessage;
- protected Runnable myOnSuccessRunnable;
- protected Activity myActivity;
-
- protected final DialogHandler myHandler = new DialogHandler();
-
- public NetworkDialog(String key) {
- myResource = ZLResource.resource("dialog").getResource(key);
- }
-
- public static void show(Activity activity, int id, INetworkLink link, Runnable onSuccessRunnable) {
- getDialog(id).showInternal(activity, link, onSuccessRunnable);
- }
-
- private void showInternal(Activity activity, INetworkLink link, Runnable onSuccessRunnable) {
- myLink = link;
- myErrorMessage = null;
- myOnSuccessRunnable = onSuccessRunnable;
- activity.showDialog(myId);
- }
-
-
- protected void sendSuccess(boolean invalidateLibrary) {
- myHandler.sendMessage(myHandler.obtainMessage(1, invalidateLibrary, null));
- }
-
- protected void sendCancel(boolean invalidateLibrary) {
- myHandler.sendMessage(myHandler.obtainMessage(0, invalidateLibrary, null));
- }
-
- protected void sendError(boolean restart, boolean invalidateLibrary, String message) {
- myHandler.sendMessage(myHandler.obtainMessage(restart ? -1 : -2, invalidateLibrary, message));
- }
-
- protected abstract View createLayout();
- protected abstract void clearData();
-
- protected abstract void onPositive(DialogInterface dialog);
- protected abstract void onNegative(DialogInterface dialog);
-
- public final Dialog createDialog(final Activity activity) {
- myActivity = activity;
- final DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int which) {
- if (which == DialogInterface.BUTTON_POSITIVE) {
- onPositive(dialog);
- } else {
- onNegative(dialog);
- }
- }
- };
-
- final View layout = createLayout();
- final ZLResource buttonResource = ZLResource.resource("dialog").getResource("button");
- return new AlertDialog.Builder(activity)
- .setView(layout)
- .setTitle(myResource.getResource("title").getValue())
- .setPositiveButton(buttonResource.getResource("ok").getValue(), listener)
- .setNegativeButton(buttonResource.getResource("cancel").getValue(), listener)
- .setOnCancelListener(new DialogInterface.OnCancelListener() {
- public void onCancel(DialogInterface dialog) {
- onNegative(dialog);
- }
- })
- .create();
- }
-
- public final void prepareDialog(final Activity activity, Dialog dialog) {
- myActivity = activity;
- prepareDialogInternal(dialog);
- }
-
- protected abstract void prepareDialogInternal(Dialog dialog);
-}
diff --git a/src/org/geometerplus/android/fbreader/network/NetworkLibraryActivity.java b/src/org/geometerplus/android/fbreader/network/NetworkLibraryActivity.java
index e4b74009d..83dc7dc82 100644
--- a/src/org/geometerplus/android/fbreader/network/NetworkLibraryActivity.java
+++ b/src/org/geometerplus/android/fbreader/network/NetworkLibraryActivity.java
@@ -24,6 +24,7 @@ import java.util.*;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
+import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
@@ -38,11 +39,44 @@ import org.geometerplus.zlibrary.ui.android.R;
import org.geometerplus.android.util.UIUtil;
-import org.geometerplus.fbreader.network.NetworkTree;
-import org.geometerplus.fbreader.network.NetworkLibrary;
+import org.geometerplus.fbreader.network.*;
+import org.geometerplus.fbreader.network.opds.OPDSCustomLink;
public class NetworkLibraryActivity extends NetworkBaseActivity {
+ static final String ADD_CATALOG = "android.fbreader.action.ADD_CATALOG";
+
+ private static final String ADD_CATALOG_TITLE_KEY = "title";
+ private static final String ADD_CATALOG_SUMMARY_KEY = "summary";
+ private static final String ADD_CATALOG_ID_KEY = "id";
+ private static final String ADD_CATALOG_URLS_MAP_KEY = "urls";
+
+ static void addLinkToIntent(Intent intent, ICustomNetworkLink link) {
+ final String textUrl = link.getUrlInfo(INetworkLink.URL_MAIN).URL;
+ intent.setData(Uri.parse(textUrl));
+ intent
+ .putExtra(ADD_CATALOG_TITLE_KEY, link.getTitle())
+ .putExtra(ADD_CATALOG_SUMMARY_KEY, link.getSummary())
+ .putExtra(ADD_CATALOG_ID_KEY, link.getId())
+ .putExtra(ADD_CATALOG_URLS_MAP_KEY, link.urlInfoMap());
+ }
+
+ static ICustomNetworkLink getLinkFromIntent(Intent intent) {
+ final Uri uri = intent.getData();
+ if (uri == null || !intent.hasExtra(ADD_CATALOG_ID_KEY)) {
+ return null;
+ }
+
+ return new OPDSCustomLink(
+ intent.getIntExtra(ADD_CATALOG_ID_KEY, ICustomNetworkLink.INVALID_ID),
+ uri.getHost(),
+ intent.getStringExtra(ADD_CATALOG_TITLE_KEY),
+ intent.getStringExtra(ADD_CATALOG_SUMMARY_KEY),
+ (HashMap)intent.getSerializableExtra(ADD_CATALOG_URLS_MAP_KEY)
+ );
+ }
+
private NetworkTree myTree;
+ private volatile Intent myIntent;
@Override
public void onCreate(Bundle icicle) {
@@ -50,17 +84,44 @@ public class NetworkLibraryActivity extends NetworkBaseActivity {
requestWindowFeature(Window.FEATURE_NO_TITLE);
setDefaultKeyMode(DEFAULT_KEYS_SEARCH_LOCAL);
+
+ myIntent = getIntent();
+ }
+
+ @Override
+ protected void onNewIntent(Intent intent) {
+ super.onNewIntent(intent);
+
+ processIntent(intent);
+ }
+
+ 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() {
+ final NetworkLibrary library = NetworkLibrary.Instance();
+ library.addCustomLink(link);
+ library.synchronize();
+ NetworkView.Instance().fireModelChangedAsync();
+ getListView().invalidateViews();
+ }
+ });
+ }
+ }
}
private void prepareView() {
if (myTree == null) {
- myTree = NetworkLibrary.Instance().getTree();
+ myTree = NetworkLibrary.Instance().getRootTree();
setListAdapter(new LibraryAdapter());
getListView().invalidateViews();
}
}
- private static Initializator myInitializator;
+ private static Initializator myInitializator;
@Override
public void onResume() {
@@ -74,6 +135,10 @@ public class NetworkLibraryActivity extends NetworkBaseActivity {
}
} else {
prepareView();
+ if (myIntent != null) {
+ processIntent(myIntent);
+ myIntent = null;
+ }
}
}
@@ -114,6 +179,10 @@ public class NetworkLibraryActivity extends NetworkBaseActivity {
String error = null;
try {
NetworkView.Instance().initialize();
+ if (myActivity.myIntent != null) {
+ myActivity.processIntent(myActivity.myIntent);
+ myActivity.myIntent = null;
+ }
} catch (ZLNetworkException e) {
error = e.getMessage();
}
@@ -170,19 +239,11 @@ public class NetworkLibraryActivity extends NetworkBaseActivity {
if (!NetworkView.Instance().isInitialized()) {
return 0;
}
- return myTree.subTrees().size() + 2; // subtrees +
+ return myTree.subTrees().size();
}
public final NetworkTree getItem(int position) {
- final int size = myTree.subTrees().size();
- if (position == 0) {
- return NetworkView.Instance().getSearchItemTree();
- } else if (position > 0 && position <= size) {
- return (NetworkTree)myTree.subTrees().get(position - 1);
- } else if (position == size + 1) {
- return NetworkView.Instance().getAddCustomCatalogItemTree();
- }
- return null;
+ return (NetworkTree)myTree.subTrees().get(position);
}
public final long getItemId(int position) {
@@ -217,11 +278,16 @@ public class NetworkLibraryActivity extends NetworkBaseActivity {
return true;
}
+ private static boolean searchIsInProgress() {
+ return NetworkView.Instance().containsItemsLoadingRunnable(
+ NetworkLibrary.Instance().getSearchItemTree().getUniqueKey()
+ );
+ }
+
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
- final boolean searchInProgress = NetworkView.Instance().containsItemsLoadingRunnable(NetworkSearchActivity.SEARCH_RUNNABLE_KEY);
- menu.findItem(MENU_SEARCH).setEnabled(!searchInProgress);
+ menu.findItem(MENU_SEARCH).setEnabled(!searchIsInProgress());
return true;
}
@@ -259,7 +325,6 @@ public class NetworkLibraryActivity extends NetworkBaseActivity {
}
}
library.setActiveLanguageCodes(newActiveCodes);
- library.invalidateChildren();
library.synchronize();
NetworkView.Instance().fireModelChanged();
}
@@ -289,7 +354,7 @@ public class NetworkLibraryActivity extends NetworkBaseActivity {
@Override
public boolean onSearchRequested() {
- if (NetworkView.Instance().containsItemsLoadingRunnable(NetworkSearchActivity.SEARCH_RUNNABLE_KEY)) {
+ if (searchIsInProgress()) {
return false;
}
final NetworkLibrary library = NetworkLibrary.Instance();
diff --git a/src/org/geometerplus/android/fbreader/network/NetworkSearchActivity.java b/src/org/geometerplus/android/fbreader/network/NetworkSearchActivity.java
index bbca41a07..a88cdc60d 100644
--- a/src/org/geometerplus/android/fbreader/network/NetworkSearchActivity.java
+++ b/src/org/geometerplus/android/fbreader/network/NetworkSearchActivity.java
@@ -32,12 +32,10 @@ import org.geometerplus.zlibrary.core.resources.ZLResource;
import org.geometerplus.zlibrary.core.network.ZLNetworkException;
import org.geometerplus.fbreader.network.*;
+import org.geometerplus.fbreader.network.tree.SearchItemTree;
public class NetworkSearchActivity extends Activity {
-
- public static final String SEARCH_RUNNABLE_KEY = "org.geometerplus.android.fbreader.network.NetworkSearchActivity";
-
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
@@ -57,7 +55,6 @@ public class NetworkSearchActivity extends Activity {
}
private class SearchHandler extends ItemsLoadingHandler {
-
private final SearchItemTree myTree;
public SearchHandler(SearchItemTree tree) {
@@ -65,11 +62,11 @@ public class NetworkSearchActivity extends Activity {
}
@Override
- public void onUpdateItems(List items) {
+ public void onUpdateItems(List items) {
SearchResult result = myTree.getSearchResult();
- for (NetworkLibraryItem item: items) {
+ for (NetworkItem item: items) {
if (item instanceof NetworkBookItem) {
- result.addBook((NetworkBookItem) item);
+ result.addBook((NetworkBookItem)item);
}
}
}
@@ -84,12 +81,12 @@ public class NetworkSearchActivity extends Activity {
@Override
public void onFinish(String errorMessage, boolean interrupted,
- Set uncommitedItems) {
+ Set uncommitedItems) {
if (interrupted) {
myTree.setSearchResult(null);
} else {
myTree.updateSubTrees();
- afterUpdateCatalog(errorMessage, myTree.getSearchResult().empty());
+ afterUpdateCatalog(errorMessage, myTree.getSearchResult().isEmpty());
}
if (NetworkView.Instance().isInitialized()) {
NetworkView.Instance().fireModelChangedAsync();
@@ -99,27 +96,36 @@ public class NetworkSearchActivity extends Activity {
private void afterUpdateCatalog(String errorMessage, boolean childrenEmpty) {
final ZLResource dialogResource = ZLResource.resource("dialog");
ZLResource boxResource = null;
- String msg = null;
+ String msg;
if (errorMessage != null) {
boxResource = dialogResource.getResource("networkError");
msg = errorMessage;
} else if (childrenEmpty) {
boxResource = dialogResource.getResource("emptySearchResults");
msg = boxResource.getResource("message").getValue();
+ } else {
+ return;
}
- if (msg != null) {
- if (NetworkView.Instance().isInitialized()) {
- final NetworkCatalogActivity activity = NetworkView.Instance().getOpenedActivity(SEARCH_RUNNABLE_KEY);
- if (activity != null) {
- final ZLResource buttonResource = dialogResource.getResource("button");
- new AlertDialog.Builder(activity)
- .setTitle(boxResource.getResource("title").getValue())
- .setMessage(msg)
- .setIcon(0)
- .setPositiveButton(buttonResource.getResource("ok").getValue(), null)
- .create().show();
- }
- }
+
+ if (!NetworkView.Instance().isInitialized()) {
+ return;
+ }
+
+ final SearchItemTree tree = NetworkLibrary.Instance().getSearchItemTree();
+ if (tree == null) {
+ return;
+ }
+
+ final NetworkCatalogActivity activity =
+ NetworkView.Instance().getOpenedActivity(tree.getUniqueKey());
+ if (activity != null) {
+ final ZLResource buttonResource = dialogResource.getResource("button");
+ new AlertDialog.Builder(activity)
+ .setTitle(boxResource.getResource("title").getValue())
+ .setMessage(msg)
+ .setIcon(0)
+ .setPositiveButton(buttonResource.getResource("ok").getValue(), null)
+ .create().show();
}
}
}
@@ -148,24 +154,24 @@ public class NetworkSearchActivity extends Activity {
final NetworkLibrary library = NetworkLibrary.Instance();
library.NetworkSearchPatternOption.setValue(pattern);
- if (NetworkView.Instance().containsItemsLoadingRunnable(SEARCH_RUNNABLE_KEY)) {
+ final SearchItemTree tree = library.getSearchItemTree();
+ if (tree == null ||
+ NetworkView.Instance().containsItemsLoadingRunnable(tree.getUniqueKey())) {
return;
}
final String summary = ZLResource.resource("networkView").getResource("searchResults").getValue().replace("%s", pattern);
final SearchResult result = new SearchResult(summary);
- final SearchItemTree tree = NetworkView.Instance().getSearchItemTree();
-
tree.setSearchResult(result);
NetworkView.Instance().fireModelChangedAsync();
final SearchHandler handler = new SearchHandler(tree);
NetworkView.Instance().startItemsLoading(
this,
- SEARCH_RUNNABLE_KEY,
+ tree.getUniqueKey(),
new SearchRunnable(handler, pattern)
);
- NetworkView.Instance().openTree(this, tree, SEARCH_RUNNABLE_KEY);
+ NetworkView.Instance().openTree(this, tree);
}
}
diff --git a/src/org/geometerplus/android/fbreader/network/NetworkView.java b/src/org/geometerplus/android/fbreader/network/NetworkView.java
index 226a30e69..77994cd7b 100644
--- a/src/org/geometerplus/android/fbreader/network/NetworkView.java
+++ b/src/org/geometerplus/android/fbreader/network/NetworkView.java
@@ -33,6 +33,7 @@ import android.view.Menu;
import org.geometerplus.zlibrary.core.network.ZLNetworkException;
import org.geometerplus.fbreader.network.*;
+import org.geometerplus.fbreader.network.tree.NetworkCatalogTree;
class NetworkView {
private static NetworkView ourInstance;
@@ -44,12 +45,13 @@ class NetworkView {
return ourInstance;
}
+ private volatile boolean myInitialized;
+ private final ArrayList myActions = new ArrayList();
+ private RefillAccountActions myTopUpActions;
+
private NetworkView() {
}
-
- private volatile boolean myInitialized;
-
public boolean isInitialized() {
return myInitialized;
}
@@ -64,7 +66,8 @@ class NetworkView {
myActions.add(new NetworkBookActions());
myActions.add(new NetworkCatalogActions());
myActions.add(new SearchItemActions());
- myActions.add(new RefillAccountActions());
+ myTopUpActions = new RefillAccountActions();
+ myActions.add(myTopUpActions);
myActions.add(new AddCustomCatalogItemActions());
myActions.trimToSize();
@@ -85,10 +88,12 @@ class NetworkView {
}
/*
- * NetworkLibraryItem's actions
+ * NetworkItem's actions
*/
- private final ArrayList myActions = new ArrayList();
+ public RefillAccountActions getTopUpActions() {
+ return myTopUpActions;
+ }
public NetworkTreeActions getActions(NetworkTree tree) {
for (NetworkTreeActions actions: myActions) {
@@ -140,9 +145,10 @@ class NetworkView {
* Code for loading network items (running items-loading service and managing items-loading runnables).
*/
- private final HashMap myItemsLoadingRunnables = new HashMap();
+ private final HashMap myItemsLoadingRunnables =
+ new HashMap();
- public void startItemsLoading(Context context, String key, ItemsLoadingRunnable runnable) {
+ public void startItemsLoading(Context context, NetworkTree.Key key, ItemsLoadingRunnable runnable) {
boolean doDownload = false;
synchronized (myItemsLoadingRunnables) {
if (!myItemsLoadingRunnables.containsKey(key)) {
@@ -158,13 +164,13 @@ class NetworkView {
}
}
- ItemsLoadingRunnable getItemsLoadingRunnable(String key) {
+ ItemsLoadingRunnable getItemsLoadingRunnable(NetworkTree.Key key) {
synchronized (myItemsLoadingRunnables) {
return myItemsLoadingRunnables.get(key);
}
}
- void removeItemsLoadingRunnable(String key) {
+ void removeItemsLoadingRunnable(NetworkTree.Key key) {
synchronized (myItemsLoadingRunnables) {
ItemsLoadingRunnable runnable = myItemsLoadingRunnables.remove(key);
if (runnable != null) {
@@ -173,14 +179,14 @@ class NetworkView {
}
}
- public final boolean containsItemsLoadingRunnable(String key) {
+ public final boolean containsItemsLoadingRunnable(NetworkTree.Key key) {
return getItemsLoadingRunnable(key) != null;
}
- public void tryResumeLoading(NetworkBaseActivity activity, NetworkTree tree, String key, Runnable expandRunnable) {
- final ItemsLoadingRunnable runnable = getItemsLoadingRunnable(key);
+ public void tryResumeLoading(NetworkBaseActivity activity, NetworkCatalogTree tree, Runnable expandRunnable) {
+ final ItemsLoadingRunnable runnable = getItemsLoadingRunnable(tree.getUniqueKey());
if (runnable != null && runnable.tryResumeLoading()) {
- openTree(activity, tree, key);
+ openTree(activity, tree);
return;
}
if (runnable == null) {
@@ -264,30 +270,17 @@ class NetworkView {
* Opening Catalogs & managing opened catalogs stack
*/
- private final LinkedList myOpenedStack = new LinkedList();
- private final HashMap myOpenedActivities = new HashMap();
-
- public void openTree(Context context, NetworkTree tree, String key) {
- final int level = tree.Level - 1; // tree.Level == 1 for catalog's root element
- if (level > myOpenedStack.size()) {
- throw new RuntimeException("Unable to open catalog with Level greater than the number of opened catalogs.\n"
- + "Catalog: " + tree.getName() + "\n"
- + "Level: " + level + "\n"
- + "Opened catalogs: " + myOpenedStack.size());
- }
- while (level < myOpenedStack.size()) {
- myOpenedStack.removeLast();
- }
- myOpenedStack.add(tree);
+ private final HashMap myOpenedActivities =
+ new HashMap();
+ public void openTree(Context context, NetworkTree tree) {
context.startActivity(
new Intent(context.getApplicationContext(), NetworkCatalogActivity.class)
- .putExtra(NetworkCatalogActivity.CATALOG_LEVEL_KEY, level)
- .putExtra(NetworkCatalogActivity.CATALOG_KEY_KEY, key)
+ .putExtra(NetworkCatalogActivity.CATALOG_KEY_KEY, tree.getUniqueKey())
);
}
- void setOpenedActivity(String key, NetworkCatalogActivity activity) {
+ void setOpenedActivity(NetworkTree.Key key, NetworkCatalogActivity activity) {
if (activity == null) {
myOpenedActivities.remove(key);
} else {
@@ -295,29 +288,7 @@ class NetworkView {
}
}
- public NetworkCatalogActivity getOpenedActivity(String key) {
+ public NetworkCatalogActivity getOpenedActivity(NetworkTree.Key key) {
return myOpenedActivities.get(key);
}
-
- public NetworkTree getOpenedTree(int level) {
- if (level < 0 || level >= myOpenedStack.size()) {
- return null;
- }
- return myOpenedStack.get(level);
- }
-
- /*
- * Special view items item
- */
-
- private final SearchItemTree mySearchItem = new SearchItemTree();
- private final AddCustomCatalogItemTree myAddCustomCatalogItem = new AddCustomCatalogItemTree();
-
- public SearchItemTree getSearchItemTree() {
- return mySearchItem;
- }
-
- public AddCustomCatalogItemTree getAddCustomCatalogItemTree() {
- return myAddCustomCatalogItem;
- }
}
diff --git a/src/org/geometerplus/android/fbreader/network/RefillAccountActions.java b/src/org/geometerplus/android/fbreader/network/RefillAccountActions.java
index 6107f3bc3..78b025c8d 100644
--- a/src/org/geometerplus/android/fbreader/network/RefillAccountActions.java
+++ b/src/org/geometerplus/android/fbreader/network/RefillAccountActions.java
@@ -26,9 +26,9 @@ import android.view.ContextMenu;
import org.geometerplus.fbreader.network.INetworkLink;
import org.geometerplus.fbreader.network.NetworkTree;
+import org.geometerplus.fbreader.network.tree.TopUpTree;
import org.geometerplus.fbreader.network.authentication.NetworkAuthenticationManager;
-
class RefillAccountActions extends NetworkTreeActions {
public static final int REFILL_VIA_SMS_ITEM_ID = 0;
public static final int REFILL_VIA_BROWSER_ITEM_ID = 1;
@@ -36,14 +36,17 @@ class RefillAccountActions extends NetworkTreeActions {
@Override
public boolean canHandleTree(NetworkTree tree) {
- return tree instanceof RefillAccountTree;
+ return tree instanceof TopUpTree;
}
@Override
public void buildContextMenu(Activity activity, ContextMenu menu, NetworkTree tree) {
+ buildContextMenu(activity, menu, ((TopUpTree)tree).Item.Link);
+ }
+
+ public void buildContextMenu(Activity activity, ContextMenu menu, INetworkLink link) {
menu.setHeaderTitle(getTitleValue("refillTitle"));
- final INetworkLink link = ((RefillAccountTree)tree).Link;
if (Util.isSmsAccountRefillingSupported(activity, link)) {
addMenuItem(menu, REFILL_VIA_SMS_ITEM_ID, "refillViaSms");
}
@@ -54,7 +57,7 @@ class RefillAccountActions extends NetworkTreeActions {
@Override
public int getDefaultActionCode(NetworkBaseActivity activity, NetworkTree tree) {
- return getDefaultActionCode(activity, ((RefillAccountTree)tree).Link);
+ return getDefaultActionCode(activity, ((TopUpTree)tree).Item.Link);
}
private int getDefaultActionCode(Activity activity, INetworkLink link) {
final boolean sms = Util.isSmsAccountRefillingSupported(activity, link);
@@ -86,9 +89,10 @@ class RefillAccountActions extends NetworkTreeActions {
@Override
public boolean runAction(NetworkBaseActivity activity, NetworkTree tree, int actionCode) {
- final INetworkLink link = ((RefillAccountTree)tree).Link;
+ final INetworkLink link = ((TopUpTree)tree).Item.Link;
return runAction(activity, link, actionCode);
}
+
public boolean runAction(Activity activity, INetworkLink link, int actionCode) {
Runnable refillRunnable = null;
switch (actionCode) {
@@ -131,7 +135,7 @@ class RefillAccountActions extends NetworkTreeActions {
if (mgr.mayBeAuthorised(false)) {
refiller.run();
} else {
- NetworkDialog.show(activity, NetworkDialog.DIALOG_AUTHENTICATION, link, new Runnable() {
+ AuthenticationDialog.show(activity, link, new Runnable() {
public void run() {
if (mgr.mayBeAuthorised(false)) {
refiller.run();
diff --git a/src/org/geometerplus/android/fbreader/network/SQLiteNetworkDatabase.java b/src/org/geometerplus/android/fbreader/network/SQLiteNetworkDatabase.java
index 3c3abf2bb..9880ed79c 100644
--- a/src/org/geometerplus/android/fbreader/network/SQLiteNetworkDatabase.java
+++ b/src/org/geometerplus/android/fbreader/network/SQLiteNetworkDatabase.java
@@ -30,6 +30,9 @@ import org.geometerplus.zlibrary.ui.android.library.ZLAndroidApplication;
import org.geometerplus.fbreader.network.ICustomNetworkLink;
import org.geometerplus.fbreader.network.NetworkDatabase;
+import org.geometerplus.fbreader.network.UrlInfo;
+
+import org.geometerplus.android.util.SQLiteUtil;
class SQLiteNetworkDatabase extends NetworkDatabase {
private final SQLiteDatabase myDatabase;
@@ -41,7 +44,7 @@ class SQLiteNetworkDatabase extends NetworkDatabase {
private void migrate() {
final int version = myDatabase.getVersion();
- final int currentCodeVersion = 1;
+ final int currentCodeVersion = 3;
if (version >= currentCodeVersion) {
return;
}
@@ -49,6 +52,10 @@ class SQLiteNetworkDatabase extends NetworkDatabase {
switch (version) {
case 0:
createTables();
+ case 1:
+ updateTables1();
+ case 2:
+ updateTables2();
}
myDatabase.setTransactionSuccessful();
myDatabase.endTransaction();
@@ -67,33 +74,30 @@ class SQLiteNetworkDatabase extends NetworkDatabase {
}
}
- private static void bindString(SQLiteStatement statement, int index, String value) {
- if (value != null) {
- statement.bindString(index, value);
- } else {
- statement.bindNull(index);
- }
- }
-
@Override
protected void loadCustomLinks(ICustomLinksHandler handler) {
- final Cursor cursor = myDatabase.rawQuery("SELECT link_id,title,site_name,summary,icon FROM CustomLinks", null);
- final HashMap linksMap = new HashMap();
+ final Cursor cursor = myDatabase.rawQuery("SELECT link_id,title,site_name,summary FROM Links", null);
+ final HashMap linksMap = new HashMap();
while (cursor.moveToNext()) {
final int id = cursor.getInt(0);
final String title = cursor.getString(1);
final String siteName = cursor.getString(2);
final String summary = cursor.getString(3);
- final String icon = cursor.getString(4);
linksMap.clear();
- final Cursor linksCursor = myDatabase.rawQuery("SELECT key,url FROM CustomLinkUrls WHERE link_id = " + id, null);
+ final Cursor linksCursor = myDatabase.rawQuery("SELECT key,url,update_time FROM LinkUrls WHERE link_id = " + id, null);
while (linksCursor.moveToNext()) {
- linksMap.put(linksCursor.getString(0), linksCursor.getString(1));
+ linksMap.put(
+ linksCursor.getString(0),
+ new UrlInfo(
+ linksCursor.getString(1),
+ SQLiteUtil.getDate(linksCursor, 2)
+ )
+ );
}
linksCursor.close();
- handler.handleCustomLinkData(id, siteName, title, summary, icon, linksMap);
+ handler.handleCustomLinkData(id, siteName, title, summary, linksMap);
}
cursor.close();
}
@@ -111,14 +115,14 @@ class SQLiteNetworkDatabase extends NetworkDatabase {
if (link.getId() == ICustomNetworkLink.INVALID_ID) {
if (myInsertCustomLinkStatement == null) {
myInsertCustomLinkStatement = myDatabase.compileStatement(
- "INSERT INTO CustomLinks (title,site_name,summary,icon) VALUES (?,?,?,?)"
+ "INSERT INTO Links (title,site_name,summary) VALUES (?,?,?)"
);
}
statement = myInsertCustomLinkStatement;
} else {
if (myUpdateCustomLinkStatement == null) {
myUpdateCustomLinkStatement = myDatabase.compileStatement(
- "UPDATE CustomLinks SET title = ?, site_name = ?, summary =?, icon = ? "
+ "UPDATE Links SET title = ?, site_name = ?, summary =? "
+ "WHERE link_id = ?"
);
}
@@ -127,55 +131,61 @@ class SQLiteNetworkDatabase extends NetworkDatabase {
statement.bindString(1, link.getTitle());
statement.bindString(2, link.getSiteName());
- bindString(statement, 3, link.getSummary());
- bindString(statement, 4, link.getIcon());
+ SQLiteUtil.bindString(statement, 3, link.getSummary());
final long id;
- final HashMap linksMap = new HashMap();
+ final HashMap linksMap = new HashMap();
if (statement == myInsertCustomLinkStatement) {
id = statement.executeInsert();
link.setId((int) id);
} else {
id = link.getId();
- statement.bindLong(5, id);
+ statement.bindLong(4, id);
statement.execute();
- final Cursor linksCursor = myDatabase.rawQuery("SELECT key,url FROM CustomLinkUrls WHERE link_id = " + link.getId(), null);
+ final Cursor linksCursor = myDatabase.rawQuery("SELECT key,url,update_time FROM LinkUrls WHERE link_id = " + link.getId(), null);
while (linksCursor.moveToNext()) {
- linksMap.put(linksCursor.getString(0), linksCursor.getString(1));
+ linksMap.put(
+ linksCursor.getString(0),
+ new UrlInfo(
+ linksCursor.getString(1),
+ SQLiteUtil.getDate(linksCursor, 2)
+ )
+ );
}
linksCursor.close();
}
- for (String key: link.getLinkKeys()) {
- final String value = link.getLink(key);
- final String dbValue = linksMap.remove(key);
+ for (String key : link.getUrlKeys()) {
+ final UrlInfo info = link.getUrlInfo(key);
+ final UrlInfo dbInfo = linksMap.remove(key);
final SQLiteStatement urlStatement;
- if (dbValue == null) {
+ if (dbInfo == null) {
if (myInsertCustomLinkUrlStatement == null) {
myInsertCustomLinkUrlStatement = myDatabase.compileStatement(
- "INSERT INTO CustomLinkUrls(url,link_id,key) VALUES (?,?,?)");
+ "INSERT OR REPLACE INTO LinkUrls(url,update_time,link_id,key) VALUES (?,?,?,?)");
}
urlStatement = myInsertCustomLinkUrlStatement;
- } else if (!value.equals(dbValue)) {
+ } else if (!info.equals(dbInfo)) {
if (myUpdateCustomLinkUrlStatement == null) {
myUpdateCustomLinkUrlStatement = myDatabase.compileStatement(
- "UPDATE CustomLinkUrls SET url = ? WHERE link_id = ? AND key = ?");
+ "UPDATE LinkUrls SET url = ?, update_time = ? WHERE link_id = ? AND key = ?");
}
urlStatement = myUpdateCustomLinkUrlStatement;
} else {
continue;
}
- urlStatement.bindString(1, value);
- urlStatement.bindLong(2, id);
- urlStatement.bindString(3, key);
+ SQLiteUtil.bindString(urlStatement, 1, info.URL);
+ SQLiteUtil.bindDate(urlStatement, 2, info.Updated);
+ urlStatement.bindLong(3, id);
+ urlStatement.bindString(4, key);
urlStatement.execute();
}
for (String key: linksMap.keySet()) {
if (myDeleteCustomLinkUrlStatement == null) {
myDeleteCustomLinkUrlStatement = myDatabase.compileStatement(
- "DELETE FROM CustomLinkUrls WHERE link_id = ? AND key = ?");
+ "DELETE FROM LinkUrls WHERE link_id = ? AND key = ?");
}
myDeleteCustomLinkUrlStatement.bindLong(1, id);
myDeleteCustomLinkUrlStatement.bindString(2, key);
@@ -197,14 +207,14 @@ class SQLiteNetworkDatabase extends NetworkDatabase {
final long id = link.getId();
if (myDeleteAllCustomLinksStatement == null) {
myDeleteAllCustomLinksStatement = myDatabase.compileStatement(
- "DELETE FROM CustomLinkUrls WHERE link_id = ?");
+ "DELETE FROM LinkUrls WHERE link_id = ?");
}
myDeleteAllCustomLinksStatement.bindLong(1, id);
myDeleteAllCustomLinksStatement.execute();
if (myDeleteCustomLinkStatement == null) {
myDeleteCustomLinkStatement = myDatabase.compileStatement(
- "DELETE FROM CustomLinks WHERE link_id = ?"
+ "DELETE FROM Links WHERE link_id = ?"
);
}
myDeleteCustomLinkStatement.bindLong(1, id);
@@ -230,4 +240,46 @@ class SQLiteNetworkDatabase extends NetworkDatabase {
"url TEXT NOT NULL," +
"CONSTRAINT CustomLinkUrls_PK PRIMARY KEY (key, link_id))");
}
+
+ private void updateTables1() {
+ myDatabase.execSQL("ALTER TABLE CustomLinks RENAME TO CustomLinks_Obsolete");
+ myDatabase.execSQL(
+ "CREATE TABLE CustomLinks(" +
+ "link_id INTEGER PRIMARY KEY," +
+ "title TEXT NOT NULL," +
+ "site_name TEXT NOT NULL," +
+ "summary TEXT," +
+ "icon TEXT)");
+ myDatabase.execSQL("INSERT INTO CustomLinks (link_id,title,site_name,summary,icon) SELECT link_id,title,site_name,summary,icon FROM CustomLinks_Obsolete");
+ myDatabase.execSQL("DROP TABLE CustomLinks_Obsolete");
+
+ myDatabase.execSQL(
+ "CREATE TABLE LinkUrls(" +
+ "key TEXT NOT NULL," +
+ "link_id INTEGER NOT NULL REFERENCES CustomLinks(link_id)," +
+ "url TEXT," +
+ "update_time INTEGER," +
+ "CONSTRAINT LinkUrls_PK PRIMARY KEY (key, link_id))");
+ myDatabase.execSQL("INSERT INTO LinkUrls (key,link_id,url) SELECT key,link_id,url FROM CustomLinkUrls");
+ myDatabase.execSQL("DROP TABLE CustomLinkUrls");
+ }
+
+ private void updateTables2() {
+ myDatabase.execSQL(
+ "CREATE TABLE Links(" +
+ "link_id INTEGER PRIMARY KEY," +
+ "title TEXT NOT NULL," +
+ "site_name TEXT NOT NULL," +
+ "summary TEXT)");
+ myDatabase.execSQL("INSERT INTO Links (link_id,title,site_name,summary) SELECT link_id,title,site_name,summary FROM CustomLinks");
+ final Cursor cursor = myDatabase.rawQuery("SELECT link_id,icon FROM CustomLinks", null);
+ while (cursor.moveToNext()) {
+ final int id = cursor.getInt(0);
+ final String url = cursor.getString(1);
+ myDatabase.execSQL("INSERT INTO LinkUrls (key,link_id,url) VALUES " +
+ "('icon'," + id + ",'" + url + "')");
+ }
+ cursor.close();
+ myDatabase.execSQL("DROP TABLE CustomLinks");
+ }
}
diff --git a/src/org/geometerplus/android/fbreader/network/SearchItemActions.java b/src/org/geometerplus/android/fbreader/network/SearchItemActions.java
index 74d4ff35f..043cf73ff 100644
--- a/src/org/geometerplus/android/fbreader/network/SearchItemActions.java
+++ b/src/org/geometerplus/android/fbreader/network/SearchItemActions.java
@@ -25,7 +25,7 @@ import android.view.ContextMenu;
import org.geometerplus.fbreader.network.NetworkTree;
import org.geometerplus.fbreader.network.SearchResult;
-
+import org.geometerplus.fbreader.network.tree.SearchItemTree;
class SearchItemActions extends NetworkTreeActions {
@@ -39,7 +39,7 @@ class SearchItemActions extends NetworkTreeActions {
@Override
public String getTreeTitle(NetworkTree tree) {
- final SearchResult result = ((SearchItemTree) tree).getSearchResult();
+ final SearchResult result = ((SearchItemTree)tree).getSearchResult();
if (result != null) {
return result.Summary;
}
@@ -50,7 +50,7 @@ class SearchItemActions extends NetworkTreeActions {
public void buildContextMenu(Activity activity, ContextMenu menu, NetworkTree tree) {
menu.setHeaderTitle(tree.getName());
- final boolean isLoading = NetworkView.Instance().containsItemsLoadingRunnable(NetworkSearchActivity.SEARCH_RUNNABLE_KEY);
+ final boolean isLoading = NetworkView.Instance().containsItemsLoadingRunnable(tree.getUniqueKey());
if (!isLoading) {
addMenuItem(menu, RUN_SEARCH_ITEM_ID, "search");
@@ -61,7 +61,7 @@ class SearchItemActions extends NetworkTreeActions {
@Override
public int getDefaultActionCode(NetworkBaseActivity activity, NetworkTree tree) {
- final boolean isLoading = NetworkView.Instance().containsItemsLoadingRunnable(NetworkSearchActivity.SEARCH_RUNNABLE_KEY);
+ final boolean isLoading = NetworkView.Instance().containsItemsLoadingRunnable(tree.getUniqueKey());
if (!isLoading) {
return RUN_SEARCH_ITEM_ID;
}
diff --git a/src/org/geometerplus/android/fbreader/network/Util.java b/src/org/geometerplus/android/fbreader/network/Util.java
index 20e07c009..bdfe5c80a 100644
--- a/src/org/geometerplus/android/fbreader/network/Util.java
+++ b/src/org/geometerplus/android/fbreader/network/Util.java
@@ -49,7 +49,7 @@ abstract class Util implements UserRegistrationConstants {
return testService(
activity,
REGISTRATION_ACTION,
- link.getLink(INetworkLink.URL_SIGN_UP)
+ link.getUrlInfo(INetworkLink.URL_SIGN_UP).URL
);
}
@@ -57,12 +57,12 @@ abstract class Util implements UserRegistrationConstants {
try {
final Intent intent = new Intent(
REGISTRATION_ACTION,
- Uri.parse(link.getLink(INetworkLink.URL_SIGN_UP))
+ Uri.parse(link.getUrlInfo(INetworkLink.URL_SIGN_UP).URL)
);
if (PackageUtil.canBeStarted(activity, intent)) {
activity.startActivityForResult(new Intent(
REGISTRATION_ACTION,
- Uri.parse(link.getLink(INetworkLink.URL_SIGN_UP))
+ Uri.parse(link.getUrlInfo(INetworkLink.URL_SIGN_UP).URL)
), USER_REGISTRATION_REQUEST_CODE);
}
} catch (ActivityNotFoundException e) {
@@ -93,7 +93,7 @@ abstract class Util implements UserRegistrationConstants {
return testService(
activity,
SMS_REFILLING_ACTION,
- link.getLink(INetworkLink.URL_MAIN)
+ link.getUrlInfo(INetworkLink.URL_MAIN).URL
);
}
@@ -101,7 +101,7 @@ abstract class Util implements UserRegistrationConstants {
try {
final Intent intent = new Intent(
SMS_REFILLING_ACTION,
- Uri.parse(link.getLink(INetworkLink.URL_MAIN))
+ Uri.parse(link.getUrlInfo(INetworkLink.URL_MAIN).URL)
);
final NetworkAuthenticationManager mgr = link.authenticationManager();
if (mgr != null) {
@@ -117,7 +117,7 @@ abstract class Util implements UserRegistrationConstants {
}
static boolean isBrowserAccountRefillingSupported(Activity activity, INetworkLink link) {
- return link.getLink(INetworkLink.URL_REFILL_ACCOUNT) != null;
+ return link.getUrlInfo(INetworkLink.URL_REFILL_ACCOUNT).URL != null;
}
static void openInBrowser(Context context, String url) {
diff --git a/src/org/geometerplus/android/util/SQLiteUtil.java b/src/org/geometerplus/android/util/SQLiteUtil.java
new file mode 100644
index 000000000..c4f411e3b
--- /dev/null
+++ b/src/org/geometerplus/android/util/SQLiteUtil.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2009-2011 Geometer Plus
+ *
+ * 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.util;
+
+import java.util.Date;
+
+import android.database.sqlite.SQLiteStatement;
+import android.database.Cursor;
+
+public abstract class SQLiteUtil {
+ public static void bindString(SQLiteStatement statement, int index, String value) {
+ if (value != null) {
+ statement.bindString(index, value);
+ } else {
+ statement.bindNull(index);
+ }
+ }
+
+ public static void bindDate(SQLiteStatement statement, int index, Date value) {
+ if (value != null) {
+ statement.bindLong(index, value.getTime());
+ } else {
+ statement.bindNull(index);
+ }
+ }
+
+ public static Date getDate(Cursor cursor, int index) {
+ if (cursor.isNull(index)) {
+ return null;
+ }
+ return new Date(cursor.getLong(index));
+ }
+}
diff --git a/src/org/geometerplus/android/util/UIUtil.java b/src/org/geometerplus/android/util/UIUtil.java
index c6fe8dbc1..1471a5906 100644
--- a/src/org/geometerplus/android/util/UIUtil.java
+++ b/src/org/geometerplus/android/util/UIUtil.java
@@ -110,19 +110,21 @@ public abstract class UIUtil {
runner.start();
}
+ public static void showErrorMessageText(Context context, String text) {
+ Toast.makeText(context, text, Toast.LENGTH_SHORT).show();
+ }
+
public static void showErrorMessage(Context context, String resourceKey) {
- Toast.makeText(
+ showErrorMessageText(
context,
- ZLResource.resource("errorMessage").getResource(resourceKey).getValue(),
- Toast.LENGTH_SHORT
- ).show();
+ ZLResource.resource("errorMessage").getResource(resourceKey).getValue()
+ );
}
public static void showErrorMessage(Context context, String resourceKey, String parameter) {
- Toast.makeText(
+ showErrorMessageText(
context,
- ZLResource.resource("errorMessage").getResource(resourceKey).getValue().replace("%s", parameter),
- Toast.LENGTH_SHORT
- ).show();
+ ZLResource.resource("errorMessage").getResource(resourceKey).getValue().replace("%s", parameter)
+ );
}
}
diff --git a/src/org/geometerplus/fbreader/formats/oeb/OEBAnnotationReader.java b/src/org/geometerplus/fbreader/formats/oeb/OEBAnnotationReader.java
index a3ceb3fa6..219727575 100644
--- a/src/org/geometerplus/fbreader/formats/oeb/OEBAnnotationReader.java
+++ b/src/org/geometerplus/fbreader/formats/oeb/OEBAnnotationReader.java
@@ -32,7 +32,7 @@ class OEBAnnotationReader extends ZLXMLReaderAdapter implements XMLNamespaces {
private static final int READ_DESCRIPTION = 1;
private int myReadState;
- private final StringBuffer myBuffer = new StringBuffer();
+ private final StringBuilder myBuffer = new StringBuilder();
String readAnnotation(ZLFile file) {
myReadState = READ_NONE;
diff --git a/src/org/geometerplus/fbreader/formats/oeb/OEBMetaInfoReader.java b/src/org/geometerplus/fbreader/formats/oeb/OEBMetaInfoReader.java
index 6588e4d99..a3d8d4fa9 100644
--- a/src/org/geometerplus/fbreader/formats/oeb/OEBMetaInfoReader.java
+++ b/src/org/geometerplus/fbreader/formats/oeb/OEBMetaInfoReader.java
@@ -83,7 +83,7 @@ class OEBMetaInfoReader extends ZLXMLReaderAdapter implements XMLNamespaces {
private int myReadState;
private boolean myReadMetaData;
- private final StringBuffer myBuffer = new StringBuffer();
+ private final StringBuilder myBuffer = new StringBuilder();
@Override
public boolean processNamespaces() {
diff --git a/src/org/geometerplus/fbreader/network/AbstractNetworkLink.java b/src/org/geometerplus/fbreader/network/AbstractNetworkLink.java
index 0fbb794fb..681be324d 100644
--- a/src/org/geometerplus/fbreader/network/AbstractNetworkLink.java
+++ b/src/org/geometerplus/fbreader/network/AbstractNetworkLink.java
@@ -19,19 +19,19 @@
package org.geometerplus.fbreader.network;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeMap;
+import java.util.*;
import org.geometerplus.zlibrary.core.util.ZLMiscUtil;
+import org.geometerplus.zlibrary.core.options.ZLStringListOption;
-public abstract class AbstractNetworkLink implements INetworkLink {
+public abstract class AbstractNetworkLink implements INetworkLink, Basket {
protected String mySiteName;
protected String myTitle;
protected String mySummary;
- protected String myIcon;
protected final String myLanguage;
- protected final TreeMap myLinks;
+ protected final TreeMap myInfos;
+
+ private ZLStringListOption myBooksInBasketOption;
/**
* Creates new NetworkLink instance.
@@ -39,65 +39,114 @@ public abstract class AbstractNetworkLink implements INetworkLink {
* @param siteName name of the corresponding website. Must be not null
.
* @param title title of the corresponding library item. Must be not null
.
* @param summary description of the corresponding library item. Can be null
.
- * @param icon string contains link's icon data/url. Can be null
.
* @param language language of the catalog. If null
we assume this catalog is multilanguage.
- * @param links map contains URLs with their identifiers; must always contain one URL with URL_MAIN
identifier
+ * @param infos map contains URL infos with their identifiers; must always contain one URL with URL_MAIN
identifier
*/
- public AbstractNetworkLink(String siteName, String title, String summary, String icon, String language, Map links) {
+ public AbstractNetworkLink(String siteName, String title, String summary, String language, Map infos) {
mySiteName = siteName;
myTitle = title;
mySummary = summary;
- myIcon = icon;
myLanguage = language != null ? language : "multi";
- myLinks = new TreeMap(links);
+ myInfos = new TreeMap(infos);
}
- public String getSiteName() {
+ public final String getSiteName() {
return mySiteName;
}
- public String getTitle() {
+ public final String getTitle() {
return myTitle;
}
- public String getSummary() {
+ public final String getSummary() {
return mySummary;
}
- public String getIcon() {
- return myIcon;
- }
-
- public String getLanguage() {
+ public final String getLanguage() {
return myLanguage;
}
- public String getLink(String urlKey) {
- return myLinks.get(urlKey);
+ public final HashMap urlInfoMap() {
+ return new HashMap(myInfos);
}
- public Set getLinkKeys() {
- return myLinks.keySet();
+ public final UrlInfo getUrlInfo(String urlKey) {
+ final UrlInfo info = myInfos.get(urlKey);
+ return info != null ? info : UrlInfo.NULL;
}
- public NetworkOperationData createOperationData(INetworkLink link,
- NetworkOperationData.OnNewItemListener listener) {
- return new NetworkOperationData(link, listener);
+ public final Set getUrlKeys() {
+ return myInfos.keySet();
+ }
+
+ public final void setSupportsBasket() {
+ if (myBooksInBasketOption == null) {
+ myBooksInBasketOption = new ZLStringListOption(mySiteName, "Basket", null);
+ }
+ }
+
+ public final Basket basket() {
+ return myBooksInBasketOption != null ? this : null;
+ }
+
+ // method from Basket interface
+ public final void add(NetworkBookItem book) {
+ if (book.Id != null && !"".equals(book.Id)) {
+ List ids = myBooksInBasketOption.getValue();
+ if (!ids.contains(book.Id)) {
+ ids = new ArrayList(ids);
+ ids.add(book.Id);
+ myBooksInBasketOption.setValue(ids);
+ }
+ }
+ }
+
+ // method from Basket interface
+ public final void remove(NetworkBookItem book) {
+ if (book.Id != null && !"".equals(book.Id)) {
+ List ids = myBooksInBasketOption.getValue();
+ if (ids.contains(book.Id)) {
+ ids = new ArrayList(ids);
+ ids.remove(book.Id);
+ myBooksInBasketOption.setValue(ids);
+ }
+ }
+ }
+
+ // method from Basket interface
+ public final void clear() {
+ myBooksInBasketOption.setValue(null);
+ }
+
+ // method from Basket interface
+ public final boolean contains(NetworkBookItem book) {
+ return myBooksInBasketOption.getValue().contains(book.Id);
+ }
+
+ // method from Basket interface
+ public final List bookIds() {
+ return myBooksInBasketOption.getValue();
+ }
+
+ public NetworkOperationData createOperationData(NetworkOperationData.OnNewItemListener listener) {
+ return new NetworkOperationData(this, listener);
}
@Override
public String toString() {
- String icon = myIcon;
- if (icon.length() > 64) {
- icon = icon.substring(0, 61) + "...";
+ String icon = getUrlInfo(URL_ICON).URL;
+ if (icon != null) {
+ if (icon.length() > 64) {
+ icon = icon.substring(0, 61) + "...";
+ }
+ icon = icon.replaceAll("\n", "");
}
- icon = icon.replaceAll("\n", "");
return "AbstractNetworkLink: {"
+ "siteName=" + mySiteName
+ "; title=" + myTitle
+ "; summary=" + mySummary
+ "; icon=" + icon
- + "; links=" + myLinks
+ + "; infos=" + myInfos
+ "}";
}
@@ -114,8 +163,7 @@ public abstract class AbstractNetworkLink implements INetworkLink {
if (!mySiteName.equals(lnk.mySiteName)
|| !myTitle.equals(lnk.myTitle)
|| !ZLMiscUtil.equals(mySummary, lnk.mySummary)
- || !ZLMiscUtil.equals(myIcon, lnk.myIcon)
- || !ZLMiscUtil.mapsEquals(myLinks, lnk.myLinks)) {
+ || !ZLMiscUtil.mapsEquals(myInfos, lnk.myInfos)) {
return false;
}
return true;
diff --git a/src/org/geometerplus/fbreader/network/Basket.java b/src/org/geometerplus/fbreader/network/Basket.java
new file mode 100644
index 000000000..c99ef1e4b
--- /dev/null
+++ b/src/org/geometerplus/fbreader/network/Basket.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2010-2011 Geometer Plus
+ *
+ * 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.*;
+
+public interface Basket {
+ void add(NetworkBookItem book);
+ void remove(NetworkBookItem book);
+ boolean contains(NetworkBookItem book);
+ List bookIds();
+ void clear();
+}
diff --git a/src/org/geometerplus/fbreader/network/ICustomNetworkLink.java b/src/org/geometerplus/fbreader/network/ICustomNetworkLink.java
index 5b6981116..b99172214 100644
--- a/src/org/geometerplus/fbreader/network/ICustomNetworkLink.java
+++ b/src/org/geometerplus/fbreader/network/ICustomNetworkLink.java
@@ -21,29 +21,24 @@ package org.geometerplus.fbreader.network;
import org.geometerplus.zlibrary.core.network.ZLNetworkException;
-public interface ICustomNetworkLink extends INetworkLink {
+import java.util.HashMap;
+public interface ICustomNetworkLink extends INetworkLink {
public static final int INVALID_ID = -1;
int getId();
void setId(int id);
- interface SaveLinkListener {
- void onSaveLink(ICustomNetworkLink link);
- }
-
- void setSaveLinkListener(SaveLinkListener listener);
- void saveLink();
-
void setSiteName(String name);
void setTitle(String title);
void setSummary(String summary);
- void setIcon(String icon);
- void setLink(String urlKey, String url);
- void removeLink(String urlKey);
+ HashMap urlInfoMap();
+ void setUrl(String urlKey, String url);
+ void removeUrl(String urlKey);
- void reloadInfo() throws ZLNetworkException;
+ boolean isObsolete(long milliSeconds);
+ void reloadInfo(boolean urlsOnly) throws ZLNetworkException;
// returns true if next methods have changed link's data:
// setSiteName, setTitle, setSummary, setIcon, setLink, removeLink
diff --git a/src/org/geometerplus/fbreader/network/INetworkLink.java b/src/org/geometerplus/fbreader/network/INetworkLink.java
index f2cdd6fdb..2dadbdb57 100644
--- a/src/org/geometerplus/fbreader/network/INetworkLink.java
+++ b/src/org/geometerplus/fbreader/network/INetworkLink.java
@@ -19,7 +19,7 @@
package org.geometerplus.fbreader.network;
-import java.util.Set;
+import java.util.*;
import org.geometerplus.zlibrary.core.network.ZLNetworkRequest;
@@ -27,9 +27,9 @@ import org.geometerplus.fbreader.network.authentication.NetworkAuthenticationMan
public interface INetworkLink {
-
String URL_MAIN = "main";
String URL_SEARCH = "search";
+ String URL_ICON = "icon";
String URL_SIGN_IN = "signIn";
String URL_SIGN_OUT = "signOut";
String URL_SIGN_UP = "signUp";
@@ -39,14 +39,20 @@ public interface INetworkLink {
String getSiteName();
String getTitle();
String getSummary();
- String getIcon();
- String getLink(String urlKey);
+
+ UrlInfo getUrlInfo(String urlKey);
+ Set getUrlKeys();
+
+ /**
+ * @return 2-letters language code or special token "multi"
+ */
String getLanguage();
- Set getLinkKeys();
-
- NetworkOperationData createOperationData(INetworkLink link,
- NetworkOperationData.OnNewItemListener listener);
+ /**
+ * @param listener Network operation listener
+ * @return instance, which represents the state of the network operation.
+ */
+ NetworkOperationData createOperationData(NetworkOperationData.OnNewItemListener listener);
ZLNetworkRequest simpleSearchRequest(String pattern, NetworkOperationData data);
ZLNetworkRequest resume(NetworkOperationData data);
@@ -54,5 +60,7 @@ public interface INetworkLink {
NetworkCatalogItem libraryItem();
NetworkAuthenticationManager authenticationManager();
+ Basket basket();
+
String rewriteUrl(String url, boolean isUrlExternal);
}
diff --git a/src/org/geometerplus/fbreader/network/NetworkBookItem.java b/src/org/geometerplus/fbreader/network/NetworkBookItem.java
index 5d151b0f6..0381e2306 100644
--- a/src/org/geometerplus/fbreader/network/NetworkBookItem.java
+++ b/src/org/geometerplus/fbreader/network/NetworkBookItem.java
@@ -25,7 +25,7 @@ import java.io.File;
import org.geometerplus.fbreader.network.authentication.NetworkAuthenticationManager;
-public final class NetworkBookItem extends NetworkLibraryItem {
+public final class NetworkBookItem extends NetworkItem {
public static class AuthorData implements Comparable {
public final String DisplayName;
@@ -59,7 +59,7 @@ public final class NetworkBookItem extends NetworkLibraryItem {
return false;
}
final AuthorData data = (AuthorData) o;
- return SortKey == data.SortKey && DisplayName == data.DisplayName;
+ return SortKey.equals(data.SortKey) && DisplayName.equals(data.DisplayName);
}
@Override
@@ -80,7 +80,7 @@ public final class NetworkBookItem extends NetworkLibraryItem {
private final LinkedList myReferences;
/**
- * Creates new NetworkLibraryItem instance.
+ * Creates new NetworkItem instance.
*
* @param link corresponding NetworkLink object. Must be not null
.
* @param id string that uniquely identifies this book item. Must be not null
.
diff --git a/src/org/geometerplus/fbreader/network/NetworkBookItemComparator.java b/src/org/geometerplus/fbreader/network/NetworkBookItemComparator.java
index eaf162871..faf44f04b 100644
--- a/src/org/geometerplus/fbreader/network/NetworkBookItemComparator.java
+++ b/src/org/geometerplus/fbreader/network/NetworkBookItemComparator.java
@@ -22,10 +22,8 @@ package org.geometerplus.fbreader.network;
import java.util.Comparator;
import java.util.LinkedList;
-
-public final class NetworkBookItemComparator implements Comparator {
-
- public int compare(NetworkLibraryItem item0, NetworkLibraryItem item1) {
+public final class NetworkBookItemComparator implements Comparator {
+ public int compare(NetworkItem item0, NetworkItem item1) {
final boolean item0isABook = item0 instanceof NetworkBookItem;
final boolean item1isABook = item1 instanceof NetworkBookItem;
diff --git a/src/org/geometerplus/fbreader/network/NetworkCatalogItem.java b/src/org/geometerplus/fbreader/network/NetworkCatalogItem.java
index b04f242b2..bd10505e3 100644
--- a/src/org/geometerplus/fbreader/network/NetworkCatalogItem.java
+++ b/src/org/geometerplus/fbreader/network/NetworkCatalogItem.java
@@ -23,10 +23,12 @@ 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 NetworkLibraryItem {
+public abstract class NetworkCatalogItem extends NetworkItem {
// catalog types:
public static enum CatalogType {
@@ -65,21 +67,6 @@ public abstract class NetworkCatalogItem extends NetworkLibraryItem {
this(link, title, summary, cover, urlByType, Accessibility.ALWAYS, CatalogType.OTHER);
}
- /**
- * Creates new NetworkCatalogItem instance with specified accessibility and CatalogType.OTHER
type.
- *
- * @param link corresponding NetworkLink object. Must be not null
.
- * @param title title of this library item. Must be not null
.
- * @param summary description of this library item. Can be null
.
- * @param cover cover url. Can be null
.
- * @param urlByType map contains URLs and their types. Must be not null
.
- * @param accessibility value defines when this library item will be accessible
- * in the network library view.
- */
- public NetworkCatalogItem(INetworkLink link, String title, String summary, String cover, Map urlByType, Accessibility accessibility) {
- this(link, title, summary, cover, urlByType, accessibility, CatalogType.OTHER);
- }
-
/**
* Creates new NetworkCatalogItem instance with specified accessibility and type.
*
@@ -144,11 +131,44 @@ public abstract class NetworkCatalogItem extends NetworkLibraryItem {
return ZLBoolean3.B3_UNDEFINED;
}
case HAS_BOOKS:
- if (mgr != null && mgr.purchasedBooks().size() > 0) {
+ if ((Link.basket() != null && Link.basket().bookIds().size() > 0) ||
+ (mgr != null && mgr.purchasedBooks().size() > 0)) {
return ZLBoolean3.B3_TRUE;
} else {
return ZLBoolean3.B3_FALSE;
}
}
}
+
+ /**
+ * 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);
+ }
}
diff --git a/src/org/geometerplus/fbreader/network/NetworkDatabase.java b/src/org/geometerplus/fbreader/network/NetworkDatabase.java
index 3961a3529..5c50013c8 100644
--- a/src/org/geometerplus/fbreader/network/NetworkDatabase.java
+++ b/src/org/geometerplus/fbreader/network/NetworkDatabase.java
@@ -35,7 +35,7 @@ public abstract class NetworkDatabase {
protected abstract void executeAsATransaction(Runnable actions);
public interface ICustomLinksHandler {
- void handleCustomLinkData(int id, String siteName, String title, String summary, String icon, Map links);
+ void handleCustomLinkData(int id, String siteName, String title, String summary, Map infos);
}
protected abstract void loadCustomLinks(ICustomLinksHandler handler);
diff --git a/src/org/geometerplus/fbreader/network/NetworkLibraryItem.java b/src/org/geometerplus/fbreader/network/NetworkItem.java
similarity index 88%
rename from src/org/geometerplus/fbreader/network/NetworkLibraryItem.java
rename to src/org/geometerplus/fbreader/network/NetworkItem.java
index cb312615c..1970da833 100644
--- a/src/org/geometerplus/fbreader/network/NetworkLibraryItem.java
+++ b/src/org/geometerplus/fbreader/network/NetworkItem.java
@@ -19,8 +19,7 @@
package org.geometerplus.fbreader.network;
-public abstract class NetworkLibraryItem {
-
+public abstract class NetworkItem {
public final INetworkLink Link;
public final String Title;
public final String Summary;
@@ -29,14 +28,14 @@ public abstract class NetworkLibraryItem {
//public org.geometerplus.fbreader.network.atom.ATOMEntry dbgEntry;
/**
- * Creates new NetworkLibraryItem instance.
+ * Creates new NetworkItem instance.
*
* @param link corresponding NetworkLink object. Must be not null
.
* @param title title of this library item. Must be not null
.
* @param summary description of this library item. Can be null
.
* @param cover cover url. Can be null
.
*/
- protected NetworkLibraryItem(INetworkLink link, String title, String summary, String cover) {
+ protected NetworkItem(INetworkLink link, String title, String summary, String cover) {
Link = link;
Title = title;
Summary = summary;
diff --git a/src/org/geometerplus/fbreader/network/NetworkLibrary.java b/src/org/geometerplus/fbreader/network/NetworkLibrary.java
index 7f276b73f..8a0f18373 100644
--- a/src/org/geometerplus/fbreader/network/NetworkLibrary.java
+++ b/src/org/geometerplus/fbreader/network/NetworkLibrary.java
@@ -31,9 +31,9 @@ import org.geometerplus.zlibrary.core.language.ZLLanguageUtil;
import org.geometerplus.fbreader.tree.FBTree;
import org.geometerplus.fbreader.network.tree.*;
+import org.geometerplus.fbreader.network.opds.OPDSCustomLink;
import org.geometerplus.fbreader.network.opds.OPDSLinkReader;
-
public class NetworkLibrary {
private static NetworkLibrary ourInstance;
@@ -119,6 +119,7 @@ public class NetworkLibrary {
allCodes.removeAll(languageCodes());
allCodes.addAll(codes);
activeLanguageCodesOption().setValue(commaSeparatedString(allCodes));
+ invalidateChildren();
}
private String commaSeparatedString(Collection codes) {
@@ -148,9 +149,9 @@ public class NetworkLibrary {
}
private final RootTree myRootTree = new RootTree();
+ private SearchItemTree mySearchItemTree;
- private boolean myUpdateChildren = true;
- private boolean myInvalidateChildren;
+ private boolean myChildrenAreInvalid = true;
private boolean myUpdateVisibility;
private NetworkLibrary() {
@@ -178,35 +179,20 @@ public class NetworkLibrary {
db.loadCustomLinks(
new NetworkDatabase.ICustomLinksHandler() {
public void handleCustomLinkData(int id, String siteName,
- String title, String summary, String icon, Map links) {
- final ICustomNetworkLink link = OPDSLinkReader.createCustomLink(id, siteName, title, summary, icon, links);
- if (link != null) {
+ String title, String summary, Map infos) {
+ if (title != null &&
+ siteName != null &&
+ infos.get(INetworkLink.URL_MAIN) != null) {
+ final ICustomNetworkLink link = new OPDSCustomLink(
+ id, siteName, title, summary, infos
+ );
addLinkInternal(link);
- link.setSaveLinkListener(myChangesListener);
}
}
}
);
}
- /*testDate(new ATOMUpdated(2010, 1, 1, 1, 0, 0, 0, 2, 0),
- new ATOMUpdated(2009, 12, 31, 23, 0, 0, 0, 0, 0));
- testDate(new ATOMUpdated(2010, 12, 31, 23, 40, 0, 0, -1, -30),
- new ATOMUpdated(2011, 1, 1, 1, 10, 0, 0, 0, 0));
- testDate(new ATOMUpdated(2010, 1, 31, 23, 40, 0, 0, -1, -30),
- new ATOMUpdated(2010, 2, 1, 1, 10, 0, 0, 0, 0));
- testDate(new ATOMUpdated(2010, 2, 28, 23, 40, 0, 0, -1, -30),
- new ATOMUpdated(2010, 3, 1, 1, 10, 0, 0, 0, 0));
- testDate(new ATOMUpdated(2012, 2, 28, 23, 40, 0, 0, -1, -30),
- new ATOMUpdated(2012, 2, 29, 1, 10, 0, 0, 0, 0));
- testDate(new ATOMUpdated(2012, 2, 15, 23, 40, 0, 0, -1, -30),
- new ATOMUpdated(2012, 2, 16, 1, 10, 0, 0, 0, 0));
- testDate(new ATOMUpdated(2012, 2, 15, 23, 40, 1, 0, 3, 30),
- new ATOMUpdated(2012, 2, 15, 23, 40, 0, 0, 3, 30));
- testDate(new ATOMUpdated(2012, 2, 15, 23, 40, 0, 0, 3, 30),
- new ATOMUpdated(2012, 2, 15, 23, 40, 1, 0, 3, 30));
- testDate(new ATOMUpdated(2012, 2, 15, 23, 40, 0, 0.001f, 3, 30),
- new ATOMUpdated(2012, 2, 15, 23, 40, 0, 0, 3, 30));*/
myIsAlreadyInitialized = true;
}
@@ -258,6 +244,15 @@ public class NetworkLibrary {
}
}
}
+ for (INetworkLink link : myLinks) {
+ if (link instanceof ICustomNetworkLink) {
+ final ICustomNetworkLink customLink = (ICustomNetworkLink)link;
+ if (customLink.isObsolete(12 * 60 * 60 * 1000)) { // 12 hours
+ customLink.reloadInfo(true);
+ NetworkDatabase.Instance().saveCustomLink(customLink);
+ }
+ }
+ }
}
}
@@ -267,13 +262,12 @@ public class NetworkLibrary {
// synchronize() method MUST be called after this method
public void finishBackgroundUpdate() {
synchronized (myBackgroundLock) {
- if (myBackgroundLinks == null) {
- return;
- }
synchronized (myLinks) {
- removeAllLoadedLinks();
- myLinks.addAll(myBackgroundLinks);
- updateChildren();
+ if (myBackgroundLinks != null) {
+ removeAllLoadedLinks();
+ myLinks.addAll(myBackgroundLinks);
+ }
+ invalidateChildren();
}
}
}
@@ -291,36 +285,23 @@ public class NetworkLibrary {
return url;
}
- public void invalidateChildren() {
- myInvalidateChildren = true;
- }
-
- public void updateChildren() {
- myUpdateChildren = true;
+ private void invalidateChildren() {
+ myChildrenAreInvalid = true;
}
public void invalidateVisibility() {
myUpdateVisibility = true;
}
-
- private static boolean linksEqual(INetworkLink l1, INetworkLink l2) {
- return l1 == l2 || l1.getSiteName().equals(l2.getSiteName());
- }
-
- private static boolean linkIsInvalid(INetworkLink link, INetworkLink nodeLink) {
- if (link instanceof ICustomNetworkLink) {
- if (link != nodeLink) {
- throw new RuntimeException("Two equal custom links!!! That's impossible");
- }
- return ((ICustomNetworkLink) link).hasChanges();
- }
- return !link.equals(nodeLink);
+ private static boolean linkIsChanged(INetworkLink link) {
+ return
+ link instanceof ICustomNetworkLink &&
+ ((ICustomNetworkLink)link).hasChanges();
}
private static void makeValid(INetworkLink link) {
if (link instanceof ICustomNetworkLink) {
- ((ICustomNetworkLink) link).resetChanges();
+ ((ICustomNetworkLink)link).resetChanges();
}
}
@@ -342,13 +323,14 @@ public class NetworkLibrary {
currentNode = nodeIterator.next();
}
if (!(currentNode instanceof NetworkCatalogTree)) {
+ toRemove.add(currentNode);
currentNode = null;
++nodeCount;
continue;
}
- final INetworkLink nodeLink = ((NetworkCatalogTree) currentNode).Item.Link;
- if (linksEqual(link, nodeLink)) {
- if (linkIsInvalid(link, nodeLink)) {
+ final INetworkLink nodeLink = ((NetworkCatalogTree)currentNode).Item.Link;
+ if (link == nodeLink) {
+ if (linkIsChanged(link)) {
toRemove.add(currentNode);
} else {
processed = true;
@@ -360,12 +342,12 @@ public class NetworkLibrary {
INetworkLink newNodeLink = null;
for (int j = i; j < links.size(); ++j) {
final INetworkLink jlnk = links.get(j);
- if (linksEqual(nodeLink, jlnk)) {
+ if (nodeLink == jlnk) {
newNodeLink = jlnk;
break;
}
}
- if (newNodeLink == null || linkIsInvalid(newNodeLink, nodeLink)) {
+ if (newNodeLink == null || linkIsChanged(nodeLink)) {
toRemove.add(currentNode);
currentNode = null;
++nodeCount;
@@ -387,30 +369,28 @@ public class NetworkLibrary {
if (currentNode == null) {
currentNode = nodeIterator.next();
}
- if (currentNode instanceof NetworkCatalogTree) {
- toRemove.add(currentNode);
- }
+ toRemove.add(currentNode);
currentNode = null;
}
for (FBTree tree : toRemove) {
tree.removeSelf();
}
+ new AddCustomCatalogItemTree(myRootTree);
+ mySearchItemTree = new SearchItemTree(myRootTree, 0);
}
private void updateVisibility() {
for (FBTree tree : myRootTree.subTrees()) {
- if (!(tree instanceof NetworkCatalogTree)) {
- continue;
+ if (tree instanceof NetworkCatalogTree) {
+ ((NetworkCatalogTree)tree).updateVisibility();
}
- ((NetworkCatalogTree) tree).updateVisibility();
}
}
public void synchronize() {
- if (myUpdateChildren || myInvalidateChildren) {
- myUpdateChildren = false;
- myInvalidateChildren = false;
+ if (myChildrenAreInvalid) {
+ myChildrenAreInvalid = false;
makeUpToDate();
}
if (myUpdateVisibility) {
@@ -419,17 +399,37 @@ public class NetworkLibrary {
}
}
- public NetworkTree getTree() {
+ public NetworkTree getRootTree() {
return myRootTree;
}
+ public SearchItemTree getSearchItemTree() {
+ return mySearchItemTree;
+ }
+
+ public NetworkTree getTreeByKey(NetworkTree.Key key) {
+ if (key.Parent == null) {
+ return key.equals(myRootTree.getUniqueKey()) ? myRootTree : null;
+ }
+ final NetworkTree parentTree = getTreeByKey(key.Parent);
+ if (parentTree == null) {
+ return null;
+ }
+ for (FBTree tree : parentTree.subTrees()) {
+ final NetworkTree nTree = (NetworkTree)tree;
+ if (key.equals(nTree.getUniqueKey())) {
+ return nTree;
+ }
+ }
+ return null;
+ }
public void simpleSearch(String pattern, final NetworkOperationData.OnNewItemListener listener) throws ZLNetworkException {
LinkedList requestList = new LinkedList();
LinkedList dataList = new LinkedList();
final NetworkOperationData.OnNewItemListener synchronizedListener = new NetworkOperationData.OnNewItemListener() {
- public synchronized void onNewItem(INetworkLink link, NetworkLibraryItem item) {
+ public synchronized void onNewItem(INetworkLink link, NetworkItem item) {
listener.onNewItem(link, item);
}
public synchronized boolean confirmInterrupt() {
@@ -442,7 +442,7 @@ public class NetworkLibrary {
synchronized (myLinks) {
for (INetworkLink link : activeLinks()) {
- final NetworkOperationData data = link.createOperationData(link, synchronizedListener);
+ final NetworkOperationData data = link.createOperationData(synchronizedListener);
final ZLNetworkRequest request = link.simpleSearchRequest(pattern, data);
if (request != null) {
dataList.add(data);
@@ -468,12 +468,6 @@ public class NetworkLibrary {
}
}
- private ICustomNetworkLink.SaveLinkListener myChangesListener = new ICustomNetworkLink.SaveLinkListener() {
- public void onSaveLink(ICustomNetworkLink link) {
- NetworkDatabase.Instance().saveCustomLink(link);
- }
- };
-
private void addLinkInternal(T link) {
synchronized (myLinks) {
myLinks.add(link);
@@ -481,9 +475,21 @@ public class NetworkLibrary {
}
public void addCustomLink(ICustomNetworkLink link) {
- addLinkInternal(link);
- link.setSaveLinkListener(myChangesListener);
- link.saveLink();
+ final int id = link.getId();
+ if (id == ICustomNetworkLink.INVALID_ID) {
+ addLinkInternal(link);
+ } else {
+ for (int i = myLinks.size() - 1; i >= 0; --i) {
+ final INetworkLink l = myLinks.get(i);
+ if (l instanceof ICustomNetworkLink &&
+ ((ICustomNetworkLink)l).getId() == id) {
+ myLinks.set(i, link);
+ break;
+ }
+ }
+ }
+ NetworkDatabase.Instance().saveCustomLink(link);
+ invalidateChildren();
}
public void removeCustomLink(ICustomNetworkLink link) {
@@ -491,28 +497,6 @@ public class NetworkLibrary {
myLinks.remove(link);
}
NetworkDatabase.Instance().deleteCustomLink(link);
- link.setSaveLinkListener(null);
- }
-
- public boolean hasCustomLinkTitle(String title, INetworkLink exceptFor) {
- synchronized (myLinks) {
- for (INetworkLink link : myLinks) {
- if (link != exceptFor && link.getTitle().equals(title)) {
- return true;
- }
- }
- }
- return false;
- }
-
- public boolean hasCustomLinkSite(String siteName, INetworkLink exceptFor) {
- synchronized (myLinks) {
- for (INetworkLink link : myLinks) {
- if (link != exceptFor && link.getSiteName().equals(siteName)) {
- return true;
- }
- }
- }
- return false;
+ invalidateChildren();
}
}
diff --git a/src/org/geometerplus/fbreader/network/NetworkOperationData.java b/src/org/geometerplus/fbreader/network/NetworkOperationData.java
index 33182660a..70adad9da 100644
--- a/src/org/geometerplus/fbreader/network/NetworkOperationData.java
+++ b/src/org/geometerplus/fbreader/network/NetworkOperationData.java
@@ -25,12 +25,16 @@ import org.geometerplus.zlibrary.core.network.ZLNetworkRequest;
public class NetworkOperationData {
public interface OnNewItemListener {
- void onNewItem(INetworkLink link, NetworkLibraryItem item);
+ void onNewItem(INetworkLink link, NetworkItem item);
void commitItems(INetworkLink link);
- // returns true to confirm interrupt reading; return false to continue reading.
- // once true has been returned, all next calls must return true.
+ /**
+ * @return true
to confirm interrupt reading;
+ * false
to continue reading.
+ * Once true
has been returned,
+ * all next calls MUST return true
.
+ */
boolean confirmInterrupt();
}
@@ -43,11 +47,11 @@ public class NetworkOperationData {
Listener = listener;
}
- public void clear() {
+ protected void clear() {
ResumeURI = null;
}
- public ZLNetworkRequest resume() {
+ public final ZLNetworkRequest resume() {
final ZLNetworkRequest request = Link.resume(this);
clear();
return request;
diff --git a/src/org/geometerplus/fbreader/network/NetworkTree.java b/src/org/geometerplus/fbreader/network/NetworkTree.java
index 22603e003..a6f3c5aa0 100644
--- a/src/org/geometerplus/fbreader/network/NetworkTree.java
+++ b/src/org/geometerplus/fbreader/network/NetworkTree.java
@@ -21,15 +21,48 @@ package org.geometerplus.fbreader.network;
import java.util.LinkedList;
import java.util.Set;
+import java.io.Serializable;
import org.geometerplus.zlibrary.core.constants.MimeTypes;
import org.geometerplus.zlibrary.core.image.ZLImage;
+import org.geometerplus.zlibrary.core.util.ZLMiscUtil;
import org.geometerplus.fbreader.tree.FBTree;
public abstract class NetworkTree extends FBTree {
- protected NetworkTree(int level) {
- super(level);
+ public static class Key implements Serializable {
+ final Key Parent;
+ final String Id;
+
+ private Key(Key parent, String id) {
+ if (id == null) {
+ throw new IllegalArgumentException("NetworkTree string id must be non-null");
+ }
+ Parent = parent;
+ Id = id;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (other == this) {
+ return true;
+ }
+ if (!(other instanceof NetworkTree.Key)) {
+ return false;
+ }
+ final NetworkTree.Key key = (NetworkTree.Key)other;
+ return Id.equals(key.Id) && ZLMiscUtil.equals(Parent, key.Parent);
+ }
+
+ @Override
+ public int hashCode() {
+ return Id.hashCode();
+ }
+
+ @Override
+ public String toString() {
+ return Parent == null ? Id : Parent.toString() + " :: " + Id;
+ }
}
protected NetworkTree() {
@@ -44,7 +77,7 @@ public abstract class NetworkTree extends FBTree {
super(parent, position);
}
- public static ZLImage createCover(NetworkLibraryItem item) {
+ public static ZLImage createCover(NetworkItem item) {
if (item.Cover == null) {
return null;
}
@@ -88,15 +121,38 @@ public abstract class NetworkTree extends FBTree {
}
- public abstract NetworkLibraryItem getHoldedItem();
+ public abstract NetworkItem getHoldedItem();
- public void removeItems(Set items) {
+ private Key myKey;
+ /**
+ * Returns unique identifier which can be used in NetworkView methods
+ * @return unique Key instance
+ */
+ public final Key getUniqueKey() {
+ if (myKey == null) {
+ //final ZLTree parentTree = getParent();
+ final Key parentKey = Parent instanceof NetworkTree ?
+ ((NetworkTree)Parent).getUniqueKey() : null;
+ myKey = new Key(parentKey, getStringId());
+ }
+ return myKey;
+ }
+
+ /**
+ * Returns id used as a part of unique key above. This string must be
+ * not null
+ * and
+ * be unique for all children of same tree
+ */
+ protected abstract String getStringId();
+
+ public void removeItems(Set items) {
if (items.isEmpty() || subTrees().isEmpty()) {
return;
}
final LinkedList treesList = new LinkedList();
for (FBTree tree: subTrees()) {
- final NetworkLibraryItem treeItem = ((NetworkTree)tree).getHoldedItem();
+ final NetworkItem treeItem = ((NetworkTree)tree).getHoldedItem();
if (treeItem != null && items.contains(treeItem)) {
treesList.add(tree);
items.remove(treeItem);
diff --git a/src/org/geometerplus/fbreader/network/SearchResult.java b/src/org/geometerplus/fbreader/network/SearchResult.java
index 68e4ae717..70a7fd413 100644
--- a/src/org/geometerplus/fbreader/network/SearchResult.java
+++ b/src/org/geometerplus/fbreader/network/SearchResult.java
@@ -23,13 +23,12 @@ import java.util.LinkedHashMap;
import java.util.LinkedList;
public class SearchResult {
-
public final String Summary;
- public final LinkedHashMap> BooksMap;
+ public final LinkedHashMap> BooksMap =
+ new LinkedHashMap>();
public SearchResult(String summary) {
Summary = summary;
- BooksMap = new LinkedHashMap>();
}
public void addBook(NetworkBookItem book) {
@@ -43,7 +42,7 @@ public class SearchResult {
}
}
- public boolean empty() {
+ public boolean isEmpty() {
return BooksMap.size() == 0;
}
}
diff --git a/src/org/geometerplus/fbreader/network/TopUpItem.java b/src/org/geometerplus/fbreader/network/TopUpItem.java
new file mode 100644
index 000000000..b19978d45
--- /dev/null
+++ b/src/org/geometerplus/fbreader/network/TopUpItem.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2010-2011 Geometer Plus
+ *
+ * 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 org.geometerplus.zlibrary.core.resources.ZLResource;
+
+public class TopUpItem extends NetworkItem {
+ public TopUpItem(INetworkLink link, String cover) {
+ super(
+ link,
+ ZLResource.resource("networkView").getResource("refillTitle").getValue(),
+ ZLResource.resource("networkView").getResource("refillSummary").getValue(),
+ cover
+ );
+ }
+}
diff --git a/src/org/geometerplus/fbreader/network/UrlInfo.java b/src/org/geometerplus/fbreader/network/UrlInfo.java
new file mode 100644
index 000000000..3ee954304
--- /dev/null
+++ b/src/org/geometerplus/fbreader/network/UrlInfo.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2010-2011 Geometer Plus
+ *
+ * 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.Date;
+import java.io.Serializable;
+
+import org.geometerplus.zlibrary.core.util.ZLMiscUtil;
+
+public final class UrlInfo implements Serializable {
+ public static final UrlInfo NULL = new UrlInfo(null, null);
+
+ public final String URL;
+ public final Date Updated;
+
+ public UrlInfo(String url, Date updated) {
+ URL = url;
+ Updated = updated;
+ }
+
+ public UrlInfo(String url) {
+ this(url, new Date());
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (o == this) {
+ return true;
+ }
+ if (!(o instanceof UrlInfo)) {
+ return false;
+ }
+
+ final UrlInfo info = (UrlInfo)o;
+ return ZLMiscUtil.equals(URL, info.URL) && ZLMiscUtil.equals(Updated, info.Updated);
+ }
+
+ @Override
+ public int hashCode() {
+ return ZLMiscUtil.hashCode(URL) + ZLMiscUtil.hashCode(Updated);
+ }
+}
diff --git a/src/org/geometerplus/fbreader/network/authentication/litres/LitResAuthenticationManager.java b/src/org/geometerplus/fbreader/network/authentication/litres/LitResAuthenticationManager.java
index 10a5994ba..d340b3372 100644
--- a/src/org/geometerplus/fbreader/network/authentication/litres/LitResAuthenticationManager.java
+++ b/src/org/geometerplus/fbreader/network/authentication/litres/LitResAuthenticationManager.java
@@ -39,7 +39,7 @@ public class LitResAuthenticationManager extends NetworkAuthenticationManager {
private String myInitializedDataSid;
private String myAccount;
- private final HashMap myPurchasedBooks = new HashMap();
+ private final HashMap myPurchasedBooks = new HashMap();
public LitResAuthenticationManager(INetworkLink link, String sslCertificate) {
super(link, sslCertificate);
@@ -89,7 +89,7 @@ public class LitResAuthenticationManager extends NetworkAuthenticationManager {
sid = mySidOption.getValue();
}
- String url = Link.getLink(INetworkLink.URL_SIGN_IN);
+ String url = Link.getUrlInfo(INetworkLink.URL_SIGN_IN).URL;
if (url == null) {
throw new ZLNetworkException(NetworkException.ERROR_UNSUPPORTED_OPERATION);
}
@@ -119,7 +119,7 @@ public class LitResAuthenticationManager extends NetworkAuthenticationManager {
@Override
public void authorise(String password) throws ZLNetworkException {
- String url = Link.getLink(INetworkLink.URL_SIGN_IN);
+ String url = Link.getUrlInfo(INetworkLink.URL_SIGN_IN).URL;
if (url == null) {
throw new ZLNetworkException(NetworkException.ERROR_UNSUPPORTED_OPERATION);
}
@@ -241,7 +241,7 @@ public class LitResAuthenticationManager extends NetworkAuthenticationManager {
if (sid.length() == 0) {
return null;
}
- final String url = Link.getLink(INetworkLink.URL_REFILL_ACCOUNT);
+ final String url = Link.getUrlInfo(INetworkLink.URL_REFILL_ACCOUNT).URL;
if (url == null) {
return null;
}
@@ -352,7 +352,7 @@ public class LitResAuthenticationManager extends NetworkAuthenticationManager {
return new LitResNetworkRequest(
LitResUtil.url(Link, query),
SSLCertificate,
- new LitResXMLReader(Link, new LinkedList())
+ new LitResXMLReader(Link, new LinkedList())
);
}
@@ -363,7 +363,7 @@ public class LitResAuthenticationManager extends NetworkAuthenticationManager {
private void loadPurchasedBooksOnSuccess(LitResNetworkRequest purchasedBooksRequest) {
LitResXMLReader reader = (LitResXMLReader)purchasedBooksRequest.Reader;
myPurchasedBooks.clear();
- for (NetworkLibraryItem item: reader.Books) {
+ for (NetworkItem item: reader.Books) {
if (item instanceof NetworkBookItem) {
NetworkBookItem book = (NetworkBookItem)item;
myPurchasedBooks.put(book.Id, book);
@@ -401,7 +401,7 @@ public class LitResAuthenticationManager extends NetworkAuthenticationManager {
@Override
public void recoverPassword(String email) throws ZLNetworkException {
- String url = Link.getLink(INetworkLink.URL_RECOVER_PASSWORD);
+ String url = Link.getUrlInfo(INetworkLink.URL_RECOVER_PASSWORD).URL;
if (url == null) {
throw new ZLNetworkException(NetworkException.ERROR_UNSUPPORTED_OPERATION);
}
diff --git a/src/org/geometerplus/fbreader/network/authentication/litres/LitResBookshelfItem.java b/src/org/geometerplus/fbreader/network/authentication/litres/LitResBookshelfItem.java
index 162d1d2f4..935c20481 100644
--- a/src/org/geometerplus/fbreader/network/authentication/litres/LitResBookshelfItem.java
+++ b/src/org/geometerplus/fbreader/network/authentication/litres/LitResBookshelfItem.java
@@ -21,15 +21,127 @@ package org.geometerplus.fbreader.network.authentication.litres;
import java.util.*;
+import org.geometerplus.zlibrary.core.resources.ZLResource;
import org.geometerplus.zlibrary.core.network.ZLNetworkException;
import org.geometerplus.fbreader.network.*;
+abstract class SortedCatalogItem extends NetworkCatalogItem {
+ private final List myChildren = new LinkedList();
+
+ private SortedCatalogItem(NetworkCatalogItem parent, ZLResource resource, List children) {
+ super(parent.Link, resource.getValue(), resource.getResource("summary").getValue(), "", parent.URLByType);
+ for (NetworkItem child : children) {
+ if (accepts(child)) {
+ myChildren.add(child);
+ }
+ }
+ final Comparator comparator = getComparator();
+ if (comparator != null) {
+ Collections.sort(myChildren, comparator);
+ }
+ }
+
+ public boolean isEmpty() {
+ return myChildren.isEmpty();
+ }
+
+ protected abstract Comparator getComparator();
+ protected boolean accepts(NetworkItem item) {
+ return item instanceof NetworkBookItem;
+ }
+
+ public SortedCatalogItem(NetworkCatalogItem parent, String resourceKey, List children) {
+ this(parent, ZLResource.resource("networkView").getResource(resourceKey), children);
+ }
+
+ @Override
+ public void onDisplayItem() {
+ }
+
+ @Override
+ public void loadChildren(NetworkOperationData.OnNewItemListener listener) throws ZLNetworkException {
+ for (NetworkItem child : myChildren) {
+ listener.onNewItem(Link, child);
+ }
+ listener.commitItems(Link);
+ }
+}
+
+class ByAuthorCatalogItem extends SortedCatalogItem {
+ ByAuthorCatalogItem(NetworkCatalogItem parent, List children) {
+ super(parent, "byAuthor", children);
+ }
+
+ @Override
+ protected Comparator getComparator() {
+ return new NetworkBookItemComparator();
+ }
+}
+
+class ByTitleCatalogItem extends SortedCatalogItem {
+ ByTitleCatalogItem(NetworkCatalogItem parent, List children) {
+ super(parent, "byTitle", children);
+ }
+
+ @Override
+ protected Comparator getComparator() {
+ return new Comparator() {
+ public int compare(NetworkItem item0, NetworkItem item1) {
+ return item0.Title.compareTo(item1.Title);
+ }
+ };
+ }
+}
+
+class ByDateCatalogItem extends SortedCatalogItem {
+ ByDateCatalogItem(NetworkCatalogItem parent, List children) {
+ super(parent, "byDate", children);
+ }
+
+ @Override
+ protected Comparator getComparator() {
+ return new Comparator() {
+ public int compare(NetworkItem item0, NetworkItem item1) {
+ return 0;
+ }
+ };
+ }
+}
+
+class BySeriesCatalogItem extends SortedCatalogItem {
+ BySeriesCatalogItem(NetworkCatalogItem parent, List children) {
+ super(parent, "bySeries", children);
+ }
+
+ @Override
+ protected Comparator getComparator() {
+ return new Comparator() {
+ public int compare(NetworkItem item0, NetworkItem item1) {
+ final NetworkBookItem book0 = (NetworkBookItem)item0;
+ final NetworkBookItem book1 = (NetworkBookItem)item1;
+ int diff = book0.SeriesTitle.compareTo(book1.SeriesTitle);
+ if (diff == 0) {
+ diff = book0.IndexInSeries - book1.IndexInSeries;
+ }
+ return diff != 0 ? diff : book0.Title.compareTo(book1.Title);
+ }
+ };
+ }
+
+ @Override
+ protected boolean accepts(NetworkItem item) {
+ return
+ item instanceof NetworkBookItem &&
+ ((NetworkBookItem)item).SeriesTitle != null;
+ }
+}
+
public class LitResBookshelfItem extends NetworkCatalogItem {
private boolean myForceReload;
public LitResBookshelfItem(INetworkLink link, String title, String summary, String cover, Map urlByType, Accessibility accessibility) {
- super(link, title, summary, cover, urlByType, accessibility);
+ super(link, title, summary, cover, urlByType, accessibility, CatalogType.OTHER);
}
@Override
@@ -54,11 +166,21 @@ public class LitResBookshelfItem extends NetworkCatalogItem {
} finally {
myForceReload = true;
// TODO: implement asynchronous loading
- ArrayList children =
- new ArrayList(mgr.purchasedBooks());
- Collections.sort(children, new NetworkBookItemComparator());
- for (NetworkLibraryItem item : children) {
- listener.onNewItem(Link, item);
+ ArrayList children =
+ new ArrayList(mgr.purchasedBooks());
+ if (children.size() <= 5) {
+ Collections.sort(children, new NetworkBookItemComparator());
+ for (NetworkItem item : children) {
+ listener.onNewItem(Link, item);
+ }
+ } else {
+ 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);
+ if (!bySeries.isEmpty()) {
+ listener.onNewItem(Link, bySeries);
+ }
}
listener.commitItems(Link);
}
diff --git a/src/org/geometerplus/fbreader/network/authentication/litres/LitResRecommendationsItem.java b/src/org/geometerplus/fbreader/network/authentication/litres/LitResRecommendationsItem.java
index 9c7bbc761..e8d73d99b 100644
--- a/src/org/geometerplus/fbreader/network/authentication/litres/LitResRecommendationsItem.java
+++ b/src/org/geometerplus/fbreader/network/authentication/litres/LitResRecommendationsItem.java
@@ -24,8 +24,10 @@ import java.util.Map;
import org.geometerplus.zlibrary.core.util.ZLNetworkUtil;
import org.geometerplus.fbreader.network.INetworkLink;
+import org.geometerplus.fbreader.network.Basket;
import org.geometerplus.fbreader.network.NetworkBookItem;
import org.geometerplus.fbreader.network.opds.OPDSCatalogItem;
+import org.geometerplus.fbreader.network.opds.OPDSNetworkLink;
public class LitResRecommendationsItem extends OPDSCatalogItem {
public LitResRecommendationsItem(INetworkLink link, String title, String summary, String cover, Map urlByType, Accessibility accessibility) {
@@ -46,6 +48,17 @@ public class LitResRecommendationsItem extends OPDSCatalogItem {
}
builder.append(book.Id);
}
+ final Basket basket = Link.basket();
+ if (basket != null) {
+ for (String bookId : basket.bookIds()) {
+ if (flag) {
+ builder.append(',');
+ } else {
+ flag = true;
+ }
+ builder.append(bookId);
+ }
+ }
return ZLNetworkUtil.appendParameter(URLByType.get(URL_CATALOG), "ids", builder.toString());
}
diff --git a/src/org/geometerplus/fbreader/network/authentication/litres/LitResXMLReader.java b/src/org/geometerplus/fbreader/network/authentication/litres/LitResXMLReader.java
index 580b026d5..1662c31b3 100644
--- a/src/org/geometerplus/fbreader/network/authentication/litres/LitResXMLReader.java
+++ b/src/org/geometerplus/fbreader/network/authentication/litres/LitResXMLReader.java
@@ -31,7 +31,7 @@ import org.geometerplus.fbreader.network.opds.HtmlToString;
class LitResXMLReader extends LitResAuthenticationXMLReader {
public final INetworkLink Link;
- public final List Books;
+ public final List Books;
private int myIndex;
@@ -55,7 +55,7 @@ class LitResXMLReader extends LitResAuthenticationXMLReader {
private HashMap myURLByType = new HashMap(); // TODO: remove
private LinkedList myReferences = new LinkedList();
- public LitResXMLReader(INetworkLink link, List books) {
+ public LitResXMLReader(INetworkLink link, List books) {
super(link.getSiteName());
Link = link;
Books = books;
diff --git a/src/org/geometerplus/fbreader/network/opds/BasketItem.java b/src/org/geometerplus/fbreader/network/opds/BasketItem.java
new file mode 100644
index 000000000..a54d7c619
--- /dev/null
+++ b/src/org/geometerplus/fbreader/network/opds/BasketItem.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2010-2011 Geometer Plus
+ *
+ * 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.opds;
+
+import java.util.Map;
+
+import org.geometerplus.zlibrary.core.util.ZLNetworkUtil;
+
+import org.geometerplus.fbreader.network.INetworkLink;
+import org.geometerplus.fbreader.network.NetworkBookItem;
+import org.geometerplus.fbreader.network.opds.OPDSNetworkLink;
+import org.geometerplus.fbreader.network.opds.OPDSCatalogItem;
+
+public class BasketItem extends OPDSCatalogItem {
+ BasketItem(OPDSNetworkLink link, String title, String summary, String cover, Map urlByType, Accessibility accessibility) {
+ super(link, title, summary, cover, urlByType, accessibility, CatalogType.BY_SERIES);
+ link.setSupportsBasket();
+ }
+
+ @Override
+ protected String getUrl() {
+ final StringBuilder builder = new StringBuilder();
+ boolean flag = false;
+ for (String bookId : Link.basket().bookIds()) {
+ if (flag) {
+ builder.append(',');
+ } else {
+ flag = true;
+ }
+ builder.append(bookId);
+ }
+
+ return ZLNetworkUtil.appendParameter(URLByType.get(URL_CATALOG), "ids", builder.toString());
+ }
+}
diff --git a/src/org/geometerplus/fbreader/network/opds/NetworkOPDSFeedReader.java b/src/org/geometerplus/fbreader/network/opds/NetworkOPDSFeedReader.java
index 7b51c18c7..809a449fe 100644
--- a/src/org/geometerplus/fbreader/network/opds/NetworkOPDSFeedReader.java
+++ b/src/org/geometerplus/fbreader/network/opds/NetworkOPDSFeedReader.java
@@ -42,7 +42,7 @@ class NetworkOPDSFeedReader implements OPDSFeedReader, OPDSConstants, MimeTypes
private int myItemsToLoad = -1;
/**
- * Creates new OPDSFeedReader instance that can be used to get NetworkLibraryItem objects from OPDS feeds.
+ * Creates new OPDSFeedReader instance that can be used to get NetworkItem objects from OPDS feeds.
*
* @param baseURL string that contains URL of the OPDS feed, that will be read using this instance of the reader
* @param result network results buffer. Must be created using OPDSNetworkLink corresponding to the OPDS feed,
@@ -203,7 +203,7 @@ class NetworkOPDSFeedReader implements OPDSFeedReader, OPDSConstants, MimeTypes
}
}
- NetworkLibraryItem item;
+ NetworkItem item;
if (hasBookLink) {
item = readBookItem(entry);
} else {
@@ -218,7 +218,7 @@ class NetworkOPDSFeedReader implements OPDSFeedReader, OPDSConstants, MimeTypes
private static final String AuthorPrefix = "author:";
private static final String AuthorsPrefix = "authors:";
- private NetworkLibraryItem readBookItem(OPDSEntry entry) {
+ private NetworkItem readBookItem(OPDSEntry entry) {
final OPDSNetworkLink opdsNetworkLink = (OPDSNetworkLink)myData.Link;
/*final String date;
if (entry.DCIssued != null) {
@@ -368,7 +368,7 @@ class NetworkOPDSFeedReader implements OPDSFeedReader, OPDSConstants, MimeTypes
}
}
- private NetworkLibraryItem readCatalogItem(OPDSEntry entry) {
+ private NetworkItem readCatalogItem(OPDSEntry entry) {
final OPDSNetworkLink opdsLink = (OPDSNetworkLink)myData.Link;
String coverURL = null;
String url = null;
@@ -457,6 +457,20 @@ class NetworkOPDSFeedReader implements OPDSFeedReader, OPDSConstants, MimeTypes
urlMap,
opdsLink.getCondition(entry.Id.Uri)
);
+ } else if (REL_BASKET.equals(litresRel)) {
+ return null;
+ /*
+ return new BasketItem(
+ opdsLink,
+ entry.Title,
+ annotation,
+ coverURL,
+ urlMap,
+ opdsLink.getCondition(entry.Id.Uri)
+ );
+ */
+ } else if (REL_TOPUP.equals(litresRel)) {
+ return new TopUpItem(opdsLink, coverURL);
} else {
return null;
}
diff --git a/src/org/geometerplus/fbreader/network/opds/OPDSCatalogItem.java b/src/org/geometerplus/fbreader/network/opds/OPDSCatalogItem.java
index c3308a9d9..d4088a83e 100644
--- a/src/org/geometerplus/fbreader/network/opds/OPDSCatalogItem.java
+++ b/src/org/geometerplus/fbreader/network/opds/OPDSCatalogItem.java
@@ -21,7 +21,6 @@ package org.geometerplus.fbreader.network.opds;
import java.util.*;
-import org.geometerplus.zlibrary.core.network.ZLNetworkManager;
import org.geometerplus.zlibrary.core.network.ZLNetworkException;
import org.geometerplus.zlibrary.core.network.ZLNetworkRequest;
@@ -49,19 +48,12 @@ public class OPDSCatalogItem extends NetworkCatalogItem {
myExtraData = null;
}
- private void doLoadChildren(NetworkOperationData.OnNewItemListener listener,
- ZLNetworkRequest networkRequest) throws ZLNetworkException {
- while (networkRequest != null) {
- try {
- ZLNetworkManager.Instance().perform(networkRequest);
- } catch (ZLNetworkException e) {
- myLoadingState = null;
- throw e;
- }
- if (listener.confirmInterrupt()) {
- return;
- }
- networkRequest = myLoadingState.resume();
+ private void doLoadChildren(ZLNetworkRequest networkRequest) throws ZLNetworkException {
+ try {
+ super.doLoadChildren(myLoadingState, networkRequest);
+ } catch (ZLNetworkException e) {
+ myLoadingState = null;
+ throw e;
}
}
@@ -78,12 +70,12 @@ public class OPDSCatalogItem extends NetworkCatalogItem {
public final void loadChildren(NetworkOperationData.OnNewItemListener listener) throws ZLNetworkException {
OPDSNetworkLink opdsLink = (OPDSNetworkLink) Link;
- myLoadingState = opdsLink.createOperationData(Link, listener);
+ myLoadingState = opdsLink.createOperationData(listener);
ZLNetworkRequest networkRequest =
opdsLink.createNetworkData(getUrl(), myLoadingState);
- doLoadChildren(listener, networkRequest);
+ doLoadChildren(networkRequest);
}
@Override
@@ -96,7 +88,7 @@ public class OPDSCatalogItem extends NetworkCatalogItem {
if (myLoadingState != null) {
myLoadingState.Listener = listener;
ZLNetworkRequest networkRequest = myLoadingState.resume();
- doLoadChildren(listener, networkRequest);
+ doLoadChildren(networkRequest);
}
}
}
diff --git a/src/org/geometerplus/fbreader/network/opds/OPDSConstants.java b/src/org/geometerplus/fbreader/network/opds/OPDSConstants.java
index 9f20b253d..0153e326d 100644
--- a/src/org/geometerplus/fbreader/network/opds/OPDSConstants.java
+++ b/src/org/geometerplus/fbreader/network/opds/OPDSConstants.java
@@ -24,6 +24,8 @@ interface OPDSConstants {
// Feed level
String REL_BOOKSHELF = "http://data.fbreader.org/rel/bookshelf";
String REL_RECOMMENDATIONS = "http://data.fbreader.org/rel/recommendations";
+ String REL_BASKET = "http://data.fbreader.org/rel/basket";
+ String REL_TOPUP = "http://data.fbreader.org/rel/topup";
//String REL_SUBSCRIPTIONS = "http://opds-spec.org/subscriptions";
// Entry level / catalog types
diff --git a/src/org/geometerplus/fbreader/network/opds/OPDSCustomLink.java b/src/org/geometerplus/fbreader/network/opds/OPDSCustomLink.java
index ada9d7aa7..9ecf0be44 100644
--- a/src/org/geometerplus/fbreader/network/opds/OPDSCustomLink.java
+++ b/src/org/geometerplus/fbreader/network/opds/OPDSCustomLink.java
@@ -32,17 +32,22 @@ import org.geometerplus.zlibrary.core.util.ZLMiscUtil;
import org.geometerplus.fbreader.network.ICustomNetworkLink;
import org.geometerplus.fbreader.network.INetworkLink;
import org.geometerplus.fbreader.network.NetworkException;
+import org.geometerplus.fbreader.network.UrlInfo;
-
-class OPDSCustomLink extends OPDSNetworkLink implements ICustomNetworkLink {
-
+public class OPDSCustomLink extends OPDSNetworkLink implements ICustomNetworkLink {
private int myId;
- private SaveLinkListener myListener;
private boolean myHasChanges;
- OPDSCustomLink(int id, String siteName, String title, String summary, String icon, Map links) {
- super(siteName, title, summary, icon, null, links, false);
+ private static String removeWWWPrefix(String siteName) {
+ if (siteName != null && siteName.startsWith("www.")) {
+ return siteName.substring(4);
+ }
+ return siteName;
+ }
+
+ public OPDSCustomLink(int id, String siteName, String title, String summary, Map infos) {
+ super(removeWWWPrefix(siteName), title, summary, null, infos, false);
myId = id;
}
@@ -54,18 +59,6 @@ class OPDSCustomLink extends OPDSNetworkLink implements ICustomNetworkLink {
myId = id;
}
- public void setSaveLinkListener(SaveLinkListener listener) {
- myListener = listener;
- }
-
- public void saveLink() {
- if (myListener != null) {
- myListener.onSaveLink(this);
- } else {
- throw new RuntimeException("Unable to save link: SaveLinkListener hasn't been set");
- }
- }
-
public boolean hasChanges() {
return myHasChanges;
}
@@ -74,12 +67,6 @@ class OPDSCustomLink extends OPDSNetworkLink implements ICustomNetworkLink {
myHasChanges = false;
}
-
- public final void setIcon(String icon) {
- myHasChanges = myHasChanges || !ZLMiscUtil.equals(myIcon, icon);
- myIcon = icon;
- }
-
public final void setSiteName(String name) {
myHasChanges = myHasChanges || !ZLMiscUtil.equals(mySiteName, name);
mySiteName = name;
@@ -95,28 +82,39 @@ class OPDSCustomLink extends OPDSNetworkLink implements ICustomNetworkLink {
myTitle = title;
}
- public final void setLink(String urlKey, String url) {
- if (url == null) {
- removeLink(urlKey);
- } else {
- final String oldUrl = myLinks.put(urlKey, url);
- myHasChanges = myHasChanges || !url.equals(oldUrl);
- }
+ public final void setUrl(String urlKey, String url) {
+ myInfos.put(urlKey, new UrlInfo(url, new Date()));
+ myHasChanges = true;
}
- public final void removeLink(String urlKey) {
- final String oldUrl = myLinks.remove(urlKey);
+ public final void removeUrl(String urlKey) {
+ final UrlInfo oldUrl = myInfos.remove(urlKey);
myHasChanges = myHasChanges || oldUrl != null;
}
+ public boolean isObsolete(long milliSeconds) {
+ final long old = System.currentTimeMillis() - milliSeconds;
+
+ final Date searchUpdateDate = getUrlInfo(URL_SEARCH).Updated;
+ if (searchUpdateDate == null || searchUpdateDate.getTime() < old) {
+ return true;
+ }
- public void reloadInfo() throws ZLNetworkException {
+ final Date iconUpdateDate = getUrlInfo(URL_ICON).Updated;
+ if (iconUpdateDate == null || iconUpdateDate.getTime() < old) {
+ return true;
+ }
+
+ return false;
+ }
+
+ public void reloadInfo(final boolean urlsOnly) throws ZLNetworkException {
final LinkedList opensearchDescriptionURLs = new LinkedList();
final List descriptions = Collections.synchronizedList(new LinkedList());
ZLNetworkException error = null;
try {
- ZLNetworkManager.Instance().perform(new ZLNetworkRequest(getLink(INetworkLink.URL_MAIN)) {
+ ZLNetworkManager.Instance().perform(new ZLNetworkRequest(getUrlInfo(URL_MAIN).URL) {
@Override
public void handleStream(URLConnection connection, InputStream inputStream) throws IOException, ZLNetworkException {
final CatalogInfoReader info = new CatalogInfoReader(URL, OPDSCustomLink.this, opensearchDescriptionURLs);
@@ -128,16 +126,14 @@ class OPDSCustomLink extends OPDSNetworkLink implements ICustomNetworkLink {
if (info.Title == null) {
throw new ZLNetworkException(NetworkException.ERROR_NO_REQUIRED_INFORMATION);
}
- myTitle = info.Title;
- if (info.Icon != null) {
- myIcon = info.Icon;
- }
- if (info.Summary != null) {
- mySummary = info.Summary;
- }
+ setUrl(URL_ICON, info.Icon);
if (info.DirectOpenSearchDescription != null) {
descriptions.add(info.DirectOpenSearchDescription);
}
+ if (!urlsOnly) {
+ myTitle = info.Title;
+ mySummary = info.Summary;
+ }
}
});
} catch (ZLNetworkException e) {
@@ -151,7 +147,7 @@ class OPDSCustomLink extends OPDSNetworkLink implements ICustomNetworkLink {
requests.add(new ZLNetworkRequest(url) {
@Override
public void handleStream(URLConnection connection, InputStream inputStream) throws IOException, ZLNetworkException {
- new OpenSearchXMLReader(URL, descriptions, 20).read(inputStream);
+ new OpenSearchXMLReader(URL, descriptions).read(inputStream);
}
});
}
@@ -166,7 +162,9 @@ class OPDSCustomLink extends OPDSNetworkLink implements ICustomNetworkLink {
if (!descriptions.isEmpty()) {
// TODO: May be do not use '%s'??? Use Description instead??? (this needs to rewrite SEARCH engine logic a little)
- setLink(URL_SEARCH, descriptions.get(0).makeQuery("%s"));
+ setUrl(URL_SEARCH, descriptions.get(0).makeQuery("%s"));
+ } else {
+ setUrl(URL_SEARCH, null);
}
if (error != null) {
throw error;
diff --git a/src/org/geometerplus/fbreader/network/opds/OPDSLinkReader.java b/src/org/geometerplus/fbreader/network/opds/OPDSLinkReader.java
index e8933fadf..ca017cebf 100644
--- a/src/org/geometerplus/fbreader/network/opds/OPDSLinkReader.java
+++ b/src/org/geometerplus/fbreader/network/opds/OPDSLinkReader.java
@@ -39,19 +39,6 @@ import org.geometerplus.fbreader.network.atom.ATOMUpdated;
public class OPDSLinkReader {
static final String CATALOGS_URL = "http://data.fbreader.org/catalogs/generic-1.2.xml";
- public static ICustomNetworkLink createCustomLink(int id, String siteName, String title, String summary, String icon, Map links) {
- if (siteName == null || title == null || links.get(INetworkLink.URL_MAIN) == null) {
- return null;
- }
- return new OPDSCustomLink(id, siteName, title, summary, icon, links);
- }
-
- public static ICustomNetworkLink createCustomLinkWithoutInfo(String siteName, String url) {
- final HashMap links = new HashMap();
- links.put(INetworkLink.URL_MAIN, url);
- return new OPDSCustomLink(ICustomNetworkLink.INVALID_ID, siteName, null, null, null, links);
- }
-
public static final int CACHE_LOAD = 0;
public static final int CACHE_UPDATE = 1;
public static final int CACHE_CLEAR = 2;
diff --git a/src/org/geometerplus/fbreader/network/opds/OPDSLinkXMLReader.java b/src/org/geometerplus/fbreader/network/opds/OPDSLinkXMLReader.java
index 418507651..c9b06758c 100644
--- a/src/org/geometerplus/fbreader/network/opds/OPDSLinkXMLReader.java
+++ b/src/org/geometerplus/fbreader/network/opds/OPDSLinkXMLReader.java
@@ -30,6 +30,7 @@ import org.geometerplus.zlibrary.core.xml.ZLStringMap;
import org.geometerplus.fbreader.network.INetworkLink;
import org.geometerplus.fbreader.network.NetworkLibrary;
import org.geometerplus.fbreader.network.NetworkCatalogItem;
+import org.geometerplus.fbreader.network.UrlInfo;
import org.geometerplus.fbreader.network.atom.ATOMLink;
import org.geometerplus.fbreader.network.atom.ATOMUpdated;
import org.geometerplus.fbreader.network.authentication.NetworkAuthenticationManager;
@@ -98,8 +99,7 @@ class OPDSLinkXMLReader extends OPDSXMLReader implements OPDSConstants, MimeType
final String summary = entry.Content;
final String language = entry.DCLanguage;
- String icon = null;
- final HashMap links = new HashMap();
+ final HashMap infos = new HashMap();
final HashMap urlConditions =
new HashMap();
for (ATOMLink link: entry.Links) {
@@ -108,34 +108,35 @@ class OPDSLinkXMLReader extends OPDSXMLReader implements OPDSConstants, MimeType
final String rel = link.getRel();
if (rel == REL_IMAGE_THUMBNAIL || rel == REL_THUMBNAIL) {
if (type == MIME_IMAGE_PNG || type == MIME_IMAGE_JPEG) {
- icon = href;
+ infos.put(INetworkLink.URL_ICON, new UrlInfo(href));
}
} else if ((rel != null && rel.startsWith(REL_IMAGE_PREFIX)) || rel == REL_COVER) {
- if (icon == null && (type == MIME_IMAGE_PNG || type == MIME_IMAGE_JPEG)) {
- icon = href;
+ if (infos.get(INetworkLink.URL_ICON) == null &&
+ (type == MIME_IMAGE_PNG || type == MIME_IMAGE_JPEG)) {
+ infos.put(INetworkLink.URL_ICON, new UrlInfo(href));
}
} else if (rel == null) {
if (type == MIME_APP_ATOM) {
- links.put(INetworkLink.URL_MAIN, href);
+ infos.put(INetworkLink.URL_MAIN, new UrlInfo(href));
}
} else if (rel == "search") {
if (type == MIME_APP_ATOM) {
final OpenSearchDescription descr = OpenSearchDescription.createDefault(href);
if (descr.isValid()) {
// TODO: May be do not use '%s'??? Use Description instead??? (this needs to rewrite SEARCH engine logic a little)
- links.put(INetworkLink.URL_SEARCH, descr.makeQuery("%s"));
+ infos.put(INetworkLink.URL_SEARCH, new UrlInfo(descr.makeQuery("%s")));
}
}
} else if (rel == REL_LINK_SIGN_IN) {
- links.put(INetworkLink.URL_SIGN_IN, href);
+ infos.put(INetworkLink.URL_SIGN_IN, new UrlInfo(href));
} else if (rel == REL_LINK_SIGN_OUT) {
- links.put(INetworkLink.URL_SIGN_OUT, href);
+ infos.put(INetworkLink.URL_SIGN_OUT, new UrlInfo(href));
} else if (rel == REL_LINK_SIGN_UP) {
- links.put(INetworkLink.URL_SIGN_UP, href);
+ infos.put(INetworkLink.URL_SIGN_UP, new UrlInfo(href));
} else if (rel == REL_LINK_REFILL_ACCOUNT) {
- links.put(INetworkLink.URL_REFILL_ACCOUNT, href);
+ infos.put(INetworkLink.URL_REFILL_ACCOUNT, new UrlInfo(href));
} else if (rel == REL_LINK_RECOVER_PASSWORD) {
- links.put(INetworkLink.URL_RECOVER_PASSWORD, href);
+ infos.put(INetworkLink.URL_RECOVER_PASSWORD, new UrlInfo(href));
} else if (rel == REL_CONDITION_NEVER) {
urlConditions.put(href, NetworkCatalogItem.Accessibility.NEVER);
} else if (rel == REL_CONDITION_SIGNED_IN) {
@@ -153,7 +154,7 @@ class OPDSLinkXMLReader extends OPDSXMLReader implements OPDSConstants, MimeType
sslCertificate = null;
}
- INetworkLink result = link(siteName, title, summary, icon, language, links, urlConditions, sslCertificate);
+ INetworkLink result = link(siteName, title, summary, language, infos, urlConditions, sslCertificate);
if (result != null) {
myListener.onNewLink(result);
}
@@ -164,13 +165,12 @@ class OPDSLinkXMLReader extends OPDSXMLReader implements OPDSConstants, MimeType
String siteName,
String title,
String summary,
- String icon,
String language,
- Map links,
+ Map infos,
HashMap urlConditions,
String sslCertificate
) {
- if (siteName == null || title == null || links.get(INetworkLink.URL_MAIN) == null) {
+ if (siteName == null || title == null || infos.get(INetworkLink.URL_MAIN) == null) {
return null;
}
@@ -178,9 +178,8 @@ class OPDSLinkXMLReader extends OPDSXMLReader implements OPDSConstants, MimeType
siteName,
title,
summary,
- icon,
language,
- links,
+ infos,
myHasStableIdentifiers
);
diff --git a/src/org/geometerplus/fbreader/network/opds/OPDSNetworkLink.java b/src/org/geometerplus/fbreader/network/opds/OPDSNetworkLink.java
index 0f282541a..4e3aaf6e9 100644
--- a/src/org/geometerplus/fbreader/network/opds/OPDSNetworkLink.java
+++ b/src/org/geometerplus/fbreader/network/opds/OPDSNetworkLink.java
@@ -34,7 +34,7 @@ import org.geometerplus.zlibrary.core.network.ZLNetworkRequest;
import org.geometerplus.fbreader.network.*;
import org.geometerplus.fbreader.network.authentication.NetworkAuthenticationManager;
-class OPDSNetworkLink extends AbstractNetworkLink {
+public class OPDSNetworkLink extends AbstractNetworkLink {
private TreeMap myRelationAliases;
private TreeMap myUrlConditions;
@@ -44,9 +44,9 @@ class OPDSNetworkLink extends AbstractNetworkLink {
private final boolean myHasStableIdentifiers;
- OPDSNetworkLink(String siteName, String title, String summary, String icon, String language,
- Map links, boolean hasStableIdentifiers) {
- super(siteName, title, summary, icon, language, links);
+ OPDSNetworkLink(String siteName, String title, String summary, String language,
+ Map infos, boolean hasStableIdentifiers) {
+ super(siteName, title, summary, language, infos);
myHasStableIdentifiers = hasStableIdentifiers;
}
@@ -113,13 +113,12 @@ class OPDSNetworkLink extends AbstractNetworkLink {
}
@Override
- public OPDSCatalogItem.State createOperationData(INetworkLink link,
- NetworkOperationData.OnNewItemListener listener) {
- return new OPDSCatalogItem.State(link, listener);
+ public OPDSCatalogItem.State createOperationData(NetworkOperationData.OnNewItemListener listener) {
+ return new OPDSCatalogItem.State(this, listener);
}
public ZLNetworkRequest simpleSearchRequest(String pattern, NetworkOperationData data) {
- final String url = getLink(URL_SEARCH);
+ final String url = getUrlInfo(URL_SEARCH).URL;
if (url == null) {
return null;
}
@@ -135,9 +134,9 @@ class OPDSNetworkLink extends AbstractNetworkLink {
}
public NetworkCatalogItem libraryItem() {
- TreeMap urlMap = new TreeMap();
- urlMap.put(NetworkCatalogItem.URL_CATALOG, getLink(URL_MAIN));
- return new OPDSCatalogItem(this, getTitle(), getSummary(), getIcon(), urlMap, myExtraData);
+ TreeMap urlMap = new TreeMap();
+ urlMap.put(NetworkCatalogItem.URL_CATALOG, getUrlInfo(URL_MAIN).URL);
+ return new OPDSCatalogItem(this, getTitle(), getSummary(), getUrlInfo(URL_ICON).URL, urlMap, myExtraData);
}
public NetworkAuthenticationManager authenticationManager() {
diff --git a/src/org/geometerplus/fbreader/network/opds/OPDSXMLReader.java b/src/org/geometerplus/fbreader/network/opds/OPDSXMLReader.java
index 1631f7aef..631266477 100644
--- a/src/org/geometerplus/fbreader/network/opds/OPDSXMLReader.java
+++ b/src/org/geometerplus/fbreader/network/opds/OPDSXMLReader.java
@@ -172,7 +172,7 @@ class OPDSXMLReader extends ZLXMLReaderAdapter {
private int myState = START;
- private final StringBuffer myBuffer = new StringBuffer();
+ private final StringBuilder myBuffer = new StringBuilder();
private HtmlToString myHtmlToString = new HtmlToString();
private boolean myFeedMetadataProcessed;
diff --git a/src/org/geometerplus/fbreader/network/opds/OpenSearchDescription.java b/src/org/geometerplus/fbreader/network/opds/OpenSearchDescription.java
index d878f20f0..5dbd8de08 100644
--- a/src/org/geometerplus/fbreader/network/opds/OpenSearchDescription.java
+++ b/src/org/geometerplus/fbreader/network/opds/OpenSearchDescription.java
@@ -23,22 +23,20 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern;
class OpenSearchDescription {
-
public static OpenSearchDescription createDefault(String template) {
- return new OpenSearchDescription(template, 20, -1, -1);
+ return new OpenSearchDescription(template, -1, -1);
}
public final String Template;
public final int IndexOffset;
public final int PageOffset;
- public final int ItemsPerPage;
+ public final int ItemsPerPage = 20;
- public OpenSearchDescription(String template, int itemsPerPage, int indexOffset, int pageOffset) {
+ OpenSearchDescription(String template, int indexOffset, int pageOffset) {
Template = template;
IndexOffset = indexOffset;
PageOffset = pageOffset;
- ItemsPerPage = itemsPerPage;
}
public boolean isValid() {
@@ -62,13 +60,7 @@ class OpenSearchDescription {
if (name == "searchTerms") {
m.appendReplacement(query, searchTerms);
} else if (name == "count") {
- if (ItemsPerPage > 0) {
- m.appendReplacement(query, String.valueOf(ItemsPerPage));
- } else if (optional) {
- m.appendReplacement(query, "");
- } else {
- return null;
- }
+ m.appendReplacement(query, String.valueOf(ItemsPerPage));
} else if (optional) {
m.appendReplacement(query, "");
} else if (name == "startIndex") {
diff --git a/src/org/geometerplus/fbreader/network/opds/OpenSearchXMLReader.java b/src/org/geometerplus/fbreader/network/opds/OpenSearchXMLReader.java
index fe03b6c76..db5d65a7f 100644
--- a/src/org/geometerplus/fbreader/network/opds/OpenSearchXMLReader.java
+++ b/src/org/geometerplus/fbreader/network/opds/OpenSearchXMLReader.java
@@ -30,15 +30,12 @@ import org.geometerplus.zlibrary.core.xml.ZLStringMap;
import org.geometerplus.zlibrary.core.xml.ZLXMLReaderAdapter;
class OpenSearchXMLReader extends ZLXMLReaderAdapter {
-
private final List myDescriptions;
- private final int myItemsPerPage;
private final String myBaseURL;
- public OpenSearchXMLReader(String baseUrl, List descriptions, int itemsPerPage) {
+ public OpenSearchXMLReader(String baseUrl, List descriptions) {
myDescriptions = descriptions;
- myItemsPerPage = itemsPerPage;
myBaseURL = baseUrl;
}
@@ -115,7 +112,7 @@ class OpenSearchXMLReader extends ZLXMLReaderAdapter {
final int indexOffset = parseInt(attributes.getValue("indexOffset"));
final int pageOffset = parseInt(attributes.getValue("pageOffset"));
final OpenSearchDescription descr =
- new OpenSearchDescription(template, myItemsPerPage, indexOffset, pageOffset);
+ new OpenSearchDescription(template, indexOffset, pageOffset);
if (descr.isValid()) {
myDescriptions.add(descr);
}
diff --git a/src/org/geometerplus/android/fbreader/network/AddCustomCatalogItemTree.java b/src/org/geometerplus/fbreader/network/tree/AddCustomCatalogItemTree.java
similarity index 72%
rename from src/org/geometerplus/android/fbreader/network/AddCustomCatalogItemTree.java
rename to src/org/geometerplus/fbreader/network/tree/AddCustomCatalogItemTree.java
index 4b111f5e5..8d6d3097d 100644
--- a/src/org/geometerplus/android/fbreader/network/AddCustomCatalogItemTree.java
+++ b/src/org/geometerplus/fbreader/network/tree/AddCustomCatalogItemTree.java
@@ -17,20 +17,16 @@
* 02110-1301, USA.
*/
-package org.geometerplus.android.fbreader.network;
+package org.geometerplus.fbreader.network.tree;
import org.geometerplus.zlibrary.core.resources.ZLResource;
-import org.geometerplus.zlibrary.ui.android.R;
-
-import org.geometerplus.fbreader.network.NetworkLibraryItem;
+import org.geometerplus.fbreader.network.NetworkItem;
import org.geometerplus.fbreader.network.NetworkTree;
-import org.geometerplus.android.fbreader.tree.ZLAndroidTree;
-
-public class AddCustomCatalogItemTree extends NetworkTree implements ZLAndroidTree {
- public AddCustomCatalogItemTree() {
- super(1);
+public class AddCustomCatalogItemTree extends NetworkTree {
+ public AddCustomCatalogItemTree(NetworkTree parent) {
+ super(parent);
}
@Override
@@ -44,11 +40,12 @@ public class AddCustomCatalogItemTree extends NetworkTree implements ZLAndroidTr
}
@Override
- public NetworkLibraryItem getHoldedItem() {
+ public NetworkItem getHoldedItem() {
return null;
}
- public int getCoverResourceId() {
- return R.drawable.ic_list_plus;
+ @Override
+ protected String getStringId() {
+ return "@Add Custom Catalog";
}
}
diff --git a/src/org/geometerplus/fbreader/network/tree/NetworkAuthorTree.java b/src/org/geometerplus/fbreader/network/tree/NetworkAuthorTree.java
index 17a02f627..b7c1ae976 100644
--- a/src/org/geometerplus/fbreader/network/tree/NetworkAuthorTree.java
+++ b/src/org/geometerplus/fbreader/network/tree/NetworkAuthorTree.java
@@ -120,7 +120,12 @@ public class NetworkAuthorTree extends NetworkTree {
}
@Override
- public NetworkLibraryItem getHoldedItem() {
+ public NetworkItem getHoldedItem() {
return null;
}
+
+ @Override
+ protected String getStringId() {
+ return "@Author:" + Author.DisplayName + ":" + Author.SortKey;
+ }
}
diff --git a/src/org/geometerplus/fbreader/network/tree/NetworkBookTree.java b/src/org/geometerplus/fbreader/network/tree/NetworkBookTree.java
index 8193d3241..5b3586547 100644
--- a/src/org/geometerplus/fbreader/network/tree/NetworkBookTree.java
+++ b/src/org/geometerplus/fbreader/network/tree/NetworkBookTree.java
@@ -69,7 +69,12 @@ public class NetworkBookTree extends NetworkTree {
}
@Override
- public NetworkLibraryItem getHoldedItem() {
+ public NetworkItem getHoldedItem() {
return Book;
}
+
+ @Override
+ protected String getStringId() {
+ return "@Book:" + Book.Id + ":" + Book.Title;
+ }
}
diff --git a/src/org/geometerplus/fbreader/network/tree/NetworkCatalogRootTree.java b/src/org/geometerplus/fbreader/network/tree/NetworkCatalogRootTree.java
index 7528becb3..987521723 100644
--- a/src/org/geometerplus/fbreader/network/tree/NetworkCatalogRootTree.java
+++ b/src/org/geometerplus/fbreader/network/tree/NetworkCatalogRootTree.java
@@ -22,8 +22,7 @@ package org.geometerplus.fbreader.network.tree;
import org.geometerplus.fbreader.network.*;
public class NetworkCatalogRootTree extends NetworkCatalogTree {
-
public NetworkCatalogRootTree(RootTree parent, INetworkLink link, int position) {
- super(parent, (NetworkCatalogItem) link.libraryItem(), position);
+ super(parent, (NetworkCatalogItem)link.libraryItem(), position);
}
}
diff --git a/src/org/geometerplus/fbreader/network/tree/NetworkCatalogTree.java b/src/org/geometerplus/fbreader/network/tree/NetworkCatalogTree.java
index 3f84f68ca..097e391e1 100644
--- a/src/org/geometerplus/fbreader/network/tree/NetworkCatalogTree.java
+++ b/src/org/geometerplus/fbreader/network/tree/NetworkCatalogTree.java
@@ -28,9 +28,8 @@ import org.geometerplus.fbreader.tree.FBTree;
import org.geometerplus.fbreader.network.*;
public class NetworkCatalogTree extends NetworkTree {
-
public final NetworkCatalogItem Item;
- public final ArrayList ChildrenItems = new ArrayList();
+ public final ArrayList ChildrenItems = new ArrayList();
private long myLoadedTime = -1;
@@ -62,7 +61,6 @@ public class NetworkCatalogTree extends NetworkTree {
return createCover(Item);
}
-
public boolean isContentValid() {
if (myLoadedTime < 0) {
return false;
@@ -80,7 +78,6 @@ public class NetworkCatalogTree extends NetworkTree {
}
}
-
public void updateVisibility() {
final LinkedList toRemove = new LinkedList();
@@ -89,7 +86,7 @@ public class NetworkCatalogTree extends NetworkTree {
int nodeCount = 0;
for (int i = 0; i < ChildrenItems.size(); ++i) {
- NetworkLibraryItem currentItem = ChildrenItems.get(i);
+ NetworkItem currentItem = ChildrenItems.get(i);
if (!(currentItem instanceof NetworkCatalogItem)) {
continue;
}
@@ -161,13 +158,18 @@ public class NetworkCatalogTree extends NetworkTree {
}
@Override
- public NetworkLibraryItem getHoldedItem() {
+ public NetworkItem getHoldedItem() {
return Item;
}
@Override
- public void removeItems(Set items) {
+ public void removeItems(Set items) {
ChildrenItems.removeAll(items);
super.removeItems(items);
}
+
+ @Override
+ protected String getStringId() {
+ return Item.getFullRequestString();
+ }
}
diff --git a/src/org/geometerplus/fbreader/network/tree/NetworkSeriesTree.java b/src/org/geometerplus/fbreader/network/tree/NetworkSeriesTree.java
index 81f838b3e..3a9af37d0 100644
--- a/src/org/geometerplus/fbreader/network/tree/NetworkSeriesTree.java
+++ b/src/org/geometerplus/fbreader/network/tree/NetworkSeriesTree.java
@@ -87,15 +87,20 @@ public class NetworkSeriesTree extends NetworkTree {
}
@Override
- public NetworkLibraryItem getHoldedItem() {
+ public NetworkItem getHoldedItem() {
return null;
}
@Override
- public void removeItems(Set items) {
+ public void removeItems(Set items) {
super.removeItems(items);
if (subTrees().isEmpty()) {
removeSelf();
}
}
+
+ @Override
+ protected String getStringId() {
+ return "@Series:" + SeriesTitle;
+ }
}
diff --git a/src/org/geometerplus/fbreader/network/tree/NetworkTreeFactory.java b/src/org/geometerplus/fbreader/network/tree/NetworkTreeFactory.java
index b9231a9c9..a61903512 100644
--- a/src/org/geometerplus/fbreader/network/tree/NetworkTreeFactory.java
+++ b/src/org/geometerplus/fbreader/network/tree/NetworkTreeFactory.java
@@ -25,11 +25,11 @@ import org.geometerplus.fbreader.network.*;
public class NetworkTreeFactory {
- public static NetworkTree createNetworkTree(NetworkCatalogTree parent, NetworkLibraryItem item) {
+ public static NetworkTree createNetworkTree(NetworkCatalogTree parent, NetworkItem item) {
return createNetworkTree(parent, item, -1);
}
- public static NetworkTree createNetworkTree(NetworkCatalogTree parent, NetworkLibraryItem item, int position) {
+ public static NetworkTree createNetworkTree(NetworkCatalogTree parent, NetworkItem item, int position) {
final int subtreesSize = parent.subTrees().size();
if (position == -1) {
position = subtreesSize;
@@ -80,6 +80,8 @@ public class NetworkTreeFactory {
}
return new NetworkBookTree(parent, book, position, showAuthors);
+ } else if (item instanceof TopUpItem) {
+ return new TopUpTree(parent, (TopUpItem)item);
}
return null;
}
diff --git a/src/org/geometerplus/fbreader/network/tree/RootTree.java b/src/org/geometerplus/fbreader/network/tree/RootTree.java
index 561566c43..09a4a6a69 100644
--- a/src/org/geometerplus/fbreader/network/tree/RootTree.java
+++ b/src/org/geometerplus/fbreader/network/tree/RootTree.java
@@ -19,7 +19,7 @@
package org.geometerplus.fbreader.network.tree;
-import org.geometerplus.fbreader.network.NetworkLibraryItem;
+import org.geometerplus.fbreader.network.NetworkItem;
import org.geometerplus.fbreader.network.NetworkTree;
public final class RootTree extends NetworkTree {
@@ -29,7 +29,12 @@ public final class RootTree extends NetworkTree {
}
@Override
- public NetworkLibraryItem getHoldedItem() {
+ public NetworkItem getHoldedItem() {
return null;
}
+
+ @Override
+ protected String getStringId() {
+ return "@Root";
+ }
}
diff --git a/src/org/geometerplus/android/fbreader/network/SearchItemTree.java b/src/org/geometerplus/fbreader/network/tree/SearchItemTree.java
similarity index 87%
rename from src/org/geometerplus/android/fbreader/network/SearchItemTree.java
rename to src/org/geometerplus/fbreader/network/tree/SearchItemTree.java
index 67979ff25..183aa41ef 100644
--- a/src/org/geometerplus/android/fbreader/network/SearchItemTree.java
+++ b/src/org/geometerplus/fbreader/network/tree/SearchItemTree.java
@@ -17,7 +17,7 @@
* 02110-1301, USA.
*/
-package org.geometerplus.android.fbreader.network;
+package org.geometerplus.fbreader.network.tree;
import java.util.Set;
import java.util.LinkedList;
@@ -29,16 +29,11 @@ import org.geometerplus.fbreader.tree.FBTree;
import org.geometerplus.fbreader.network.*;
import org.geometerplus.fbreader.network.tree.NetworkAuthorTree;
-import org.geometerplus.zlibrary.ui.android.R;
-
-import org.geometerplus.android.fbreader.tree.ZLAndroidTree;
-
-public class SearchItemTree extends NetworkTree implements ZLAndroidTree {
-
+public class SearchItemTree extends NetworkTree {
private SearchResult myResult;
- public SearchItemTree() {
- super(1);
+ public SearchItemTree(NetworkTree parent, int position) {
+ super(parent, position);
}
@Override
@@ -51,10 +46,6 @@ public class SearchItemTree extends NetworkTree implements ZLAndroidTree {
return ZLResource.resource("networkView").getResource("searchSummary").getValue();
}
- public int getCoverResourceId() {
- return R.drawable.ic_list_searchresult;
- }
-
public void setSearchResult(SearchResult result) {
myResult = result;
clear();
@@ -99,7 +90,12 @@ public class SearchItemTree extends NetworkTree implements ZLAndroidTree {
}
@Override
- public NetworkLibraryItem getHoldedItem() {
+ public NetworkItem getHoldedItem() {
return null;
}
+
+ @Override
+ protected String getStringId() {
+ return "@Search";
+ }
}
diff --git a/src/org/geometerplus/android/fbreader/network/RefillAccountTree.java b/src/org/geometerplus/fbreader/network/tree/TopUpTree.java
similarity index 54%
rename from src/org/geometerplus/android/fbreader/network/RefillAccountTree.java
rename to src/org/geometerplus/fbreader/network/tree/TopUpTree.java
index a70ea64eb..9e3099862 100644
--- a/src/org/geometerplus/android/fbreader/network/RefillAccountTree.java
+++ b/src/org/geometerplus/fbreader/network/tree/TopUpTree.java
@@ -17,47 +17,36 @@
* 02110-1301, USA.
*/
-package org.geometerplus.android.fbreader.network;
+package org.geometerplus.fbreader.network.tree;
+import org.geometerplus.zlibrary.core.image.ZLImage;
import org.geometerplus.zlibrary.core.network.ZLNetworkException;
-import org.geometerplus.zlibrary.core.resources.ZLResource;
-import org.geometerplus.fbreader.network.INetworkLink;
-import org.geometerplus.fbreader.network.NetworkLibraryItem;
+import org.geometerplus.fbreader.network.TopUpItem;
import org.geometerplus.fbreader.network.NetworkTree;
-import org.geometerplus.fbreader.network.tree.NetworkCatalogTree;
import org.geometerplus.fbreader.network.authentication.NetworkAuthenticationManager;
-import org.geometerplus.zlibrary.ui.android.R;
+public class TopUpTree extends NetworkTree {
+ public final TopUpItem Item;
-import org.geometerplus.android.fbreader.tree.ZLAndroidTree;
-
-class RefillAccountTree extends NetworkTree implements ZLAndroidTree {
- public final INetworkLink Link;
-
- public RefillAccountTree(NetworkCatalogTree parentTree) {
- super(parentTree.Level + 1);
- Link = parentTree.Item.Link;
- }
-
- public RefillAccountTree(INetworkLink link) {
- super(1);
- Link = link;
+ TopUpTree(NetworkCatalogTree parentTree, TopUpItem item) {
+ super(parentTree);
+ Item = item;
}
@Override
public String getName() {
- return ZLResource.resource("networkView").getResource("refillTitle").getValue();
+ return Item.Title;
}
@Override
public String getSummary() {
- final NetworkAuthenticationManager mgr = Link.authenticationManager();
+ final NetworkAuthenticationManager mgr = Item.Link.authenticationManager();
try {
if (mgr.isAuthorised(false)) {
final String account = mgr.currentAccount();
if (account != null) {
- return ZLResource.resource("networkView").getResource("refillSummary").getValue().replace("%s", account);
+ return Item.Summary.replace("%s", account);
}
}
} catch (ZLNetworkException e) {
@@ -66,11 +55,17 @@ class RefillAccountTree extends NetworkTree implements ZLAndroidTree {
}
@Override
- public NetworkLibraryItem getHoldedItem() {
- return null;
+ protected ZLImage createCover() {
+ return createCover(Item);
}
- public int getCoverResourceId() {
- return R.drawable.ic_list_library_wallet;
+ @Override
+ public TopUpItem getHoldedItem() {
+ return Item;
+ }
+
+ @Override
+ protected String getStringId() {
+ return "@TopUp Account";
}
}
diff --git a/src/org/geometerplus/fbreader/tree/FBTree.java b/src/org/geometerplus/fbreader/tree/FBTree.java
index 743b394dc..0cf94b8d9 100644
--- a/src/org/geometerplus/fbreader/tree/FBTree.java
+++ b/src/org/geometerplus/fbreader/tree/FBTree.java
@@ -29,10 +29,6 @@ public abstract class FBTree extends ZLTree implements Comparable
+ *
+ * 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.zlibrary.core.options;
+
+import java.util.*;
+
+public class ZLStringListOption extends ZLOption {
+ private final List myDefaultValue;
+ private List myValue;
+
+ private static String listToString(List list) {
+ if (list == null || list.isEmpty()) {
+ return "";
+ }
+ final StringBuilder builder = new StringBuilder();
+ boolean first = true;
+ for (String s : list) {
+ if (first) {
+ first = false;
+ } else {
+ builder.append(",");
+ }
+ builder.append(s);
+ }
+ return builder.toString();
+ }
+
+ private static List stringToList(String str) {
+ if (str == null || "".equals(str)) {
+ return Collections.emptyList();
+ }
+ return Arrays.asList(str.split(","));
+ }
+
+ public ZLStringListOption(String group, String optionName, List defaultValue) {
+ super(group, optionName);
+ myDefaultValue = (defaultValue != null) ? defaultValue : Collections.emptyList();
+ myValue = myDefaultValue;
+ }
+
+ public List getValue() {
+ if (!myIsSynchronized) {
+ final String value = getConfigValue(listToString(myDefaultValue));
+ if (value != null) {
+ myValue = stringToList(value);
+ }
+ myIsSynchronized = true;
+ }
+ return Collections.unmodifiableList(myValue);
+ }
+
+ public void setValue(List value) {
+ if (value == null) {
+ value = Collections.emptyList();
+ }
+ if (myIsSynchronized && (myValue.equals(value))) {
+ return;
+ }
+ myValue = new ArrayList(value);
+ if (value.equals(myDefaultValue)) {
+ unsetConfigValue();
+ } else {
+ setConfigValue(listToString(value));
+ }
+ myIsSynchronized = true;
+ }
+}
diff --git a/src/org/geometerplus/zlibrary/core/tree/ZLTree.java b/src/org/geometerplus/zlibrary/core/tree/ZLTree.java
index 676246ec6..b3036fe12 100644
--- a/src/org/geometerplus/zlibrary/core/tree/ZLTree.java
+++ b/src/org/geometerplus/zlibrary/core/tree/ZLTree.java
@@ -27,10 +27,6 @@ public abstract class ZLTree> implements Iterable {
public final int Level;
private ArrayList mySubTrees;
- protected ZLTree(int level) {
- this(level, null, 0);
- }
-
protected ZLTree() {
this(null);
}
@@ -40,10 +36,6 @@ public abstract class ZLTree> implements Iterable {
}
protected ZLTree(T parent, int position) {
- this(0, parent, position);
- }
-
- private ZLTree(int nullLevel, T parent, int position) {
if (parent != null && (position < 0 || position > parent.subTrees().size())) {
throw new IndexOutOfBoundsException("`position` value equals " + position + " but must be in range [0; " + parent.subTrees().size() + "]");
}
@@ -52,7 +44,7 @@ public abstract class ZLTree> implements Iterable {
Level = parent.Level + 1;
parent.addSubTree((T)this, position);
} else {
- Level = nullLevel;
+ Level = 0;
}
}
diff --git a/src/org/geometerplus/zlibrary/core/util/ZLMiscUtil.java b/src/org/geometerplus/zlibrary/core/util/ZLMiscUtil.java
index 7ca090cb0..082c60f7e 100644
--- a/src/org/geometerplus/zlibrary/core/util/ZLMiscUtil.java
+++ b/src/org/geometerplus/zlibrary/core/util/ZLMiscUtil.java
@@ -27,6 +27,10 @@ public abstract class ZLMiscUtil {
return (o0 == null) ? (o1 == null) : o0.equals(o1);
}
+ public static int hashCode(Object o) {
+ return o != null ? o.hashCode() : 0;
+ }
+
public static boolean listsEquals(List list1, List list2) {
if (list1 == null) {
return list2 == null || list2.isEmpty();