feat: check for updates (using status-go)
This commit is contained in:
parent
04037d1d64
commit
75a3ff858c
|
@ -38,6 +38,7 @@ type SignalType* {.pure.} = enum
|
|||
HistoryArchivesSeeding = "community.historyArchivesSeeding"
|
||||
HistoryArchivesUnseeded = "community.historyArchivesUnseeded"
|
||||
HistoryArchiveDownloaded = "community.historyArchiveDownloaded"
|
||||
UpdateAvailable = "update.available"
|
||||
Unknown
|
||||
|
||||
proc event*(self:SignalType):string =
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
import json
|
||||
import base
|
||||
import signal_type
|
||||
|
||||
type UpdateAvailableSignal* = ref object of Signal
|
||||
available*: bool
|
||||
version*: string
|
||||
url*: string
|
||||
|
||||
proc fromEvent*(T: type UpdateAvailableSignal, jsonSignal: JsonNode): UpdateAvailableSignal =
|
||||
result = UpdateAvailableSignal()
|
||||
result.signalType = SignalType.UpdateAvailable
|
||||
if jsonSignal["event"].kind != JNull:
|
||||
result.available = jsonSignal["event"]["available"].getBool()
|
||||
result.version = jsonSignal["event"]["version"].getStr()
|
||||
result.url = jsonSignal["event"]["url"].getStr()
|
||||
|
|
@ -92,6 +92,7 @@ QtObject:
|
|||
of SignalType.HistoryArchivesSeeding: HistoryArchivesSignal.historyArchivesSeedingFromEvent(jsonSignal)
|
||||
of SignalType.HistoryArchivesUnseeded: HistoryArchivesSignal.historyArchivesUnseededFromEvent(jsonSignal)
|
||||
of SignalType.HistoryArchiveDownloaded: HistoryArchivesSignal.historyArchiveDownloadedFromEvent(jsonSignal)
|
||||
of SignalType.UpdateAvailable: UpdateAvailableSignal.fromEvent(jsonSignal)
|
||||
else: Signal()
|
||||
|
||||
result.signalType = signalType
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{.used.}
|
||||
|
||||
import ./remote_signals/[base, chronicles_logs, community, discovery_summary, envelope, expired, mailserver, messages,
|
||||
peerstats, signal_type, stats, wallet, whisper_filter, keycard]
|
||||
peerstats, signal_type, stats, wallet, whisper_filter, keycard, update_available]
|
||||
|
||||
export base, chronicles_logs, community, discovery_summary, envelope, expired, mailserver, messages, peerstats,
|
||||
signal_type, stats, wallet, whisper_filter, keycard
|
||||
signal_type, stats, wallet, whisper_filter, keycard, update_available
|
||||
|
|
|
@ -24,7 +24,7 @@ proc delete*(self: Controller) =
|
|||
proc init*(self: Controller) =
|
||||
self.events.on(SIGNAL_VERSION_FETCHED) do(e: Args):
|
||||
let args = VersionArgs(e)
|
||||
self.delegate.versionFetched(args.version)
|
||||
self.delegate.versionFetched(args.available, args.version, args.url)
|
||||
|
||||
proc getAppVersion*(self: Controller): string =
|
||||
return self.aboutService.getAppVersion()
|
||||
|
|
|
@ -17,7 +17,7 @@ method getAppVersion*(self: AccessInterface): string {.base.} =
|
|||
method getNodeVersion*(self: AccessInterface): string {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method versionFetched*(self: AccessInterface, version: string) {.base.} =
|
||||
method versionFetched*(self: AccessInterface, available: bool, version: string, url: string) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method checkForUpdates*(self: AccessInterface) {.base.} =
|
||||
|
|
|
@ -55,5 +55,5 @@ method getNodeVersion*(self: Module): string =
|
|||
method checkForUpdates*(self: Module) =
|
||||
self.controller.checkForUpdates()
|
||||
|
||||
method versionFetched*(self: Module, version: string) =
|
||||
self.view.versionFetched(version)
|
||||
method versionFetched*(self: Module, available: bool, version: string, url: string) =
|
||||
self.view.versionFetched(available, version, url)
|
||||
|
|
|
@ -7,7 +7,6 @@ QtObject:
|
|||
type
|
||||
View* = ref object of QObject
|
||||
delegate: io_interface.AccessInterface
|
||||
newVersion*: string
|
||||
fetching*: bool
|
||||
|
||||
proc delete*(self: View) =
|
||||
|
@ -18,14 +17,6 @@ QtObject:
|
|||
result.QObject.setup
|
||||
result.delegate = delegate
|
||||
result.fetching = false
|
||||
result.newVersion = $(%*{
|
||||
"available": false,
|
||||
"version": "",
|
||||
"url": ""
|
||||
})
|
||||
|
||||
proc load*(self: View) =
|
||||
self.delegate.viewDidLoad()
|
||||
|
||||
proc getCurrentVersion*(self: View): string {.slot.} =
|
||||
return self.delegate.getAppVersion()
|
||||
|
@ -33,31 +24,26 @@ QtObject:
|
|||
proc nodeVersion*(self: View): string {.slot.} =
|
||||
return self.delegate.getNodeVersion()
|
||||
|
||||
proc appVersionFetched(self: View) {.signal.}
|
||||
proc appVersionFetched*(self: View, available: bool, version: string, url: string) {.signal.}
|
||||
|
||||
proc fetchingChanged(self: View) {.signal.}
|
||||
|
||||
proc versionFetched*(self: View, version: string) =
|
||||
self.newVersion = version
|
||||
proc versionFetched*(self: View, available: bool, version: string, url: string) =
|
||||
self.fetching = false
|
||||
self.fetchingChanged()
|
||||
self.appVersionFetched()
|
||||
self.appVersionFetched(available, version, url)
|
||||
|
||||
proc checkForUpdates*(self: View) {.slot.} =
|
||||
self.fetching = true
|
||||
self.fetchingChanged()
|
||||
self.delegate.checkForUpdates()
|
||||
|
||||
proc getNewVersion*(self: View): string {.slot.} =
|
||||
return self.newVersion
|
||||
|
||||
QtProperty[string] newVersion:
|
||||
read = getNewVersion
|
||||
notify = appVersionFetched
|
||||
|
||||
|
||||
proc getFetching*(self: View): bool {.slot.} =
|
||||
return self.fetching
|
||||
|
||||
QtProperty[bool] fetching:
|
||||
read = getFetching
|
||||
notify = fetchingChanged
|
||||
|
||||
proc load*(self: View) =
|
||||
self.delegate.viewDidLoad()
|
||||
|
|
|
@ -1,26 +0,0 @@
|
|||
include ../../common/json_utils
|
||||
include ../../../app/core/tasks/common
|
||||
|
||||
proc getLatestVersionJSON(): string =
|
||||
var jsonObj = %*{
|
||||
"version": "",
|
||||
"url": ""
|
||||
}
|
||||
try:
|
||||
debug "Getting latest version information"
|
||||
|
||||
let latestVersion = getLatestVersion()
|
||||
|
||||
jsonObj["version"] = %*latestVersion.version
|
||||
jsonObj["url"] = %*latestVersion.url
|
||||
|
||||
except Exception as e:
|
||||
error "Error while getting latest version information", msg = e.msg
|
||||
|
||||
return $jsonObj
|
||||
|
||||
const checkForUpdatesTask: Task = proc(argEncoded: string) {.gcsafe, nimcall.} =
|
||||
debug "Check for updates - async"
|
||||
let arg = decode[QObjectTaskArg](argEncoded)
|
||||
let response = getLatestVersionJSON()
|
||||
arg.finish(response)
|
|
@ -1,22 +1,29 @@
|
|||
import NimQml, json, chronicles
|
||||
|
||||
import ../../../app/core/eventemitter
|
||||
import ../../../app/core/tasks/[qt, threadpool]
|
||||
import ../../../constants
|
||||
|
||||
import ../settings/service as settings_service
|
||||
import ../network/types
|
||||
import ../../../app/core/eventemitter
|
||||
import ../../../app/core/tasks/[qt, threadpool]
|
||||
import ../../../app/core/signals/types as signal_types
|
||||
import ../../../backend/backend
|
||||
import ./update
|
||||
|
||||
include async_tasks
|
||||
import ../../../backend/about as status_about
|
||||
import ../../../constants
|
||||
|
||||
logScope:
|
||||
topics = "about-service"
|
||||
|
||||
# This is changed during compilation by reading the VERSION file
|
||||
const DESKTOP_VERSION {.strdefine.} = "0.0.0"
|
||||
|
||||
const APP_UPDATES_ENS* = "desktop.status.eth"
|
||||
|
||||
type
|
||||
VersionArgs* = ref object of Args
|
||||
available*: bool
|
||||
version*: string
|
||||
url*: string
|
||||
|
||||
|
||||
|
||||
# Signals which may be emitted by this service:
|
||||
const SIGNAL_VERSION_FETCHED* = "versionFetched"
|
||||
|
@ -28,9 +35,6 @@ QtObject:
|
|||
threadpool: ThreadPool
|
||||
settingsService: settings_service.Service
|
||||
|
||||
# Forward declaration
|
||||
proc asyncRequestLatestVersion(self: Service)
|
||||
|
||||
proc delete*(self: Service) =
|
||||
self.QObject.delete
|
||||
|
||||
|
@ -43,12 +47,6 @@ QtObject:
|
|||
result.events = events
|
||||
result.threadpool = threadpool
|
||||
|
||||
proc init*(self: Service) =
|
||||
# TODO uncomment this once the latest version calls is fixed
|
||||
# to fix this, you need to re-upload the version and files to IPFS and pin them
|
||||
# self.asyncRequestLatestVersion()
|
||||
discard
|
||||
|
||||
proc getAppVersion*(self: Service): string =
|
||||
return DESKTOP_VERSION
|
||||
|
||||
|
@ -58,29 +56,19 @@ QtObject:
|
|||
except Exception as e:
|
||||
error "Error getting Node version"
|
||||
|
||||
proc emitSignal(self: Service, versionJsonObj: JsonNode) =
|
||||
self.events.emit(SIGNAL_VERSION_FETCHED, VersionArgs(version: $versionJsonObj))
|
||||
|
||||
proc asyncRequestLatestVersion(self: Service) =
|
||||
let arg = QObjectTaskArg(
|
||||
tptr: cast[ByteAddress](checkForUpdatesTask),
|
||||
vptr: cast[ByteAddress](self.vptr),
|
||||
slot: "latestVersionSuccess"
|
||||
)
|
||||
self.threadpool.start(arg)
|
||||
|
||||
proc checkForUpdates*(self: Service) =
|
||||
self.asyncRequestLatestVersion()
|
||||
try:
|
||||
discard status_about.checkForUpdates(types.Mainnet, APP_UPDATES_ENS, DESKTOP_VERSION)
|
||||
except Exception as e:
|
||||
error "Error checking for updates", msg=e.msg
|
||||
|
||||
proc latestVersionSuccess*(self: Service, latestVersionJSON: string) {.slot.} =
|
||||
var latestVersionObj = parseJSON(latestVersionJSON)
|
||||
|
||||
var newVersionAvailable = false
|
||||
let latestVersion = latestVersionObj{"version"}.getStr()
|
||||
if(latestVersion.len > 0):
|
||||
newVersionAvailable = isNewer(DESKTOP_VERSION, latestVersion)
|
||||
|
||||
latestVersionObj["available"] = newJBool(newVersionAvailable)
|
||||
|
||||
self.emitSignal(latestVersionObj)
|
||||
proc init*(self: Service) =
|
||||
self.events.on(SignalType.UpdateAvailable.event) do(e: Args):
|
||||
var updateSignal = UpdateAvailableSignal(e)
|
||||
self.events.emit(SIGNAL_VERSION_FETCHED, VersionArgs(
|
||||
available: updateSignal.available,
|
||||
version: updateSignal.version,
|
||||
url: updateSignal.url))
|
||||
|
||||
self.checkForUpdates()
|
||||
|
||||
|
|
|
@ -1,32 +0,0 @@
|
|||
import json, chronicles, httpclient, net, options
|
||||
import strutils
|
||||
import semver
|
||||
|
||||
import ../../../backend/ens as status_ens
|
||||
|
||||
const APP_UPDATES_ENS* = "desktop.status.eth"
|
||||
const CHECK_VERSION_TIMEOUT_MS* = 5000
|
||||
|
||||
type
|
||||
VersionInfo* = object
|
||||
version*: string
|
||||
url*: string
|
||||
|
||||
proc getLatestVersion*(): VersionInfo =
|
||||
let response = status_ens.resourceUrl(chainId=1, username=APP_UPDATES_ENS)
|
||||
let host = response.result{"Host"}.getStr
|
||||
if host == "":
|
||||
raise newException(ValueError, "ENS does not have a content hash")
|
||||
|
||||
let url = "https://" & host & response.result{"Path"}.getStr
|
||||
|
||||
# Read version from folder
|
||||
let secureSSLContext = newContext()
|
||||
let client = newHttpClient(sslContext = secureSSLContext, timeout = CHECK_VERSION_TIMEOUT_MS)
|
||||
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
|
|
@ -0,0 +1,9 @@
|
|||
import json
|
||||
import ./core
|
||||
import response_type
|
||||
|
||||
export response_type
|
||||
|
||||
proc checkForUpdates*(chainId: int, ensAddress: string, currVersion: string): RpcResponse[JsonNode] {.raises: [Exception].} =
|
||||
let payload = %* [chainId, ensAddress, currVersion]
|
||||
result = callPrivateRPC("updates_check", payload)
|
|
@ -9,6 +9,20 @@ QtObject {
|
|||
property var communitiesModuleInst: communitiesModule
|
||||
property var observedCommunity: communitiesModuleInst.observedCommunity
|
||||
|
||||
property bool newVersionAvailable: false
|
||||
property string latestVersion
|
||||
property string downloadURL
|
||||
|
||||
function setLatestVersionInfo(newVersionAvailable, latestVersion, downloadURL) {
|
||||
root.newVersionAvailable = newVersionAvailable;
|
||||
root.latestVersion = latestVersion;
|
||||
root.downloadURL = downloadURL;
|
||||
}
|
||||
|
||||
function resetLastVersion(){
|
||||
root.newVersionAvailable = false
|
||||
}
|
||||
|
||||
property AppSearchStore appSearchStore: AppSearchStore {
|
||||
appSearchModule: root.mainModuleInst.appSearchModule
|
||||
}
|
||||
|
|
|
@ -43,21 +43,14 @@ Item {
|
|||
property RootStore rootStore: RootStore { }
|
||||
// set from main.qml
|
||||
property var sysPalette
|
||||
property var newVersionJSON: {
|
||||
try {
|
||||
return JSON.parse(rootStore.aboutModuleInst.newVersion)
|
||||
} catch (e) {
|
||||
console.error("Error parsing version data", e)
|
||||
return {}
|
||||
}
|
||||
}
|
||||
|
||||
signal openContactsPopup()
|
||||
|
||||
Connections {
|
||||
target: rootStore.aboutModuleInst
|
||||
onAppVersionFetched: {
|
||||
if (!newVersionJSON.available) {
|
||||
rootStore.setLatestVersionInfo(available, version, url);
|
||||
if (!available) {
|
||||
versionUpToDate.show()
|
||||
} else {
|
||||
versionWarning.show()
|
||||
|
@ -81,10 +74,10 @@ Item {
|
|||
onOpenDownloadModalRequested: {
|
||||
const downloadPage = downloadPageComponent.createObject(appMain,
|
||||
{
|
||||
newVersionAvailable: newVersionJSON.available,
|
||||
downloadURL: newVersionJSON.url,
|
||||
newVersionAvailable: available,
|
||||
downloadURL: url,
|
||||
currentVersion: rootStore.profileSectionStore.getCurrentVersion(),
|
||||
newVersion: newVersionJSON.version
|
||||
newVersion: version
|
||||
})
|
||||
return downloadPage
|
||||
}
|
||||
|
@ -414,13 +407,16 @@ Item {
|
|||
id: versionWarning
|
||||
width: parent.width
|
||||
height: 32
|
||||
visible: !!newVersionJSON.available
|
||||
visible: appMain.rootStore.newVersionAvailable
|
||||
color: Style.current.green
|
||||
btnWidth: 100
|
||||
text: qsTr("A new version of Status (%1) is available").arg(newVersionJSON.version)
|
||||
text: qsTr("A new version of Status (%1) is available").arg(appMain.rootStore.latestVersion)
|
||||
btnText: qsTr("Download")
|
||||
onClick: function(){
|
||||
Global.openDownloadModal()
|
||||
Global.openDownloadModal(appMain.rootStore.newVersionAvailable, appMain.rootStore.latestVersion, appMain.rootStore.downloadURL)
|
||||
}
|
||||
onClosed: {
|
||||
appMain.rootStore.resetLastVersion();
|
||||
}
|
||||
|
||||
function show() {
|
||||
|
|
|
@ -10,20 +10,23 @@ import "./"
|
|||
Rectangle {
|
||||
id: root
|
||||
height: visible ? 32 : 0
|
||||
implicitHeight: height
|
||||
color: Style.current.red
|
||||
|
||||
property string text: ""
|
||||
property string btnText: ""
|
||||
property int btnWidth: 58
|
||||
property bool closing: false
|
||||
|
||||
property var onClick: function() {}
|
||||
|
||||
signal closed()
|
||||
|
||||
function close() {
|
||||
closeBtn.clicked(null)
|
||||
closed();
|
||||
}
|
||||
|
||||
signal closed
|
||||
|
||||
Row {
|
||||
spacing: Style.current.halfPadding
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
|
@ -89,10 +92,21 @@ Rectangle {
|
|||
id: closeBtn
|
||||
anchors.fill: closeImg
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: ParallelAnimation {
|
||||
PropertyAnimation { target: root; property: "visible"; to: false; }
|
||||
PropertyAnimation { target: root; property: "y"; to: -1 * root.height }
|
||||
onFinished: root.closed()
|
||||
onClicked: {
|
||||
closing = true
|
||||
}
|
||||
}
|
||||
|
||||
ParallelAnimation {
|
||||
running: closing
|
||||
PropertyAnimation { target: root; property: "visible"; to: false; }
|
||||
PropertyAnimation { target: root; property: "y"; to: -1 * root.height }
|
||||
onRunningChanged: {
|
||||
if(!running){
|
||||
closing = false;
|
||||
root.y = 0;
|
||||
root.closed();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,6 +15,9 @@ Item {
|
|||
property alias tooltipUnder: copyToClipboardBtn.tooltipUnder
|
||||
property var store
|
||||
|
||||
property alias textFont: name.font
|
||||
property alias textColor: name.color
|
||||
|
||||
id: root
|
||||
width: parent.width
|
||||
height: name.height
|
||||
|
|
|
@ -19,7 +19,8 @@ QtObject {
|
|||
signal openImagePopup(var image, var contextMenu)
|
||||
signal openLinkInBrowser(string link)
|
||||
signal openChooseBrowserPopup(string link)
|
||||
signal openDownloadModalRequested()
|
||||
signal openPopupRequested(var popupComponent, var params)
|
||||
signal openDownloadModalRequested(bool available, string version, string url)
|
||||
signal settingsLoaded()
|
||||
signal openBackUpSeedPopup()
|
||||
signal openCreateChatView()
|
||||
|
@ -40,8 +41,8 @@ QtObject {
|
|||
return popup;
|
||||
}
|
||||
|
||||
function openDownloadModal(){
|
||||
openDownloadModalRequested();
|
||||
function openDownloadModal(available, version, url){
|
||||
openDownloadModalRequested(available, version, url);
|
||||
}
|
||||
|
||||
function changeAppSectionBySectionType(sectionType, subsection = 0) {
|
||||
|
|
Loading…
Reference in New Issue