feat(wallet): add favorites for saved addresses

Depends on statug-go favourite flag extension and merging of `favourites`
with `saved_address` tables and API

Additional changes:

- Remove duplicate name instead of ESN

Closes: #6546
This commit is contained in:
Stefan 2022-08-18 16:44:48 +02:00 committed by Stefan Dunca
parent 95b1333758
commit 7af95eaada
17 changed files with 78 additions and 46 deletions

View File

@ -29,8 +29,8 @@ proc init*(self: Controller) =
proc getSavedAddresses*(self: Controller): seq[saved_address_service.SavedAddressDto] =
return self.savedAddressService.getSavedAddresses()
proc createOrUpdateSavedAddress*(self: Controller, name, address: string): string =
return self.savedAddressService.createOrUpdateSavedAddress(name, address)
proc createOrUpdateSavedAddress*(self: Controller, name: string, address: string, favourite: bool): string =
return self.savedAddressService.createOrUpdateSavedAddress(name, address, favourite)
proc deleteSavedAddress*(self: Controller, address: string): string =
return self.savedAddressService.deleteSavedAddress(address)

View File

@ -17,7 +17,7 @@ method viewDidLoad*(self: AccessInterface) {.base.} =
method loadSavedAddresses*(self: AccessInterface) {.base.} =
raise newException(ValueError, "No implementation available")
method createOrUpdateSavedAddress*(self: AccessInterface, name, address: string): string {.base.} =
method createOrUpdateSavedAddress*(self: AccessInterface, name: string, address: string, favourite: bool): string {.base.} =
raise newException(ValueError, "No implementation available")
method deleteSavedAddress*(self: AccessInterface, address: string): string {.base.} =

View File

@ -4,18 +4,22 @@ type
Item* = object
name: string
address: string
favourite: bool
proc initItem*(
name: string,
address: string,
favourite: bool
): Item =
result.name = name
result.address = address
result.favourite = favourite
proc `$`*(self: Item): string =
result = fmt"""AllTokensItem(
name: {self.name},
address: {self.address},
favourite: {self.favourite},
]"""
proc getName*(self: Item): string =
@ -23,3 +27,6 @@ proc getName*(self: Item): string =
proc getAddress*(self: Item): string =
return self.address
proc getFavourite*(self: Item): bool =
return self.favourite

View File

@ -6,6 +6,7 @@ type
ModelRole {.pure.} = enum
Name = UserRole + 1,
Address
Favourite
QtObject:
type
@ -43,6 +44,7 @@ QtObject:
{
ModelRole.Name.int:"name",
ModelRole.Address.int:"address",
ModelRole.Favourite.int:"favourite",
}.toTable
method data(self: Model, index: QModelIndex, role: int): QVariant =
@ -60,6 +62,8 @@ QtObject:
result = newQVariant(item.getName())
of ModelRole.Address:
result = newQVariant(item.getAddress())
of ModelRole.Favourite:
result = newQVariant(item.getFavourite())
proc rowData(self: Model, index: int, column: string): string {.slot.} =
if (index >= self.items.len):
@ -68,6 +72,7 @@ QtObject:
case column:
of "name": result = $item.getName()
of "address": result = $item.getAddress()
of "favourite": result = $item.getFavourite()
proc setItems*(self: Model, items: seq[Item]) =
self.beginResetModel()

View File

@ -36,6 +36,7 @@ method loadSavedAddresses*(self: Module) =
savedAddresses.map(s => initItem(
s.name,
s.address,
s.favourite
))
)
@ -53,8 +54,8 @@ method viewDidLoad*(self: Module) =
self.moduleLoaded = true
self.delegate.savedAddressesModuleDidLoad()
method createOrUpdateSavedAddress*(self: Module, name: string, address: string): string =
return self.controller.createOrUpdateSavedAddress(name, address)
method createOrUpdateSavedAddress*(self: Module, name: string, address: string, favourite: bool): string =
return self.controller.createOrUpdateSavedAddress(name, address, favourite)
method deleteSavedAddress*(self: Module, address: string): string =
return self.controller.deleteSavedAddress(address)

View File

@ -37,8 +37,8 @@ QtObject:
proc setItems*(self: View, items: seq[Item]) =
self.model.setItems(items)
proc createOrUpdateSavedAddress*(self: View, name: string, address: string): string {.slot.} =
return self.delegate.createOrUpdateSavedAddress(name, address)
proc createOrUpdateSavedAddress*(self: View, name: string, address: string, favourite: bool): string {.slot.} =
return self.delegate.createOrUpdateSavedAddress(name, address, favourite)
proc deleteSavedAddress*(self: View, address: string): string {.slot.} =
return self.delegate.deleteSavedAddress(address)

View File

