mirror of
https://git.wownero.com/wowlet/wowlet.git
synced 2024-08-15 01:03:14 +00:00
Initial Android app proof-of-concept
This commit is contained in:
parent
cfee938516
commit
8b5bdc4c6a
6 changed files with 280 additions and 3 deletions
|
@ -28,7 +28,7 @@ by running this command: `pandoc wowlet.1.md -s -t man -o wowlet.1 && gzip wowle
|
||||||
apt install -y git cmake libqrencode-dev build-essential cmake libboost-all-dev \
|
apt install -y git cmake libqrencode-dev build-essential cmake libboost-all-dev \
|
||||||
miniupnpc libunbound-dev graphviz doxygen libunwind8-dev pkg-config libssl-dev \
|
miniupnpc libunbound-dev graphviz doxygen libunwind8-dev pkg-config libssl-dev \
|
||||||
libzmq3-dev libsodium-dev libhidapi-dev libnorm-dev libusb-1.0-0-dev libpgm-dev \
|
libzmq3-dev libsodium-dev libhidapi-dev libnorm-dev libusb-1.0-0-dev libpgm-dev \
|
||||||
libprotobuf-dev protobuf-compiler libgcrypt20-dev
|
libprotobuf-dev protobuf-compiler libgcrypt20-dev libpng-dev
|
||||||
```
|
```
|
||||||
|
|
||||||
## Mac OS
|
## Mac OS
|
||||||
|
@ -107,6 +107,4 @@ To skip the wizards and open a wallet directly use `--wallet-file`:
|
||||||
./wowlet --use-local-tor --wallet-file /home/user/Wownero/wallets/bla.keys
|
./wowlet --use-local-tor --wallet-file /home/user/Wownero/wallets/bla.keys
|
||||||
```
|
```
|
||||||
|
|
||||||
It is recommended that you use `--stagenet` for development. Testnet is also possible,
|
|
||||||
but you'll have to provide Wownero a testnet node of your own.
|
|
||||||
|
|
||||||
|
|
45
src/mobile/README.md
Normal file
45
src/mobile/README.md
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
# Wowlet Mobile (Android)
|
||||||
|
|
||||||
|
This directory contains an unfinished QML application that will show:
|
||||||
|
|
||||||
|
![https://i.imgur.com/yhCsSgj.jpg](https://i.imgur.com/yhCsSgj.jpg)
|
||||||
|
|
||||||
|
## Building
|
||||||
|
|
||||||
|
Credits go to Monero GUI team for providing the initial work on Qt5+Android.
|
||||||
|
|
||||||
|
Build a Docker image:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker build --tag wowlet:android --build-arg THREADS=14 --file Dockerfile.android .
|
||||||
|
```
|
||||||
|
|
||||||
|
Building Wowlet for arm64-v8a:
|
||||||
|
|
||||||
|
```Bash
|
||||||
|
docker run --rm -it -v $PWD:/wowlet -w /wowlet -e THREADS=6 wowlet:android
|
||||||
|
```
|
||||||
|
|
||||||
|
Installing the resulting `.apk` on your device:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
adb install build/Android/release/android-build//build/outputs/apk/debug/android-build-debug.apk
|
||||||
|
```
|
||||||
|
|
||||||
|
Viewing debug logs:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
adb logcat | grep --line-buffered "D wowlet"
|
||||||
|
```
|
||||||
|
|
||||||
|
# Development
|
||||||
|
|
||||||
|
To show this on desktop, you will need the following CMake definitions:
|
||||||
|
|
||||||
|
`-DANDROID_DEBUG=ON -DWITH_SCANNER=ON`
|
||||||
|
|
||||||
|
Start wowlet with the `--android-debug` flag:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./wowlet --android-debug
|
||||||
|
```
|
102
src/mobile/main.cpp
Normal file
102
src/mobile/main.cpp
Normal file
|
@ -0,0 +1,102 @@
|
||||||
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
// Copyright (c) 2020-2021, The Monero Project.
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <QResource>
|
||||||
|
#include <QApplication>
|
||||||
|
#include <QCoreApplication>
|
||||||
|
#include <QQmlComponent>
|
||||||
|
#include <QObject>
|
||||||
|
#include <QtCore>
|
||||||
|
#include <QtGui>
|
||||||
|
#include <QQmlApplicationEngine>
|
||||||
|
#include <QtQml>
|
||||||
|
#include <QFileInfo>
|
||||||
|
#include <QQuickView>
|
||||||
|
#include <QQuickItem>
|
||||||
|
|
||||||
|
#include "libwalletqt/TransactionInfo.h"
|
||||||
|
#include "libwalletqt/TransactionHistory.h"
|
||||||
|
#include "model/TransactionHistoryModel.h"
|
||||||
|
#include "model/TransactionHistoryProxyModel.h"
|
||||||
|
#include "libwalletqt/WalletManager.h"
|
||||||
|
|
||||||
|
#include "utils/keysfiles.h"
|
||||||
|
#include "mobile/main.h"
|
||||||
|
|
||||||
|
namespace mobile {
|
||||||
|
|
||||||
|
Mobile::Mobile(AppContext *ctx, QCommandLineParser *parser, QObject *parent) :
|
||||||
|
QObject(parent), ctx(ctx), m_parser(parser) {
|
||||||
|
AppContext::isQML = true;
|
||||||
|
m_pClipboard = QGuiApplication::clipboard();
|
||||||
|
desktopMode = true;
|
||||||
|
|
||||||
|
// turn on auto tx commits
|
||||||
|
ctx->autoCommitTx = true;
|
||||||
|
|
||||||
|
// QR code scanning from screenshots
|
||||||
|
m_qrScreenshotPreviewPath = ctx->configDirectoryVR + "/screenshot_preview";
|
||||||
|
m_qrScreenshotImagePath = ctx->configDirectoryVR + "/screenshot";
|
||||||
|
m_qrScreenshotTimer.setSingleShot(true);
|
||||||
|
|
||||||
|
qDebug() << "QMLSCENE_DEVICE: " << qgetenv("QMLSCENE_DEVICE");
|
||||||
|
|
||||||
|
m_engine.rootContext()->setContextProperty("homePath", QDir::homePath());
|
||||||
|
m_engine.rootContext()->setContextProperty("applicationDirectory", QApplication::applicationDirPath());
|
||||||
|
m_engine.rootContext()->setContextProperty("idealThreadCount", QThread::idealThreadCount());
|
||||||
|
m_engine.rootContext()->setContextProperty("qtRuntimeVersion", qVersion());
|
||||||
|
m_engine.rootContext()->setContextProperty("ctx", ctx);
|
||||||
|
|
||||||
|
m_engine.rootContext()->setContextProperty("Mobile", this);
|
||||||
|
qRegisterMetaType<NetworkType::Type>();
|
||||||
|
qmlRegisterType<NetworkType>("wowlet.NetworkType", 1, 0, "NetworkType");
|
||||||
|
|
||||||
|
qmlRegisterUncreatableType<WalletKeysFiles>("wowlet.WalletKeysFiles", 1, 0, "WalletKeysFiles", "WalletKeysFiles can't be instantiated directly");
|
||||||
|
qmlRegisterUncreatableType<Wallet>("wowlet.Wallet", 1, 0, "Wallet", "Wallet can't be instantiated directly");
|
||||||
|
qmlRegisterType<WalletManager>("wowlet.WalletManager", 1, 0, "WalletManager");
|
||||||
|
|
||||||
|
qmlRegisterUncreatableType<TransactionHistoryProxyModel>("wowlet.TransactionHistoryProxyModel", 1, 0, "TransactionHistoryProxyModel", "TransactionHistoryProxyModel can't be instantiated directly");
|
||||||
|
qmlRegisterUncreatableType<TransactionHistoryModel>("wowlet.TransactionHistoryModel", 1, 0, "TransactionHistoryModel", "TransactionHistoryModel can't be instantiated directly");
|
||||||
|
qmlRegisterUncreatableType<TransactionInfo>("wowlet.TransactionInfo", 1, 0, "TransactionInfo", "TransactionHistory can't be instantiated directly");
|
||||||
|
qmlRegisterUncreatableType<TransactionHistory>("wowlet.TransactionHistory", 1, 0, "TransactionHistory", "TransactionHistory can't be instantiated directly");
|
||||||
|
|
||||||
|
qRegisterMetaType<PendingTransaction::Priority>();
|
||||||
|
qRegisterMetaType<TransactionInfo::Direction>();
|
||||||
|
qRegisterMetaType<TransactionHistoryModel::TransactionInfoRole>();
|
||||||
|
|
||||||
|
auto widgetUrl = QUrl(QStringLiteral("qrc:///main"));
|
||||||
|
m_engine.load(widgetUrl);
|
||||||
|
if (m_engine.rootObjects().isEmpty())
|
||||||
|
{
|
||||||
|
qCritical() << "Error: no root objects";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
QObject *rootObject = m_engine.rootObjects().first();
|
||||||
|
if (!rootObject)
|
||||||
|
{
|
||||||
|
qCritical() << "Error: no root objects";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int wege = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mobile::takeQRScreenshot() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mobile::onCheckQRScreenshot() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
QString Mobile::checkQRScreenshotResults(std::vector<std::string> results) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Mobile::~Mobile() {
|
||||||
|
// bla
|
||||||
|
int wegeg = 1;
|
||||||
|
}
|
||||||
|
}
|
92
src/mobile/main.h
Normal file
92
src/mobile/main.h
Normal file
|
@ -0,0 +1,92 @@
|
||||||
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
// Copyright (c) 2020-2021, The Monero Project.
|
||||||
|
|
||||||
|
#ifndef WOWLET_MAIN_H
|
||||||
|
#define WOWLET_MAIN_H
|
||||||
|
|
||||||
|
#include <QtCore>
|
||||||
|
#include <QQmlError>
|
||||||
|
#include <QQmlApplicationEngine>
|
||||||
|
#include <QtQml>
|
||||||
|
#include <QGuiApplication>
|
||||||
|
#include <QClipboard>
|
||||||
|
#include <QTimer>
|
||||||
|
#include <globals.h>
|
||||||
|
|
||||||
|
#include "appcontext.h"
|
||||||
|
#include "utils/config.h"
|
||||||
|
#include "QR-Code-scanner/Decoder.h"
|
||||||
|
|
||||||
|
namespace mobile {
|
||||||
|
|
||||||
|
class Mobile : public QObject {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit Mobile(AppContext *ctx, QCommandLineParser *cmdargs, QObject *parent = nullptr);
|
||||||
|
~Mobile() override;
|
||||||
|
|
||||||
|
QList<QQmlError> errors;
|
||||||
|
|
||||||
|
Q_INVOKABLE double cdiv(double amount) { return amount / globals::cdiv; }
|
||||||
|
Q_INVOKABLE double add(double x, double y) const { return Utils::roundUp(x + y, 4); } // round ceil 4 decimals
|
||||||
|
Q_INVOKABLE double sub(double x, double y) const { return Utils::roundUp(x - y, 4); } // round ceil 4 decimals
|
||||||
|
|
||||||
|
Q_INVOKABLE void onCreateTransaction(const QString &address, const QString &amount_str, const QString description, bool all) {
|
||||||
|
auto amount = WalletManager::amountFromString(amount_str);
|
||||||
|
ctx->onCreateTransaction(address, amount, description, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
Q_INVOKABLE void setClipboard(const QString &text) {
|
||||||
|
m_pClipboard->setText(text, QClipboard::Clipboard);
|
||||||
|
m_pClipboard->setText(text, QClipboard::Selection);
|
||||||
|
}
|
||||||
|
|
||||||
|
Q_INVOKABLE QString preferredFiat() {
|
||||||
|
return config()->get(Config::preferredFiatCurrency).toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
Q_INVOKABLE QString fiatToWow(double amount) {
|
||||||
|
auto preferredFiatCurrency = config()->get(Config::preferredFiatCurrency).toString();
|
||||||
|
if (amount <= 0) return QString("0.00");
|
||||||
|
|
||||||
|
double conversionAmount = AppContext::prices->convert(preferredFiatCurrency, "WOW", amount);
|
||||||
|
return QString("%1").arg(QString::number(conversionAmount, 'f', 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
Q_INVOKABLE QString wowToFiat(double amount) {
|
||||||
|
auto preferredFiatCurrency = config()->get(Config::preferredFiatCurrency).toString();
|
||||||
|
if (amount <= 0) return QString("0.00");
|
||||||
|
|
||||||
|
double conversionAmount = AppContext::prices->convert("WOW", preferredFiatCurrency, amount);
|
||||||
|
if(conversionAmount <= 0) return QString("0.00");
|
||||||
|
return QString("~%1").arg(QString::number(conversionAmount, 'f', 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
Q_INVOKABLE void takeQRScreenshot();
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void qrScreenshotFailed(QString error);
|
||||||
|
void qrScreenshotSuccess(QString address);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void onCheckQRScreenshot();
|
||||||
|
|
||||||
|
private:
|
||||||
|
AppContext *ctx;
|
||||||
|
QQmlApplicationEngine m_engine;
|
||||||
|
|
||||||
|
bool desktopMode = false;
|
||||||
|
QString m_qrScreenshotPreviewPath;
|
||||||
|
QString m_qrScreenshotImagePath;
|
||||||
|
|
||||||
|
QCommandLineParser *m_parser;
|
||||||
|
QClipboard *m_pClipboard;
|
||||||
|
QTimer m_qrScreenshotTimer;
|
||||||
|
QrDecoder m_qrDecoder;
|
||||||
|
|
||||||
|
static QString checkQRScreenshotResults(std::vector<std::string> results);
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //WOWLET_MAIN_H
|
35
src/mobile/main.qml
Normal file
35
src/mobile/main.qml
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
import QtQuick 2.7
|
||||||
|
import QtQuick.Controls 2.0
|
||||||
|
import QtQuick.Layouts 1.2
|
||||||
|
import QtGraphicalEffects 1.0
|
||||||
|
import QtQuick.Window 2.0
|
||||||
|
import QtQuick.Controls.Styles 1.4
|
||||||
|
import QtQuick.Dialogs 1.2
|
||||||
|
import QtGraphicalEffects 1.0
|
||||||
|
|
||||||
|
import "."
|
||||||
|
|
||||||
|
import wowlet.Wallet 1.0
|
||||||
|
import wowlet.WalletManager 1.0
|
||||||
|
|
||||||
|
ApplicationWindow {
|
||||||
|
visible: true
|
||||||
|
id: appWindow
|
||||||
|
width: 1080
|
||||||
|
height: 2400
|
||||||
|
color: "#2C3539"
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
onClicked: {
|
||||||
|
Qt.quit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Text {
|
||||||
|
text: "Wowlet"
|
||||||
|
color: "white"
|
||||||
|
anchors.centerIn: parent
|
||||||
|
font.pointSize: 62
|
||||||
|
}
|
||||||
|
}
|
5
src/mobile/qml.qrc
Normal file
5
src/mobile/qml.qrc
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
<!DOCTYPE RCC><RCC version="1.0">
|
||||||
|
<qresource prefix="/">
|
||||||
|
<file alias="main">main.qml</file>
|
||||||
|
</qresource>
|
||||||
|
</RCC>
|
Loading…
Reference in a new issue