1
0
Fork 0
mirror of https://github.com/geometer/FBReaderJ.git synced 2025-10-03 17:59:33 +02:00

book purchasing (in progress)

This commit is contained in:
Nikolay Pultsin 2011-10-02 15:12:40 +01:00
parent 0b19b5fc6f
commit 55d238b687
5 changed files with 190 additions and 130 deletions

View file

@ -1,6 +1,4 @@
buy book after topup
buy book after registration
buy several books
buy book after auto-sign-in
auto-sign-in
do we cache cover images?

View file

@ -129,6 +129,15 @@
<node name="buyAllBooks" value="Buy all books"/>
</node>
</node>
<node name="buyBook">
<node name="title" value="Purchase book" />
<node name="titleSeveralBooks" value="Purchase books" />
<node name="confirm" value="Are you sure you want to buy &#10;&#8220;%s&#8221;?" />
<node name="confirmSeveralBooks" value="Are you sure you want to buy %s books?" />
<node name="alreadyBought" value="Book is already bought" />
<node name="noAccountInformation" value="Cannot load account state" />
<node name="unsufficientFunds" value="This purchase costs %0 and you have only %1" />
</node>
<node name="networkBookView">
<node name="bookInfo" value="Book Info" />
<node name="description" value="Description" />
@ -243,6 +252,8 @@
<node name="editInfo" value="Edit" />
<node name="reloadInfo" value="Reload" />
<node name="topup" value="Top up"/>
<node name="pay" value="Pay"/>
<node name="refresh" value="Refresh"/>
</node>
<node name="plugin">
<node name="installTitle" value="Install plugin"/>
@ -626,6 +637,7 @@
<node name="loadingCatalogInfo" value="Loading catalog information. Please, wait&#8230;" />
<node name="loadingNetworkBookInfo" value="Loading book information. Please, wait&#8230;" />
<node name="updatingCatalogsList" value="Updating catalogs list. Please, wait&#8230;"/>
<node name="updatingAccountInformation" value="Updating account information. Please, wait&#8230;"/>
</node>
<node name="networkError">
<node name="internalError" value="Internal server error" />
@ -665,16 +677,6 @@
<node name="languageFilterDialog">
<node name="title" value="Language filter" />
</node>
<node name="purchaseConfirmBox">
<node name="title" value="Purchase book" />
<node name="message" value="Are you sure you want to buy &#10;&#8220;%s&#8221;?" />
<node name="titleSeveralBooks" value="Purchase books" />
<node name="messageSeveralBooks" value="Are you sure you want to buy %s books?" />
</node>
<node name="alreadyPurchasedBox">
<node name="title" value="Purchase book" />
<node name="message" value="Book is already bought" />
</node>
</node>
<node name="errorMessage">
<node name="cannotRunAndroidMarket" value="Cannot access Android Market. Please, install %s manually"/>

View file

