diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index c30317de6..fa7cd9c54 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -131,9 +131,17 @@
-
+
+
+
+
+
+
+
+
+
diff --git a/AndroidManifest.xml.pattern b/AndroidManifest.xml.pattern
index b86275398..63239e669 100644
--- a/AndroidManifest.xml.pattern
+++ b/AndroidManifest.xml.pattern
@@ -131,9 +131,17 @@
-
+
+
+
+
+
+
+
+
+
diff --git a/ChangeLog b/ChangeLog
index 897575fef..3826d0f1e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,7 @@
===== 0.99.14 (??? ??, 2011) =====
* Thai localization (by Samphan Pojanasophanakul)
* Fixed TTF font style detection
+* opds:// URLs support has been implemented
===== 0.99.13 (Feb 13, 2011) =====
* Fixed book/position forgetting bug
diff --git a/TODO.0.99.X b/TODO.0.99.X
index 806a7b04c..a80fba2d9 100644
--- a/TODO.0.99.X
+++ b/TODO.0.99.X
@@ -2,3 +2,4 @@ DONE hyphenations are not changed after language changing in book info dialog
* scrolling: 4 directions
* scrolling: add 3D animation
DONE 'disable douple tapping' option
+* float numbers as series index
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/assets/resources/application/cs.xml b/assets/resources/application/cs.xml
index e6b9fc776..1f3675b06 100644
--- a/assets/resources/application/cs.xml
+++ b/assets/resources/application/cs.xml
@@ -586,7 +586,7 @@
-
+
diff --git a/assets/resources/application/de.xml b/assets/resources/application/de.xml
index fbaa9f16f..798cce98b 100644
--- a/assets/resources/application/de.xml
+++ b/assets/resources/application/de.xml
@@ -587,7 +587,7 @@
-
+
diff --git a/assets/resources/application/en.xml b/assets/resources/application/en.xml
index 908552790..a6716c999 100644
--- a/assets/resources/application/en.xml
+++ b/assets/resources/application/en.xml
@@ -587,7 +587,7 @@
-
+
diff --git a/assets/resources/application/fr.xml b/assets/resources/application/fr.xml
index fa0bf4275..e135a0364 100644
--- a/assets/resources/application/fr.xml
+++ b/assets/resources/application/fr.xml
@@ -589,7 +589,7 @@
-
+
diff --git a/assets/resources/application/gl.xml b/assets/resources/application/gl.xml
index a6cb03a1e..0727f73fa 100644
--- a/assets/resources/application/gl.xml
+++ b/assets/resources/application/gl.xml
@@ -586,7 +586,7 @@
-
+
diff --git a/assets/resources/application/hu.xml b/assets/resources/application/hu.xml
index ccc685770..0ec9cff66 100644
--- a/assets/resources/application/hu.xml
+++ b/assets/resources/application/hu.xml
@@ -586,7 +586,7 @@
-
+
diff --git a/assets/resources/application/it.xml b/assets/resources/application/it.xml
index a67ec653f..a83e043da 100644
--- a/assets/resources/application/it.xml
+++ b/assets/resources/application/it.xml
@@ -586,7 +586,7 @@
-
+
diff --git a/assets/resources/application/nl.xml b/assets/resources/application/nl.xml
index a747968c5..53bb8f849 100644
--- a/assets/resources/application/nl.xml
+++ b/assets/resources/application/nl.xml
@@ -586,7 +586,7 @@
-
+
diff --git a/assets/resources/application/ru.xml b/assets/resources/application/ru.xml
index 527b39d14..37a817825 100644
--- a/assets/resources/application/ru.xml
+++ b/assets/resources/application/ru.xml
@@ -585,7 +585,7 @@
-
+
diff --git a/assets/resources/application/th.xml b/assets/resources/application/th.xml
index 21a59a643..a503eab27 100644
--- a/assets/resources/application/th.xml
+++ b/assets/resources/application/th.xml
@@ -590,7 +590,7 @@
-
+
diff --git a/assets/resources/application/uk.xml b/assets/resources/application/uk.xml
index 37fce895f..24f781809 100644
--- a/assets/resources/application/uk.xml
+++ b/assets/resources/application/uk.xml
@@ -586,7 +586,7 @@
-
+
diff --git a/assets/resources/application/vi.xml b/assets/resources/application/vi.xml
index 98d7f67e7..40e0f9e6c 100644
--- a/assets/resources/application/vi.xml
+++ b/assets/resources/application/vi.xml
@@ -586,7 +586,7 @@
-
+
diff --git a/assets/resources/application/zh.xml b/assets/resources/application/zh.xml
index ebc704b90..d772f0b45 100644
--- a/assets/resources/application/zh.xml
+++ b/assets/resources/application/zh.xml
@@ -586,7 +586,7 @@
-
+
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/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 10a0d932c..9891c8566 100644
--- a/src/org/geometerplus/android/fbreader/FBReader.java
+++ b/src/org/geometerplus/android/fbreader/FBReader.java
@@ -28,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;
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..56c4b13fd
--- /dev/null
+++ b/src/org/geometerplus/android/fbreader/network/AddCustomCatalogActivity.java
@@ -0,0 +1,287 @@
+/*
+ * 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.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.ICustomNetworkLink;
+import org.geometerplus.fbreader.network.opds.OPDSLinkReader;
+
+import org.geometerplus.android.util.UIUtil;
+
+public class AddCustomCatalogActivity extends Activity {
+ private ZLResource myResource;
+ private Integer myCatalogId;
+ private String myIcon;
+
+ @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();
+ final Uri uri = intent.getData();
+ myCatalogId = ICustomNetworkLink.INVALID_ID;
+ if (uri != null) {
+ myCatalogId = intent.getIntExtra(
+ NetworkLibraryActivity.ADD_CATALOG_ID_KEY, myCatalogId
+ );
+ if (myCatalogId != ICustomNetworkLink.INVALID_ID) {
+ setTextById(R.id.add_custom_catalog_url, uri.toString());
+ setTextById(R.id.add_custom_catalog_title, intent.getStringExtra(NetworkLibraryActivity.ADD_CATALOG_TITLE_KEY));
+ setTextById(R.id.add_custom_catalog_summary, intent.getStringExtra(NetworkLibraryActivity.ADD_CATALOG_SUMMARY_KEY));
+ myIcon = intent.getStringExtra(NetworkLibraryActivity.ADD_CATALOG_ICON_KEY);
+ } else {
+ loadInfoByUri(uri);
+ }
+ setExtraFieldsVisibility(true);
+ } 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 (!getExtraFieldsVisibility()) {
+ loadInfoByUri(uri);
+ } else if (isEmptyString(title)) {
+ setErrorByKey("titleIsEmpty");
+ } else {
+ startActivity(
+ new Intent(
+ NetworkLibraryActivity.ADD_CATALOG,
+ uri,
+ AddCustomCatalogActivity.this,
+ NetworkLibraryActivity.class
+ )
+ .putExtra(NetworkLibraryActivity.ADD_CATALOG_TITLE_KEY, title)
+ .putExtra(NetworkLibraryActivity.ADD_CATALOG_SUMMARY_KEY, summary)
+ .putExtra(NetworkLibraryActivity.ADD_CATALOG_ICON_KEY, myIcon)
+ .putExtra(NetworkLibraryActivity.ADD_CATALOG_ID_KEY, myCatalogId)
+ .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP)
+ );
+ finish();
+ }
+ }
+
+ private boolean isEmptyString(String s) {
+ return s == null || s.length() == 0;
+ }
+
+ private boolean getExtraFieldsVisibility() {
+ return findViewById(R.id.add_custom_catalog_title_group).getVisibility() == View.VISIBLE;
+ }
+
+ 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);
+ String siteName = uri.getHost();
+ if (isEmptyString(siteName)) {
+ setErrorByKey("invalidUrl");
+ return;
+ }
+
+ if (siteName.startsWith("www.")) {
+ siteName = siteName.substring(4);
+ }
+ final ICustomNetworkLink link =
+ OPDSLinkReader.createCustomLink(siteName, null, null, null, textUrl);
+
+ final Runnable loadInfoRunnable = new Runnable() {
+ private String myError;
+
+ public void run() {
+ try {
+ myError = null;
+ link.reloadInfo();
+ } catch (ZLNetworkException e) {
+ myError = e.getMessage();
+ }
+ runOnUiThread(new Runnable() {
+ public void run() {
+ if (myError == null) {
+ setTextById(R.id.add_custom_catalog_title, link.getTitle());
+ setTextById(R.id.add_custom_catalog_summary, link.getSummary());
+ myIcon = link.getIcon();
+ setExtraFieldsVisibility(true);
+ } else {
+ runErrorDialog(myError);
+ myIcon = 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..63f804209 100644
--- a/src/org/geometerplus/android/fbreader/network/AddCustomCatalogItemActions.java
+++ b/src/org/geometerplus/android/fbreader/network/AddCustomCatalogItemActions.java
@@ -20,6 +20,7 @@
package org.geometerplus.android.fbreader.network;
import android.app.Activity;
+import android.content.Intent;
import android.view.Menu;
import android.view.ContextMenu;
@@ -70,6 +71,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/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/NetworkBookActions.java b/src/org/geometerplus/android/fbreader/network/NetworkBookActions.java
index 0826089dc..cbb000d92 100644
--- a/src/org/geometerplus/android/fbreader/network/NetworkBookActions.java
+++ b/src/org/geometerplus/android/fbreader/network/NetworkBookActions.java
@@ -309,7 +309,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)
);
}
}
diff --git a/src/org/geometerplus/android/fbreader/network/NetworkCatalogActions.java b/src/org/geometerplus/android/fbreader/network/NetworkCatalogActions.java
index 5ccd099ab..8a666abbd 100644
--- a/src/org/geometerplus/android/fbreader/network/NetworkCatalogActions.java
+++ b/src/org/geometerplus/android/fbreader/network/NetworkCatalogActions.java
@@ -23,6 +23,8 @@ 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;
@@ -245,8 +247,22 @@ class NetworkCatalogActions extends NetworkTreeActions {
new RefillAccountActions().runStandalone(activity, ((RefillAccountTree)activity.getDefaultTree()).Link);
return true;
case CUSTOM_CATALOG_EDIT:
- NetworkDialog.show(activity, NetworkDialog.DIALOG_CUSTOM_CATALOG, ((NetworkCatalogTree)tree).Item.Link, null);
+ {
+ final ICustomNetworkLink link =
+ (ICustomNetworkLink)((NetworkCatalogTree)tree).Item.Link;
+ final String textUrl = link.getLink(INetworkLink.URL_MAIN);
+ if (textUrl != null) {
+ activity.startActivity(
+ new Intent(activity, AddCustomCatalogActivity.class)
+ .setData(Uri.parse(textUrl))
+ .putExtra(NetworkLibraryActivity.ADD_CATALOG_TITLE_KEY, link.getTitle())
+ .putExtra(NetworkLibraryActivity.ADD_CATALOG_SUMMARY_KEY, link.getSummary())
+ .putExtra(NetworkLibraryActivity.ADD_CATALOG_ICON_KEY, link.getIcon())
+ .putExtra(NetworkLibraryActivity.ADD_CATALOG_ID_KEY, link.getId())
+ );
+ }
return true;
+ }
case CUSTOM_CATALOG_REMOVE:
removeCustomLink((ICustomNetworkLink)((NetworkCatalogTree)tree).Item.Link);
return true;
diff --git a/src/org/geometerplus/android/fbreader/network/NetworkDialog.java b/src/org/geometerplus/android/fbreader/network/NetworkDialog.java
index 5a9347a77..45b8d4599 100644
--- a/src/org/geometerplus/android/fbreader/network/NetworkDialog.java
+++ b/src/org/geometerplus/android/fbreader/network/NetworkDialog.java
@@ -39,7 +39,6 @@ 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();
@@ -50,9 +49,6 @@ abstract class NetworkDialog {
case DIALOG_AUTHENTICATION:
dlg = new AuthenticationDialog();
break;
- case DIALOG_CUSTOM_CATALOG:
- dlg = new CustomCatalogDialog();
- break;
}
if (dlg != null) {
dlg.myId = id;
diff --git a/src/org/geometerplus/android/fbreader/network/NetworkLibraryActivity.java b/src/org/geometerplus/android/fbreader/network/NetworkLibraryActivity.java
index 1041dcd9d..7ff160ae1 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;
@@ -40,9 +41,19 @@ import org.geometerplus.android.util.UIUtil;
import org.geometerplus.fbreader.network.NetworkTree;
import org.geometerplus.fbreader.network.NetworkLibrary;
+import org.geometerplus.fbreader.network.ICustomNetworkLink;
+import org.geometerplus.fbreader.network.opds.OPDSLinkReader;
public class NetworkLibraryActivity extends NetworkBaseActivity {
+ final static String ADD_CATALOG = "android.fbreader.action.ADD_CATALOG";
+
+ final static String ADD_CATALOG_TITLE_KEY = "title";
+ final static String ADD_CATALOG_SUMMARY_KEY = "summary";
+ final static String ADD_CATALOG_ICON_KEY = "icon";
+ final static String ADD_CATALOG_ID_KEY = "id";
+
private NetworkTree myTree;
+ private volatile Intent myIntent;
@Override
public void onCreate(Bundle icicle) {
@@ -50,6 +61,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) {
+ final String action = intent.getAction();
+ if (ADD_CATALOG.equals(action)) {
+ final Uri uri = intent.getData();
+ final String title = intent.getStringExtra(ADD_CATALOG_TITLE_KEY);
+ final String summary = intent.getStringExtra(ADD_CATALOG_SUMMARY_KEY);
+ final String icon = intent.getStringExtra(ADD_CATALOG_ICON_KEY);
+ final int id = intent.getIntExtra(ADD_CATALOG_ID_KEY, ICustomNetworkLink.INVALID_ID);
+ if (uri == null || title == null) {
+ return;
+ }
+ final ICustomNetworkLink link = OPDSLinkReader.createCustomLink(
+ id, uri.getHost(), title, summary, icon, uri.toString()
+ );
+ if (link != null) {
+ runOnUiThread(new Runnable() {
+ public void run() {
+ final NetworkLibrary library = NetworkLibrary.Instance();
+ library.addCustomLink(link);
+ library.updateChildren();
+ library.synchronize();
+ NetworkView.Instance().fireModelChangedAsync();
+ getListView().invalidateViews();
+ }
+ });
+ }
+ }
}
private void prepareView() {
@@ -74,6 +123,10 @@ public class NetworkLibraryActivity extends NetworkBaseActivity {
}
} else {
prepareView();
+ if (myIntent != null) {
+ processIntent(myIntent);
+ myIntent = null;
+ }
}
}
@@ -114,6 +167,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();
}
diff --git a/src/org/geometerplus/android/fbreader/network/SQLiteNetworkDatabase.java b/src/org/geometerplus/android/fbreader/network/SQLiteNetworkDatabase.java
index 3c3abf2bb..c9973f4db 100644
--- a/src/org/geometerplus/android/fbreader/network/SQLiteNetworkDatabase.java
+++ b/src/org/geometerplus/android/fbreader/network/SQLiteNetworkDatabase.java
@@ -41,7 +41,7 @@ class SQLiteNetworkDatabase extends NetworkDatabase {
private void migrate() {
final int version = myDatabase.getVersion();
- final int currentCodeVersion = 1;
+ final int currentCodeVersion = 2;
if (version >= currentCodeVersion) {
return;
}
@@ -49,6 +49,8 @@ class SQLiteNetworkDatabase extends NetworkDatabase {
switch (version) {
case 0:
createTables();
+ case 1:
+ updateTables1();
}
myDatabase.setTransactionSuccessful();
myDatabase.endTransaction();
@@ -155,7 +157,7 @@ class SQLiteNetworkDatabase extends NetworkDatabase {
if (dbValue == null) {
if (myInsertCustomLinkUrlStatement == null) {
myInsertCustomLinkUrlStatement = myDatabase.compileStatement(
- "INSERT INTO CustomLinkUrls(url,link_id,key) VALUES (?,?,?)");
+ "INSERT OR REPLACE INTO CustomLinkUrls(url,link_id,key) VALUES (?,?,?)");
}
urlStatement = myInsertCustomLinkUrlStatement;
} else if (!value.equals(dbValue)) {
@@ -230,4 +232,17 @@ 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");
+ }
}
diff --git a/src/org/geometerplus/fbreader/network/ICustomNetworkLink.java b/src/org/geometerplus/fbreader/network/ICustomNetworkLink.java
index 5b6981116..7bd1e623e 100644
--- a/src/org/geometerplus/fbreader/network/ICustomNetworkLink.java
+++ b/src/org/geometerplus/fbreader/network/ICustomNetworkLink.java
@@ -22,19 +22,11 @@ package org.geometerplus.fbreader.network;
import org.geometerplus.zlibrary.core.network.ZLNetworkException;
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);
diff --git a/src/org/geometerplus/fbreader/network/NetworkLibrary.java b/src/org/geometerplus/fbreader/network/NetworkLibrary.java
index 876b455e8..0b14619ca 100644
--- a/src/org/geometerplus/fbreader/network/NetworkLibrary.java
+++ b/src/org/geometerplus/fbreader/network/NetworkLibrary.java
@@ -182,7 +182,6 @@ public class NetworkLibrary {
final ICustomNetworkLink link = OPDSLinkReader.createCustomLink(id, siteName, title, summary, icon, links);
if (link != null) {
addLinkInternal(link);
- link.setSaveLinkListener(myChangesListener);
}
}
}
@@ -303,11 +302,6 @@ public class NetworkLibrary {
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) {
@@ -347,7 +341,7 @@ public class NetworkLibrary {
continue;
}
final INetworkLink nodeLink = ((NetworkCatalogTree) currentNode).Item.Link;
- if (linksEqual(link, nodeLink)) {
+ if (link == nodeLink) {
if (linkIsInvalid(link, nodeLink)) {
toRemove.add(currentNode);
} else {
@@ -360,7 +354,7 @@ 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;
}
@@ -468,12 +462,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 +469,20 @@ 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);
}
public void removeCustomLink(ICustomNetworkLink link) {
@@ -491,7 +490,6 @@ public class NetworkLibrary {
myLinks.remove(link);
}
NetworkDatabase.Instance().deleteCustomLink(link);
- link.setSaveLinkListener(null);
}
public boolean hasCustomLinkTitle(String title, INetworkLink exceptFor) {
diff --git a/src/org/geometerplus/fbreader/network/opds/OPDSCustomLink.java b/src/org/geometerplus/fbreader/network/opds/OPDSCustomLink.java
index ada9d7aa7..3fbe25a3b 100644
--- a/src/org/geometerplus/fbreader/network/opds/OPDSCustomLink.java
+++ b/src/org/geometerplus/fbreader/network/opds/OPDSCustomLink.java
@@ -33,11 +33,8 @@ import org.geometerplus.fbreader.network.ICustomNetworkLink;
import org.geometerplus.fbreader.network.INetworkLink;
import org.geometerplus.fbreader.network.NetworkException;
-
class OPDSCustomLink extends OPDSNetworkLink implements ICustomNetworkLink {
-
private int myId;
- private SaveLinkListener myListener;
private boolean myHasChanges;
@@ -54,18 +51,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;
}
diff --git a/src/org/geometerplus/fbreader/network/opds/OPDSLinkReader.java b/src/org/geometerplus/fbreader/network/opds/OPDSLinkReader.java
index e8933fadf..3c9a786ec 100644
--- a/src/org/geometerplus/fbreader/network/opds/OPDSLinkReader.java
+++ b/src/org/geometerplus/fbreader/network/opds/OPDSLinkReader.java
@@ -46,10 +46,14 @@ public class OPDSLinkReader {
return new OPDSCustomLink(id, siteName, title, summary, icon, links);
}
- public static ICustomNetworkLink createCustomLinkWithoutInfo(String siteName, String url) {
+ public static ICustomNetworkLink createCustomLink(int id, String siteName, String title, String summary, String icon, String url) {
final HashMap links = new HashMap();
links.put(INetworkLink.URL_MAIN, url);
- return new OPDSCustomLink(ICustomNetworkLink.INVALID_ID, siteName, null, null, null, links);
+ return new OPDSCustomLink(id, siteName, title, summary, icon, links);
+ }
+
+ public static ICustomNetworkLink createCustomLink(String siteName, String title, String summary, String icon, String url) {
+ return createCustomLink(ICustomNetworkLink.INVALID_ID, siteName, title, summary, icon, url);
}
public static final int CACHE_LOAD = 0;