feat: Version Updating

Fixes #1290
This commit is contained in:
Richard Ramos 2021-06-17 14:41:11 -04:00 committed by Iuri Matias
parent 07364c16cf
commit db3b7ecfd9
14 changed files with 765 additions and 528 deletions

3
.gitmodules vendored
View File

@ -103,3 +103,6 @@
[submodule "ui/StatusQ"] [submodule "ui/StatusQ"]
path = ui/StatusQ path = ui/StatusQ
url = https://github.com/status-im/StatusQ url = https://github.com/status-im/StatusQ
[submodule "vendor/semver.nim"]
path = vendor/semver.nim
url = https://github.com/euantorano/semver.nim

View File

@ -164,6 +164,12 @@ endif
NIM_PARAMS += --outdir:./bin NIM_PARAMS += --outdir:./bin
# App version
VERSIONFILE=VERSION
DESKTOP_VERSION=`cat $(VERSIONFILE)`
NIM_PARAMS += -d:DESKTOP_VERSION="$(DESKTOP_VERSION)"
$(DOTHERSIDE): | deps $(DOTHERSIDE): | deps
echo -e $(BUILD_MSG) "DOtherSide" echo -e $(BUILD_MSG) "DOtherSide"
+ cd vendor/DOtherSide && \ + cd vendor/DOtherSide && \

View File

@ -24,4 +24,4 @@ proc delete*(self: UtilsController) =
delete self.view delete self.view
proc init*(self: UtilsController) = proc init*(self: UtilsController) =
discard self.view.asyncCheckForUpdates()

View File

@ -1,6 +1,7 @@
import NimQml, os, strformat, strutils, parseUtils, chronicles import NimQml, os, strformat, strutils, parseUtils, chronicles
import stint import stint
import ../../status/[status, wallet, settings] import ../../status/[status, wallet, settings, updates]
import ../../status/tasks/[qt, task_runner_impl]
import ../../status/stickers import ../../status/stickers
import ../../status/tokens as status_tokens import ../../status/tokens as status_tokens
import ../../status/types import ../../status/types
@ -9,13 +10,25 @@ import ../../status/ens as status_ens
import ../utils/image_utils import ../utils/image_utils
import web3/[ethtypes, conversions] import web3/[ethtypes, conversions]
import stew/byteutils import stew/byteutils
import json
const DESKTOP_VERSION {.strdefine.} = "0.0.0"
type CheckForNewVersionTaskArg = ref object of QObjectTaskArg
QtObject: QtObject:
type UtilsView* = ref object of QObject type UtilsView* = ref object of QObject
status*: Status status*: Status
newVersion*: string
proc setup(self: UtilsView) = proc setup(self: UtilsView) =
self.QObject.setup self.QObject.setup
self.newVersion = $(%*{
"available": false,
"version": "0.0.0",
"url": "about:blank"
})
proc delete*(self: UtilsView) = proc delete*(self: UtilsView) =
self.QObject.delete self.QObject.delete
@ -112,4 +125,67 @@ QtObject:
close(f) close(f)
else: else:
raise newException(IOError, "cannot open: " & filename) raise newException(IOError, "cannot open: " & filename)
proc getCurrentVersion*(self: UtilsView): string {.slot.} =
return DESKTOP_VERSION
proc newVersionChanged(self: UtilsView) {.signal.}
proc getLatestVersionJSON(): string =
var version = ""
var url = ""
try:
debug "Getting latest version information"
let latestVersion = getLatestVersion()
version = latestVersion.version
url = latestVersion.url
except Exception as e:
error "Error while getting latest version information", msg = e.msg
result = $(%*{
"version": version,
"url": url
})
const checkForUpdatesTask: Task = proc(argEncoded: string) {.gcsafe, nimcall.} =
debug "Check for updates - async"
let arg = decode[CheckForNewVersionTaskArg](argEncoded)
arg.finish(getLatestVersionJSON())
proc asyncRequestLatestVersion[T](self: T, slot: string) =
let arg = CheckForNewVersionTaskArg(
tptr: cast[ByteAddress](checkForUpdatesTask),
vptr: cast[ByteAddress](self.vptr),
slot: slot
)
self.status.tasks.threadpool.start(arg)
proc latestVersionSuccess*(self: UtilsView, latestVersionJSON: string) {.slot.} =
let latestVersionObj = parseJSON(latestVersionJSON)
let latestVersion = latestVersionObj{"version"}.getStr()
if latestVersion == "": return
let available = isNewer(DESKTOP_VERSION, latestVersion)
latestVersionObj["available"] = newJBool(available)
debug "New version?", available, info=latestVersion
self.newVersion = $(%*latestVersionObj)
self.newVersionChanged()
proc checkForUpdates*(self: UtilsView) {.slot.} =
if self.status.settings.getCurrentNetwork() != Network.Mainnet: return
debug "Check for updates - sync"
self.latestVersionSuccess(getLatestVersionJSON())
proc asyncCheckForUpdates*(self: UtilsView) {.slot.} =
if self.status.settings.getCurrentNetwork() != Network.Mainnet: return
self.asyncRequestLatestVersion("latestVersionSuccess")
proc getNewVersion*(self: UtilsView): string {.slot.} =
return self.newVersion
QtProperty[string] newVersion:
read = getNewVersion
notify = newVersionChanged

