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 \
|
||||
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 \
|
||||
libprotobuf-dev protobuf-compiler libgcrypt20-dev
|
||||
libprotobuf-dev protobuf-compiler libgcrypt20-dev libpng-dev
|
||||
```
|
||||
|
||||
## 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
|
||||
```
|
||||
|
||||
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