@ -60,13 +60,19 @@ public class BuyBooksActivity extends Activity {
activity.startActivity(intent);
}
private NetworkLibrary myLibrary;
private INetworkLink myLink;
private List<NetworkBookItem> myBooks;
private Money myCost;
private Money myAccount;
@Override
protected void onCreate(Bundle bundle) {
super.onCreate(bundle);
Thread.setDefaultUncaughtExceptionHandler(new org.geometerplus.zlibrary.ui.android.library.UncaughtExceptionHandler(this));
setContentView(R.layout.buy_book);
final NetworkLibrary library = NetworkLibrary.Instance();
myLibrary = NetworkLibrary.Instance();
final List<NetworkTree.Key> keys =
(List<NetworkTree.Key>)getIntent().getSerializableExtra(
@ -76,25 +82,43 @@ public class BuyBooksActivity extends Activity {
finish();
return;
}
final List<NetworkBookItem> books = new ArrayList<NetworkBookItem>(keys.size());
myBooks = new ArrayList<NetworkBookItem>(keys.size());
for (NetworkTree.Key k : keys) {
final NetworkTree tree = library.getTreeByKey(k);
final NetworkTree tree = myLibrary.getTreeByKey(k);
if (tree instanceof NetworkBookTree) {
books.add(((NetworkBookTree)tree).Book);
myBooks.add(((NetworkBookTree)tree).Book);
} else {
finish();
return;
}
}
myCost = Money.ZERO;
for (NetworkBookItem b : myBooks) {
if (b.getStatus() != NetworkBookItem.Status.CanBePurchased) {
continue;
}
final BookBuyUrlInfo info = b.buyInfo();
if (info == null || info.Price == null) {
// TODO: error message
finish();
return;
}
myCost = myCost.add(info.Price);
}
// we assume all the books are from the same catalog
final INetworkLink link = books.get(0).Link;
final NetworkAuthenticationManager mgr = link.authenticationManager();
myLink = myBooks.get(0).Link;
final NetworkAuthenticationManager mgr = myLink.authenticationManager();
if (mgr == null) {
finish();
return;
}
myAccount = mgr.currentAccount();
setupUI();
}
private void setupUI() {
final ZLResource dialogResource = ZLResource.resource("dialog");
final ZLResource buttonResource = dialogResource.getResource("button");
@ -104,39 +128,117 @@ public class BuyBooksActivity extends Activity {
final Button cancelButton =
(Button)findViewById(R.id.buy_book_buttons).findViewById(R.id.cancel_button);
final Runnable buyRunnable = new Runnable() {
public void run() {
Money cost = Money.ZERO;
System.err.println("cost = " + cost);
try {
final Money account = mgr.currentAccount();
System.err.println("account = " + account);
if (account != null) {
for (NetworkBookItem b : books) {
final BookBuyUrlInfo info = b.buyInfo();
if (b.getStatus() != NetworkBookItem.Status.CanBePurchased) {
continue;
}
if (info == null || info.Price == null) {
cost = null;
break;
}
cost = cost.add(info.Price);
System.err.println("cost = " + cost);
final ZLResource resource = ZLResource.resource("buyBook");
if (myBooks.size() > 1) {
setTitle(resource.getResource("titleSeveralBooks").getValue());
} else {
setTitle(resource.getResource("title").getValue());
}
if (myAccount == null) {
textArea.setText(resource.getResource("noAccountInformation").getValue());
okButton.setText(buttonResource.getResource("refresh").getValue());
cancelButton.setText(buttonResource.getResource("cancel").getValue());
okButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
refreshAccountInformation();
}
});
cancelButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
finish();
}
});
} else if (myCost.compareTo(myAccount) > 0) {
textArea.setText(
resource.getResource("unsufficientFunds").getValue()
.replace("%0", myCost.toString())
.replace("%1", myAccount.toString())
);
okButton.setText(buttonResource.getResource("pay").getValue());
cancelButton.setText(buttonResource.getResource("refresh").getValue());
okButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
TopupMenuActivity.runMenu(BuyBooksActivity.this, myLink, myCost.subtract(myAccount));
}
});
cancelButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
refreshAccountInformation();
}
});
} else {
okButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
UIUtil.wait("purchaseBook", buyRunnable(), BuyBooksActivity.this);
}
});
cancelButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
finish();
}
});
if (myBooks.size() > 1) {
textArea.setText(
resource.getResource("confirmSeveralBooks").getValue()
.replace("%s", String.valueOf(myBooks.size()))
);
okButton.setText(buttonResource.getResource("buy").getValue());
cancelButton.setText(buttonResource.getResource("cancel").getValue());
} else if (myBooks.get(0).getStatus() == NetworkBookItem.Status.CanBePurchased) {
textArea.setText(
resource.getResource("confirm").getValue().replace("%s", myBooks.get(0).Title)
);
okButton.setText(buttonResource.getResource("buy").getValue());
cancelButton.setText(buttonResource.getResource("cancel").getValue());
} else {
textArea.setText(resource.getResource("alreadyBought").getValue());
cancelButton.setText(buttonResource.getResource("ok").getValue());
okButton.setVisibility(View.GONE);
}
}
}
@Override
protected void onResume() {
super.onResume();
refreshAccountInformation();
}
private void refreshAccountInformation() {
UIUtil.wait(
"updatingAccountInformation",
new Runnable() {
public void run() {
final NetworkAuthenticationManager mgr = myLink.authenticationManager();
try {
mgr.refreshAccountInformation();
final Money oldAccount = myAccount;
myAccount = mgr.currentAccount();
if (myAccount != null && !myAccount.equals(oldAccount)) {
runOnUiThread(new Runnable() {
public void run() {
setupUI();
}
});
}
cost = cost.subtract(account);
System.err.println("cost = " + cost);
} else {
cost = null;
myLibrary.invalidateVisibility();
myLibrary.synchronize();
} catch (ZLNetworkException e) {
// ignore
}
System.err.println("cost = " + cost);
if (cost != null && cost.compareTo(Money.ZERO) > 0 && books.size() > 1) {
// we only throw this exception if there are more than 1 book in list
// for 1 book we prefer to send request to server and got an error
throw new ZLNetworkException(NetworkException.ERROR_PURCHASE_NOT_ENOUGH_MONEY);
}
for (final NetworkBookItem b : books) {
}
},
this
);
}
private Runnable buyRunnable() {
return new Runnable() {
public void run() {
try {
final NetworkAuthenticationManager mgr = myLink.authenticationManager();
for (final NetworkBookItem b : myBooks) {
if (b.getStatus() != NetworkBookItem.Status.CanBePurchased) {
continue;
}
@ -149,62 +251,24 @@ public class BuyBooksActivity extends Activity {
}
finish();
} catch (final ZLNetworkException e) {
if (NetworkException.ERROR_PURCHASE_NOT_ENOUGH_MONEY.equals(e.getCode())) {
TopupMenuActivity.runMenu(BuyBooksActivity.this, link, cost);
finish();
} else {
final ZLResource boxResource = dialogResource.getResource("networkError");
runOnUiThread(new Runnable() {
public void run() {
new AlertDialog.Builder(BuyBooksActivity.this)
.setTitle(boxResource.getResource("title").getValue())
.setMessage(e.getMessage())
.setIcon(0)
.setPositiveButton(buttonResource.getResource("ok").getValue(), null)
.create().show();
}
});
}
final ZLResource dialogResource = ZLResource.resource("dialog");
final ZLResource buttonResource = dialogResource.getResource("button");
final ZLResource boxResource = dialogResource.getResource("networkError");
runOnUiThread(new Runnable() {
public void run() {
new AlertDialog.Builder(BuyBooksActivity.this)
.setTitle(boxResource.getResource("title").getValue())
.setMessage(e.getMessage())
.setIcon(0)
.setPositiveButton(buttonResource.getResource("ok").getValue(), null)
.create().show();
}
});
} finally {
library.invalidateVisibility();
library.synchronize();
myLibrary.invalidateVisibility();
myLibrary.synchronize();
}
}
};
okButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
UIUtil.wait("purchaseBook", buyRunnable, BuyBooksActivity.this);
}
});
cancelButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
finish();
}
});
if (books.size() > 1 || books.get(0).getStatus() == NetworkBookItem.Status.CanBePurchased) {
final ZLResource boxResource = dialogResource.getResource("purchaseConfirmBox");
if (books.size() == 1) {
setTitle(boxResource.getResource("title").getValue());
textArea.setText(
boxResource.getResource("message").getValue().replace("%s", books.get(0).Title)
);
} else {
setTitle(boxResource.getResource("titleSeveralBooks").getValue());
textArea.setText(
boxResource.getResource("messageSeveralBooks").getValue()
.replace("%s", String.valueOf(books.size()))
);
}
okButton.setText(buttonResource.getResource("buy").getValue());
cancelButton.setText(buttonResource.getResource("cancel").getValue());
} else {
final ZLResource boxResource = dialogResource.getResource("alreadyPurchasedBox");
setTitle(boxResource.getResource("title").getValue());
textArea.setText(boxResource.getResource("message").getValue());
cancelButton.setText(buttonResource.getResource("ok").getValue());
okButton.setVisibility(View.GONE);
}
}
}