View File

@ -5,3 +5,5 @@ export STATUSGODIR
export KEYSTOREDIR export KEYSTOREDIR
export TMPDIR export TMPDIR
export LOGDIR export LOGDIR
const APP_UPDATES_ENS* = "desktop.status.eth"

View File

@ -11,11 +11,11 @@ import nbaser
import stew/byteutils import stew/byteutils
from base32 import nil from base32 import nil
const HTTPS_SCHEME = "https" const HTTPS_SCHEME* = "https"
const IPFS_GATEWAY = ".infura.status.im" const IPFS_GATEWAY* = ".infura.status.im"
const SWARM_GATEWAY = "swarm-gateways.net" const SWARM_GATEWAY* = "swarm-gateways.net"
const base58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz" const base58* = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
logScope: logScope:
topics = "provider-model" topics = "provider-model"

44
src/status/updates.nim Normal file
View File

@ -0,0 +1,44 @@
import ens, provider
import stew/byteutils
from base32 import nil
import chronicles, httpclient, net
import nbaser, strutils
import semver
import constants
type
VersionInfo* = object
version*: string
url*: string
proc getLatestVersion*(): VersionInfo =
let contentHash = contenthash(APP_UPDATES_ENS)
if contentHash == "":
raise newException(ValueError, "ENS does not have a content hash")
var url: string = ""
let decodedHash = contentHash.decodeENSContentHash()
case decodedHash[0]:
of ENSType.IPFS:
let base32Hash = base32.encode(string.fromBytes(base58.decode(decodedHash[1]))).toLowerAscii().replace("=", "")
url = "https://" & base32Hash & IPFS_GATEWAY
of ENSType.SWARM:
url = "https://" & SWARM_GATEWAY & "/bzz:/" & decodedHash[1]
of ENSType.IPNS:
url = "https://" & decodedHash[1]
else:
warn "Unknown content for", contentHash
raise newException(ValueError, "Unknown content for " & contentHash)
# Read version from folder
let secureSSLContext = newContext()
let client = newHttpClient(sslContext = secureSSLContext)
result.version = client.getContent(url & "/VERSION" ).strip()
result.url = url
proc isNewer*(currentVersion, versionToCheck: string): bool =
let lastVersion = parseVersion(versionToCheck)
let currVersion = parseVersion(currentVersion)
result = lastVersion > currVersion

View File

@ -23,7 +23,7 @@ Item {
//% "App version" //% "App version"
name: qsTrId("version") name: qsTrId("version")
//% "Version: %1" //% "Version: %1"
description: qsTrId("version---1").arg("0.1.0-beta.11") description: qsTrId("version---1").arg(utilsModel.getCurrentVersion())
tooltipUnder: true tooltipUnder: true
} }
@ -50,7 +50,8 @@ Item {
parent.font.underline = false parent.font.underline = false
} }
onClicked: { onClicked: {
appMain.openLink("https://github.com/status-im/nim-status-client/releases") utilsModel.checkForUpdates();
openPopup(downloadModalComponent, {newVersionAvailable: newVersionJSON.available, downloadURL: newVersionJSON.url})
} }
} }
} }

View File

@ -3,8 +3,8 @@ import QtQuick.Controls 2.13
import QtQuick.Layouts 1.13 import QtQuick.Layouts 1.13
import "../../../imports" import "../../../imports"
import "../../../shared" import "../../../shared"
import "../Profile/Sections"
import "." import "."
import StatusQ.Layout 0.1 import StatusQ.Layout 0.1
Item { Item {
@ -21,17 +21,9 @@ Item {
SignPhraseModal { SignPhraseModal {
id: signPhrasePopup id: signPhrasePopup
} }
SeedPhraseBackupWarning {
id: seedPhraseWarning
width: parent.width
anchors.top: parent.top
}
StatusAppTwoPanelLayout { StatusAppTwoPanelLayout {
anchors.top: seedPhraseWarning.bottom anchors.fill: parent
height: walletView.height - seedPhraseWarning.height
width: walletView.width
Component.onCompleted: { Component.onCompleted: {
if(onboardingModel.firstTimeLogin){ if(onboardingModel.firstTimeLogin){

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,68 @@
import QtQuick 2.13
import QtQuick.Controls 2.13
import QtQuick.Layouts 1.13
import "../imports"
import "../shared/status"
import "./"
ModalPopup {
id: popup
property bool newVersionAvailable: true
property string downloadURL: "https://github.com/status-im/status-desktop/releases/latest"
height: 240
width: 400
title: newVersionAvailable ?
qsTr("New version available!") :
qsTr("No new version available")
SVGImage {
visible: newVersionAvailable
id: imgExclamation
width: 13.33
height: 13.33
sourceSize.height: height * 2
sourceSize.width: width * 2
anchors.horizontalCenter: parent.horizontalCenter
fillMode: Image.PreserveAspectFit
source: "../app/img/exclamation_outline.svg"
}
StyledText {
visible: newVersionAvailable
id: innerText
text: qsTr("Make sure you have your account password and seed phrase stored. Without them you can lock yourself out of your account and lose funds.")
font.pixelSize: 13
color: Style.current.red
anchors.top: imgExclamation.bottom
anchors.topMargin: Style.current.halfPadding
anchors.left: parent.left
anchors.right: parent.right
wrapMode: Text.WordWrap
horizontalAlignment: Text.AlignHCenter
}
StyledText {
visible: !newVersionAvailable
id: innerText2
text: qsTr("You are up to date!")
font.pixelSize: 15
anchors.left: parent.left
anchors.right: parent.right
wrapMode: Text.WordWrap
}
footer: StatusButton {
id: confirmButton
text: newVersionAvailable ?
qsTr("Download") :
qsTr("Ok")
anchors.right: parent.right
onClicked: newVersionAvailable ? appMain.openLink(downloadURL) : close()
}
}

View File

@ -2,16 +2,19 @@ import QtQuick 2.13
import QtQuick.Controls 2.13 import QtQuick.Controls 2.13
import QtQuick.Layouts 1.13 import QtQuick.Layouts 1.13
import QtGraphicalEffects 1.13 import QtGraphicalEffects 1.13
import "../../../imports" import "../imports"
import "../../../shared"
import "../Profile/Sections"
import "." import "."
Rectangle { Rectangle {
id: root id: root
visible: !profileModel.mnemonic.isBackedUp
height: visible ? 32 : 0 height: visible ? 32 : 0
color: Style.current.red color: Style.current.red
property string text: ""
property string btnText: ""
property int btnWidth: 58
property var onClick: function() {}
Row { Row {
spacing: Style.current.halfPadding spacing: Style.current.halfPadding
@ -19,20 +22,19 @@ Rectangle {
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
StyledText { StyledText {
//% "Back up your seed phrase" text: root.text
text: qsTrId("back-up-your-seed-phrase")
font.pixelSize: 13 font.pixelSize: 13
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
color: Style.current.white color: Style.current.white
} }
Button { Button {
width: 58 width: btnWidth
height: 24 height: 24
contentItem: Item { contentItem: Item {
anchors.fill: parent anchors.fill: parent
Text { Text {
text: "Back up" text: btnText
font.pixelSize: 13 font.pixelSize: 13
font.weight: Font.Medium font.weight: Font.Medium
font.family: Style.current.fontRegular.name font.family: Style.current.fontRegular.name
@ -54,7 +56,7 @@ Rectangle {
MouseArea { MouseArea {
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
anchors.fill: parent anchors.fill: parent
onClicked: backupSeedModal.open() onClicked: root.onClick()
} }
} }
} }
@ -65,7 +67,7 @@ Rectangle {
anchors.topMargin: 6 anchors.topMargin: 6
anchors.right: parent.right anchors.right: parent.right
anchors.rightMargin: 18 anchors.rightMargin: 18
source: "../../img/close-white.svg" source: "img/close-white.svg"
height: 20 height: 20
width: 20 width: 20
} }
@ -83,10 +85,4 @@ Rectangle {
PropertyAnimation { target: root; property: "y"; to: -1 * root.height } PropertyAnimation { target: root; property: "y"; to: -1 * root.height }
} }
} }
BackupSeedModal {
id: backupSeedModal
}
} }

View File

@ -0,0 +1,4 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M10.6866 5.31319C10.8818 5.50846 10.8818 5.82504 10.6866 6.0203L8.94244 7.76442C8.81227 7.89459 8.81227 8.10565 8.94244 8.23582L10.6866 9.97994C10.8818 10.1752 10.8818 10.4918 10.6866 10.687C10.4913 10.8823 10.1747 10.8823 9.97945 10.687L8.23534 8.94293C8.10516 8.81276 7.89411 8.81276 7.76393 8.94293L6.01989 10.687C5.82463 10.8822 5.50805 10.8822 5.31279 10.687C5.11753 10.4917 5.11753 10.1751 5.31279 9.97986L7.05682 8.23582C7.187 8.10565 7.187 7.89459 7.05682 7.76442L5.31279 6.02038C5.11753 5.82512 5.11753 5.50854 5.31279 5.31328C5.50805 5.11801 5.82463 5.11801 6.01989 5.31328L7.76393 7.05731C7.89411 7.18749 8.10516 7.18749 8.23534 7.05731L9.97945 5.31319C10.1747 5.11793 10.4913 5.11793 10.6866 5.31319Z" fill="#FFFFFF"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M7.99967 14.6668C11.6816 14.6668 14.6663 11.6821 14.6663 8.00016C14.6663 4.31826 11.6816 1.3335 7.99967 1.3335C4.31778 1.3335 1.33301 4.31826 1.33301 8.00016C1.33301 11.6821 4.31778 14.6668 7.99967 14.6668ZM7.99967 13.6668C11.1293 13.6668 13.6663 11.1298 13.6663 8.00016C13.6663 4.87055 11.1293 2.3335 7.99967 2.3335C4.87006 2.3335 2.33301 4.87055 2.33301 8.00016C2.33301 11.1298 4.87006 13.6668 7.99967 13.6668Z" fill="#FFFFFF"/>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

1
vendor/semver.nim vendored Submodule

@ -0,0 +1 @@
Subproject commit 3b7ace48704236329363290c62ce43f4d35f684d