feat: waku2 store
- add toggle to enable store functionality - output messages to csv - add custom waku2 nodes
This commit is contained in:
parent
810a6bb5f5
commit
fb526840a4
|
@ -64,7 +64,7 @@ proc getMailservers*(self: FleetConfiguration, fleet: Fleet, isWakuV2: bool): Ta
|
|||
# TODO: If using wakuV2, this assumes that Waku nodes in fleet.status.json are also store nodes.
|
||||
# Maybe it make senses to add a "waku-store" section in case we want to have separate node types?
|
||||
# Discuss with @iurimatias, @cammellos and Vac team
|
||||
let fleetKey = if isWakuV2: $FleetNodes.Waku else: $FleetNodes.Mailservers
|
||||
let fleetKey = if isWakuV2: $FleetNodes.TCP_P2P_Waku else: $FleetNodes.Mailservers
|
||||
if not self.fleet[$fleet].hasKey(fleetKey) :
|
||||
result = initTable[string,string]()
|
||||
return
|
||||
|
|
|
@ -58,6 +58,18 @@ proc setBloomLevel*(self: Controller, bloomLevel: string) =
|
|||
|
||||
self.delegate.onBloomLevelSet()
|
||||
|
||||
method toggleWakuV2Store*(self: Controller) =
|
||||
let enabled = self.nodeConfigurationService.isWakuV2StoreEnabled()
|
||||
if (not self.nodeConfigurationService.setWakuV2StoreEnabled(not enabled)):
|
||||
# in the future we may do a call from here to show a popup about this error
|
||||
error "an error occurred, we couldn't enable community history archive support"
|
||||
return
|
||||
self.delegate.onWakuV2StoreToggled()
|
||||
|
||||
method isWakuV2StoreEnabled*(self: Controller): bool =
|
||||
return self.nodeConfigurationService.isWakuV2StoreEnabled()
|
||||
|
||||
|
||||
proc getWakuV2LightClientEnabled*(self: Controller): bool =
|
||||
return self.nodeConfigurationService.getV2LightMode()
|
||||
|
||||
|
|
|
@ -21,6 +21,9 @@ method onFleetSet*(self: AccessInterface) {.base.} =
|
|||
method onBloomLevelSet*(self: AccessInterface) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method onWakuV2StoreToggled*(self: AccessInterface) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method onWakuV2LightClientSet*(self: AccessInterface) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
|
@ -92,3 +95,9 @@ method toggleNodeManagementSection*(self: AccessInterface) {.base.} =
|
|||
|
||||
method enableDeveloperFeatures*(self: AccessInterface) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method isWakuV2StoreEnabled*(self: AccessInterface): bool {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method toggleWakuV2Store*(self: AccessInterface) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
|
|
@ -130,3 +130,12 @@ method toggleCommunitiesPortalSection*(self: Module) =
|
|||
|
||||
method toggleNodeManagementSection*(self: Module) =
|
||||
self.controller.toggleNodeManagementSection()
|
||||
|
||||
method onWakuV2StoreToggled*(self: Module) =
|
||||
self.view.emitWakuV2StoreEnabledSignal()
|
||||
|
||||
method toggleWakuV2Store*(self: Module) =
|
||||
self.controller.toggleWakuV2Store()
|
||||
|
||||
method isWakuV2StoreEnabled*(self: Module): bool =
|
||||
self.controller.isWakuV2StoreEnabled()
|
||||
|
|
|
@ -119,3 +119,16 @@ QtObject:
|
|||
|
||||
proc toggleCommunitiesPortalSection*(self: View) {.slot.} =
|
||||
self.delegate.toggleCommunitiesPortalSection()
|
||||
|
||||
proc isWakuV2StoreEnabledChanged*(self: View) {.signal.}
|
||||
proc getIsWakuV2StoreEnabled*(self: View): bool {.slot.} =
|
||||
return self.delegate.isWakuV2StoreEnabled()
|
||||
QtProperty[bool] isWakuV2StoreEnabled:
|
||||
read = getIsWakuV2StoreEnabled
|
||||
notify = isWakuV2StoreEnabledChanged
|
||||
|
||||
proc emitWakuV2StoreEnabledSignal*(self: View) =
|
||||
self.isWakuV2StoreEnabledChanged()
|
||||
|
||||
proc toggleWakuV2Store*(self: View) {.slot.} =
|
||||
self.delegate.toggleWakuV2Store()
|
||||
|
|
|
@ -65,9 +65,15 @@ method getDevicesModule*(self: AccessInterface): QVariant {.base.} =
|
|||
method syncModuleDidLoad*(self: AccessInterface) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method wakuModuleDidLoad*(self: AccessInterface) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method getSyncModule*(self: AccessInterface): QVariant {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method getWakuModule*(self: AccessInterface): QVariant {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method notificationsModuleDidLoad*(self: AccessInterface) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
|
|
|
@ -32,6 +32,7 @@ import ./about/module as about_module
|
|||
import ./advanced/module as advanced_module
|
||||
import ./devices/module as devices_module
|
||||
import ./sync/module as sync_module
|
||||
import ./waku/module as waku_module
|
||||
import ./notifications/module as notifications_module
|
||||
import ./ens_usernames/module as ens_usernames_module
|
||||
import ./communities/module as communities_module
|
||||
|
@ -55,6 +56,7 @@ type
|
|||
advancedModule: advanced_module.AccessInterface
|
||||
devicesModule: devices_module.AccessInterface
|
||||
syncModule: sync_module.AccessInterface
|
||||
wakuModule: waku_module.AccessInterface
|
||||
notificationsModule: notifications_module.AccessInterface
|
||||
ensUsernamesModule: ens_usernames_module.AccessInterface
|
||||
communitiesModule: communities_module.AccessInterface
|
||||
|
@ -98,6 +100,7 @@ proc newModule*(delegate: delegate_interface.AccessInterface,
|
|||
result.advancedModule = advanced_module.newModule(result, events, settingsService, stickersService, nodeConfigurationService)
|
||||
result.devicesModule = devices_module.newModule(result, events, settingsService, devicesService)
|
||||
result.syncModule = sync_module.newModule(result, events, settingsService, nodeConfigurationService, mailserversService)
|
||||
result.wakuModule = waku_module.newModule(result, events, settingsService, nodeConfigurationService)
|
||||
result.notificationsModule = notifications_module.newModule(result, events, settingsService, chatService, contactsService)
|
||||
result.ensUsernamesModule = ens_usernames_module.newModule(
|
||||
result, events, settingsService, ensService, walletAccountService, networkService, tokenService
|
||||
|
@ -117,6 +120,7 @@ method delete*(self: Module) =
|
|||
self.advancedModule.delete
|
||||
self.devicesModule.delete
|
||||
self.syncModule.delete
|
||||
self.wakuModule.delete
|
||||
self.communitiesModule.delete
|
||||
self.keycardModule.delete
|
||||
|
||||
|
@ -134,6 +138,7 @@ method load*(self: Module) =
|
|||
self.advancedModule.load()
|
||||
self.devicesModule.load()
|
||||
self.syncModule.load()
|
||||
self.wakuModule.load()
|
||||
self.notificationsModule.load()
|
||||
self.ensUsernamesModule.load()
|
||||
self.communitiesModule.load()
|
||||
|
@ -167,6 +172,9 @@ proc checkIfModuleDidLoad(self: Module) =
|
|||
if(not self.syncModule.isLoaded()):
|
||||
return
|
||||
|
||||
if(not self.wakuModule.isLoaded()):
|
||||
return
|
||||
|
||||
if(not self.notificationsModule.isLoaded()):
|
||||
return
|
||||
|
||||
|
@ -227,9 +235,15 @@ method getDevicesModule*(self: Module): QVariant =
|
|||
method syncModuleDidLoad*(self: Module) =
|
||||
self.checkIfModuleDidLoad()
|
||||
|
||||
method wakuModuleDidLoad*(self: Module) =
|
||||
self.checkIfModuleDidLoad()
|
||||
|
||||
method getSyncModule*(self: Module): QVariant =
|
||||
self.syncModule.getModuleAsVariant()
|
||||
|
||||
method getWakuModule*(self: Module): QVariant =
|
||||
self.wakuModule.getModuleAsVariant()
|
||||
|
||||
method notificationsModuleDidLoad*(self: Module) =
|
||||
self.checkIfModuleDidLoad()
|
||||
|
||||
|
|
|
@ -51,6 +51,11 @@ QtObject:
|
|||
QtProperty[QVariant] syncModule:
|
||||
read = getSyncModule
|
||||
|
||||
proc getWakuModule(self: View): QVariant {.slot.} =
|
||||
return self.delegate.getWakuModule()
|
||||
QtProperty[QVariant] wakuModule:
|
||||
read = getWakuModule
|
||||
|
||||
proc getNotificationsModule(self: View): QVariant {.slot.} =
|
||||
return self.delegate.getNotificationsModule()
|
||||
QtProperty[QVariant] notificationsModule:
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
import Tables, chronicles
|
||||
import io_interface
|
||||
|
||||
import ../../../../core/eventemitter
|
||||
import ../../../../core/fleets/fleet_configuration
|
||||
import ../../../../../app_service/service/settings/service as settings_service
|
||||
import ../../../../../app_service/service/node_configuration/service as node_configuration_service
|
||||
|
||||
logScope:
|
||||
topics = "profile-section-waku-module-controller"
|
||||
|
||||
type
|
||||
Controller* = ref object of RootObj
|
||||
delegate: io_interface.AccessInterface
|
||||
events: EventEmitter
|
||||
settingsService: settings_service.Service
|
||||
nodeConfigurationService: node_configuration_service.Service
|
||||
|
||||
proc newController*(delegate: io_interface.AccessInterface,
|
||||
events: EventEmitter,
|
||||
settingsService: settings_service.Service,
|
||||
nodeConfigurationService: node_configuration_service.Service): Controller =
|
||||
result = Controller()
|
||||
result.delegate = delegate
|
||||
result.events = events
|
||||
result.settingsService = settingsService
|
||||
result.nodeConfigurationService = nodeConfigurationService
|
||||
|
||||
proc delete*(self: Controller) =
|
||||
discard
|
||||
|
||||
proc init*(self: Controller) =
|
||||
discard
|
||||
|
||||
proc getAllWakuNodes*(self: Controller): seq[string] =
|
||||
return self.nodeConfigurationService.getAllWakuNodes()
|
||||
|
||||
proc saveNewWakuNode*(self: Controller, nodeAddress: string) =
|
||||
self.nodeConfigurationService.saveNewWakuNode(nodeAddress)
|
|
@ -0,0 +1,25 @@
|
|||
import NimQml
|
||||
|
||||
type
|
||||
AccessInterface* {.pure inheritable.} = ref object of RootObj
|
||||
|
||||
method delete*(self: AccessInterface) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method load*(self: AccessInterface) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method isLoaded*(self: AccessInterface): bool {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method getModuleAsVariant*(self: AccessInterface): QVariant {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method viewDidLoad*(self: AccessInterface) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method isAutomaticSelection*(self: AccessInterface): bool {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method saveNewWakuNode*(self: AccessInterface, nodeAddress: string) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
|
@ -0,0 +1,11 @@
|
|||
|
||||
type
|
||||
Item* = ref object
|
||||
nodeAddress: string
|
||||
|
||||
proc initItem*(nodeAddress: string): Item =
|
||||
result = Item()
|
||||
result.nodeAddress = nodeAddress
|
||||
|
||||
proc nodeAddress*(self: Item): string =
|
||||
self.nodeAddress
|
|
@ -0,0 +1,62 @@
|
|||
import NimQml, Tables
|
||||
import item
|
||||
|
||||
type
|
||||
ModelRole {.pure.} = enum
|
||||
NodeAddress = UserRole + 1
|
||||
|
||||
QtObject:
|
||||
type Model* = ref object of QAbstractListModel
|
||||
items*: seq[Item]
|
||||
|
||||
proc setup(self: Model) =
|
||||
self.QAbstractListModel.setup
|
||||
|
||||
proc delete(self: Model) =
|
||||
self.items = @[]
|
||||
self.QAbstractListModel.delete
|
||||
|
||||
proc newModel*(): Model =
|
||||
new(result, delete)
|
||||
result.setup
|
||||
|
||||
method rowCount(self: Model, index: QModelIndex = nil): int =
|
||||
return self.items.len
|
||||
|
||||
method roleNames(self: Model): Table[int, string] =
|
||||
{
|
||||
ModelRole.NodeAddress.int:"nodeAddress"
|
||||
}.toTable
|
||||
|
||||
method data(self: Model, index: QModelIndex, role: int): QVariant =
|
||||
if not index.isValid:
|
||||
return
|
||||
if index.row < 0 or index.row >= self.items.len:
|
||||
return
|
||||
let item = self.items[index.row]
|
||||
let enumRole = role.ModelRole
|
||||
|
||||
case enumRole:
|
||||
of ModelRole.NodeAddress:
|
||||
result = newQVariant(item.nodeAddress)
|
||||
|
||||
proc addItem*(self: Model, item: Item) =
|
||||
let parentModelIndex = newQModelIndex()
|
||||
defer: parentModelIndex.delete
|
||||
|
||||
self.beginInsertRows(parentModelIndex, self.items.len, self.items.len)
|
||||
self.items.add(item)
|
||||
self.endInsertRows()
|
||||
|
||||
proc addItems*(self: Model, items: seq[Item]) =
|
||||
if(items.len == 0):
|
||||
return
|
||||
|
||||
let parentModelIndex = newQModelIndex()
|
||||
defer: parentModelIndex.delete
|
||||
|
||||
let first = self.items.len
|
||||
let last = first + items.len - 1
|
||||
self.beginInsertRows(parentModelIndex, first, last)
|
||||
self.items.add(items)
|
||||
self.endInsertRows()
|
|
@ -0,0 +1,66 @@
|
|||
import NimQml, chronicles
|
||||
import io_interface
|
||||
import ../io_interface as delegate_interface
|
||||
import view, controller, model, item
|
||||
|
||||
import ../../../../core/eventemitter
|
||||
import ../../../../../app_service/service/settings/service as settings_service
|
||||
import ../../../../../app_service/service/node_configuration/service as node_configuration_service
|
||||
|
||||
export io_interface
|
||||
|
||||
logScope:
|
||||
topics = "profile-section-waku-module"
|
||||
|
||||
type
|
||||
Module* = ref object of io_interface.AccessInterface
|
||||
delegate: delegate_interface.AccessInterface
|
||||
controller: Controller
|
||||
view: View
|
||||
viewVariant: QVariant
|
||||
moduleLoaded: bool
|
||||
|
||||
proc newModule*(delegate: delegate_interface.AccessInterface,
|
||||
events: EventEmitter,
|
||||
settingsService: settings_service.Service,
|
||||
nodeConfigurationService: node_configuration_service.Service): Module =
|
||||
result = Module()
|
||||
result.delegate = delegate
|
||||
result.view = view.newView(result)
|
||||
result.viewVariant = newQVariant(result.view)
|
||||
result.controller = controller.newController(result, events, settingsService, nodeConfigurationService)
|
||||
result.moduleLoaded = false
|
||||
|
||||
method delete*(self: Module) =
|
||||
self.view.delete
|
||||
self.viewVariant.delete
|
||||
self.controller.delete
|
||||
|
||||
method load*(self: Module) =
|
||||
self.controller.init()
|
||||
self.view.load()
|
||||
|
||||
method isLoaded*(self: Module): bool =
|
||||
return self.moduleLoaded
|
||||
|
||||
proc initModel(self: Module) =
|
||||
var items: seq[Item]
|
||||
let allWakuNodes = self.controller.getAllWakuNodes()
|
||||
for w in allWakuNodes:
|
||||
let item = initItem(w)
|
||||
items.add(item)
|
||||
|
||||
self.view.model().addItems(items)
|
||||
|
||||
method viewDidLoad*(self: Module) =
|
||||
self.initModel()
|
||||
self.moduleLoaded = true
|
||||
self.delegate.wakuModuleDidLoad()
|
||||
|
||||
method getModuleAsVariant*(self: Module): QVariant =
|
||||
return self.viewVariant
|
||||
|
||||
method saveNewWakuNode*(self: Module, nodeAddress: string) =
|
||||
self.controller.saveNewWakuNode(nodeAddress)
|
||||
let item = initItem(nodeAddress)
|
||||
self.view.model().addItem(item)
|
|
@ -0,0 +1,39 @@
|
|||
import NimQml
|
||||
import io_interface, model
|
||||
|
||||
QtObject:
|
||||
type
|
||||
View* = ref object of QObject
|
||||
delegate: io_interface.AccessInterface
|
||||
activeMailserver: string
|
||||
model: Model
|
||||
modelVariant: QVariant
|
||||
|
||||
proc delete*(self: View) =
|
||||
self.model.delete
|
||||
self.modelVariant.delete
|
||||
self.QObject.delete
|
||||
|
||||
proc newView*(delegate: io_interface.AccessInterface): View =
|
||||
new(result, delete)
|
||||
result.QObject.setup
|
||||
result.delegate = delegate
|
||||
result.activeMailserver = ""
|
||||
result.model = newModel()
|
||||
result.modelVariant = newQVariant(result.model)
|
||||
|
||||
proc load*(self: View) =
|
||||
self.delegate.viewDidLoad()
|
||||
|
||||
proc model*(self: View): Model =
|
||||
return self.model
|
||||
|
||||
proc modelChanged*(self: View) {.signal.}
|
||||
proc getModel(self: View): QVariant {.slot.} =
|
||||
return self.modelVariant
|
||||
QtProperty[QVariant] model:
|
||||
read = getModel
|
||||
notify = modelChanged
|
||||
|
||||
proc saveNewWakuNode(self: View, address: string) {.slot.} =
|
||||
self.delegate.saveNewWakuNode(address)
|
|
@ -100,6 +100,9 @@ type
|
|||
EnableDiscV5*: bool
|
||||
UDPPort*: int
|
||||
AutoUpdate*: bool
|
||||
EnableStore*: bool
|
||||
StoreCapacity*: int
|
||||
StoreSeconds*: int
|
||||
|
||||
ShhextConfig* = object
|
||||
PFSEnabled*: bool
|
||||
|
@ -322,6 +325,9 @@ proc toWaku2Config*(jsonObj: JsonNode): Waku2Config =
|
|||
discard jsonObj.getProp("EnableDiscV5", result.EnableDiscV5)
|
||||
discard jsonObj.getProp("UDPPort", result.UDPPort)
|
||||
discard jsonObj.getProp("AutoUpdate", result.AutoUpdate)
|
||||
discard jsonObj.getProp("EnableStore", result.EnableStore)
|
||||
discard jsonObj.getProp("StoreCapacity", result.StoreCapacity)
|
||||
discard jsonObj.getProp("StoreSeconds", result.StoreSeconds)
|
||||
|
||||
proc toWakuConfig*(jsonObj: JsonNode): WakuConfig =
|
||||
discard jsonObj.getProp("Enabled", result.Enabled)
|
||||
|
|
|
@ -33,6 +33,7 @@ type
|
|||
configuration: NodeConfigDto
|
||||
fleetConfiguration: FleetConfiguration
|
||||
settingsService: settings_service.Service
|
||||
wakuNodes: seq[string]
|
||||
events: EventEmitter
|
||||
|
||||
# Forward declarations
|
||||
|
@ -48,6 +49,7 @@ proc newService*(fleetConfiguration: FleetConfiguration, settingsService: settin
|
|||
result.fleetConfiguration = fleetConfiguration
|
||||
result.settingsService = settingsService
|
||||
result.events = events
|
||||
result.wakuNodes = @[]
|
||||
|
||||
proc adaptNodeSettingsForTheAppNeed(self: Service) =
|
||||
self.configuration.DataDir = "./ethereum"
|
||||
|
@ -68,6 +70,10 @@ proc init*(self: Service) =
|
|||
let response = status_node_config.getNodeConfig()
|
||||
self.configuration = response.result.toNodeConfigDto()
|
||||
|
||||
let wakuNodes = self.configuration.ClusterConfig.WakuNodes
|
||||
for nodeAddress in wakuNodes:
|
||||
self.wakuNodes.add(nodeAddress)
|
||||
|
||||
self.adaptNodeSettingsForTheAppNeed()
|
||||
except Exception as e:
|
||||
let errDesription = e.msg
|
||||
|
@ -202,6 +208,15 @@ proc getFleet*(self: Service): Fleet =
|
|||
proc getFleetAsString*(self: Service): string =
|
||||
result = $self.getFleet()
|
||||
|
||||
proc getAllWakuNodes*(self: Service): seq[string] =
|
||||
return self.wakuNodes
|
||||
|
||||
proc saveNewWakuNode*(self: Service, nodeAddress: string) =
|
||||
var newConfiguration = self.configuration
|
||||
newConfiguration.ClusterConfig.WakuNodes.add(nodeAddress)
|
||||
self.configuration = newConfiguration
|
||||
discard self.saveConfiguration(newConfiguration)
|
||||
|
||||
proc setFleet*(self: Service, fleet: string): bool =
|
||||
if(not self.settingsService.saveFleet(fleet)):
|
||||
error "error saving fleet ", procName="setFleet"
|
||||
|
@ -270,3 +285,13 @@ proc isV2LightMode*(self: Service): bool =
|
|||
|
||||
proc isFullNode*(self: Service): bool =
|
||||
return self.configuration.WakuConfig.FullNode
|
||||
|
||||
method isWakuV2StoreEnabled*(self: Service): bool =
|
||||
return self.configuration.WakuV2Config.EnableStore
|
||||
|
||||
proc setWakuV2StoreEnabled*(self: Service, enabled: bool, storeCapacity: int = 0, storeSeconds: int = 0): bool =
|
||||
var newConfiguration = self.configuration
|
||||
newConfiguration.WakuV2Config.EnableStore = enabled
|
||||
newConfiguration.WakuV2Config.StoreCapacity = storeCapacity
|
||||
newConfiguration.WakuV2Config.StoreSeconds = storeSeconds
|
||||
return self.saveConfiguration(newConfiguration)
|
||||
|
|
|
@ -145,6 +145,8 @@ QtObject {
|
|||
|
||||
property var walletSectionTransactionsInst: walletSectionTransactions
|
||||
|
||||
property bool isWakuV2StoreEnabled: advancedModule ? advancedModule.isWakuV2StoreEnabled : false
|
||||
|
||||
property string communityTags: communitiesModule.tags
|
||||
|
||||
property var stickersModuleInst: stickersModule
|
||||
|
|
|
@ -26,8 +26,7 @@ StatusModal {
|
|||
}
|
||||
|
||||
onOpened: {
|
||||
nameInput.text = "";
|
||||
enodeInput.text = "";
|
||||
addrInput.text = "";
|
||||
}
|
||||
|
||||
contentItem: StatusScrollView {
|
||||
|
@ -37,29 +36,19 @@ StatusModal {
|
|||
Column {
|
||||
id: nodesColumn
|
||||
width: parent.width
|
||||
StatusInput {
|
||||
id: nameInput
|
||||
label: qsTr("Name")
|
||||
placeholderText: qsTr("Specify a name")
|
||||
validators: [StatusMinLengthValidator {
|
||||
minLength: 1
|
||||
errorMessage: qsTr("You need to enter a name")
|
||||
}]
|
||||
validationMode: StatusInput.ValidationMode.Always
|
||||
}
|
||||
|
||||
StatusInput {
|
||||
id: enodeInput
|
||||
label: popup.advancedStore.isWakuV2 ? qsTr("Storenode multiaddress") : qsTr("History node address")
|
||||
placeholderText: popup.advancedStore.isWakuV2 ? "/ip4/0.0.0.0/tcp/123/..." : "enode://{enode-id}:{password}@{ip-address}:{port-number}"
|
||||
id: addrInput
|
||||
label: qsTr("Node multiaddress or DNS Discovery address")
|
||||
placeholderText: "/ipv4/0.0.0.0/tcp/123/..."
|
||||
validators: [
|
||||
StatusMinLengthValidator {
|
||||
minLength: 1
|
||||
errorMessage: popup.advancedStore.isWakuV2 ? qsTr("You need to enter the storenode multiaddress") : qsTr("You need to enter the enode address")
|
||||
errorMessage: qsTr("You need to enter a value")
|
||||
},
|
||||
StatusRegularExpressionValidator {
|
||||
errorMessage: popup.advancedStore.isWakuV2 ? qsTr('Multiaddress must start with a "/"') : qsTr("The format must be: enode://{enode-id}:{password}@{ip-address}:{port}")
|
||||
regularExpression: popup.advancedStore.isWakuV2 ? /\/.+/ : /enode:\/\/[a-z0-9]+:[a-z0-9]+@(\b25[0-5]|\b2[0-4][0-9]|\b[01]?[0-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}:[0-9]+/
|
||||
errorMessage: qsTr("Value should start with '/' or 'enr:'")
|
||||
regularExpression: /(\/|enr:).+/
|
||||
}]
|
||||
validationMode: StatusInput.ValidationMode.Always
|
||||
}
|
||||
|
@ -69,10 +58,9 @@ StatusModal {
|
|||
rightButtons: [
|
||||
StatusButton {
|
||||
text: qsTr("Save")
|
||||
enabled: nameInput.valid && enodeInput.valid
|
||||
// enabled: nameInput.text !== "" && enodeInput.text !== ""
|
||||
enabled: addrInput.valid
|
||||
onClicked: {
|
||||
root.messagingStore.saveNewMailserver(nameInput.text, enodeInput.text)
|
||||
root.messagingStore.saveNewWakuNode(addrInput.text)
|
||||
popup.close()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,80 @@
|
|||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.3
|
||||
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
import StatusQ.Components 0.1
|
||||
import StatusQ.Controls 0.1
|
||||
import StatusQ.Controls.Validators 0.1
|
||||
import StatusQ.Popups 0.1
|
||||
|
||||
|
||||
import utils 1.0
|
||||
|
||||
StatusModal {
|
||||
id: popup
|
||||
|
||||
anchors.centerIn: parent
|
||||
height: 560
|
||||
header.title: qsTr("Waku nodes")
|
||||
|
||||
property var messagingStore
|
||||
property var advancedStore
|
||||
|
||||
onClosed: {
|
||||
destroy()
|
||||
}
|
||||
|
||||
onOpened: {
|
||||
nameInput.text = "";
|
||||
enodeInput.text = "";
|
||||
}
|
||||
|
||||
contentItem: StatusScrollView {
|
||||
height: parent.height
|
||||
width: parent.width
|
||||
|
||||
Column {
|
||||
id: nodesColumn
|
||||
width: parent.width
|
||||
StatusInput {
|
||||
id: nameInput
|
||||
label: qsTr("Name")
|
||||
placeholderText: qsTr("Specify a name")
|
||||
validators: [StatusMinLengthValidator {
|
||||
minLength: 1
|
||||
errorMessage: qsTr("You need to enter a name")
|
||||
}]
|
||||
validationMode: StatusInput.ValidationMode.Always
|
||||
}
|
||||
|
||||
StatusInput {
|
||||
id: enodeInput
|
||||
label: popup.advancedStore.isWakuV2 ? qsTr("Storenode multiaddress") : qsTr("History node address")
|
||||
placeholderText: popup.advancedStore.isWakuV2 ? "/ip4/0.0.0.0/tcp/123/..." : "enode://{enode-id}:{password}@{ip-address}:{port-number}"
|
||||
validators: [
|
||||
StatusMinLengthValidator {
|
||||
minLength: 1
|
||||
errorMessage: popup.advancedStore.isWakuV2 ? qsTr("You need to enter the storenode multiaddress") : qsTr("You need to enter the enode address")
|
||||
},
|
||||
StatusRegularExpressionValidator {
|
||||
errorMessage: popup.advancedStore.isWakuV2 ? qsTr('Multiaddress must start with a "/"') : qsTr("The format must be: enode://{enode-id}:{password}@{ip-address}:{port}")
|
||||
regularExpression: popup.advancedStore.isWakuV2 ? /\/.+/ : /enode:\/\/[a-z0-9]+:[a-z0-9]+@(\b25[0-5]|\b2[0-4][0-9]|\b[01]?[0-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}:[0-9]+/
|
||||
}]
|
||||
validationMode: StatusInput.ValidationMode.Always
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rightButtons: [
|
||||
StatusButton {
|
||||
text: qsTr("Save")
|
||||
enabled: nameInput.valid && enodeInput.valid
|
||||
// enabled: nameInput.text !== "" && enodeInput.text !== ""
|
||||
onClicked: {
|
||||
root.messagingStore.saveNewMailserver(nameInput.text, enodeInput.text)
|
||||
popup.close()
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
|
@ -26,9 +26,7 @@ StatusModal {
|
|||
|
||||
property var messagingStore
|
||||
property var advancedStore
|
||||
property string nameValidationError: ""
|
||||
property string enodeValidationError: ""
|
||||
|
||||
|
||||
onClosed: {
|
||||
destroy()
|
||||
}
|
||||
|
@ -41,74 +39,16 @@ StatusModal {
|
|||
id: nodesColumn
|
||||
width: parent.width
|
||||
|
||||
StatusListItem {
|
||||
width: parent.width
|
||||
title: qsTr("Use Waku nodes")
|
||||
components: [
|
||||
StatusSwitch {
|
||||
checked: root.messagingStore.useMailservers
|
||||
onCheckedChanged: root.messagingStore.toggleUseMailservers(checked)
|
||||
}
|
||||
]
|
||||
onClicked: {
|
||||
root.messagingStore.toggleUseMailservers(!root.messagingStore.useMailservers)
|
||||
}
|
||||
}
|
||||
|
||||
Separator {
|
||||
width: parent.width
|
||||
}
|
||||
|
||||
StatusListItem {
|
||||
width: parent.width
|
||||
title: qsTr("Select node automatically")
|
||||
components: [
|
||||
StatusSwitch {
|
||||
id: automaticSelectionSwitch
|
||||
checked: root.messagingStore.automaticMailserverSelection
|
||||
onCheckedChanged: root.messagingStore.enableAutomaticMailserverSelection(checked)
|
||||
}
|
||||
]
|
||||
onClicked: {
|
||||
automaticSelectionSwitch.checked = !automaticSelectionSwitch.checked
|
||||
}
|
||||
}
|
||||
|
||||
StatusSectionHeadline {
|
||||
text: qsTr("Waku Nodes")
|
||||
visible: !automaticSelectionSwitch.checked
|
||||
width: parent.width
|
||||
height: visible ? implicitHeight : 0
|
||||
}
|
||||
|
||||
ButtonGroup {
|
||||
id: nodesButtonGroup
|
||||
}
|
||||
|
||||
Repeater {
|
||||
id: mailServersListView
|
||||
model: root.messagingStore.mailservers
|
||||
id: wakunodesListView
|
||||
model: root.messagingStore.wakunodes
|
||||
delegate: Component {
|
||||
StatusListItem {
|
||||
title: qsTr("Node %1").arg(index + 1)
|
||||
subTitle: model.name
|
||||
visible: !automaticSelectionSwitch.checked
|
||||
height: visible ? implicitHeight : 0
|
||||
subTitle: model.nodeAddress
|
||||
components: [
|
||||
StatusRadioButton {
|
||||
id: nodeRadioBtn
|
||||
ButtonGroup.group: nodesButtonGroup
|
||||
checked: model.nodeAddress === root.messagingStore.activeMailserver
|
||||
onCheckedChanged: {
|
||||
if (checked) {
|
||||
root.messagingStore.setActiveMailserver(model.name)
|
||||
}
|
||||
}
|
||||
}
|
||||
// TODO: add a button to delete nodes and restore default fleet nodes if necessary
|
||||
]
|
||||
onClicked: {
|
||||
nodeRadioBtn.checked = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,136 @@
|
|||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.3
|
||||
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
import StatusQ.Components 0.1
|
||||
import StatusQ.Controls 0.1
|
||||
import StatusQ.Controls.Validators 0.1
|
||||
import StatusQ.Popups 0.1
|
||||
|
||||
import "."
|
||||
|
||||
import utils 1.0
|
||||
import shared 1.0
|
||||
import shared.panels 1.0
|
||||
import shared.popups 1.0
|
||||
import shared.status 1.0
|
||||
import shared.controls 1.0
|
||||
|
||||
StatusModal {
|
||||
id: root
|
||||
|
||||
anchors.centerIn: parent
|
||||
height: 560
|
||||
header.title: qsTr("History Nodes")
|
||||
|
||||
property var messagingStore
|
||||
property var advancedStore
|
||||
property string nameValidationError: ""
|
||||
property string enodeValidationError: ""
|
||||
|
||||
onClosed: {
|
||||
destroy()
|
||||
}
|
||||
|
||||
contentItem: StatusScrollView {
|
||||
height: parent.height
|
||||
width: parent.width
|
||||
|
||||
Column {
|
||||
id: nodesColumn
|
||||
width: parent.width
|
||||
|
||||
StatusListItem {
|
||||
width: parent.width
|
||||
title: qsTr("Use Waku nodes")
|
||||
components: [
|
||||
StatusSwitch {
|
||||
checked: root.messagingStore.useMailservers
|
||||
onCheckedChanged: root.messagingStore.toggleUseMailservers(checked)
|
||||
}
|
||||
]
|
||||
onClicked: {
|
||||
root.messagingStore.toggleUseMailservers(!root.messagingStore.useMailservers)
|
||||
}
|
||||
}
|
||||
|
||||
Separator {
|
||||
width: parent.width
|
||||
}
|
||||
|
||||
StatusListItem {
|
||||
width: parent.width
|
||||
title: qsTr("Select node automatically")
|
||||
components: [
|
||||
StatusSwitch {
|
||||
id: automaticSelectionSwitch
|
||||
checked: root.messagingStore.automaticMailserverSelection
|
||||
onCheckedChanged: root.messagingStore.enableAutomaticMailserverSelection(checked)
|
||||
}
|
||||
]
|
||||
onClicked: {
|
||||
automaticSelectionSwitch.checked = !automaticSelectionSwitch.checked
|
||||
}
|
||||
}
|
||||
|
||||
StatusSectionHeadline {
|
||||
text: qsTr("Waku Nodes")
|
||||
visible: !automaticSelectionSwitch.checked
|
||||
width: parent.width
|
||||
height: visible ? implicitHeight : 0
|
||||
}
|
||||
|
||||
ButtonGroup {
|
||||
id: nodesButtonGroup
|
||||
}
|
||||
|
||||
Repeater {
|
||||
id: mailServersListView
|
||||
model: root.messagingStore.mailservers
|
||||
delegate: Component {
|
||||
StatusListItem {
|
||||
title: qsTr("Node %1").arg(index + 1)
|
||||
subTitle: model.name
|
||||
visible: !automaticSelectionSwitch.checked
|
||||
height: visible ? implicitHeight : 0
|
||||
components: [
|
||||
StatusRadioButton {
|
||||
id: nodeRadioBtn
|
||||
ButtonGroup.group: nodesButtonGroup
|
||||
checked: model.nodeAddress === root.messagingStore.activeMailserver
|
||||
onCheckedChanged: {
|
||||
if (checked) {
|
||||
root.messagingStore.setActiveMailserver(model.name)
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
onClicked: {
|
||||
nodeRadioBtn.checked = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StatusBaseText {
|
||||
text: qsTr("Add a new node")
|
||||
color: Theme.palette.primaryColor1
|
||||
width: parent.width
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: Global.openPopup(wakuNodeModalComponent)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: wakuNodeModalComponent
|
||||
AddWakuNodeModal {
|
||||
messagingStore: root.messagingStore
|
||||
advancedStore: root.advancedStore
|
||||
}
|
||||
}
|
||||
}
|
|
@ -13,6 +13,8 @@ QtObject {
|
|||
property bool isTelemetryEnabled: advancedModule? advancedModule.isTelemetryEnabled : false
|
||||
property bool isAutoMessageEnabled: advancedModule? advancedModule.isAutoMessageEnabled : false
|
||||
property bool isDebugEnabled: advancedModule? advancedModule.isDebugEnabled : false
|
||||
property bool isCommunityHistoryArchiveSupportEnabled: advancedModule? advancedModule.isCommunityHistoryArchiveSupportEnabled : false
|
||||
property bool isWakuV2StoreEnabled: advancedModule ? advancedModule.isWakuV2StoreEnabled : false
|
||||
|
||||
property var customNetworksModel: advancedModule? advancedModule.customNetworksModel : []
|
||||
|
||||
|
@ -32,6 +34,7 @@ QtObject {
|
|||
readonly property string communitiesPortal: "communitiesPortal"
|
||||
readonly property string communityPermissions: "communityPermissions"
|
||||
readonly property string discordImportTool: "discordImportTool"
|
||||
readonly property string wakuV2StoreEnabled: "wakuV2StoreEnabled"
|
||||
}
|
||||
|
||||
function logDir() {
|
||||
|
@ -113,6 +116,10 @@ QtObject {
|
|||
else if (feature === experimentalFeatures.communitiesPortal) {
|
||||
advancedModule.toggleCommunitiesPortalSection()
|
||||
}
|
||||
else if (feature === experimentalFeatures.wakuV2StoreEnabled) {
|
||||
// toggle history archive support
|
||||
advancedModule.toggleWakuV2Store()
|
||||
}
|
||||
else if (feature === experimentalFeatures.activityCenter) {
|
||||
localAccountSensitiveSettings.isActivityCenterEnabled = !localAccountSensitiveSettings.isActivityCenterEnabled
|
||||
}
|
||||
|
|
|
@ -6,8 +6,10 @@ QtObject {
|
|||
|
||||
property var privacyModule
|
||||
property var syncModule
|
||||
property var wakuModule
|
||||
|
||||
property var mailservers: syncModule.model
|
||||
property var wakunodes: wakuModule.model
|
||||
|
||||
property bool useMailservers: syncModule.useMailservers
|
||||
|
||||
|
@ -31,6 +33,10 @@ QtObject {
|
|||
root.syncModule.saveNewMailserver(name, nodeAddress)
|
||||
}
|
||||
|
||||
function saveNewWakuNode(nodeAddress) {
|
||||
root.wakuModule.saveNewWakuNode(nodeAddress)
|
||||
}
|
||||
|
||||
function enableAutomaticMailserverSelection(checked) {
|
||||
if (automaticMailserverSelection === checked) {
|
||||
return
|
||||
|
|
|
@ -25,6 +25,7 @@ QtObject {
|
|||
property MessagingStore messagingStore: MessagingStore {
|
||||
privacyModule: profileSectionModuleInst.privacyModule
|
||||
syncModule: profileSectionModuleInst.syncModule
|
||||
wakuModule: profileSectionModuleInst.wakuModule
|
||||
}
|
||||
|
||||
property DevicesStore devicesStore: DevicesStore {
|
||||
|
|
|
@ -185,6 +185,19 @@ SettingsContentBase {
|
|||
}
|
||||
}
|
||||
|
||||
// TODO: replace with StatusQ component
|
||||
StatusSettingsLineButton {
|
||||
anchors.leftMargin: 0
|
||||
anchors.rightMargin: 0
|
||||
text: qsTr("WakuV2 Store")
|
||||
isSwitch: true
|
||||
visible: root.advancedStore.isWakuV2
|
||||
switchChecked: root.advancedStore.isWakuV2StoreEnabled
|
||||
onClicked: {
|
||||
Global.openPopup(enableWakuV2StoreComponent)
|
||||
}
|
||||
}
|
||||
|
||||
StatusSectionHeadline {
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
|
@ -278,7 +291,7 @@ SettingsContentBase {
|
|||
anchors.right: parent.right
|
||||
anchors.leftMargin: Style.current.padding
|
||||
anchors.rightMargin: Style.current.padding
|
||||
visible: root.advancedStore.isWakuV2
|
||||
visible: root.advancedStore.isWakuV2 && root.advancedStore.fleet != Constants.status_prod
|
||||
text: qsTr("WakuV2 mode")
|
||||
topPadding: Style.current.bigPadding
|
||||
bottomPadding: Style.current.padding
|
||||
|
@ -487,6 +500,27 @@ SettingsContentBase {
|
|||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: enableWakuV2StoreComponent
|
||||
ConfirmationDialog {
|
||||
property bool mode: false
|
||||
|
||||
id: confirmDialog
|
||||
showCancelButton: true
|
||||
confirmationText: qsTr("Are you sure you want to %1 WakuV2 Store? You need to restart the app for this change to take effect.")
|
||||
.arg(root.advancedStore.isWakuV2StoreEnabled ?
|
||||
qsTr("disable") :
|
||||
qsTr("enable"))
|
||||
onConfirmButtonClicked: {
|
||||
root.advancedStore.toggleExperimentalFeature(root.advancedStore.experimentalFeatures.wakuV2StoreEnabled)
|
||||
close()
|
||||
}
|
||||
onCancelButtonClicked: {
|
||||
close()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: enableDebugComponent
|
||||
ConfirmationDialog {
|
||||
|
|
|
@ -337,7 +337,7 @@ SettingsContentBase {
|
|||
|
||||
StatusListItem {
|
||||
Layout.fillWidth: true
|
||||
title: qsTr("Waku nodes")
|
||||
title: qsTr("History nodes")
|
||||
label: root.messagingStore.getMailserverNameForNodeAddress(root.messagingStore.activeMailserver)
|
||||
components: [
|
||||
StatusIcon {
|
||||
|
@ -346,11 +346,33 @@ SettingsContentBase {
|
|||
color: Theme.palette.baseColor1
|
||||
}
|
||||
]
|
||||
onClicked: Global.openPopup(wakuNodeModalComponent)
|
||||
onClicked: Global.openPopup(wakuStoreModalComponent)
|
||||
}
|
||||
|
||||
Component {
|
||||
id: wakuNodeModalComponent
|
||||
id: wakuStoreModalComponent
|
||||
WakuStoreModal {
|
||||
messagingStore: root.messagingStore
|
||||
advancedStore: root.advancedStore
|
||||
}
|
||||
}
|
||||
|
||||
StatusListItem {
|
||||
Layout.fillWidth: true
|
||||
title: qsTr("Waku Nodes")
|
||||
visible: root.advancedStore.isWakuV2
|
||||
components: [
|
||||
StatusIcon {
|
||||
icon: "chevron-down"
|
||||
rotation: 270
|
||||
color: Theme.palette.baseColor1
|
||||
}
|
||||
]
|
||||
onClicked: Global.openPopup(wakuNodesModalComponent)
|
||||
}
|
||||
|
||||
Component {
|
||||
id: wakuNodesModalComponent
|
||||
WakuNodesModal {
|
||||
messagingStore: root.messagingStore
|
||||
advancedStore: root.advancedStore
|
||||
|
|
Loading…
Reference in New Issue