@ -6,17 +6,21 @@ type
SavedAddressDto* = ref object of RootObj
name*: string
address*: string
favourite*: bool
proc newSavedAddressDto*(
name: string,
address: string,
favourite: bool
): SavedAddressDto =
return SavedAddressDto(
name: name,
address: address,
favourite: favourite
)
proc toSavedAddressDto*(jsonObj: JsonNode): SavedAddressDto =
result = SavedAddressDto()
discard jsonObj.getProp("name", result.name)
discard jsonObj.getProp("address", result.address)
discard jsonObj.getProp("favourite", result.favourite)

View File

@ -25,7 +25,7 @@ proc newService*(events: EventEmitter): Service =
result = Service()
result.events = events
proc fetchAddresses(self: Service) =
proc fetchAddresses(self: Service) =
try:
let response = backend.getSavedAddresses()
@ -39,15 +39,18 @@ proc fetchAddresses(self: Service) =
proc init*(self: Service) =
self.fetchAddresses()
proc updateAddresses(self: Service) =
self.fetchAddresses()
self.events.emit(SIGNAL_SAVED_ADDRESS_CHANGED, Args())
proc getSavedAddresses*(self: Service): seq[SavedAddressDto] =
return self.savedAddresses
proc createOrUpdateSavedAddress*(self: Service, name, address: string): string =
proc createOrUpdateSavedAddress*(self: Service, name: string, address: string, favourite: bool): string =
try:
discard backend.addSavedAddress(backend.SavedAddress(name: name, address: address))
self.fetchAddresses()
self.events.emit(SIGNAL_SAVED_ADDRESS_CHANGED, Args())
discard backend.addSavedAddress(backend.SavedAddress(name: name, address: address, favourite: favourite))
self.updateAddresses()
return ""
except Exception as e:
let errDesription = e.msg
@ -56,13 +59,11 @@ proc createOrUpdateSavedAddress*(self: Service, name, address: string): string =
proc deleteSavedAddress*(self: Service, address: string): string =
try:
let response = backend.deleteSavedAddress(address)
var response = backend.deleteSavedAddress(address)
if not response.error.isNil:
raise newException(Exception, response.error.message)
self.fetchAddresses()
self.events.emit(SIGNAL_SAVED_ADDRESS_CHANGED, Args())
self.updateAddresses()
return ""
except Exception as e:
let errDesription = e.msg

View File

@ -28,6 +28,7 @@ type
SavedAddress* = ref object of RootObj
name* {.serializedFieldName("name").}: string
address* {.serializedFieldName("address").}: string
favourite* {.serializedFieldName("favourite").}: bool
Network* = ref object of RootObj
chainId* {.serializedFieldName("chainId").}: int

View File