View file

@ -62,6 +62,7 @@ public abstract class NetworkAuthenticationManager {
public abstract void authorise(String password) throws ZLNetworkException;
public abstract void logOut();
public abstract BookUrlInfo downloadReference(NetworkBookItem book);
public abstract void refreshAccountInformation() throws ZLNetworkException;
public final boolean mayBeAuthorised(boolean useNetwork) {
try {

View file

@ -267,7 +267,7 @@ public class LitResAuthenticationManager extends NetworkAuthenticationManager {
logOut(false);
throw new ZLNetworkException(NetworkException.ERROR_AUTHENTICATION_FAILED);
}
networkRequest = loadPurchasedBooks();
networkRequest = loadPurchasedBooksRequest();
}
ZLNetworkException exception = null;
@ -279,7 +279,6 @@ public class LitResAuthenticationManager extends NetworkAuthenticationManager {
synchronized (this) {
if (exception != null) {
//loadPurchasedBooksOnError();
if (NetworkException.ERROR_AUTHENTICATION_FAILED.equals(exception.getCode())) {
logOut(false);
}
@ -317,35 +316,41 @@ public class LitResAuthenticationManager extends NetworkAuthenticationManager {
return;
}
purchasedBooksRequest = loadPurchasedBooks();
accountRequest = loadAccount();
purchasedBooksRequest = loadPurchasedBooksRequest();
accountRequest = loadAccountRequest();
}
final LinkedList<ZLNetworkRequest> requests = new LinkedList<ZLNetworkRequest>();
requests.add(purchasedBooksRequest);
requests.add(accountRequest);
ZLNetworkException exception = null;
try {
ZLNetworkManager.Instance().perform(requests);
synchronized (this) {
myInitializedDataSid = sid;
loadPurchasedBooksOnSuccess(purchasedBooksRequest);
myAccount = new Money(((LitResPurchaseXMLReader)accountRequest.Reader).Account, "RUB");
}
} catch (ZLNetworkException e) {
exception = e;
}
synchronized (this) {
if (exception != null) {
synchronized (this) {
myInitializedDataSid = null;
loadPurchasedBooksOnError();
loadAccountOnError();
throw exception;
myAccount = null;
}
myInitializedDataSid = sid;
loadPurchasedBooksOnSuccess(purchasedBooksRequest);
loadAccountOnSuccess(accountRequest);
throw e;
}
}
private LitResNetworkRequest loadPurchasedBooks() {
@Override
public void refreshAccountInformation() throws ZLNetworkException {
final LitResNetworkRequest accountRequest = loadAccountRequest();
ZLNetworkManager.Instance().perform(accountRequest);
synchronized (this) {
myAccount = new Money(((LitResPurchaseXMLReader)accountRequest.Reader).Account, "RUB");
}
}
private LitResNetworkRequest loadPurchasedBooksRequest() {
final String sid = mySidOption.getValue();
final String query = "pages/catalit_browser/";
@ -376,28 +381,18 @@ public class LitResAuthenticationManager extends NetworkAuthenticationManager {
}
}
private LitResNetworkRequest loadAccount() {
final String sid = mySidOption.getValue();
private LitResNetworkRequest loadAccountRequest() {
final String query = "pages/purchase_book/";
final LitResNetworkRequest request = new LitResNetworkRequest(
LitResUtil.url(Link, query),
new LitResPurchaseXMLReader(Link.getSiteName())
);
request.addPostParameter("sid", sid);
request.addPostParameter("sid", mySidOption.getValue());
request.addPostParameter("art", "0");
return request;
}
private void loadAccountOnError() {
myAccount = null;
}
private void loadAccountOnSuccess(LitResNetworkRequest accountRequest) {
LitResPurchaseXMLReader reader = (LitResPurchaseXMLReader)accountRequest.Reader;
myAccount = new Money(reader.Account, "RUB");
}
@Override
public boolean passwordRecoverySupported() {
return true;