Skip to content

Commit

Permalink
Progress #19: Initial work on PurchaseWrapper
Browse files Browse the repository at this point in the history
Begin implementation of PurchaseWrapper, which wraps CapnP Purchase
APIs. Complete notification is done, still to do is getting prces,
notifying server of payment
  • Loading branch information
nathanielhourt committed Jan 20, 2016
1 parent 049e83e commit b4418ff
Show file tree
Hide file tree
Showing 9 changed files with 98 additions and 7 deletions.
1 change: 1 addition & 0 deletions StubBackend/PurchaseImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ ::kj::Promise<void> PurchaseImpl::paymentSent(Purchase::Server::PaymentSentConte
void PurchaseImpl::sendNotification()
{
KJ_IF_MAYBE(notifier, completionNotifier) {
notifier->notifyRequest().setMessage("true");
notifier->notifyRequest().send();
}
}
2 changes: 1 addition & 1 deletion StubBackend/PurchaseImpl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,6 @@ class PurchaseImpl : public Purchase::Server

bool isComplete = false;
QMap<QString, QList<Price>> promosAndPrices;
kj::Maybe<Notifier<capnp::AnyPointer>::Client> completionNotifier;
kj::Maybe<Notifier<capnp::Text>::Client> completionNotifier;
std::function<void()> callback;
};
2 changes: 2 additions & 0 deletions VotingApp/VotingApp.qbs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ QtGuiApplication {
"wrappers/Converters.hpp",
"wrappers/PurchaseContestRequest.cpp",
"wrappers/PurchaseContestRequest.hpp",
"wrappers/PurchaseWrapper.cpp",
"wrappers/PurchaseWrapper.hpp",
"wrappers/README.md",
"qml-promise/src/Promise.cpp",
"qml-promise/src/Promise.hpp",
Expand Down
2 changes: 2 additions & 0 deletions VotingApp/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#include "wrappers/Datagram.hpp"
#include "wrappers/ContestGeneratorWrapper.hpp"
#include "wrappers/PurchaseContestRequest.hpp"
#include "wrappers/PurchaseWrapper.hpp"
#include "wrappers/ContestCreator.hpp"
#include "wrappers/BackendWrapper.hpp"
#include "wrappers/ChainAdaptorWrapper.hpp"
Expand Down Expand Up @@ -71,6 +72,7 @@ int main(int argc, char *argv[])
REGISTER_WRAPPER(ContestGenerator);
REGISTER_WRAPPER(ContestCreator);
REGISTER_WRAPPER(PurchaseContestRequest);
REGISTER_WRAPPER(Purchase);
#undef REGISTER_WRAPPER

// Register enum wrappers
Expand Down
9 changes: 5 additions & 4 deletions VotingApp/wrappers/PurchaseContestRequest.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "PurchaseContestRequest.hpp"
#include "PurchaseWrapper.hpp"
#include "Converters.hpp"

#include <PromiseConverter.hpp>
Expand Down Expand Up @@ -62,7 +63,8 @@ PurchaseContestRequestWrapper::PurchaseContestRequestWrapper(PurchaseRequest&& r
QObject* parent)
: QObject(parent),
tasks(taskTracker),
request(kj::mv(request))
request(kj::mv(request)),
converter(tasks)
{
// When the contestants change, automatically update the request
connect(&m_contestants, &QQmlVariantListModel::dataChanged,
Expand All @@ -83,7 +85,6 @@ bool PurchaseContestRequestWrapper::sponsorshipEnabled() const {
QVariantMap PurchaseContestRequestWrapper::submit() {
auto promise = request.send();
auto purchase = promise.getPurchaseApi();
PromiseConverter converter(tasks);
auto qmlPromise = converter.convert(kj::mv(promise),
[] (capnp::Response<ContestCreator::PurchaseContestResults> r) -> QVariantList
{
Expand All @@ -94,8 +95,8 @@ QVariantMap PurchaseContestRequestWrapper::submit() {
return QVariantList() << results;
});

// TODO: Replace 'false' below with the wrapped purchase API
return QVariantMap{{"purchaseApi", false},{"surchargePromise", QVariant::fromValue(qmlPromise)}};
return QVariantMap{{"purchaseApi", QVariant::fromValue(new PurchaseWrapper(kj::mv(purchase), tasks, this))},
{"surchargePromise", QVariant::fromValue(qmlPromise)}};
}

void PurchaseContestRequestWrapper::disableSponsorship() {
Expand Down
3 changes: 3 additions & 0 deletions VotingApp/wrappers/PurchaseContestRequest.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

#include <QObject>

#include <PromiseConverter.hpp>
#include <contestcreator.capnp.h>

#include "vendor/QQmlEnumClassHelper.h"
Expand Down Expand Up @@ -48,6 +49,8 @@ class PurchaseContestRequestWrapper : public QObject
kj::TaskSet& tasks;
QQmlVariantListModel m_contestants;
QQmlVariantListModel m_promoCodes;
PromiseConverter converter;

public:
using PurchaseRequest = capnp::Request<::ContestCreator::PurchaseContestParams,
::ContestCreator::PurchaseContestResults>;
Expand Down
40 changes: 40 additions & 0 deletions VotingApp/wrappers/PurchaseWrapper.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#include "PurchaseWrapper.hpp"

namespace swv {

void PurchaseWrapper::setComplete(bool complete)
{
if (complete == m_complete) return;
m_complete = complete;
emit completeChanged(complete);
}

PurchaseWrapper::PurchaseWrapper(Purchase::Client&& api, kj::TaskSet& tasks, QObject *parent)
: QObject(parent),
api(kj::mv(api)),
tasks(tasks),
converter(tasks)
{
class CompleteNotifier : public Notifier<capnp::Text>::Server {
PurchaseWrapper& wrapper;
virtual ::kj::Promise<void> notify(NotifyContext context) {
wrapper.setComplete(context.getParams().getMessage() == "true");
return kj::READY_NOW;
}

public:
CompleteNotifier(PurchaseWrapper& wrapper) : wrapper(wrapper) {}
};

auto request = api.subscribeRequest();
request.setNotifier(kj::heap<CompleteNotifier>(*this));
tasks.add(request.send().then([](capnp::Response<Purchase::SubscribeResults>){}));
tasks.add(api.completeRequest().send().then([this] (capnp::Response<Purchase::CompleteResults> r) {
setComplete(r.getResult());
}));
}

PurchaseWrapper::~PurchaseWrapper() noexcept
{}

} // namespace swv
42 changes: 42 additions & 0 deletions VotingApp/wrappers/PurchaseWrapper.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#ifndef PURCHASEWRAPPER_HPP
#define PURCHASEWRAPPER_HPP

#include <purchase.capnp.h>
#include <PromiseConverter.hpp>

#include <QObject>

namespace swv {

/**
* @brief The PurchaseWrapper class provides a QML-friendly interface to the CapnP Purchase type
*
* PurchaseWrapper subscribes to a push notification from the server when the purchase is complete, so the complete
* property will be updated automatically as soon as the purchase completes.
*/
class PurchaseWrapper : public QObject
{
Q_OBJECT
Q_PROPERTY(bool complete READ complete NOTIFY completeChanged)

Purchase::Client api;
kj::TaskSet& tasks;
PromiseConverter converter;
bool m_complete = false;

void setComplete(bool complete);

public:
explicit PurchaseWrapper(Purchase::Client&& api, kj::TaskSet& tasks, QObject *parent = 0);
virtual ~PurchaseWrapper() noexcept;

bool complete() const {
return m_complete;
}

signals:
void completeChanged(bool complete);
};

} // namespace swv
#endif // PURCHASEWRAPPER_HPP
4 changes: 2 additions & 2 deletions shared/capnp/purchase.capnp
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ interface Purchase {
# Check the status of the purchase
prices @1 (promoCode :Text) -> (prices :List(Price));
# Get the price of the purchase in all available coins
subscribe @2 (notifier :Notifier) -> ();
# Get notified when the purchase is complete
subscribe @2 (notifier :Notifier(Text)) -> ();
# Get notified when the purchase is complete. Notification message will either be "true" or "false"
paymentSent @3 (priceSelection :Price) -> ();
# Used to notify the server that the payment has been sent

Expand Down

0 comments on commit b4418ff

Please sign in to comment.