mirror of
https://github.com/geometer/FBReaderJ.git
synced 2025-10-05 19:42:17 +02:00
New CustomCatalogDialog
git-svn-id: https://only.mawhrin.net/repos/FBReaderJ/trunk@1644 6a642e6f-84f6-412e-ac94-c4a38d5a04b0
This commit is contained in:
parent
cb3a2778b7
commit
b5b0f37ceb
21 changed files with 396 additions and 85 deletions
|
@ -6,9 +6,9 @@ DONE Иконка к "Добавить каталог"
|
|||
DONE Комментарий к этому пункту = "Добавление OPDS-каталога вручную"
|
||||
** Какую-нибудь иконку к добавленным вручную каталогам
|
||||
DONE Звездочку к 2-м обязательным пунктам при добавлении каталога
|
||||
?? Убрать 3-й пункт при добавлении????
|
||||
DONE Убрать 3-й пункт при добавлении
|
||||
DONE Может быть сделать примеры мелким шрифтом под полями
|
||||
** Сразу (по нажатию Ok) проверять и говорить, верный ли URL (Ex: Это не OPDS-каталог)
|
||||
DONE Сразу (по нажатию Ok) проверять и говорить, верный ли URL (Ex: Это не OPDS-каталог)
|
||||
Это не должно мешать добавлению, но пользователь д.б. предупрежден
|
||||
(типа -- это не OPDS каталог -> Edit/Continue/Cancel)
|
||||
кстати, при проверке можно было бы попробовать получить значение 3-го поля (summary)
|
||||
|
@ -39,8 +39,8 @@ DONE Network library: Объединять книги по сериям
|
|||
DONE Поддержка дополнительных currency codes (см. пункт 8.6.3.1)
|
||||
|
||||
?? Читать информацию для custom-каталогов из сети
|
||||
** поиск (пункт 7.5)
|
||||
** обложка
|
||||
** поиск (пункт 7.5): чтение дополнительного XML-файла описания поиска
|
||||
** обложка: поддержка .ico иконок в теге <icon></icon>
|
||||
?? Поддержка перехда по URL на OPDS-каталог из браузера (добавлять каталог в библиотеку)
|
||||
|
||||
** Отображать ошибки / сообщения при загрузке каталогов
|
||||
|
|
|
@ -137,6 +137,8 @@
|
|||
<node name="button">
|
||||
<node name="buy" value="Kaufen" />
|
||||
<node name="buyAndDownload" value="Kaufen und runterladen" />
|
||||
<node name="continue" toBeTranslated="true" value="Continue" />
|
||||
<node name="editUrl" toBeTranslated="true" value="Edit URL" />
|
||||
</node>
|
||||
<node name="BookInfo">
|
||||
<node name="fileName" value="Datei Name"/>
|
||||
|
@ -270,6 +272,7 @@
|
|||
<node name="signOut" value="Signing out. Bitte warten..." />
|
||||
<node name="purchaseBook" value="Buch wird gekauft. Bitte warten..." />
|
||||
<node name="registerUser" value="Neuer Account wird registriert. Bitte warten..." />
|
||||
<node name="loadingCatalogInfo" toBeTranslated="true" value="Loading catalog information. Please, wait..." />
|
||||
</node>
|
||||
<node name="networkError">
|
||||
<node name="internalError" value="Interner Server-Fehler" />
|
||||
|
@ -286,6 +289,8 @@
|
|||
<node name="tooManyRegistrations" value="Zu viele Registrierungen von Ihrer IP; bitte in einigen Minuten noch einmal probieren" />
|
||||
<node name="noUserEmail" value="Es gibt keinen registrierten Nutzer mit dieser Email-Adresse " />
|
||||
<node name="unsupportedOperation" value="Operation wird nicht unterstützt" />
|
||||
<node name="notAnOPDS" toBeTranslated="true" value="This is not an OPDS catalog" />
|
||||
<node name="noRequiredInformation" toBeTranslated="true" value="Required information is not specified in the catalog" />
|
||||
</node>
|
||||
<node name="emptyCatalogBox">
|
||||
<node name="title" value="Information" />
|
||||
|
|
|
@ -136,6 +136,8 @@
|
|||
<node name="button">
|
||||
<node name="buy" value="Buy" />
|
||||
<node name="buyAndDownload" value="Buy and download" />
|
||||
<node name="continue" value="Continue" />
|
||||
<node name="editUrl" value="Edit URL" />
|
||||
</node>
|
||||
<node name="BookInfo">
|
||||
<node name="fileName" value="File name"/>
|
||||
|
@ -269,6 +271,7 @@
|
|||
<node name="signOut" value="Signing out. Please, wait..." />
|
||||
<node name="purchaseBook" value="Purchase book. Please, wait..." />
|
||||
<node name="registerUser" value="Registering new account. Please, wait..." />
|
||||
<node name="loadingCatalogInfo" value="Loading catalog information. Please, wait..." />
|
||||
</node>
|
||||
<node name="networkError">
|
||||
<node name="internalError" value="Internal server error" />
|
||||
|
@ -285,6 +288,8 @@
|
|||
<node name="tooManyRegistrations" value="Too many registrations from your IP; try again in a few minutes" />
|
||||
<node name="noUserEmail" value="No user was registered with specified e-mail address" />
|
||||
<node name="unsupportedOperation" value="Unsupported operation" />
|
||||
<node name="notAnOPDS" value="This is not an OPDS catalog" />
|
||||
<node name="noRequiredInformation" value="Required information is not specified in the catalog" />
|
||||
</node>
|
||||
<node name="emptyCatalogBox">
|
||||
<node name="title" value="Information" />
|
||||
|
|
|
@ -137,6 +137,8 @@
|
|||
<node name="button">
|
||||
<node name="buy" value="Acheter"/>
|
||||
<node name="buyAndDownload" value="Acheter et télécharger"/>
|
||||
<node name="continue" toBeTranslated="true" value="Continue" />
|
||||
<node name="editUrl" toBeTranslated="true" value="Edit URL" />
|
||||
</node>
|
||||
<node name="BookInfo">
|
||||
<node name="fileName" value="Nom du fichier"/>
|
||||
|
@ -270,6 +272,7 @@
|
|||
<node name="signOut" value="Déconnexion en cours. Patientez, s'il-vous plait..." />
|
||||
<node name="purchaseBook" value="Achat du livre. Veuillez patienter..."/>
|
||||
<node name="registerUser" value="Inscription en cours. Veuillez patienter..."/>
|
||||
<node name="loadingCatalogInfo" toBeTranslated="true" value="Loading catalog information. Please, wait..." />
|
||||
</node>
|
||||
<node name="networkError">
|
||||
<node name="internalError" value="Erreur interne du serveur"/>
|
||||
|
@ -286,6 +289,8 @@
|
|||
<node name="tooManyRegistrations" value="Trop d'inscriptions depuis votre IP ; essayer à nouvea dans quelques minutes"/>
|
||||
<node name="noUserEmail" value="Aucun utilisateur n'est inscrit avec l'adresse email indiquée"/>
|
||||
<node name="unsupportedOperation" value="Opération non supportée"/>
|
||||
<node name="notAnOPDS" toBeTranslated="true" value="This is not an OPDS catalog" />
|
||||
<node name="noRequiredInformation" toBeTranslated="true" value="Required information is not specified in the catalog" />
|
||||
</node>
|
||||
<node name="emptyCatalogBox">
|
||||
<node name="title" value="Information"/>
|
||||
|
|
|
@ -137,6 +137,8 @@
|
|||
<node name="button">
|
||||
<node name="buy" value="Vásárlás" />
|
||||
<node name="buyAndDownload" value="Vásárlás és letöltés" />
|
||||
<node name="continue" toBeTranslated="true" value="Continue" />
|
||||
<node name="editUrl" toBeTranslated="true" value="Edit URL" />
|
||||
</node>
|
||||
<node name="BookInfo">
|
||||
<node name="fileName" value="Fájlnév"/>
|
||||
|
@ -270,6 +272,7 @@
|
|||
<node name="signOut" value="Kijelentkezés. Kérjük, várjon..." />
|
||||
<node name="purchaseBook" value="Könyv vásárlása. Kérjük, várjon..." />
|
||||
<node name="registerUser" value="Fiók létrehozása. Kérjük, várjon..." />
|
||||
<node name="loadingCatalogInfo" toBeTranslated="true" value="Loading catalog information. Please, wait..." />
|
||||
</node>
|
||||
<node name="networkError">
|
||||
<node name="internalError" value="Belső szerverhiba" />
|
||||
|
@ -286,6 +289,8 @@
|
|||
<node name="tooManyRegistrations" value="Túl sok regisztrációs kérés erről az IP-címről; próbálja meg pár perc múlva ismét!" />
|
||||
<node name="noUserEmail" value="Nincs regisztrált felhasználónk ezzel az e-mail címmel" />
|
||||
<node name="unsupportedOperation" value="nem támogaott művelet" />
|
||||
<node name="notAnOPDS" toBeTranslated="true" value="This is not an OPDS catalog" />
|
||||
<node name="noRequiredInformation" toBeTranslated="true" value="Required information is not specified in the catalog" />
|
||||
</node>
|
||||
<node name="emptyCatalogBox">
|
||||
<node name="title" value="Információ" />
|
||||
|
|
|
@ -137,6 +137,8 @@
|
|||
<node name="button">
|
||||
<node name="buy" value="Compra" />
|
||||
<node name="buyAndDownload" value="Compra e scarica" />
|
||||
<node name="continue" toBeTranslated="true" value="Continue" />
|
||||
<node name="editUrl" toBeTranslated="true" value="Edit URL" />
|
||||
</node>
|
||||
<node name="BookInfo">
|
||||
<node name="fileName" value="Nome file"/>
|
||||
|
@ -270,6 +272,7 @@
|
|||
<node name="signOut" value="Disconnessione. Attendere prego..." />
|
||||
<node name="purchaseBook" value="Acquisto libro. Attendere prego..." />
|
||||
<node name="registerUser" value="Registrazione nuovo account. Attendere prego..." />
|
||||
<node name="loadingCatalogInfo" toBeTranslated="true" value="Loading catalog information. Please, wait..." />
|
||||
</node>
|
||||
<node name="networkError">
|
||||
<node name="internalError" value="Errore Server Interno" />
|
||||
|
@ -286,6 +289,8 @@
|
|||
<node name="tooManyRegistrations" value="Troppe registrazioni dal tuo IP; riprova fra qualche minuto" />
|
||||
<node name="noUserEmail" value="Nessun utente è registrato con questo indirizzo e-mail" />
|
||||
<node name="unsupportedOperation" value="Operazione non supportata" />
|
||||
<node name="notAnOPDS" toBeTranslated="true" value="This is not an OPDS catalog" />
|
||||
<node name="noRequiredInformation" toBeTranslated="true" value="Required information is not specified in the catalog" />
|
||||
</node>
|
||||
<node name="emptyCatalogBox">
|
||||
<node name="title" value="Informazioni" />
|
||||
|
|
|
@ -136,6 +136,8 @@
|
|||
<node name="button">
|
||||
<node name="buy" value="Купить" />
|
||||
<node name="buyAndDownload" value="Купить и скачать" />
|
||||
<node name="continue" value="Продолжить" />
|
||||
<node name="editUrl" value="Изменить URL" />
|
||||
</node>
|
||||
<node name="BookInfo">
|
||||
<node name="fileName" value="Файл"/>
|
||||
|
@ -269,6 +271,7 @@
|
|||
<node name="signOut" value="Выход из системы. Подождите, пожалуйста..." />
|
||||
<node name="purchaseBook" value="Идет покупка книги. Подождите, пожалуйста..." />
|
||||
<node name="registerUser" value="Регистрируем пользователя. Подождите, пожалуйста..." />
|
||||
<node name="loadingCatalogInfo" value="Загрузка информации из каталога. Подождите, пожалуйста..." />
|
||||
</node>
|
||||
<node name="networkError">
|
||||
<node name="internalError" value="Внутренняя ошибка сервера" />
|
||||
|
@ -285,6 +288,8 @@
|
|||
<node name="tooManyRegistrations" value="Слишком много регистраций с вашего IP; попробуйте еще раз через пару минут" />
|
||||
<node name="noUserEmail" value="Нет пользователя с таким адресом" />
|
||||
<node name="unsupportedOperation" value="Неподдерживаемая операция" />
|
||||
<node name="notAnOPDS" value="Это не OPDS каталог" />
|
||||
<node name="noRequiredInformation" value="Требуемая информация не найдена в каталоге" />
|
||||
</node>
|
||||
<node name="emptyCatalogBox">
|
||||
<node name="title" value="Информация" />
|
||||
|
|
|
@ -137,6 +137,8 @@
|
|||
<node name="button">
|
||||
<node name="buy" value="Mua" />
|
||||
<node name="buyAndDownload" value="Mua và Tải về" />
|
||||
<node name="continue" toBeTranslated="true" value="Continue" />
|
||||
<node name="editUrl" toBeTranslated="true" value="Edit URL" />
|
||||
</node>
|
||||
<node name="BookInfo">
|
||||
<node name="fileName" value="Tên tập tin"/>
|
||||
|
@ -270,6 +272,7 @@
|
|||
<node name="signOut" value="Đang thoát. Xin chờ..." />
|
||||
<node name="purchaseBook" value="Mua sách. Xin chờ..." />
|
||||
<node name="registerUser" value="Đang đăng ký tài khoản. Xin chờ..." />
|
||||
<node name="loadingCatalogInfo" toBeTranslated="true" value="Loading catalog information. Please, wait..." />
|
||||
</node>
|
||||
<node name="networkError">
|
||||
<node name="internalError" value="Lỗi mạng nội bộ " />
|
||||
|
@ -286,6 +289,8 @@
|
|||
<node name="tooManyRegistrations" value="Có quá nhiều đăng ký từ IP của bạn; thử lại sau vài phút" />
|
||||
<node name="noUserEmail" value="Không người nào đang ký với địa chỉ email xác định" />
|
||||
<node name="unsupportedOperation" value="Thao tác không được hỗ trợ" />
|
||||
<node name="notAnOPDS" toBeTranslated="true" value="This is not an OPDS catalog" />
|
||||
<node name="noRequiredInformation" toBeTranslated="true" value="Required information is not specified in the catalog" />
|
||||
</node>
|
||||
<node name="emptyCatalogBox">
|
||||
<node name="title" value="Thông tin" />
|
||||
|
|
|
@ -137,6 +137,8 @@
|
|||
<node name="button">
|
||||
<node name="buy" value="购买" />
|
||||
<node name="buyAndDownload" value="购买 下载" />
|
||||
<node name="continue" toBeTranslated="true" value="Continue" />
|
||||
<node name="editUrl" toBeTranslated="true" value="Edit URL" />
|
||||
</node>
|
||||
<node name="BookInfo">
|
||||
<node name="fileName" value="文件" />
|
||||
|
@ -270,6 +272,7 @@
|
|||
<node name="signOut" value="退出. 正在处理,请稍等..." />
|
||||
<node name="purchaseBook" value="书籍购买中. 请等待..." />
|
||||
<node name="registerUser" value="正在注册新账号,请稍等..." />
|
||||
<node name="loadingCatalogInfo" toBeTranslated="true" value="Loading catalog information. Please, wait..." />
|
||||
</node>
|
||||
<node name="networkError">
|
||||
<node name="internalError" value="内部服务器出错" />
|
||||
|
@ -286,6 +289,8 @@
|
|||
<node name="tooManyRegistrations" value="来自你的IP的注册数过多, 请稍候再尝试注册" />
|
||||
<node name="noUserEmail" value="你的电子邮箱可以注册 " />
|
||||
<node name="unsupportedOperation" value="非法操作" />
|
||||
<node name="notAnOPDS" toBeTranslated="true" value="This is not an OPDS catalog" />
|
||||
<node name="noRequiredInformation" toBeTranslated="true" value="Required information is not specified in the catalog" />
|
||||
</node>
|
||||
<node name="emptyCatalogBox">
|
||||
<node name="title" value="信息" />
|
||||
|
|
|
@ -11,16 +11,18 @@
|
|||
android:paddingRight="10dp"
|
||||
android:orientation="vertical"
|
||||
>
|
||||
<TextView
|
||||
android:id="@+id/network_catalog_title_text"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:singleLine="true"
|
||||
/>
|
||||
<RelativeLayout
|
||||
android:id="@+id/network_catalog_title_group"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
>
|
||||
<TextView
|
||||
android:id="@+id/network_catalog_title_text"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:singleLine="true"
|
||||
android:layout_alignParentTop="true"
|
||||
/>
|
||||
<TextView
|
||||
android:id="@+id/network_catalog_title_star"
|
||||
android:layout_width="wrap_content"
|
||||
|
@ -29,6 +31,7 @@
|
|||
android:textColor="#ffff0000"
|
||||
android:layout_marginLeft="4dp"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_below="@id/network_catalog_title_text"
|
||||
/>
|
||||
<EditText
|
||||
android:id="@+id/network_catalog_title"
|
||||
|
@ -37,27 +40,32 @@
|
|||
android:singleLine="true"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_toLeftOf="@id/network_catalog_title_star"
|
||||
android:layout_below="@id/network_catalog_title_text"
|
||||
/>
|
||||
<TextView
|
||||
android:id="@+id/network_catalog_title_example"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:singleLine="true"
|
||||
android:gravity="right"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_below="@id/network_catalog_title"
|
||||
/>
|
||||
</RelativeLayout>
|
||||
<TextView
|
||||
android:id="@+id/network_catalog_title_example"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:singleLine="true"
|
||||
android:gravity="right"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/network_catalog_url_text"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:singleLine="true"
|
||||
android:layout_marginTop="5dp"
|
||||
/>
|
||||
<RelativeLayout
|
||||
android:id="@+id/network_catalog_url_group"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="5dp"
|
||||
>
|
||||
<TextView
|
||||
android:id="@+id/network_catalog_url_text"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:singleLine="true"
|
||||
android:layout_alignParentTop="true"
|
||||
/>
|
||||
<TextView
|
||||
android:id="@+id/network_catalog_url_star"
|
||||
android:layout_width="wrap_content"
|
||||
|
@ -66,6 +74,7 @@
|
|||
android:textColor="#ffff0000"
|
||||
android:layout_marginLeft="4dp"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_below="@id/network_catalog_url_text"
|
||||
/>
|
||||
<EditText
|
||||
android:id="@+id/network_catalog_url"
|
||||
|
@ -75,37 +84,49 @@
|
|||
android:inputType="textUri"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_toLeftOf="@id/network_catalog_url_star"
|
||||
android:layout_below="@id/network_catalog_url_text"
|
||||
/>
|
||||
<TextView
|
||||
android:id="@+id/network_catalog_url_example"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:singleLine="true"
|
||||
android:gravity="right"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_below="@id/network_catalog_url"
|
||||
/>
|
||||
</RelativeLayout>
|
||||
<TextView
|
||||
android:id="@+id/network_catalog_url_example"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:singleLine="true"
|
||||
android:gravity="right"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/network_catalog_summary_text"
|
||||
<RelativeLayout
|
||||
android:id="@+id/network_catalog_summary_group"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:singleLine="true"
|
||||
android:layout_marginTop="5dp"
|
||||
/>
|
||||
<EditText
|
||||
android:id="@+id/network_catalog_summary"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:singleLine="true"
|
||||
/>
|
||||
<TextView
|
||||
android:id="@+id/network_catalog_summary_example"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:singleLine="true"
|
||||
android:gravity="right"
|
||||
/>
|
||||
|
||||
>
|
||||
<TextView
|
||||
android:id="@+id/network_catalog_summary_text"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:singleLine="true"
|
||||
android:layout_alignParentTop="true"
|
||||
/>
|
||||
<EditText
|
||||
android:id="@+id/network_catalog_summary"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:singleLine="true"
|
||||
android:layout_below="@id/network_catalog_summary_text"
|
||||
/>
|
||||
<TextView
|
||||
android:id="@+id/network_catalog_summary_example"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:singleLine="true"
|
||||
android:gravity="right"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_below="@id/network_catalog_summary"
|
||||
/>
|
||||
</RelativeLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/network_catalog_error"
|
||||
|
|
|
@ -19,15 +19,18 @@
|
|||
|
||||
package org.geometerplus.android.fbreader.network;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
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.ui.android.dialogs.ZLAndroidDialogManager;
|
||||
|
||||
import org.geometerplus.zlibrary.ui.android.R;
|
||||
|
||||
import org.geometerplus.fbreader.network.*;
|
||||
|
@ -40,6 +43,8 @@ class CustomCatalogDialog extends NetworkDialog {
|
|||
private String myUrl;
|
||||
private String mySummary;
|
||||
|
||||
private boolean myLinkWithoutInfo;
|
||||
|
||||
public CustomCatalogDialog() {
|
||||
super("CustomCatalogDialog");
|
||||
}
|
||||
|
@ -47,6 +52,7 @@ class CustomCatalogDialog extends NetworkDialog {
|
|||
@Override
|
||||
protected void clearData() {
|
||||
myTitle = myUrl = mySummary = null;
|
||||
myLinkWithoutInfo = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -72,9 +78,11 @@ class CustomCatalogDialog extends NetworkDialog {
|
|||
|
||||
if (myTitle.length() == 0) {
|
||||
myTitle = null;
|
||||
final String err = myResource.getResource("titleIsEmpty").getValue();
|
||||
sendError(true, false, err);
|
||||
return;
|
||||
if (myLink != null) {
|
||||
final String err = myResource.getResource("titleIsEmpty").getValue();
|
||||
sendError(true, false, err);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (myUrl.length() == 0) {
|
||||
myUrl = null;
|
||||
|
@ -103,7 +111,7 @@ class CustomCatalogDialog extends NetworkDialog {
|
|||
}
|
||||
|
||||
final NetworkLibrary library = NetworkLibrary.Instance();
|
||||
if (library.hasCustomLinkTitle(myTitle, (ICustomNetworkLink) myLink)) {
|
||||
if (myLink != null && library.hasCustomLinkTitle(myTitle, (ICustomNetworkLink) myLink)) {
|
||||
final String err = myResource.getResource("titleAlreadyExists").getValue();
|
||||
sendError(true, false, err);
|
||||
return;
|
||||
|
@ -114,27 +122,75 @@ class CustomCatalogDialog extends NetworkDialog {
|
|||
return;
|
||||
}
|
||||
|
||||
if (myLink == null) {
|
||||
final OPDSLinkReader reader = new OPDSLinkReader();
|
||||
final HashMap<String, String> links = new HashMap<String, String>();
|
||||
links.put(INetworkLink.URL_MAIN, myUrl);
|
||||
final ICustomNetworkLink link = reader.createCustomLink(ICustomNetworkLink.INVALID_ID,
|
||||
siteName, myTitle, mySummary, null, links);
|
||||
if (link != null) {
|
||||
NetworkLibrary.Instance().addCustomLink(link);
|
||||
} else {
|
||||
throw new RuntimeException("Unable to create link!!! Impossible!!!");
|
||||
}
|
||||
myLink = link;
|
||||
} else {
|
||||
if (myLink != null) {
|
||||
final ICustomNetworkLink link = (ICustomNetworkLink) myLink;
|
||||
link.setSiteName(siteName);
|
||||
link.setTitle(myTitle);
|
||||
link.setSummary(mySummary);
|
||||
link.setLink(INetworkLink.URL_MAIN, myUrl);
|
||||
link.saveLink();
|
||||
|
||||
if (myLinkWithoutInfo) {
|
||||
NetworkLibrary.Instance().addCustomLink(link);
|
||||
myLinkWithoutInfo = false;
|
||||
} else {
|
||||
link.saveLink();
|
||||
}
|
||||
sendSuccess(true);
|
||||
return;
|
||||
}
|
||||
sendSuccess(true);
|
||||
|
||||
final OPDSLinkReader reader = new OPDSLinkReader();
|
||||
|
||||
myLinkWithoutInfo = true;
|
||||
myLink = reader.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() {
|
||||
final ICustomNetworkLink link = (ICustomNetworkLink) myLink;
|
||||
final String err = link.reloadInfo();
|
||||
handler.sendMessage(handler.obtainMessage(0, err));
|
||||
}
|
||||
};
|
||||
((ZLAndroidDialogManager)ZLAndroidDialogManager.Instance()).wait("loadingCatalogInfo", loadInfoRunnable, myActivity);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -149,15 +205,19 @@ class CustomCatalogDialog extends NetworkDialog {
|
|||
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 != null) ? myTitle : "");
|
||||
((TextView) dialog.findViewById(R.id.network_catalog_url)).setText((myUrl != null) ? myUrl : "");
|
||||
((TextView) dialog.findViewById(R.id.network_catalog_summary)).setText((mySummary != null) ? mySummary : "");
|
||||
((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) ? View.VISIBLE : View.GONE;
|
||||
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);
|
||||
|
|
|
@ -40,4 +40,6 @@ public interface ICustomNetworkLink extends INetworkLink {
|
|||
|
||||
void setLink(String urlKey, String url);
|
||||
void removeLink(String urlKey);
|
||||
|
||||
String reloadInfo();
|
||||
}
|
||||
|
|
|
@ -34,7 +34,7 @@ public class ATOMFeedMetadata extends ATOMCommonAttributes {
|
|||
public LinkedList<ATOMLink> Links = new LinkedList<ATOMLink>();
|
||||
public ATOMLogo Logo;
|
||||
//public String Rights; // TODO: implement ATOMTextConstruct
|
||||
//public String Subtitle; // TODO: implement ATOMTextConstruct
|
||||
public String Subtitle; // TODO: implement ATOMTextConstruct
|
||||
public String Title; // TODO: implement ATOMTextConstruct
|
||||
public ATOMUpdated Updated;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
* Copyright (C) 2010 Geometer Plus <contact@geometerplus.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
package org.geometerplus.fbreader.network.opds;
|
||||
|
||||
import org.geometerplus.zlibrary.core.util.ZLNetworkUtil;
|
||||
|
||||
import org.geometerplus.fbreader.network.atom.ATOMLink;
|
||||
|
||||
public class CatalogInfoReader implements OPDSFeedReader {
|
||||
|
||||
public boolean FeedStarted;
|
||||
public String Icon;
|
||||
public String Title;
|
||||
public String Summary;
|
||||
|
||||
public String OpensearchDescriptionURL;
|
||||
public String SearchURL;
|
||||
|
||||
private final String myBaseURL;
|
||||
private final OPDSLink myLink;
|
||||
|
||||
public CatalogInfoReader(String baseUrl, OPDSLink link) {
|
||||
myBaseURL = baseUrl;
|
||||
myLink = link;
|
||||
}
|
||||
|
||||
public boolean processFeedMetadata(OPDSFeedMetadata feed, boolean beforeEntries) {
|
||||
Icon = (feed.Icon != null) ? feed.Icon.Uri : null;
|
||||
Title = feed.Title;
|
||||
Summary = feed.Subtitle;
|
||||
|
||||
for (ATOMLink link: feed.Links) {
|
||||
String type = link.getType();
|
||||
String rel = myLink.relation(link.getRel(), type);
|
||||
if (rel == "search") {
|
||||
if (type == OPDSConstants.MIME_APP_OPENSEARCHDESCRIPTION) {
|
||||
OpensearchDescriptionURL = ZLNetworkUtil.url(myBaseURL, link.getHref());
|
||||
} else if (type == OPDSConstants.MIME_APP_ATOM) {
|
||||
SearchURL = ZLNetworkUtil.url(myBaseURL, link.getHref());
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void processFeedStart() {
|
||||
FeedStarted = true;
|
||||
}
|
||||
|
||||
public void processFeedEnd() {
|
||||
}
|
||||
|
||||
public boolean processFeedEntry(OPDSEntry entry) {
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -60,7 +60,7 @@ class NetworkOPDSFeedReader implements OPDSFeedReader {
|
|||
myData.ResumeURI = myBaseURL;
|
||||
}
|
||||
|
||||
public void processFeedMetadata(OPDSFeedMetadata feed, boolean beforeEntries) {
|
||||
public boolean processFeedMetadata(OPDSFeedMetadata feed, boolean beforeEntries) {
|
||||
if (beforeEntries) {
|
||||
myIndex = feed.OpensearchStartIndex - 1;
|
||||
if (feed.OpensearchItemsPerPage > 0) {
|
||||
|
@ -70,7 +70,7 @@ class NetworkOPDSFeedReader implements OPDSFeedReader {
|
|||
myItemsToLoad = len;
|
||||
}
|
||||
}
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
final OPDSLink opdsLink = (OPDSLink) myData.Link;
|
||||
for (ATOMLink link: feed.Links) {
|
||||
|
@ -80,6 +80,7 @@ class NetworkOPDSFeedReader implements OPDSFeedReader {
|
|||
myNextURL = ZLNetworkUtil.url(myBaseURL, link.getHref());
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void processFeedEnd() {
|
||||
|
@ -129,11 +130,49 @@ class NetworkOPDSFeedReader implements OPDSFeedReader {
|
|||
&& myData.Listener.confirmInterrupt();
|
||||
}
|
||||
|
||||
private String calculateEntryId(OPDSEntry entry) {
|
||||
if (entry.Id != null) {
|
||||
return entry.Id.Uri;
|
||||
}
|
||||
|
||||
String id = null;
|
||||
int idType = 0;
|
||||
|
||||
final OPDSLink opdsLink = (OPDSLink) myData.Link;
|
||||
for (ATOMLink link: entry.Links) {
|
||||
final String type = link.getType();
|
||||
final String rel = opdsLink.relation(link.getRel(), type);
|
||||
|
||||
if (rel == null && type == OPDSConstants.MIME_APP_ATOM) {
|
||||
return ZLNetworkUtil.url(myBaseURL, link.getHref());
|
||||
}
|
||||
int relType = BookReference.Format.NONE;
|
||||
if (rel == null || rel.equals(OPDSConstants.REL_ACQUISITION_PREFIX)) {
|
||||
relType = formatByMimeType(type);
|
||||
}
|
||||
if (relType != BookReference.Format.NONE
|
||||
&& (id == null || idType < relType)) {
|
||||
id = ZLNetworkUtil.url(myBaseURL, link.getHref());
|
||||
idType = relType;
|
||||
}
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
public boolean processFeedEntry(OPDSEntry entry) {
|
||||
if (myItemsToLoad >= 0) {
|
||||
--myItemsToLoad;
|
||||
}
|
||||
|
||||
if (entry.Id == null) {
|
||||
final String id = calculateEntryId(entry);
|
||||
if (id == null) {
|
||||
return tryInterrupt();
|
||||
}
|
||||
entry.Id = new ATOMId();
|
||||
entry.Id.Uri = id;
|
||||
}
|
||||
|
||||
if (mySkipUntilId != null) {
|
||||
if (mySkipUntilId.equals(entry.Id.Uri)) {
|
||||
mySkipUntilId = null;
|
||||
|
|
|
@ -50,6 +50,9 @@ interface OPDSConstants {
|
|||
String MIME_APP_PDF = "application/pdf";
|
||||
String MIME_APP_ATOM = "application/atom+xml";
|
||||
|
||||
// MIME type for Opensearch Description XML document
|
||||
String MIME_APP_OPENSEARCHDESCRIPTION = "application/opensearchdescription+xml";
|
||||
|
||||
// a special MIME type for the litres OPDS catalog
|
||||
String MIME_APP_LITRES = "application/litres+xml";
|
||||
|
||||
|
|
|
@ -19,9 +19,17 @@
|
|||
|
||||
package org.geometerplus.fbreader.network.opds;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URLConnection;
|
||||
import java.util.Map;
|
||||
|
||||
import org.geometerplus.zlibrary.core.network.ZLNetworkManager;
|
||||
import org.geometerplus.zlibrary.core.network.ZLNetworkRequest;
|
||||
|
||||
import org.geometerplus.fbreader.network.ICustomNetworkLink;
|
||||
import org.geometerplus.fbreader.network.INetworkLink;
|
||||
import org.geometerplus.fbreader.network.NetworkErrors;
|
||||
|
||||
|
||||
class OPDSCustomLink extends OPDSLink implements ICustomNetworkLink {
|
||||
|
@ -81,4 +89,35 @@ class OPDSCustomLink extends OPDSLink implements ICustomNetworkLink {
|
|||
public final void removeLink(String urlKey) {
|
||||
myLinks.remove(urlKey);
|
||||
}
|
||||
|
||||
|
||||
public String reloadInfo() {
|
||||
return ZLNetworkManager.Instance().perform(new ZLNetworkRequest(getLink(INetworkLink.URL_MAIN)) {
|
||||
@Override
|
||||
public String handleStream(URLConnection connection, InputStream inputStream) throws IOException {
|
||||
final CatalogInfoReader info = new CatalogInfoReader(URL, OPDSCustomLink.this);
|
||||
new OPDSXMLReader(info).read(inputStream);
|
||||
|
||||
if (!info.FeedStarted) {
|
||||
return NetworkErrors.errorMessage("notAnOPDS");
|
||||
}
|
||||
if (info.Title == null) {
|
||||
return NetworkErrors.errorMessage("noRequiredInformation");
|
||||
}
|
||||
myTitle = info.Title;
|
||||
if (info.Icon != null) {
|
||||
myIcon = info.Icon;
|
||||
}
|
||||
if (info.Summary != null) {
|
||||
mySummary = info.Summary;
|
||||
}
|
||||
if (info.SearchURL != null) {
|
||||
setLink(URL_SEARCH, info.SearchURL);
|
||||
} else if (info.OpensearchDescriptionURL != null) {
|
||||
// TODO: implement OpensearchDescription reading
|
||||
}
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,7 +22,9 @@ package org.geometerplus.fbreader.network.opds;
|
|||
interface OPDSFeedReader {
|
||||
|
||||
void processFeedStart();
|
||||
void processFeedMetadata(OPDSFeedMetadata feed, boolean beforeEntries);
|
||||
|
||||
// return true to interrupt reading; return false to continue reading
|
||||
boolean processFeedMetadata(OPDSFeedMetadata feed, boolean beforeEntries);
|
||||
|
||||
// return true to interrupt reading; return false to continue reading
|
||||
boolean processFeedEntry(OPDSEntry entry);
|
||||
|
|
|
@ -115,7 +115,12 @@ class OPDSLink extends AbstractNetworkLink {
|
|||
}
|
||||
|
||||
private final String searchURL(String query) {
|
||||
return getLink(URL_SEARCH).replace("%s", query);
|
||||
final String url = getLink(URL_SEARCH);
|
||||
final String searchTerms = "{searchTerms}";
|
||||
if (url.contains(searchTerms)) {
|
||||
return url.replace(searchTerms, query);
|
||||
}
|
||||
return url.replace("%s", query);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -102,6 +102,12 @@ public class OPDSLinkReader extends ZLXMLReaderAdapter {
|
|||
return link;
|
||||
}
|
||||
|
||||
public ICustomNetworkLink createCustomLinkWithoutInfo(String siteName, String url) {
|
||||
final HashMap<String, String> links = new HashMap<String, String>();
|
||||
links.put(INetworkLink.URL_MAIN, url);
|
||||
return new OPDSCustomLink(ICustomNetworkLink.INVALID_ID, siteName, null, null, null, links);
|
||||
}
|
||||
|
||||
public INetworkLink readDocument(ZLFile file) {
|
||||
mySiteName = myTitle = mySummary = myIcon = /*mySearchType = */myAuthenticationType = mySSLCertificate = null;
|
||||
myHasStableIdentifiers = false;
|
||||
|
|
|
@ -135,6 +135,7 @@ class OPDSXMLReader extends ZLXMLReaderAdapter {
|
|||
private static final int OPENSEARCH_ITEMSPERPAGE = 32;
|
||||
private static final int OPENSEARCH_STARTINDEX = 33;
|
||||
private static final int FEC_HACK_SPAN = 34;
|
||||
private static final int F_SUBTITLE = 35;
|
||||
|
||||
|
||||
private static final String TAG_FEED = "feed";
|
||||
|
@ -152,6 +153,7 @@ class OPDSXMLReader extends ZLXMLReaderAdapter {
|
|||
private static final String TAG_TITLE = "title";
|
||||
private static final String TAG_UPDATED = "updated";
|
||||
private static final String TAG_PRICE = "price";
|
||||
private static final String TAG_SUBTITLE = "subtitle";
|
||||
|
||||
private static final String TAG_HACK_SPAN = "span";
|
||||
|
||||
|
@ -196,6 +198,7 @@ class OPDSXMLReader extends ZLXMLReaderAdapter {
|
|||
}
|
||||
myBuffer.delete(0, myBuffer.length());
|
||||
|
||||
boolean interruptReading = false;
|
||||
switch (myState) {
|
||||
case START:
|
||||
if (tagPrefix == myAtomNamespaceId && tag == TAG_FEED) {
|
||||
|
@ -229,6 +232,11 @@ class OPDSXMLReader extends ZLXMLReaderAdapter {
|
|||
//myTitle.readAttributes(attributes);
|
||||
myHtmlToString.setupTextContent(attributes.getValue("type"));
|
||||
myState = F_TITLE;
|
||||
} else if (tag == TAG_SUBTITLE) {
|
||||
//mySubtitle = new ATOMTitle(); // TODO:implement ATOMTextConstruct & ATOMSubtitle
|
||||
//mySubtitle.readAttributes(attributes);
|
||||
myHtmlToString.setupTextContent(attributes.getValue("type"));
|
||||
myState = F_SUBTITLE;
|
||||
} else if (tag == TAG_UPDATED) {
|
||||
myUpdated = new ATOMUpdated();
|
||||
myUpdated.readAttributes(attributes);
|
||||
|
@ -238,8 +246,8 @@ class OPDSXMLReader extends ZLXMLReaderAdapter {
|
|||
myEntry.readAttributes(attributes);
|
||||
myState = F_ENTRY;
|
||||
// Process feed metadata just before first feed entry
|
||||
if (myFeed != null && myFeed.Id != null && !myFeedMetadataProcessed) {
|
||||
myFeedReader.processFeedMetadata(myFeed, true);
|
||||
if (myFeed != null && !myFeedMetadataProcessed) {
|
||||
interruptReading = myFeedReader.processFeedMetadata(myFeed, true);
|
||||
myFeedMetadataProcessed = true;
|
||||
}
|
||||
}
|
||||
|
@ -354,13 +362,14 @@ class OPDSXMLReader extends ZLXMLReaderAdapter {
|
|||
case FE_SUMMARY:
|
||||
case FE_TITLE:
|
||||
case F_TITLE:
|
||||
case F_SUBTITLE:
|
||||
myHtmlToString.processTextContent(false, tag, attributes, bufferContent);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
return interruptReading;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -390,8 +399,8 @@ class OPDSXMLReader extends ZLXMLReaderAdapter {
|
|||
break;
|
||||
case FEED:
|
||||
if (tagPrefix == myAtomNamespaceId && tag == TAG_FEED) {
|
||||
if (myFeed != null && myFeed.Id != null) {
|
||||
myFeedReader.processFeedMetadata(myFeed, false);
|
||||
if (myFeed != null) {
|
||||
interruptReading = myFeedReader.processFeedMetadata(myFeed, false);
|
||||
}
|
||||
myFeed = null;
|
||||
myFeedReader.processFeedEnd();
|
||||
|
@ -400,7 +409,7 @@ class OPDSXMLReader extends ZLXMLReaderAdapter {
|
|||
break;
|
||||
case F_ENTRY:
|
||||
if (tagPrefix == myAtomNamespaceId && tag == TAG_ENTRY) {
|
||||
if (myEntry != null && myEntry.Id != null) {
|
||||
if (myEntry != null) {
|
||||
interruptReading = myFeedReader.processFeedEntry(myEntry);
|
||||
}
|
||||
myEntry = null;
|
||||
|
@ -448,6 +457,18 @@ class OPDSXMLReader extends ZLXMLReaderAdapter {
|
|||
myHtmlToString.processTextContent(true, tag, null, bufferContent);
|
||||
}
|
||||
break;
|
||||
case F_SUBTITLE:
|
||||
if (tagPrefix == myAtomNamespaceId && tag == TAG_SUBTITLE) {
|
||||
// TODO:implement ATOMTextConstruct & ATOMSubtitle
|
||||
final String subtitle = myHtmlToString.finishTextContent(bufferContent);
|
||||
if (myFeed != null) {
|
||||
myFeed.Subtitle = subtitle;
|
||||
}
|
||||
myState = FEED;
|
||||
} else {
|
||||
myHtmlToString.processTextContent(true, tag, null, bufferContent);
|
||||
}
|
||||
break;
|
||||
case F_UPDATED:
|
||||
if (tagPrefix == myAtomNamespaceId && tag == TAG_UPDATED) {
|
||||
// FIXME:uri can be lost:buffer will be truncated, if there are extension tags inside the <id> tag
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue