diff --git a/.gitignore b/.gitignore index 9fad268a59..fe2d5d459e 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,6 @@ data/ noBackup/ .idea *.pro.user +*.pro.autosave +.vscode +bin/ \ No newline at end of file diff --git a/Makefile b/Makefile index 1a047c7ed0..79fd35d89a 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ SHELL := bash build: - nim c -d:release -L:libstatus.a -L:-lm --outdir:. src/nim_status_client.nim + nim c -L:lib/libstatus.a -L:-lm --outdir:./bin src/nim_status_client.nim build-osx: - nim c -d:release -L:libstatus.dylib -L:-lm -L:"-framework Foundation -framework Security -framework IOKit -framework CoreServices" --outdir:. src/nim_status_client.nim + nim c -L:lib/libstatus.dylib -L:-lm -L:"-framework Foundation -framework Security -framework IOKit -framework CoreServices" --outdir:./bin src/nim_status_client.nim diff --git a/README.md b/README.md index 5aff45113c..2190cbb0a2 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,7 @@ export PATH=$PATH:/path/to/Qt/5.14.2/clang_64/bin ### 3. Clone and build DOtherside For Linux: + ``` sudo apt-get install build-essential libgl1-mesa-dev sudo apt-get install doxygen @@ -70,5 +71,69 @@ make build-osx ### 8. Run the app ``` -./nim_status_client +./bin/nim_status_client +``` + +### 9. "Cold" reload using VSCode + +We can setup a "cold" reload, whereby the app will be rebuilt and restarted when changes in the source are saved. This will not save state, as the app will be restarted, but it will save us some time from manually restarting the app. We can handily force an app rebuild/relaunch with the shortcut `Cmd+Shift+b` (execute the default build task, which we'll setup below). + +To enable a meagre app reload during development, first creates a task in `.vscode/tasks.json`. This task sets up the default build task for the workspace, and depends on the task that compiles our nim: + +```json +({ + "label": "Build Nim Status Client", + "type": "shell", + "command": "nim", + "args": [ + "c", + "-L:lib/libstatus.dylib", + "-L:-lm", + "-L:\"-framework Foundation -framework Security -framework IOKit -framework CoreServices\"", + "--outdir:./bin", + "src/nim_status_client.nim" + ], + "options": { + "cwd": "${workspaceRoot}" + } +}, +{ + "label": "Run nim_status_client", + "type": "shell", + "command": "bash", + "args": ["./run.sh"], + "options": { + "cwd": "${workspaceRoot}/.vscode" + }, + "dependsOn": ["Build Nim Status Client"], + "group": { + "kind": "build", + "isDefault": true + } +}) +``` + +Next, add a `.vscode/run.sh` file, changing the `DOtherSide` lib path to be specific to your environment: + +```bash +export LD_LIBRARY_PATH="/Users/emizzle/repos/github.com/filcuc/DOtherSide/build/lib" +../bin/nim_status_client +``` + +# Auto build on save (for the "cold" reload effect) + +Finally, to get trigger this default build task when our files our saved, we need to enable a task to be run while `.nim` files are saved, and when `.qml` files are saved. + +### Build on save + +To build on save of our source files, first install the "Trigger Task on Save" VS Code extension to detect changes to our changable files, which will trigger a build/run. Once installed, update `settings.json` like so: + +```json +"files.autoSave": "afterDelay", +"triggerTaskOnSave.tasks": { + "Run nim_status_client": ["ui/**/*", "src/*.nim"] +}, +"triggerTaskOnSave.restart": true, +"triggerTaskOnSave.showStatusBarToggle": true + ``` diff --git a/libstatus.h b/lib/libstatus.h similarity index 100% rename from libstatus.h rename to lib/libstatus.h diff --git a/main.qml b/main.qml deleted file mode 100644 index 49b25a506e..0000000000 --- a/main.qml +++ /dev/null @@ -1,602 +0,0 @@ -import QtQuick 2.3 -import QtQuick.Controls 1.3 -import QtQuick.Controls 2.3 -import QtQuick.Layouts 1.3 -import Qt.labs.platform 1.1 -import "./imports" - -ApplicationWindow { - id: applicationWindow - width: 1024 - height: 768 - title: "Nim Status Client" - visible: true - font.family: "Inter" - - SystemTrayIcon { - visible: true - icon.source: "status-logo.png" - - onActivated: { - applicationWindow.show() - applicationWindow.raise() - applicationWindow.requestActivate() - } - } - - RowLayout { - id: rowLayout - width: parent.width - height: parent.height - anchors.fill: parent - // spacing: 50 - - TabBar { - id: tabBar - y: 0 - width: 50 - height: width *2 + spacing - Layout.preferredHeight: 0 - currentIndex: 0 - topPadding: 57 - rightPadding: 19 - leftPadding: 19 - transformOrigin: Item.Top - Layout.alignment: Qt.AlignLeft | Qt.AlignTop - Layout.fillHeight: true - anchors.top: parent.top - spacing: 5 - Layout.fillWidth: true - Layout.minimumWidth: 80 - Layout.preferredWidth: 80 - Layout.maximumWidth: 80 - Layout.minimumHeight: 0 - background: Rectangle { - color: "#00000000" - border.color: Theme.grey - } - - TabButton { - id: chatBtn - x: 0 - width: 40 - height: 40 - text: "" - padding: 0 - transformOrigin: Item.Center - anchors.horizontalCenter: parent.horizontalCenter - background: Rectangle { - color: Theme.lightBlue - opacity: parent.checked ? 1 : 0 - radius: 50 - } - - Image { - id: image - anchors.verticalCenter: parent.verticalCenter - anchors.horizontalCenter: parent.horizontalCenter - fillMode: Image.PreserveAspectFit - source: parent.checked ? "img/messageActive.svg" : "img/message.svg" - } - } - - TabButton { - id: walletBtn - width: 40 - height: 40 - text: "" - anchors.topMargin: 50 - anchors.horizontalCenter: parent.horizontalCenter - anchors.top: chatBtn.top - background: Rectangle { - color: Theme.lightBlue - opacity: parent.checked ? 1 : 0 - radius: 50 - } - - Image { - id: image1 - anchors.verticalCenter: parent.verticalCenter - anchors.horizontalCenter: parent.horizontalCenter - fillMode: Image.PreserveAspectFit - source: parent.checked ? "img/walletActive.svg" : "img/wallet.svg" - } - } - - TabButton { - id: browserBtn - width: 40 - height: 40 - text: "" - anchors.topMargin: 50 - anchors.horizontalCenter: parent.horizontalCenter - anchors.top: walletBtn.top - background: Rectangle { - color: Theme.lightBlue - opacity: parent.checked ? 1 : 0 - radius: 50 - } - - Image { - id: image2 - anchors.verticalCenter: parent.verticalCenter - anchors.horizontalCenter: parent.horizontalCenter - fillMode: Image.PreserveAspectFit - source: parent.checked ? "img/compassActive.svg" : "img/compass.svg" - } - } - - TabButton { - id: profileBtn - width: 40 - height: 40 - text: "" - anchors.topMargin: 50 - anchors.horizontalCenter: parent.horizontalCenter - anchors.top: browserBtn.top - background: Rectangle { - color: Theme.lightBlue - opacity: parent.checked ? 1 : 0 - radius: 50 - } - - Image { - id: image3 - anchors.verticalCenter: parent.verticalCenter - anchors.horizontalCenter: parent.horizontalCenter - fillMode: Image.PreserveAspectFit - source: parent.checked ? "img/profileActive.svg" : "img/profile.svg" - } - } - } - - StackLayout { - width: parent.width - Layout.fillWidth: true - currentIndex: tabBar.currentIndex - - SplitView { - id: splitView - x: 9 - y: 0 - Layout.fillHeight: true - // anchors.fill: parent - // width: parent.width - Layout.leftMargin: 0 - Layout.fillWidth: true - Layout.minimumWidth: 100 - Layout.preferredWidth: 200 - // Layout.preferredHeight: 100 - - Item { - id: element1 - width: 300 - height: parent.height - Layout.minimumWidth: 200 - - ColumnLayout { - anchors.rightMargin: 0 - anchors.fill: parent - - Item { - Layout.preferredHeight: 100 - Layout.fillHeight: false - Layout.fillWidth: true - - Text { - id: element - x: 772 - text: qsTr("Chat") - anchors.top: parent.top - anchors.topMargin: 17 - font.bold: true - anchors.horizontalCenter: parent.horizontalCenter - font.pixelSize: 17 - } - - Rectangle { - id: searchBox - height: 36 - color: Theme.grey - anchors.top: parent.top - anchors.topMargin: 59 - radius: 8 - anchors.right: parent.right - anchors.rightMargin: 65 - anchors.left: parent.left - anchors.leftMargin: Theme.padding - - TextField { - id: searchText - placeholderText: qsTr("Search") - anchors.left: parent.left - anchors.leftMargin: 32 - anchors.verticalCenter: parent.verticalCenter - font.pixelSize: 12 - background: { - } - } - - Image { - id: image4 - anchors.left: parent.left - anchors.leftMargin: Theme.smallPadding - anchors.verticalCenter: parent.verticalCenter - fillMode: Image.PreserveAspectFit - source: "img/search.svg" - } - - MouseArea { - id: mouseArea - anchors.fill: parent - onClicked : { - searchText.forceActiveFocus(Qt.MouseFocusReason) - } - } - } - - Rectangle { - id: addChat - width: 36 - height: 36 - color: Theme.blue - radius: 50 - anchors.right: parent.right - anchors.rightMargin: Theme.padding - anchors.top: parent.top - anchors.topMargin: 59 - - Text { - id: element3 - color: "#ffffff" - text: qsTr("+") - anchors.verticalCenterOffset: -1 - anchors.horizontalCenterOffset: 1 - anchors.horizontalCenter: parent.horizontalCenter - anchors.verticalCenter: parent.verticalCenter - lineHeight: 1 - fontSizeMode: Text.FixedSize - font.bold: true - font.pixelSize: 28 - } - } - } - - Item { - Layout.fillHeight: true - Layout.fillWidth: true - - Component { - id: chatViewDelegate - - Rectangle { - id: wrapper - height: 64 - color: ListView.isCurrentItem ? Theme.lightBlue : Theme.transparent - anchors.right: parent.right - anchors.rightMargin: Theme.padding - anchors.top: applicationWindow.top - anchors.topMargin: 0 - anchors.left: parent.left - anchors.leftMargin: Theme.padding - radius: 8 - - MouseArea { - anchors.fill: parent - onClicked: listView.currentIndex = index - } - - Rectangle { - id: contactImage - width: 40 - color: Theme.darkGrey - anchors.left: parent.left - anchors.leftMargin: Theme.padding - anchors.top: parent.top - anchors.topMargin: 12 - anchors.bottom: parent.bottom - anchors.bottomMargin: 12 - radius: 50 - } - - Text { - id: contactInfo - text: "Name:" + name - font.weight: Font.Medium - font.pixelSize: 15 - anchors.left: contactImage.right - anchors.leftMargin: Theme.padding - anchors.top: parent.top - anchors.topMargin: Theme.smallPadding - color: "black" - } - Text { - id: lastChatMessage - text: "Chatting blah blah..." - anchors.bottom: parent.bottom - anchors.bottomMargin: Theme.smallPadding - font.pixelSize: 15 - anchors.left: contactImage.right - anchors.leftMargin: Theme.padding - color: Theme.darkGrey - } - Text { - id: contactTime - text: "12:22 AM" - anchors.right: parent.right - anchors.rightMargin: Theme.padding - anchors.top: parent.top - anchors.topMargin: Theme.smallPadding - font.pixelSize: 11 - color: Theme.darkGrey - } - Rectangle { - id: contactNumberChatsCircle - width: 22 - height: 22 - radius: 50 - anchors.bottom: parent.bottom - anchors.bottomMargin: Theme.smallPadding - anchors.right: parent.right - anchors.rightMargin: Theme.padding - color: Theme.blue - Text { - id: contactNumberChats - text: qsTr("1") - anchors.horizontalCenter: parent.horizontalCenter - anchors.verticalCenter: parent.verticalCenter - color: "white" - } - } - } - } - - ListView { - id: listView - anchors.topMargin: 24 - anchors.fill: parent - model: chatsModel - delegate: chatViewDelegate - } - } - } - } - - Item { - width: parent.width/2 - height: parent.height - - ColumnLayout { - anchors.rightMargin: 0 - anchors.fill: parent - - RowLayout { - id: chatContainer - Layout.fillWidth: true - Layout.fillHeight: true - Layout.alignment: Qt.AlignLeft | Qt.AlignTop - - Rectangle { - id: chatBox - height: 140 - color: "#00000000" - Layout.alignment: Qt.AlignLeft | Qt.AlignTop - Layout.fillWidth: true - border.color: "#00000000" - - Image { - id: chatImage - width: 30 - height: 30 - anchors.left: parent.left - anchors.leftMargin: 16 - anchors.top: parent.top - anchors.topMargin: 16 - fillMode: Image.PreserveAspectFit - source: "img/placeholder-profile.png" - } - - TextEdit { - id: chatName - text: qsTr("Slushy Welltodo Woodborer") - anchors.top: parent.top - anchors.topMargin: 22 - anchors.left: chatImage.right - anchors.leftMargin: 16 - font.bold: true - font.pixelSize: 14 - readOnly: true - selectByMouse: true - } - - TextEdit { - id: chatText - text: qsTr("I’m generally against putting too many rules on social interaction because it makes interaction anything but social, but technical specifics on how to get on board or participate in a team are I think generally useful, especially if they prevent maintainers from pasting the same response to every PR / issue.") - font.family: "Inter" - wrapMode: Text.WordWrap - anchors.right: parent.right - anchors.rightMargin: 60 - anchors.left: chatName.left - anchors.leftMargin: 0 - anchors.top: chatName.bottom - anchors.topMargin: 16 - font.pixelSize: 14 - readOnly: true - selectByMouse: true - } - - TextEdit { - id: chatTime - color: Theme.darkGrey - font.family: "Inter" - text: qsTr("7:30 AM") - anchors.bottom: parent.bottom - anchors.bottomMargin: 16 - anchors.right: parent.right - anchors.rightMargin: 16 - font.pixelSize: 10 - readOnly: true - selectByMouse: true - } - } - } - - RowLayout { - id: separator - height: 16 - Layout.fillWidth: true - Layout.alignment: Qt.AlignLeft | Qt.AlignTop - anchors.top: chatContainer.bottom - anchors.topMargin: Theme.padding - - Item { - id: separatorContent - width: 200 - height: 16 - Layout.fillHeight: false - Layout.fillWidth: true - - Rectangle { - id: lineSeparator1 - height: 1 - color: "#00000000" - border.color: "#eef2f5" - anchors.top: parent.top - anchors.topMargin: 8 - anchors.right: separatorText.left - anchors.rightMargin: 14 - anchors.left: parent.left - anchors.leftMargin: 16 - } - - Text { - id: separatorText - color: Theme.darkGrey - text: qsTr("Yesterday") - font.pixelSize: 12 - anchors.centerIn: parent - } - - Rectangle { - id: lineSeparator2 - height: 1 - color: "#00000000" - anchors.right: parent.right - anchors.rightMargin: 16 - anchors.left: separatorText.right - border.color: "#eef2f5" - anchors.top: parent.top - anchors.leftMargin: 14 - anchors.topMargin: 8 - } - } - - } - - RowLayout { - id: resultContainer - Layout.fillHeight: true - TextArea { id: callResult; Layout.fillWidth: true; text: logic.callResult; readOnly: true } - } - - RowLayout { - id: chatInputContainer - height: 70 - Layout.bottomMargin: 20 - Layout.alignment: Qt.AlignLeft | Qt.AlignBottom - transformOrigin: Item.Bottom - anchors.bottom: parent.bottom - anchors.bottomMargin: 0 - - Item { - id: element2 - width: 200 - height: 70 - Layout.fillWidth: true - - Rectangle { - id: rectangle - color: "#00000000" - border.color: Theme.grey - anchors.fill: parent - - Button { - id: chatSendBtn - x: 100 - width: 30 - height: 30 - text: "\u2191" - font.bold: true - font.pointSize: 12 - anchors.top: parent.top - anchors.topMargin: 20 - anchors.right: parent.right - anchors.rightMargin: 16 - onClicked: logic.onSend(txtData.text) - enabled: txtData.text !== "" - background: Rectangle { - color: parent.enabled ? Theme.blue : Theme.grey - radius: 50 - } - } - - TextField { - id: txtData - text: "" - leftPadding: 0 - padding: 0 - font.pixelSize: 14 - placeholderText: qsTr("Type a message...") - anchors.right: chatSendBtn.left - anchors.rightMargin: 16 - anchors.top: parent.top - anchors.topMargin: 24 - anchors.left: parent.left - anchors.leftMargin: 24 - background: {} - } - - MouseArea { - id: mouseArea1 - anchors.rightMargin: 50 - anchors.fill: parent - onClicked : { - txtData.forceActiveFocus(Qt.MouseFocusReason) - } - } - } - } - } - } - - } - - - } - - ColumnLayout { - anchors.fill: parent - - RowLayout { - Layout.fillHeight: true - TextArea { id: accountResult; Layout.fillWidth: true; text: logic.accountResult; readOnly: true } - } - } - - Item { - - } - } - } - - -} - - - - -/*##^## -Designer { - D{i:0;formeditorZoom:0.8999999761581421}D{i:61;anchors_height:100;anchors_width:100} -} -##^##*/ diff --git a/src/nim_status_client.nim b/src/nim_status_client.nim index e5e89fa4ff..de726781c7 100644 --- a/src/nim_status_client.nim +++ b/src/nim_status_client.nim @@ -3,17 +3,15 @@ import applicationView import chats import state import status -import libstatus -import json proc mainProc() = # From QT docs: - # For any GUI application using Qt, there is precisely one QApplication object, - # no matter whether the application has 0, 1, 2 or more windows at any given time. - # For non-QWidget based Qt applications, use QGuiApplication instead, as it does + # For any GUI application using Qt, there is precisely one QApplication object, + # no matter whether the application has 0, 1, 2 or more windows at any given time. + # For non-QWidget based Qt applications, use QGuiApplication instead, as it does # not depend on the QtWidgets library. Use QCoreApplication for non GUI apps var app = newQApplication() - defer: app.delete() # Defer will run this just before mainProc() function ends + defer: app.delete() # Defer will run this just before mainProc() function ends var chatsModel = newChatsModel(); defer: chatsModel.delete @@ -32,7 +30,7 @@ proc mainProc() = let logic = newApplicationView(app, status.callPrivateRPC) defer: logic.delete - + let logicVariant = newQVariant(logic) defer: logicVariant.delete @@ -54,8 +52,8 @@ proc mainProc() = engine.setRootContextProperty("logic", logicVariant) engine.setRootContextProperty("chatsModel", chatsVariant) - engine.load("main.qml") - + engine.load("../ui/main.qml") + # Qt main event loop is entered here # The termination of the loop will be performed when exit() or quit() is called app.exec() diff --git a/src/status.nim b/src/status.nim index dfe993cf5c..7f45e22fd5 100644 --- a/src/status.nim +++ b/src/status.nim @@ -39,50 +39,50 @@ proc subscribeToTest*() = var result = "" var payload = %* { - "jsonrpc": "2.0", + "jsonrpc": "2.0", "id": 3, - "method": "wakuext_startMessenger", + "method": "wakuext_startMessenger", "params": [] } result = $libstatus.callPrivateRPC($payload) payload = %* { - "jsonrpc": "2.0", + "jsonrpc": "2.0", "id": 3, - "method": "wakuext_loadFilters", + "method": "wakuext_loadFilters", "params": [ [{ - "ChatID":"test", - "OneToOne":false + "ChatID": "test", + "OneToOne": false }] ] } result = $libstatus.callPrivateRPC($payload) payload = %* { - "jsonrpc": "2.0", + "jsonrpc": "2.0", "id": 4, - "method": "wakuext_saveChat", + "method": "wakuext_saveChat", "params": [ { - "lastClockValue":0, - "color":"#51d0f0", - "name":"test", - "lastMessage":nil, - "active":true, - "id":"test", - "unviewedMessagesCount":0, - "chatType":2, - "timestamp":1588940692659 + "lastClockValue": 0, + "color": "#51d0f0", + "name": "test", + "lastMessage": nil, + "active": true, + "id": "test", + "unviewedMessagesCount": 0, + "chatType": 2, + "timestamp": 1588940692659 } ] } result = $libstatus.callPrivateRPC($payload) payload = %* { - "jsonrpc": "2.0", + "jsonrpc": "2.0", "id": 3, - "method": "wakuext_chatMessages", + "method": "wakuext_chatMessages", "params": [ "test", nil, 20 ] @@ -100,17 +100,18 @@ proc setupNewAccount*() = # 1 result = $libstatus.initKeystore(keystoredir); - # 2 + # 2 result = $libstatus.openAccounts(datadir); - + # 3 let multiAccountConfig = %* { "n": 5, "mnemonicPhraseLength": 12, - "bip39Passphrase": "", + "bip39Passphrase": "", "paths": ["m/43'/60'/1581'/0'/0", "m/44'/60'/0'/0/0"] } - result = $libstatus.multiAccountGenerateAndDeriveAddresses($multiAccountConfig); + result = $libstatus.multiAccountGenerateAndDeriveAddresses( + $multiAccountConfig); let generatedAddresses = result.parseJson let account0 = generatedAddresses[0] @@ -118,7 +119,8 @@ proc setupNewAccount*() = let password = "0x2cd9bf92c5e20b1b410f5ace94d963a96e89156fbe65b70365e8596b37f1f165" #qwerty let multiAccount = %* { "accountID": account0["id"].getStr, - "paths": ["m/44'/60'/0'/0", "m/43'/60'/1581'", "m/43'/60'/1581'/0'/0", "m/44'/60'/0'/0/0"], + "paths": ["m/44'/60'/0'/0", "m/43'/60'/1581'", "m/43'/60'/1581'/0'/0", + "m/44'/60'/0'/0/0"], "password": password } result = $libstatus.multiAccountStoreDerivedAccounts($multiAccount); @@ -138,92 +140,103 @@ proc setupNewAccount*() = "mnemonic": account0["mnemonic"].getStr, "public-key": multiAccounts["m/43'/60'/1581'/0'/0"]["publicKey"].getStr, "name": accountData["name"].getStr, - "address": account0["address"].getStr, + "address": account0["address"].getStr, "eip1581-address": multiAccounts["m/43'/60'/1581'"]["address"].getStr, "dapps-address": multiAccounts["m/44'/60'/0'/0/0"]["address"].getStr, - "wallet-root-address": multiAccounts["m/44'/60'/0'/0"]["address"].getStr, + "wallet-root-address": multiAccounts["m/44'/60'/0'/0"]["address"].getStr, "preview-privacy?": true, "signing-phrase": "dust gear boss", "log-level": "INFO", "latest-derived-path": 0, "networks/networks": [ + { + "id": "testnet_rpc", + "etherscan-link": "https://ropsten.etherscan.io/address/", + "name": "Ropsten with upstream RPC", + "config": { - "id": "testnet_rpc", - "etherscan-link": "https://ropsten.etherscan.io/address/", - "name": "Ropsten with upstream RPC", - "config": { - "NetworkId": 3, - "DataDir": "/ethereum/testnet_rpc", - "UpstreamConfig": { - "Enabled": true, - "URL": "https://ropsten.infura.io/v3/f315575765b14720b32382a61a89341a", - }, + "NetworkId": 3, + "DataDir": "/ethereum/testnet_rpc", + "UpstreamConfig": + { + "Enabled": true, + "URL": "https://ropsten.infura.io/v3/f315575765b14720b32382a61a89341a", }, }, + }, + { + "id": "rinkeby_rpc", + "etherscan-link": "https://rinkeby.etherscan.io/address/", + "name": "Rinkeby with upstream RPC", + "config": { - "id": "rinkeby_rpc", - "etherscan-link": "https://rinkeby.etherscan.io/address/", - "name": "Rinkeby with upstream RPC", - "config": { - "NetworkId": 4, - "DataDir": "/ethereum/rinkeby_rpc", - "UpstreamConfig": { - "Enabled": true, - "URL": "https://rinkeby.infura.io/v3/f315575765b14720b32382a61a89341a", - }, + "NetworkId": 4, + "DataDir": "/ethereum/rinkeby_rpc", + "UpstreamConfig": + { + "Enabled": true, + "URL": "https://rinkeby.infura.io/v3/f315575765b14720b32382a61a89341a", }, }, + }, + { + "id": "goerli_rpc", + "etherscan-link": "https://goerli.etherscan.io/address/", + "name": "Goerli with upstream RPC", + "config": { - "id": "goerli_rpc", - "etherscan-link": "https://goerli.etherscan.io/address/", - "name": "Goerli with upstream RPC", - "config": { - "NetworkId": 5, - "DataDir": "/ethereum/goerli_rpc", - "UpstreamConfig": { - "Enabled": true, - "URL": "https://goerli.blockscout.com/", - }, + "NetworkId": 5, + "DataDir": "/ethereum/goerli_rpc", + "UpstreamConfig": + { + "Enabled": true, + "URL": "https://goerli.blockscout.com/", }, }, + }, + { + "id": "mainnet_rpc", + "etherscan-link": "https://etherscan.io/address/", + "name": "Mainnet with upstream RPC", + "config": { - "id": "mainnet_rpc", - "etherscan-link": "https://etherscan.io/address/", - "name": "Mainnet with upstream RPC", - "config": { - "NetworkId": 1, - "DataDir": "/ethereum/mainnet_rpc", - "UpstreamConfig": { - "Enabled": true, - "URL": "https://mainnet.infura.io/v3/f315575765b14720b32382a61a89341a", - }, + "NetworkId": 1, + "DataDir": "/ethereum/mainnet_rpc", + "UpstreamConfig": + { + "Enabled": true, + "URL": "https://mainnet.infura.io/v3/f315575765b14720b32382a61a89341a", }, }, + }, + { + "id": "xdai_rpc", + "name": "xDai Chain", + "config": { - "id": "xdai_rpc", - "name": "xDai Chain", - "config": { - "NetworkId": 100, - "DataDir": "/ethereum/xdai_rpc", - "UpstreamConfig": { - "Enabled": true, - "URL": "https://dai.poa.network" - }, + "NetworkId": 100, + "DataDir": "/ethereum/xdai_rpc", + "UpstreamConfig": + { + "Enabled": true, + "URL": "https://dai.poa.network" }, }, + }, + { + "id": "poa_rpc", + "name": "POA Network", + "config": { - "id": "poa_rpc", - "name": "POA Network", - "config": { - "NetworkId": 99, - "DataDir": "/ethereum/poa_rpc", - "UpstreamConfig": { - "Enabled": true, - "URL": "https://core.poa.network" - }, + "NetworkId": 99, + "DataDir": "/ethereum/poa_rpc", + "UpstreamConfig": + { + "Enabled": true, + "URL": "https://core.poa.network" }, }, - ], + }], "currency": "usd", "photo-path": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAmElEQVR4nOzX4QmAIBBA4Yp2aY52aox2ao6mqf+SoajwON73M0J4HBy6TEEYQmMIjSE0htCECVlbDziv+/n6fuzb3OP/UmEmYgiNITRNm+LPqO2UE2YihtAYQlN818ptoZzau1btOakwEzGExhCa5hdi7d2p1zZLhZmIITSG0PhCpDGExhANEmYihtAYQmMIjSE0bwAAAP//kHQdRIWYzToAAAAASUVORK5CYII=", "waku-enabled": true, @@ -234,9 +247,9 @@ proc setupNewAccount*() = "networks/current-network": "mainnet_rpc", "installation-id": "5d6bc316-a97e-5b89-9541-ad01f8eb7397", } - + let configJSON = %* { - "BrowsersConfig": { + "BrowsersConfig": { "Enabled": true }, "ClusterConfig": { @@ -318,41 +331,42 @@ proc setupNewAccount*() = "Enabled": true } } - + let subaccountData = %* [ { "public-key": multiAccounts["m/44'/60'/0'/0/0"]["publicKey"], "address": multiAccounts["m/44'/60'/0'/0/0"]["address"], - "color":"#4360df", - "wallet":true, - "path":"m/44'/60'/0'/0/0", - "name":"Status account" + "color": "#4360df", + "wallet": true, + "path": "m/44'/60'/0'/0/0", + "name": "Status account" }, { "public-key": multiAccounts["m/43'/60'/1581'/0'/0"]["publicKey"], "address": multiAccounts["m/43'/60'/1581'/0'/0"]["address"], - "name":"Delectable Overjoyed Nauplius", - "photo-path":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAmElEQVR4nOzX4QmAIBBA4Yp2aY52aox2ao6mqf+SoajwON73M0J4HBy6TEEYQmMIjSE0htCECVlbDziv+/n6fuzb3OP/UmEmYgiNITRNm+LPqO2UE2YihtAYQlN818ptoZzau1btOakwEzGExhCa5hdi7d2p1zZLhZmIITSG0PhCpDGExhANEmYihtAYQmMIjSE0bwAAAP//kHQdRIWYzToAAAAASUVORK5CYII=", - "path":"m/43'/60'/1581'/0'/0", - "chat":true + "name": "Delectable Overjoyed Nauplius", + "photo-path": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAmElEQVR4nOzX4QmAIBBA4Yp2aY52aox2ao6mqf+SoajwON73M0J4HBy6TEEYQmMIjSE0htCECVlbDziv+/n6fuzb3OP/UmEmYgiNITRNm+LPqO2UE2YihtAYQlN818ptoZzau1btOakwEzGExhCa5hdi7d2p1zZLhZmIITSG0PhCpDGExhANEmYihtAYQmMIjSE0bwAAAP//kHQdRIWYzToAAAAASUVORK5CYII=", + "path": "m/43'/60'/1581'/0'/0", + "chat": true } ] - - result = $libstatus.saveAccountAndLogin($accountData, password, $settingsJSON, $configJSON, $subaccountData) + + result = $libstatus.saveAccountAndLogin($accountData, password, $settingsJSON, + $configJSON, $subaccountData) let saveResult = result.parseJson - + if saveResult["error"].getStr == "": echo "Account saved succesfully" - + proc callRPC*(inputJSON: string): string = - return $libstatus.callRPC(inputJSON) + return $libstatus.callRPC(inputJSON) proc callPrivateRPC*(inputJSON: string): string = - return $libstatus.callPrivateRPC(inputJSON) + return $libstatus.callPrivateRPC(inputJSON) proc addPeer*(peer: string): string = - return $libstatus.addPeer(peer) + return $libstatus.addPeer(peer) # proc onMessage*(callback: proc(message: string)): void = # $libstatus.setSignalEventCallback(callback) diff --git a/ui/app/AppMain.qml b/ui/app/AppMain.qml new file mode 100644 index 0000000000..45fc3d1ff0 --- /dev/null +++ b/ui/app/AppMain.qml @@ -0,0 +1,387 @@ +import QtQuick 2.3 +import QtQuick.Controls 1.3 +import QtQuick.Controls 2.3 +import QtQuick.Layouts 1.3 +import Qt.labs.platform 1.1 +import "../imports" + +RowLayout { + id: rowLayout + width: parent.height + height: parent.width + anchors.fill: parent + // spacing: 50 + + TabBar { + id: tabBar + y: 0 + width: 50 + height: width *2 + spacing + Layout.preferredHeight: 0 + currentIndex: 0 + topPadding: 57 + rightPadding: 19 + leftPadding: 19 + transformOrigin: Item.Top + Layout.alignment: Qt.AlignLeft | Qt.AlignTop + Layout.fillHeight: true + spacing: 5 + Layout.fillWidth: true + Layout.minimumWidth: 80 + Layout.preferredWidth: 80 + Layout.maximumWidth: 80 + Layout.minimumHeight: 0 + background: Rectangle { + color: "#00000000" + border.color: Theme.grey + } + + TabButton { + id: chatBtn + x: 0 + width: 40 + height: 40 + text: "" + padding: 0 + transformOrigin: Item.Center + anchors.horizontalCenter: parent.horizontalCenter + background: Rectangle { + color: Theme.lightBlue + opacity: parent.checked ? 1 : 0 + radius: 50 + } + + Image { + id: image + anchors.verticalCenter: parent.verticalCenter + anchors.horizontalCenter: parent.horizontalCenter + fillMode: Image.PreserveAspectFit + source: parent.checked ? "img/messageActive.svg" : "img/message.svg" + } + } + + TabButton { + id: walletBtn + width: 40 + height: 40 + text: "" + anchors.topMargin: 50 + anchors.horizontalCenter: parent.horizontalCenter + anchors.top: chatBtn.top + background: Rectangle { + color: Theme.lightBlue + opacity: parent.checked ? 1 : 0 + radius: 50 + } + + Image { + id: image1 + anchors.verticalCenter: parent.verticalCenter + anchors.horizontalCenter: parent.horizontalCenter + fillMode: Image.PreserveAspectFit + source: parent.checked ? "img/walletActive.svg" : "img/wallet.svg" + } + } + + TabButton { + id: browserBtn + width: 40 + height: 40 + text: "" + anchors.topMargin: 50 + anchors.horizontalCenter: parent.horizontalCenter + anchors.top: walletBtn.top + background: Rectangle { + color: Theme.lightBlue + opacity: parent.checked ? 1 : 0 + radius: 50 + } + + Image { + id: image2 + anchors.verticalCenter: parent.verticalCenter + anchors.horizontalCenter: parent.horizontalCenter + fillMode: Image.PreserveAspectFit + source: parent.checked ? "img/compassActive.svg" : "img/compass.svg" + } + } + + TabButton { + id: profileBtn + width: 40 + height: 40 + text: "" + anchors.topMargin: 50 + anchors.horizontalCenter: parent.horizontalCenter + anchors.top: browserBtn.top + background: Rectangle { + color: Theme.lightBlue + opacity: parent.checked ? 1 : 0 + radius: 50 + } + + Image { + id: image3 + anchors.verticalCenter: parent.verticalCenter + anchors.horizontalCenter: parent.horizontalCenter + fillMode: Image.PreserveAspectFit + source: parent.checked ? "img/profileActive.svg" : "img/profile.svg" + } + } + } + + + StackLayout { + anchors.left: tabBar.right + anchors.leftMargin: 0 + anchors.right: parent.right + anchors.rightMargin: 0 + Layout.fillWidth: true + currentIndex: tabBar.currentIndex + + SplitView { + id: splitView + x: 0 + y: 0 + Layout.fillHeight: true + // anchors.fill: parent + // width: parent.width + Layout.leftMargin: 0 + Layout.fillWidth: true + + Item { + id: element1 + width: 300 + height: parent.height + Layout.minimumWidth: 200 + + ColumnLayout { + anchors.rightMargin: 0 + anchors.fill: parent + + Item { + Layout.preferredHeight: 100 + Layout.fillHeight: false + Layout.fillWidth: true + + Text { + id: element + x: 772 + text: qsTr("Chat") + anchors.top: parent.top + anchors.topMargin: 17 + font.bold: true + anchors.horizontalCenter: parent.horizontalCenter + font.pixelSize: 17 + } + + Rectangle { + id: searchBox + height: 36 + color: Theme.grey + anchors.top: parent.top + anchors.topMargin: 59 + radius: 8 + anchors.right: parent.right + anchors.rightMargin: 65 + anchors.left: parent.left + anchors.leftMargin: 16 + + TextField { + id: searchText + placeholderText: qsTr("Search") + anchors.left: parent.left + anchors.leftMargin: 32 + anchors.verticalCenter: parent.verticalCenter + font.pixelSize: 12 + background: Rectangle { + color: "#00000000" + } + } + + Image { + id: image4 + anchors.left: parent.left + anchors.leftMargin: 10 + anchors.verticalCenter: parent.verticalCenter + fillMode: Image.PreserveAspectFit + source: "img/search.svg" + } + + MouseArea { + id: mouseArea + anchors.fill: parent + onClicked : { + searchText.forceActiveFocus(Qt.MouseFocusReason) + } + } + } + + Rectangle { + id: addChat + width: 36 + height: 36 + color: Theme.blue + radius: 50 + anchors.right: parent.right + anchors.rightMargin: 16 + anchors.top: parent.top + anchors.topMargin: 59 + + Text { + id: element3 + color: "#ffffff" + text: qsTr("+") + anchors.verticalCenterOffset: -1 + anchors.horizontalCenterOffset: 1 + anchors.horizontalCenter: parent.horizontalCenter + anchors.verticalCenter: parent.verticalCenter + lineHeight: 1 + fontSizeMode: Text.FixedSize + font.bold: true + font.pixelSize: 28 + } + } + } + + Item { + Layout.fillHeight: true + Layout.fillWidth: true + + Component { + id: chatViewDelegate + + Rectangle { + id: wrapper + height: 64 + color: ListView.isCurrentItem ? Theme.lightBlue : Theme.transparent + anchors.right: parent.right + anchors.rightMargin: 16 + anchors.top: applicationWindow.top + anchors.topMargin: 0 + anchors.left: parent.left + anchors.leftMargin: 16 + radius: 8 + + MouseArea { + anchors.fill: parent + onClicked: listView.currentIndex = index + } + + Rectangle { + id: contactImage + width: 40 + color: Theme.darkGrey + anchors.left: parent.left + anchors.leftMargin: 16 + anchors.top: parent.top + anchors.topMargin: 12 + anchors.bottom: parent.bottom + anchors.bottomMargin: 12 + radius: 50 + } + + Text { + id: contactInfo + text: "Name:" + name + font.weight: Font.Medium + font.pixelSize: 15 + anchors.left: contactImage.right + anchors.leftMargin: 16 + anchors.top: parent.top + anchors.topMargin: 10 + color: "black" + } + Text { + id: lastChatMessage + text: "Chatting blah blah..." + anchors.bottom: parent.bottom + anchors.bottomMargin: 10 + font.pixelSize: 15 + anchors.left: contactImage.right + anchors.leftMargin: 16 + color: Theme.darkGrey + } + Text { + id: contactTime + text: "12:22 AM" + anchors.right: parent.right + anchors.rightMargin: 16 + anchors.top: parent.top + anchors.topMargin: 10 + font.pixelSize: 11 + color: Theme.darkGrey + } + Rectangle { + id: contactNumberChatsCircle + width: 22 + height: 22 + radius: 50 + anchors.bottom: parent.bottom + anchors.bottomMargin: 10 + anchors.right: parent.right + anchors.rightMargin: 16 + color: Theme.blue + Text { + id: contactNumberChats + text: qsTr("1") + anchors.horizontalCenter: parent.horizontalCenter + anchors.verticalCenter: parent.verticalCenter + color: "white" + } + } + } + } + + ListView { + id: listView + anchors.topMargin: 24 + anchors.fill: parent + model: chatsModel + delegate: chatViewDelegate + } + } + } + } + + ColumnLayout { + anchors.rightMargin: 0 + + RowLayout { + Layout.fillHeight: true + TextArea { id: callResult; Layout.fillWidth: true; text: logic.callResult; readOnly: true } + } + + RowLayout { + Layout.bottomMargin: 20 + Layout.alignment: Qt.AlignLeft | Qt.AlignBottom + transformOrigin: Item.Bottom + Label { text: "data2" } + TextField { id: txtData; Layout.fillWidth: true; text: "" } + Button { + text: "Send" + onClicked: logic.onSend(txtData.text) + enabled: txtData.text !== "" + } + } + } + } + + ColumnLayout { + RowLayout { + Layout.fillHeight: true + TextArea { id: accountResult; Layout.fillWidth: true; text: logic.accountResult; readOnly: true } + } + } + + Item { + + } + } +} + +/*##^## +Designer { + D{i:0;height:770;width:1232} +} +##^##*/ diff --git a/img/compass.svg b/ui/app/img/compass.svg similarity index 100% rename from img/compass.svg rename to ui/app/img/compass.svg diff --git a/img/compassActive.svg b/ui/app/img/compassActive.svg similarity index 100% rename from img/compassActive.svg rename to ui/app/img/compassActive.svg diff --git a/img/message.svg b/ui/app/img/message.svg similarity index 100% rename from img/message.svg rename to ui/app/img/message.svg diff --git a/img/messageActive.svg b/ui/app/img/messageActive.svg similarity index 100% rename from img/messageActive.svg rename to ui/app/img/messageActive.svg diff --git a/img/profile.svg b/ui/app/img/profile.svg similarity index 100% rename from img/profile.svg rename to ui/app/img/profile.svg diff --git a/img/profileActive.svg b/ui/app/img/profileActive.svg similarity index 100% rename from img/profileActive.svg rename to ui/app/img/profileActive.svg diff --git a/img/search.svg b/ui/app/img/search.svg similarity index 100% rename from img/search.svg rename to ui/app/img/search.svg diff --git a/img/wallet.svg b/ui/app/img/wallet.svg similarity index 100% rename from img/wallet.svg rename to ui/app/img/wallet.svg diff --git a/img/walletActive.svg b/ui/app/img/walletActive.svg similarity index 100% rename from img/walletActive.svg rename to ui/app/img/walletActive.svg diff --git a/ui/app/qmldir b/ui/app/qmldir new file mode 100644 index 0000000000..bf938e4e85 --- /dev/null +++ b/ui/app/qmldir @@ -0,0 +1 @@ +AppMain 1.0 AppMain.qml \ No newline at end of file diff --git a/imports/Theme.qml b/ui/imports/Theme.qml similarity index 100% rename from imports/Theme.qml rename to ui/imports/Theme.qml diff --git a/imports/qmldir b/ui/imports/qmldir similarity index 100% rename from imports/qmldir rename to ui/imports/qmldir diff --git a/ui/main.qml b/ui/main.qml new file mode 100644 index 0000000000..e9b3838eb0 --- /dev/null +++ b/ui/main.qml @@ -0,0 +1,64 @@ +import QtQuick 2.3 +import QtQuick.Controls 1.3 +import QtQuick.Controls 2.3 +import QtQuick.Layouts 1.3 +import Qt.labs.platform 1.1 +import "./onboarding" as Onboarding +import "./app" as App + +ApplicationWindow { + id: applicationWindow + width: 1232 + height: 770 + title: "Nim Status Client" + visible: true + + SystemTrayIcon { + visible: true + icon.source: "shared/img/status-logo.png" + menu: Menu { + MenuItem { + text: qsTr("Quit") + onTriggered: Qt.quit() + } + } + + onActivated: { + applicationWindow.show() + applicationWindow.raise() + applicationWindow.requestActivate() + } + } + + Rectangle { + id: rctAppBg + color: "#FFFFFF" + Layout.fillHeight: true + Layout.fillWidth: true + anchors.fill: parent + border.width: 0 + + Onboarding.Intro { + id: onboarding + visible: !app.visible + anchors.fill: parent + } + + App.AppMain { + id: app + // TODO: Set this to a logic result determining when we need to show the onboarding screens + // Set to true to hide the onboarding screens manually + // Set to false to show the onboarding screens manually + visible: false // logic.accountResult !== "" + anchors.fill: parent + } + } + +} + + +/*##^## +Designer { + D{i:9;anchors_height:40;anchors_width:40} +} +##^##*/ diff --git a/nim-status-client.pro b/ui/nim-status-client.pro similarity index 64% rename from nim-status-client.pro rename to ui/nim-status-client.pro index 96802c7b06..0c05e9041f 100644 --- a/nim-status-client.pro +++ b/ui/nim-status-client.pro @@ -49,4 +49,32 @@ DISTFILES += \ Inter-ThinItalic.otf \ Inter-V.otf \ Theme.qml \ - imports/qmldir + app/AppMain.qml \ + app/img/compass.svg \ + app/img/compassActive.svg \ + app/img/message.svg \ + app/img/messageActive.svg \ + app/img/profile.svg \ + app/img/profileActive.svg \ + app/img/search.svg \ + app/img/wallet.svg \ + app/img/walletActive.svg \ + app/qmldir \ + imports/qmldir \ + onboarding/Intro.qml \ + onboarding/img/browser-dark@2x.jpg \ + onboarding/img/browser-dark@3x.jpg \ + onboarding/img/browser@2x.jpg \ + onboarding/img/browser@3x.jpg \ + onboarding/img/chat-dark@2x.jpg \ + onboarding/img/chat-dark@3x.jpg \ + onboarding/img/chat@2x.jpg \ + onboarding/img/chat@3x.jpg \ + onboarding/img/next.svg \ + onboarding/img/wallet-dark@2x.jpg \ + onboarding/img/wallet-dark@3x.jpg \ + onboarding/img/wallet@2x.jpg \ + onboarding/img/wallet@3x.jpg \ + onboarding/qmldir \ + shared/Image.qml \ + shared/qmldir diff --git a/ui/onboarding/Intro.qml b/ui/onboarding/Intro.qml new file mode 100644 index 0000000000..b103f15e8e --- /dev/null +++ b/ui/onboarding/Intro.qml @@ -0,0 +1,350 @@ +import QtQuick 2.3 +import QtQuick.Controls 1.3 +import QtQuick.Controls 2.3 +import QtQuick.Layouts 1.3 + +RowLayout { + id: obLayout + anchors.fill: parent + Layout.fillWidth: true + Layout.fillHeight: true + + Rectangle { + border.width: 0 + Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter + Layout.fillHeight: true + Layout.fillWidth: true + + SwipeView { + id: vwOnboarding + width: parent.width + height: parent.height + currentIndex: 0 + interactive: false + anchors.fill: parent + + Item { + id: itmSlide1 + + Image { + id: img1 + anchors.horizontalCenter: parent.horizontalCenter + sourceSize.width: 414 + sourceSize.height: 414 + anchors.topMargin: 17 + fillMode: Image.PreserveAspectFit + source: "img/chat@2x.jpg" + } + + Text { + id: txtTitle1 + text: qsTr("Truly private communication") + anchors.right: parent.right + anchors.rightMargin: 177 + anchors.left: parent.left + anchors.leftMargin: 177 + anchors.top: img1.bottom + anchors.topMargin: 44 + font.letterSpacing: -0.2 + font.weight: Font.Bold + lineHeight: 1 + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignHCenter + transformOrigin: Item.Center + font.bold: true + font.pixelSize: 22 + font.kerning: true + + } + + Text { + id: txtDesc1 + x: 772 + color: "#939BA1" + text: qsTr("Chat over a peer-to-peer, encrypted network\n where messages can't be censored or hacked") + font.weight: Font.Normal + style: Text.Normal + anchors.horizontalCenterOffset: 0 + anchors.top: txtTitle1.bottom + anchors.topMargin: 14 + font.bold: true + anchors.horizontalCenter: parent.horizontalCenter + font.pixelSize: 15 + } + + Button { + id: btnNext1 + width: 40 + height: 40 + anchors.top: txtDesc1.top + anchors.bottomMargin: -2 + anchors.bottom: txtDesc1.bottom + anchors.topMargin: -2 + anchors.left: txtDesc1.right + anchors.leftMargin: 32 + onClicked: vwOnboarding.currentIndex++ + background: Rectangle { + id: rctNext1 + color: "#ECEFFC" + border.width: 0 + radius: 50 + + Image { + anchors.horizontalCenter: parent.horizontalCenter + anchors.verticalCenter: parent.verticalCenter + source: "img/next.svg" + } + } + } + } + Item { + id: itmSlide2 + + Image { + id: img2 + anchors.horizontalCenter: parent.horizontalCenter + sourceSize.width: 414 + sourceSize.height: 414 + anchors.top: parent.top + anchors.topMargin: 17 + fillMode: Image.PreserveAspectFit + source: "img/wallet@2x.jpg" + } + + Text { + id: txtTitle2 + text: qsTr("Secure crypto wallet") + anchors.right: parent.right + anchors.rightMargin: 177 + anchors.left: parent.left + anchors.leftMargin: 177 + anchors.top: img2.bottom + anchors.topMargin: 44 + font.letterSpacing: -0.2 + font.weight: Font.Bold + lineHeight: 1 + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignHCenter + transformOrigin: Item.Center + font.bold: true + font.pixelSize: 22 + font.kerning: true + + } + + Button { + id: btnPrev2 + width: 40 + height: 40 + anchors.top: txtDesc2.top + anchors.bottomMargin: -2 + anchors.bottom: txtDesc2.bottom + anchors.topMargin: -2 + anchors.right: txtDesc2.left + anchors.rightMargin: 32 + onClicked: vwOnboarding.currentIndex-- + background: Rectangle { + id: rctPrev2 + color: "#ECEFFC" + border.width: 0 + radius: 50 + + Image { + rotation: 180 + anchors.horizontalCenter: parent.horizontalCenter + anchors.verticalCenter: parent.verticalCenter + source: "img/next.svg" + } + } + } + + Text { + id: txtDesc2 + x: 772 + color: "#939BA1" + text: qsTr("Send and receive digital assets anywhere in the\nworld--no bank account required") + font.weight: Font.Normal + style: Text.Normal + anchors.horizontalCenterOffset: 0 + anchors.top: txtTitle2.bottom + anchors.topMargin: 14 + font.bold: true + anchors.horizontalCenter: parent.horizontalCenter + font.pixelSize: 15 + } + + Button { + id: btnNext2 + width: 40 + height: 40 + anchors.top: txtDesc2.top + anchors.bottomMargin: -2 + anchors.bottom: txtDesc2.bottom + anchors.topMargin: -2 + anchors.left: txtDesc2.right + anchors.leftMargin: 32 + onClicked: vwOnboarding.currentIndex++ + background: Rectangle { + id: rctNext2 + color: "#ECEFFC" + border.width: 0 + radius: 50 + + Image { + anchors.horizontalCenter: parent.horizontalCenter + anchors.verticalCenter: parent.verticalCenter + source: "img/next.svg" + } + } + } + } + Item { + id: itmSlide3 + + Image { + id: img3 + anchors.horizontalCenter: parent.horizontalCenter + sourceSize.width: 414 + sourceSize.height: 414 + anchors.topMargin: 17 + fillMode: Image.PreserveAspectFit + source: "img/browser@2x.jpg" + } + + Text { + id: txtTitle3 + text: qsTr("Decentralized apps") + anchors.right: parent.right + anchors.rightMargin: 177 + anchors.left: parent.left + anchors.leftMargin: 177 + anchors.top: img3.bottom + anchors.topMargin: 44 + font.letterSpacing: -0.2 + font.weight: Font.Bold + lineHeight: 1 + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignHCenter + transformOrigin: Item.Center + font.bold: true + font.pixelSize: 22 + font.kerning: true + + } + + Button { + id: btnPrev3 + width: 40 + height: 40 + anchors.top: txtDesc3.top + anchors.bottomMargin: -2 + anchors.bottom: txtDesc3.bottom + anchors.topMargin: -2 + anchors.right: txtDesc3.left + anchors.rightMargin: 32 + onClicked: vwOnboarding.currentIndex-- + background: Rectangle { + id: rctPrev3 + color: "#ECEFFC" + border.width: 0 + radius: 50 + + Image { + rotation: 180 + anchors.horizontalCenter: parent.horizontalCenter + anchors.verticalCenter: parent.verticalCenter + source: "img/next.svg" + } + } + } + + Text { + id: txtDesc3 + x: 772 + color: "#939BA1" + text: qsTr("Explore games, exchanges and social networks\nwhere you alone own your data") + font.weight: Font.Normal + style: Text.Normal + anchors.horizontalCenterOffset: 0 + anchors.top: txtTitle3.bottom + anchors.topMargin: 14 + font.bold: true + anchors.horizontalCenter: parent.horizontalCenter + font.pixelSize: 15 + } + } + } + + Rectangle { + id: rctPageIndicator + border.width: 0 + anchors.bottom: vwOnboarding.bottom + anchors.bottomMargin: 191 + anchors.top: vwOnboarding.top + anchors.topMargin: 567 + anchors.horizontalCenter: parent.horizontalCenter + width: parent.width + + + PageIndicator { + id: pgOnboarding + anchors.horizontalCenter: parent.horizontalCenter + spacing: 5 + padding: 0 + topPadding: 0 + bottomPadding: 0 + rightPadding: 0 + leftPadding: 0 + font.pixelSize: 6 + count: vwOnboarding.count + currentIndex: vwOnboarding.currentIndex + } + } + + Button { + id: btnGetStarted + rightPadding: 32 + leftPadding: 32 + bottomPadding: 11 + topPadding: 11 + width: 146 + height: 44 + anchors.top: rctPageIndicator.bottom + anchors.topMargin: 87 + anchors.horizontalCenter: parent.horizontalCenter + onClicked: app.visible = true + background: Rectangle { + color: "#ECEFFC" + radius: 8 + } + + Text { + id: txtGetStarted + color: "#4360DF" + text: qsTr("Get started") + font.weight: Font.DemiBold + font.pointSize: 15 + anchors.verticalCenter: parent.verticalCenter + anchors.horizontalCenter: parent.horizontalCenter + } + } + + Text { + id: txtPrivacyPolicy + x: 772 + text: qsTr("Status does not collect, share or sell any personal data. By continuing you agree with the privacy policy.") + anchors.top: btnGetStarted.bottom + anchors.topMargin: 17 + anchors.horizontalCenter: parent.horizontalCenter + font.pixelSize: 12 + font.letterSpacing: 0.1 + color: "#939BA1" + } + } +} + +/*##^## +Designer { + D{i:0;autoSize:true;height:770;width:1232} +} +##^##*/ diff --git a/ui/onboarding/img/browser-dark@2x.jpg b/ui/onboarding/img/browser-dark@2x.jpg new file mode 100755 index 0000000000..56ffbf1e99 Binary files /dev/null and b/ui/onboarding/img/browser-dark@2x.jpg differ diff --git a/ui/onboarding/img/browser-dark@3x.jpg b/ui/onboarding/img/browser-dark@3x.jpg new file mode 100755 index 0000000000..d2c4961d4a Binary files /dev/null and b/ui/onboarding/img/browser-dark@3x.jpg differ diff --git a/ui/onboarding/img/browser@2x.jpg b/ui/onboarding/img/browser@2x.jpg new file mode 100755 index 0000000000..e49bba0716 Binary files /dev/null and b/ui/onboarding/img/browser@2x.jpg differ diff --git a/ui/onboarding/img/browser@3x.jpg b/ui/onboarding/img/browser@3x.jpg new file mode 100755 index 0000000000..03db2a3a11 Binary files /dev/null and b/ui/onboarding/img/browser@3x.jpg differ diff --git a/ui/onboarding/img/chat-dark@2x.jpg b/ui/onboarding/img/chat-dark@2x.jpg new file mode 100755 index 0000000000..7332a89495 Binary files /dev/null and b/ui/onboarding/img/chat-dark@2x.jpg differ diff --git a/ui/onboarding/img/chat-dark@3x.jpg b/ui/onboarding/img/chat-dark@3x.jpg new file mode 100755 index 0000000000..eeb9eb5373 Binary files /dev/null and b/ui/onboarding/img/chat-dark@3x.jpg differ diff --git a/ui/onboarding/img/chat@2x.jpg b/ui/onboarding/img/chat@2x.jpg new file mode 100755 index 0000000000..7e671f02df Binary files /dev/null and b/ui/onboarding/img/chat@2x.jpg differ diff --git a/ui/onboarding/img/chat@3x.jpg b/ui/onboarding/img/chat@3x.jpg new file mode 100755 index 0000000000..9cb00ced8d Binary files /dev/null and b/ui/onboarding/img/chat@3x.jpg differ diff --git a/ui/onboarding/img/next.svg b/ui/onboarding/img/next.svg new file mode 100644 index 0000000000..a95e58bc90 --- /dev/null +++ b/ui/onboarding/img/next.svg @@ -0,0 +1,3 @@ + + + diff --git a/ui/onboarding/img/wallet-dark@2x.jpg b/ui/onboarding/img/wallet-dark@2x.jpg new file mode 100755 index 0000000000..fe1b27f1e2 Binary files /dev/null and b/ui/onboarding/img/wallet-dark@2x.jpg differ diff --git a/ui/onboarding/img/wallet-dark@3x.jpg b/ui/onboarding/img/wallet-dark@3x.jpg new file mode 100755 index 0000000000..a6ec1ba4a0 Binary files /dev/null and b/ui/onboarding/img/wallet-dark@3x.jpg differ diff --git a/ui/onboarding/img/wallet@2x.jpg b/ui/onboarding/img/wallet@2x.jpg new file mode 100755 index 0000000000..7891717dfc Binary files /dev/null and b/ui/onboarding/img/wallet@2x.jpg differ diff --git a/ui/onboarding/img/wallet@3x.jpg b/ui/onboarding/img/wallet@3x.jpg new file mode 100755 index 0000000000..7f49721541 Binary files /dev/null and b/ui/onboarding/img/wallet@3x.jpg differ diff --git a/ui/onboarding/qmldir b/ui/onboarding/qmldir new file mode 100644 index 0000000000..27c23c7c74 --- /dev/null +++ b/ui/onboarding/qmldir @@ -0,0 +1 @@ +Intro 1.0 Intro.qml \ No newline at end of file diff --git a/ui/shared/Image.qml b/ui/shared/Image.qml new file mode 100644 index 0000000000..9bf34ee49a --- /dev/null +++ b/ui/shared/Image.qml @@ -0,0 +1,10 @@ +Image { + source: { + if (Screen.PixelDensity < 40) + "image_low_dpi.png" + else if (Screen.PixelDensity > 300) + "image_high_dpi.png" + else + "image.png" + } +} \ No newline at end of file diff --git a/status-logo.png b/ui/shared/img/status-logo.png similarity index 100% rename from status-logo.png rename to ui/shared/img/status-logo.png diff --git a/ui/shared/qmldir b/ui/shared/qmldir new file mode 100644 index 0000000000..1048c10e9d --- /dev/null +++ b/ui/shared/qmldir @@ -0,0 +1 @@ +Image 1.0 Image.qml \ No newline at end of file