@ -20,6 +20,7 @@ StatusDialog {
property bool edit: false
property string address
property alias name: nameInput.text
property bool favourite: false
property var contactsStore
signal save(string name, string address)

View File

@ -167,8 +167,8 @@ QtObject {
// walletModelV2Inst.collectiblesView.collections.getCollectionTraitMaxValue(collectionIndex, traitType).toString();
}
function createOrUpdateSavedAddress(name, address) {
return walletSectionSavedAddresses.createOrUpdateSavedAddress(name, address)
function createOrUpdateSavedAddress(name, address, favourite) {
return walletSectionSavedAddresses.createOrUpdateSavedAddress(name, address, favourite)
}
function deleteSavedAddress(address) {

View File

@ -6,6 +6,7 @@ import utils 1.0
import StatusQ.Controls 0.1
import StatusQ.Components 0.1
import StatusQ.Core 0.1
import StatusQ.Core.Utils 0.1
import StatusQ.Core.Theme 0.1
import StatusQ.Popups 0.1
import shared.controls 1.0
@ -26,9 +27,9 @@ Item {
id: _internal
property bool loading: false
property string error: ""
function saveAddress(name, address) {
function saveAddress(name, address, favourite) {
loading = true
error = RootStore.createOrUpdateSavedAddress(name, address)
error = RootStore.createOrUpdateSavedAddress(name, address, favourite)
loading = false
}
function deleteSavedAddress(address) {
@ -106,11 +107,12 @@ Item {
delegate: SavedAddressesDelegate {
name: model.name
address: model.address
favourite: model.favourite
store: RootStore
contactsStore: root.contactsStore
onOpenSendModal: root.sendModal.open(address);
saveAddress: function(name, address) {
_internal.saveAddress(name, address)
saveAddress: function(name, address, favourite) {
_internal.saveAddress(name, address, favourite)
}
deleteSavedAddress: function(address) {
_internal.deleteSavedAddress(address)
@ -126,7 +128,7 @@ Item {
onClosed: destroy()
contactsStore: root.contactsStore
onSave: {
_internal.saveAddress(name, address)
_internal.saveAddress(name, address, favourite)
close()
}
}

View File

@ -6,6 +6,7 @@ import utils 1.0
import StatusQ.Controls 0.1
import StatusQ.Components 0.1
import StatusQ.Core 0.1
import StatusQ.Core.Utils 0.1
import StatusQ.Core.Theme 0.1
import StatusQ.Popups 0.1
import shared.controls 1.0
@ -20,8 +21,11 @@ StatusListItem {
property var contactsStore
property string name
property string address
property var saveAddress: function (name, address) {}
property bool favourite: false
property var saveAddress: function (name, address, favourite) {}
property var deleteSavedAddress: function (address) {}
// TODO: fetch this from status-go
readonly property string ensName: ""
signal openSendModal()
@ -29,11 +33,11 @@ StatusListItem {
title: name
objectName: name
subTitle: name + " \u2022 " + Utils.getElidedCompressedPk(address)
subTitle: (ensName.length > 0 ? ensName + " \u2022 " : "")
+ Utils.elideText(address, 6, 4)
color: "transparent"
border.color: Theme.palette.baseColor5
//TODO uncomment when #6456 is fixed
//titleTextIcon: RootStore.favouriteAddress ? "star-icon" : ""
titleTextIcon: root.favourite ? "star-icon" : ""
statusListItemComponentsSlot.spacing: 0
property bool showButtons: sensor.containsMouse
@ -51,22 +55,21 @@ StatusListItem {
store: root.store
textToCopy: root.address
},
//TODO uncomment when #6456 is fixed
// StatusRoundButton {
// icon.color: root.showButtons ? Theme.palette.directColor1 : Theme.palette.baseColor1
// type: StatusRoundButton.Type.Tertiary
// icon.name: root.favouriteAddress ? "favourite" : "unfavourite"
// onClicked: {
// RootStore.setFavourite();
// }
// },
StatusRoundButton {
icon.color: root.showButtons ? Theme.palette.directColor1 : Theme.palette.baseColor1
type: StatusRoundButton.Type.Tertiary
icon.name: root.favourite ? "unfavourite" : "favourite"
onClicked: {
root.saveAddress(root.name, root.address, !root.favourite)
}
},
StatusRoundButton {
visible: !!root.name
icon.color: root.showButtons ? Theme.palette.directColor1 : Theme.palette.baseColor1
type: StatusRoundButton.Type.Tertiary
icon.name: "more"
onClicked: {
editDeleteMenu.openMenu(root.name, root.address);
editDeleteMenu.openMenu(root.name, root.address, root.favourite);
}
},
StatusRoundButton {
@ -88,14 +91,17 @@ StatusListItem {
id: editDeleteMenu
property string contactName
property string contactAddress
function openMenu(name, address) {
property bool storeFavourite
function openMenu(name, address, favourite) {
contactName = name;
contactAddress = address;
storeFavourite = favourite;
popup();
}
onClosed: {
contactName = "";
contactAddress = "";
storeFavourite = false;
}
StatusMenuItem {
text: qsTr("Edit")
@ -106,7 +112,8 @@ StatusListItem {
{
edit: true,
address: editDeleteMenu.contactAddress,
name: editDeleteMenu.contactName
name: editDeleteMenu.contactName,
favourite: editDeleteMenu.storeFavourite
})
}
}
@ -119,6 +126,7 @@ StatusListItem {
onTriggered: {
deleteAddressConfirm.name = editDeleteMenu.contactName;
deleteAddressConfirm.address = editDeleteMenu.contactAddress;
deleteAddressConfirm.favourite = editDeleteMenu.storeFavourite;
deleteAddressConfirm.open()
}
}
@ -132,7 +140,7 @@ StatusListItem {
onClosed: destroy()
contactsStore: root.contactsStore
onSave: {
root.saveAddress(name, address)
root.saveAddress(name, address, favourite)
close()
}
}
@ -142,6 +150,7 @@ StatusListItem {
id: deleteAddressConfirm
property string address
property string name
property bool favourite
anchors.centerIn: parent
header.title: qsTr("Are you sure?")
header.subTitle: name

View File

@ -21,6 +21,7 @@ StatusDialog {
property bool addAddress: false
property string address
property alias name: nameInput.text
property bool favourite: false
property var contactsStore
signal save(string name, string address)

View File

@ -184,8 +184,8 @@ QtObject {
return walletSectionSavedAddresses.getNameByAddress(address)
}
function createOrUpdateSavedAddress(name, address) {
return walletSectionSavedAddresses.createOrUpdateSavedAddress(name, address)
function createOrUpdateSavedAddress(name, address, favourite) {
return walletSectionSavedAddresses.createOrUpdateSavedAddress(name, address, favourite)
}
function deleteSavedAddress(address) {

View File

@ -100,8 +100,8 @@ Item {
store: RootStore
contactsStore: root.contactsStore
onOpenSendModal: root.sendModal.open(address);
saveAddress: function(name, address) {
RootStore.createOrUpdateSavedAddress(name, address)
saveAddress: function(name, address, favourite) {
RootStore.createOrUpdateSavedAddress(name, address, favourite)
}
deleteSavedAddress: function(address) {
RootStore.deleteSavedAddress(address)

2
vendor/status-go vendored

@ -1 +1 @@
Subproject commit 1485b3b4c808dd875d30f17e4be842fcc44c8d35
Subproject commit 9db69df9a06badd099df462d92375f77fd69ff23