Browse Source

Initial Android app proof-of-concept

pull/48/head
dsc 3 months ago
parent
commit
8b5bdc4c6a
  1. 4
      docs/HACKING.md
  2. 45
      src/mobile/README.md
  3. 102
      src/mobile/main.cpp
  4. 92
      src/mobile/main.h
  5. 35
      src/mobile/main.qml
  6. 5
      src/mobile/qml.qrc

4
docs/HACKING.md

@ -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

@ -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

@ -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

@ -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

@ -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

@ -0,0 +1,5 @@
<!DOCTYPE RCC><RCC version="1.0">
<qresource prefix="/">
<file alias="main">main.qml</file>
</qresource>
</RCC>
Loading…
Cancel
Save