feat: Onboarding carousel
Onboarding carousel completed Redo folder restructuring NOTES: 1. nim_status_client binary is output to `./bin/nim_status_client`, so you'll need to update your workflow to run this file. README has been updated to reflect this. Also, if you're running VSCode, instructions for code reload were added. 2. All `ui` files now live in `ui/` 3. All lib files (ie `libstatus`) now live in `lib/` 4. Removed the Qt Creater user project file as this is unique to each user 5. Moved the project file to `ui/`, so just open up the `ui` folder in Qt creator and it should locate the project file 6. `-d:release` removed from compilation as it wasn't needed 7. Broke up main.qml in to the main app and onboarding components, however this should be broken down further into more reusable components 8. Click "Get started" to show chat Format some files using nimpretty
3
.gitignore
vendored
@ -6,3 +6,6 @@ data/
|
||||
noBackup/
|
||||
.idea
|
||||
*.pro.user
|
||||
*.pro.autosave
|
||||
.vscode
|
||||
bin/
|
4
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
|
||||
|
67
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
|
||||
|
||||
```
|
||||
|
602
main.qml
@ -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}
|
||||
}
|
||||
##^##*/
|
@ -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()
|
||||
|
220
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)
|
||||
|
387
ui/app/AppMain.qml
Normal file
@ -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}
|
||||
}
|
||||
##^##*/
|
Before Width: | Height: | Size: 680 B After Width: | Height: | Size: 680 B |
Before Width: | Height: | Size: 655 B After Width: | Height: | Size: 655 B |
Before Width: | Height: | Size: 869 B After Width: | Height: | Size: 869 B |
Before Width: | Height: | Size: 883 B After Width: | Height: | Size: 883 B |
Before Width: | Height: | Size: 622 B After Width: | Height: | Size: 622 B |
Before Width: | Height: | Size: 611 B After Width: | Height: | Size: 611 B |
Before Width: | Height: | Size: 709 B After Width: | Height: | Size: 709 B |
Before Width: | Height: | Size: 657 B After Width: | Height: | Size: 657 B |
Before Width: | Height: | Size: 646 B After Width: | Height: | Size: 646 B |
1
ui/app/qmldir
Normal file
@ -0,0 +1 @@
|
||||
AppMain 1.0 AppMain.qml
|
64
ui/main.qml
Normal file
@ -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}
|
||||
}
|
||||
##^##*/
|
@ -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
|
350
ui/onboarding/Intro.qml
Normal file
@ -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}
|
||||
}
|
||||
##^##*/
|
BIN
ui/onboarding/img/browser-dark@2x.jpg
Executable file
After Width: | Height: | Size: 41 KiB |
BIN
ui/onboarding/img/browser-dark@3x.jpg
Executable file
After Width: | Height: | Size: 67 KiB |
BIN
ui/onboarding/img/browser@2x.jpg
Executable file
After Width: | Height: | Size: 40 KiB |
BIN
ui/onboarding/img/browser@3x.jpg
Executable file
After Width: | Height: | Size: 68 KiB |
BIN
ui/onboarding/img/chat-dark@2x.jpg
Executable file
After Width: | Height: | Size: 48 KiB |
BIN
ui/onboarding/img/chat-dark@3x.jpg
Executable file
After Width: | Height: | Size: 83 KiB |
BIN
ui/onboarding/img/chat@2x.jpg
Executable file
After Width: | Height: | Size: 48 KiB |
BIN
ui/onboarding/img/chat@3x.jpg
Executable file
After Width: | Height: | Size: 89 KiB |
3
ui/onboarding/img/next.svg
Normal file
@ -0,0 +1,3 @@
|
||||
<svg width="9" height="16" viewBox="0 0 9 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M8.70719 8.71434L1.69578 15.7079C1.3074 16.0953 0.681196 16.0988 0.291074 15.7097C-0.0963472 15.3232 -0.0907033 14.6911 0.292809 14.3085L6.61881 7.99859L0.292809 1.68865C-0.0955705 1.30126 -0.0990483 0.676638 0.291074 0.287507C0.678495 -0.0989301 1.31227 -0.0933004 1.69578 0.289237L8.70719 7.28284C8.93181 7.50689 9.02769 7.81029 8.99313 8.10159C8.97295 8.32613 8.8772 8.54476 8.70719 8.71434Z" fill="#4360DF"/>
|
||||
</svg>
|
After Width: | Height: | Size: 563 B |
BIN
ui/onboarding/img/wallet-dark@2x.jpg
Executable file
After Width: | Height: | Size: 62 KiB |
BIN
ui/onboarding/img/wallet-dark@3x.jpg
Executable file
After Width: | Height: | Size: 104 KiB |
BIN
ui/onboarding/img/wallet@2x.jpg
Executable file
After Width: | Height: | Size: 62 KiB |
BIN
ui/onboarding/img/wallet@3x.jpg
Executable file
After Width: | Height: | Size: 112 KiB |
1
ui/onboarding/qmldir
Normal file
@ -0,0 +1 @@
|
||||
Intro 1.0 Intro.qml
|
10
ui/shared/Image.qml
Normal file
@ -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"
|
||||
}
|
||||
}
|
Before Width: | Height: | Size: 5.6 KiB After Width: | Height: | Size: 5.6 KiB |
1
ui/shared/qmldir
Normal file
@ -0,0 +1 @@
|
||||
Image 1.0 Image.qml
|