refactor: move stickers to own model

Remove from ChatModel and add StickerModel
This commit is contained in:
emizzle 2020-09-09 13:25:08 +10:00 committed by Iuri Matias
parent 68aafaba6f
commit 4f0cdad8c7
7 changed files with 156 additions and 115 deletions

View File

@ -36,11 +36,12 @@ proc init*(self: ChatController) =
self.status.mailservers.init() self.status.mailservers.init()
self.status.chat.init() self.status.chat.init()
self.status.stickers.init()
self.view.obtainAvailableStickerPacks() self.view.obtainAvailableStickerPacks()
let pubKey = status_settings.getSetting[string](Setting.PublicKey, "0x0") let pubKey = status_settings.getSetting[string](Setting.PublicKey, "0x0")
self.view.pubKey = pubKey self.view.pubKey = pubKey
let recentStickers = self.status.chat.getRecentStickers() let recentStickers = self.status.stickers.getRecentStickers()
for sticker in recentStickers: for sticker in recentStickers:
self.view.addRecentStickerToList(sticker) self.view.addRecentStickerToList(sticker)
self.status.chat.addStickerToRecent(sticker) self.status.stickers.addStickerToRecent(sticker)

View File

@ -1,12 +1,14 @@
import NimQml, Tables, json, sequtils, chronicles, times, re, sugar, strutils, os, strformat import NimQml, Tables, json, sequtils, chronicles, times, re, sugar, strutils, os, strformat
import ../../status/status import ../../status/status
import ../../status/mailservers import ../../status/mailservers
import ../../status/stickers
import ../../status/libstatus/accounts/constants import ../../status/libstatus/accounts/constants
import ../../status/libstatus/mailservers as status_mailservers import ../../status/libstatus/mailservers as status_mailservers
import ../../status/accounts as status_accounts import ../../status/accounts as status_accounts
import ../../status/chat as status_chat import ../../status/chat as status_chat
import ../../status/messages as status_messages import ../../status/messages as status_messages
import ../../status/libstatus/wallet as status_wallet import ../../status/libstatus/wallet as status_wallet
import ../../status/libstatus/stickers as status_stickers
import ../../status/contacts as status_contacts import ../../status/contacts as status_contacts
import ../../status/ens as status_ens import ../../status/ens as status_ens
import ../../status/chat/[chat, message] import ../../status/chat/[chat, message]
@ -98,26 +100,26 @@ QtObject:
read = getStickerPackList read = getStickerPackList
proc getStickerMarketAddress(self: ChatsView): QVariant {.slot.} = proc getStickerMarketAddress(self: ChatsView): QVariant {.slot.} =
newQVariant($self.status.chat.getStickerMarketAddress) newQVariant($self.status.stickers.getStickerMarketAddress)
QtProperty[QVariant] stickerMarketAddress: QtProperty[QVariant] stickerMarketAddress:
read = getStickerMarketAddress read = getStickerMarketAddress
proc getStickerBuyPackGasEstimate*(self: ChatsView, packId: int, address: string, price: string): string {.slot.} = proc getStickerBuyPackGasEstimate*(self: ChatsView, packId: int, address: string, price: string): string {.slot.} =
try: try:
result = self.status.chat.buyPackGasEstimate(packId, address, price) result = self.status.stickers.buyPackGasEstimate(packId, address, price)
except: except:
result = "400000" result = "400000"
proc buyStickerPack*(self: ChatsView, packId: int, address: string, price: string, gas: string, gasPrice: string, password: string): string {.slot.} = proc buyStickerPack*(self: ChatsView, packId: int, address: string, price: string, gas: string, gasPrice: string, password: string): string {.slot.} =
try: try:
result = $(%self.status.chat.buyStickerPack(packId, address, price, gas, gasPrice, password)) result = $(%self.status.stickers.buyStickerPack(packId, address, price, gas, gasPrice, password))
except RpcException as e: except RpcException as e:
result = fmt"""{{ "error": {{ "message": "{e.msg}" }} }}""" result = fmt"""{{ "error": {{ "message": "{e.msg}" }} }}"""
proc obtainAvailableStickerPacks*(self: ChatsView) = proc obtainAvailableStickerPacks*(self: ChatsView) =
spawnAndSend(self, "setAvailableStickerPacks") do: spawnAndSend(self, "setAvailableStickerPacks") do:
let availableStickerPacks = status_chat.getAvailableStickerPacks() let availableStickerPacks = status_stickers.getAvailableStickerPacks()
var packs: seq[StickerPack] = @[] var packs: seq[StickerPack] = @[]
for packId, stickerPack in availableStickerPacks.pairs: for packId, stickerPack in availableStickerPacks.pairs:
packs.add(stickerPack) packs.add(stickerPack)
@ -126,14 +128,14 @@ QtObject:
proc setAvailableStickerPacks*(self: ChatsView, availableStickersJSON: string) {.slot.} = proc setAvailableStickerPacks*(self: ChatsView, availableStickersJSON: string) {.slot.} =
let currAcct = status_wallet.getWalletAccounts()[0] # TODO: make generic let currAcct = status_wallet.getWalletAccounts()[0] # TODO: make generic
let currAddr = parseAddress(currAcct.address) let currAddr = parseAddress(currAcct.address)
let installedStickerPacks = self.status.chat.getInstalledStickerPacks() let installedStickerPacks = self.status.stickers.getInstalledStickerPacks()
let purchasedStickerPacks = self.status.chat.getPurchasedStickerPacks(currAddr) let purchasedStickerPacks = self.status.stickers.getPurchasedStickerPacks(currAddr)
let availableStickers = JSON.decode($availableStickersJSON, seq[StickerPack]) let availableStickers = JSON.decode($availableStickersJSON, seq[StickerPack])
for stickerPack in availableStickers: for stickerPack in availableStickers:
let isInstalled = installedStickerPacks.hasKey(stickerPack.id) let isInstalled = installedStickerPacks.hasKey(stickerPack.id)
let isBought = purchasedStickerPacks.contains(stickerPack.id) let isBought = purchasedStickerPacks.contains(stickerPack.id)
self.status.chat.availableStickerPacks[stickerPack.id] = stickerPack self.status.stickers.availableStickerPacks[stickerPack.id] = stickerPack
self.addStickerPackToList(stickerPack, isInstalled, isBought) self.addStickerPackToList(stickerPack, isInstalled, isBought)
proc getChatsList(self: ChatsView): QVariant {.slot.} = proc getChatsList(self: ChatsView): QVariant {.slot.} =
@ -244,12 +246,12 @@ QtObject:
notify = activeChannelChanged notify = activeChannelChanged
proc installStickerPack*(self: ChatsView, packId: int) {.slot.} = proc installStickerPack*(self: ChatsView, packId: int) {.slot.} =
self.status.chat.installStickerPack(packId) self.status.stickers.installStickerPack(packId)
self.stickerPacks.updateStickerPackInList(packId, true) self.stickerPacks.updateStickerPackInList(packId, true)
proc uninstallStickerPack*(self: ChatsView, packId: int) {.slot.} = proc uninstallStickerPack*(self: ChatsView, packId: int) {.slot.} =
self.status.chat.uninstallStickerPack(packId) self.status.stickers.uninstallStickerPack(packId)
self.status.chat.removeRecentStickers(packId) self.status.stickers.removeRecentStickers(packId)
self.stickerPacks.updateStickerPackInList(packId, false) self.stickerPacks.updateStickerPackInList(packId, false)
self.recentStickers.removeStickersFromList(packId) self.recentStickers.removeStickersFromList(packId)

View File

@ -3,17 +3,13 @@ import libstatus/contracts as status_contracts
import libstatus/chat as status_chat import libstatus/chat as status_chat
import libstatus/mailservers as status_mailservers import libstatus/mailservers as status_mailservers
import libstatus/chatCommands as status_chat_commands import libstatus/chatCommands as status_chat_commands
import libstatus/stickers as status_stickers
import libstatus/accounts/constants as constants import libstatus/accounts/constants as constants
import libstatus/types import libstatus/types
import mailservers import mailservers, stickers
import profile/profile import profile/profile
import chat/[chat, message] import chat/[chat, message]
import signals/messages import signals/messages
import ens import ens
import eth/common/eth_types
from eth/common/utils import parseAddress
from libstatus/utils as libstatus_utils import eth2Wei, gwei2Wei, toUInt64
logScope: logScope:
topics = "chat-model" topics = "chat-model"
@ -49,10 +45,6 @@ type
channels*: Table[string, Chat] channels*: Table[string, Chat]
msgCursor*: Table[string, string] msgCursor*: Table[string, string]
emojiCursor*: Table[string, string] emojiCursor*: Table[string, string]
recentStickers*: seq[Sticker]
availableStickerPacks*: Table[int, StickerPack]
installedStickerPacks*: Table[int, StickerPack]
purchasedStickerPacks*: seq[int]
lastMessageTimestamps*: Table[string, int64] lastMessageTimestamps*: Table[string, int64]
MessageArgs* = ref object of Args MessageArgs* = ref object of Args
@ -68,13 +60,8 @@ proc newChatModel*(events: EventEmitter): ChatModel =
result.channels = initTable[string, Chat]() result.channels = initTable[string, Chat]()
result.msgCursor = initTable[string, string]() result.msgCursor = initTable[string, string]()
result.emojiCursor = initTable[string, string]() result.emojiCursor = initTable[string, string]()
result.recentStickers = @[]
result.availableStickerPacks = initTable[int, StickerPack]()
result.installedStickerPacks = initTable[int, StickerPack]()
result.purchasedStickerPacks = @[]
result.lastMessageTimestamps = initTable[string, int64]() result.lastMessageTimestamps = initTable[string, int64]()
proc delete*(self: ChatModel) = proc delete*(self: ChatModel) =
discard discard
@ -127,84 +114,6 @@ proc join*(self: ChatModel, chatId: string, chatType: ChatType) =
self.events.emit("channelJoined", ChannelArgs(chat: chat)) self.events.emit("channelJoined", ChannelArgs(chat: chat))
# TODO: Replace this with a more generalised way of estimating gas so can be used for token transfers
proc buyPackGasEstimate*(self: ChatModel, packId: int, address: string, price: string): string =
let
priceTyped = eth2Wei(parseFloat(price), 18) # SNT
hexGas = status_stickers.buyPackGasEstimate(packId.u256, parseAddress(address), priceTyped)
result = $fromHex[int](hexGas)
proc getStickerMarketAddress*(self: ChatModel): EthAddress =
result = status_contracts.getContract("sticker-market").address
proc buyStickerPack*(self: ChatModel, packId: int, address, price, gas, gasPrice, password: string): RpcResponse =
try:
let
addressTyped = parseAddress(address)
priceTyped = eth2Wei(parseFloat(price), 18) # SNT
gasTyped = cast[uint64](parseFloat(gas).toUInt64)
gasPriceTyped = gwei2Wei(parseFloat(gasPrice)).truncate(int)
result = status_stickers.buyPack(packId.u256, addressTyped, priceTyped, gasTyped, gasPriceTyped, password)
except RpcException as e:
raise
proc getPurchasedStickerPacks*(self: ChatModel, address: EthAddress): seq[int] =
if self.purchasedStickerPacks != @[]:
return self.purchasedStickerPacks
try:
var
balance = status_stickers.getBalance(address)
tokenIds = toSeq[0..<balance].map(idx => status_stickers.tokenOfOwnerByIndex(address, idx.u256))
self.purchasedStickerPacks = tokenIds.map(tokenId => status_stickers.getPackIdFromTokenId(tokenId.u256))
result = self.purchasedStickerPacks
except RpcException:
error "Error getting purchased sticker packs", message = getCurrentExceptionMsg()
result = @[]
proc getInstalledStickerPacks*(self: ChatModel): Table[int, StickerPack] =
if self.installedStickerPacks != initTable[int, StickerPack]():
return self.installedStickerPacks
self.installedStickerPacks = status_stickers.getInstalledStickerPacks()
result = self.installedStickerPacks
proc getAvailableStickerPacks*(): Table[int, StickerPack] =
var availableStickerPacks = initTable[int, StickerPack]()
try:
let numPacks = status_stickers.getPackCount()
for i in 0..<numPacks:
try:
let stickerPack = status_stickers.getPackData(i.u256)
availableStickerPacks[stickerPack.id] = stickerPack
except:
continue
result = availableStickerPacks
except RpcException:
error "Error in getAvailableStickerPacks", message = getCurrentExceptionMsg()
result = initTable[int, StickerPack]()
proc getRecentStickers*(self: ChatModel): seq[Sticker] =
result = status_stickers.getRecentStickers()
proc installStickerPack*(self: ChatModel, packId: int) =
if not self.availableStickerPacks.hasKey(packId):
return
let pack = self.availableStickerPacks[packId]
self.installedStickerPacks[packId] = pack
status_stickers.saveInstalledStickerPacks(self.installedStickerPacks)
proc removeRecentStickers*(self: ChatModel, packId: int) =
self.recentStickers.keepItIf(it.packId != packId)
status_stickers.saveRecentStickers(self.recentStickers)
proc uninstallStickerPack*(self: ChatModel, packId: int) =
if not self.installedStickerPacks.hasKey(packId):
return
let pack = self.availableStickerPacks[packId]
self.installedStickerPacks.del(packId)
status_stickers.saveInstalledStickerPacks(self.installedStickerPacks)
proc init*(self: ChatModel) = proc init*(self: ChatModel) =
let chatList = status_chat.loadChats() let chatList = status_chat.loadChats()
@ -263,7 +172,6 @@ proc clearHistory*(self: ChatModel, chatId: string) =
let chat = self.channels[chatId] let chat = self.channels[chatId]
self.events.emit("chatHistoryCleared", ChannelArgs(chat: chat)) self.events.emit("chatHistoryCleared", ChannelArgs(chat: chat))
proc setActiveChannel*(self: ChatModel, chatId: string) = proc setActiveChannel*(self: ChatModel, chatId: string) =
self.events.emit("activeChannelChanged", ChatIdArg(chatId: chatId)) self.events.emit("activeChannelChanged", ChatIdArg(chatId: chatId))
@ -282,17 +190,9 @@ proc sendImage*(self: ChatModel, chatId: string, image: string) =
var response = status_chat.sendImageMessage(chatId, image) var response = status_chat.sendImageMessage(chatId, image)
discard self.processMessageUpdateAfterSend(response) discard self.processMessageUpdateAfterSend(response)
proc addStickerToRecent*(self: ChatModel, sticker: Sticker, save: bool = false) =
self.recentStickers.insert(sticker, 0)
self.recentStickers = self.recentStickers.deduplicate()
if self.recentStickers.len > 24:
self.recentStickers = self.recentStickers[0..23] # take top 24 most recent
if save:
status_stickers.saveRecentStickers(self.recentStickers)
proc sendSticker*(self: ChatModel, chatId: string, sticker: Sticker) = proc sendSticker*(self: ChatModel, chatId: string, sticker: Sticker) =
var response = status_chat.sendStickerMessage(chatId, sticker) var response = status_chat.sendStickerMessage(chatId, sticker)
self.addStickerToRecent(sticker, save = true) self.events.emit("stickerSent", StickerArgs(sticker: sticker, save: true))
var (chats, messages) = self.processChatUpdate(parseJson(response)) var (chats, messages) = self.processChatUpdate(parseJson(response))
self.events.emit("chatUpdate", ChatUpdateArgs(messages: messages, chats: chats, contacts: @[])) self.events.emit("chatUpdate", ChatUpdateArgs(messages: messages, chats: chats, contacts: @[]))
self.events.emit("sendingMessage", MessageArgs(id: messages[0].id, channel: messages[0].chatId)) self.events.emit("sendingMessage", MessageArgs(id: messages[0].id, channel: messages[0].chatId))

View File

@ -231,3 +231,18 @@ proc getRecentStickers*(): seq[Sticker] =
# stickers are re-reversed when added to the view due to the nature of # stickers are re-reversed when added to the view due to the nature of
# inserting recent stickers at the front of the list # inserting recent stickers at the front of the list
result.insert(Sticker(hash: $hash, packId: packId), 0) result.insert(Sticker(hash: $hash, packId: packId), 0)
proc getAvailableStickerPacks*(): Table[int, StickerPack] =
var availableStickerPacks = initTable[int, StickerPack]()
try:
let numPacks = getPackCount()
for i in 0..<numPacks:
try:
let stickerPack = getPackData(i.u256)
availableStickerPacks[stickerPack.id] = stickerPack
except:
continue
result = availableStickerPacks
except RpcException:
error "Error in getAvailableStickerPacks", message = getCurrentExceptionMsg()
result = initTable[int, StickerPack]()

View File

@ -14,6 +14,9 @@ import messages as messages
import contacts as contacts import contacts as contacts
import profile import profile
import network as network import network as network
import stickers
export stickers
type Status* = ref object type Status* = ref object
events*: EventEmitter events*: EventEmitter
@ -26,6 +29,7 @@ type Status* = ref object
profile*: ProfileModel profile*: ProfileModel
contacts*: ContactModel contacts*: ContactModel
network*: NetworkModel network*: NetworkModel
stickers*: StickersModel
proc newStatusInstance*(): Status = proc newStatusInstance*(): Status =
result = Status() result = Status()
@ -40,6 +44,7 @@ proc newStatusInstance*(): Status =
result.profile = profile.newProfileModel() result.profile = profile.newProfileModel()
result.contacts = contacts.newContactModel(result.events) result.contacts = contacts.newContactModel(result.events)
result.network = network.newNetworkModel(result.events) result.network = network.newNetworkModel(result.events)
result.stickers = stickers.newStickersModel(result.events)
proc initNode*(self: Status) = proc initNode*(self: Status) =
libstatus_accounts.initNode() libstatus_accounts.initNode()

118
src/status/stickers.nim Normal file
View File

@ -0,0 +1,118 @@
import
tables, strutils, sequtils, sugar
import
chronicles, eth/common/eth_types, eventemitter
from eth/common/utils import parseAddress
import
libstatus/types, libstatus/stickers as status_stickers,
libstatus/contracts as status_contracts
from libstatus/utils as libstatus_utils import eth2Wei, gwei2Wei, toUInt64
logScope:
topics = "stickers-model"
type
StickersModel* = ref object
events*: EventEmitter
recentStickers*: seq[Sticker]
availableStickerPacks*: Table[int, StickerPack]
installedStickerPacks*: Table[int, StickerPack]
purchasedStickerPacks*: seq[int]
StickerArgs* = ref object of Args
sticker*: Sticker
save*: bool
# forward declaration
proc addStickerToRecent*(self: StickersModel, sticker: Sticker, save: bool = false)
proc newStickersModel*(events: EventEmitter): StickersModel =
result = StickersModel()
result.events = events
result.recentStickers = @[]
result.availableStickerPacks = initTable[int, StickerPack]()
result.installedStickerPacks = initTable[int, StickerPack]()
result.purchasedStickerPacks = @[]
proc init*(self: StickersModel) =
self.events.on("stickerSent") do(e: Args):
var evArgs = StickerArgs(e)
self.addStickerToRecent(evArgs.sticker, evArgs.save)
# TODO: Replace this with a more generalised way of estimating gas so can be used for token transfers
proc buyPackGasEstimate*(self: StickersModel, packId: int, address: string, price: string): string =
let
priceTyped = eth2Wei(parseFloat(price), 18) # SNT
hexGas = status_stickers.buyPackGasEstimate(packId.u256, parseAddress(address), priceTyped)
result = $fromHex[int](hexGas)
proc getStickerMarketAddress*(self: StickersModel): EthAddress =
result = status_contracts.getContract("sticker-market").address
proc buyStickerPack*(self: StickersModel, packId: int, address, price, gas, gasPrice, password: string): RpcResponse =
try:
let
addressTyped = parseAddress(address)
priceTyped = eth2Wei(parseFloat(price), 18) # SNT
gasTyped = cast[uint64](parseFloat(gas).toUInt64)
gasPriceTyped = gwei2Wei(parseFloat(gasPrice)).truncate(int)
result = status_stickers.buyPack(packId.u256, addressTyped, priceTyped, gasTyped, gasPriceTyped, password)
except RpcException as e:
raise
proc getPurchasedStickerPacks*(self: StickersModel, address: EthAddress): seq[int] =
if self.purchasedStickerPacks != @[]:
return self.purchasedStickerPacks
try:
var
balance = status_stickers.getBalance(address)
tokenIds = toSeq[0..<balance].map(idx => status_stickers.tokenOfOwnerByIndex(address, idx.u256))
self.purchasedStickerPacks = tokenIds.map(tokenId => status_stickers.getPackIdFromTokenId(tokenId.u256))
result = self.purchasedStickerPacks
except RpcException:
error "Error getting purchased sticker packs", message = getCurrentExceptionMsg()
result = @[]
proc getInstalledStickerPacks*(self: StickersModel): Table[int, StickerPack] =
if self.installedStickerPacks != initTable[int, StickerPack]():
return self.installedStickerPacks
self.installedStickerPacks = status_stickers.getInstalledStickerPacks()
result = self.installedStickerPacks
proc getAvailableStickerPacks*(self: StickersModel): Table[int, StickerPack] = status_stickers.getAvailableStickerPacks()
proc getRecentStickers*(self: StickersModel): seq[Sticker] =
result = status_stickers.getRecentStickers()
proc installStickerPack*(self: StickersModel, packId: int) =
if not self.availableStickerPacks.hasKey(packId):
return
let pack = self.availableStickerPacks[packId]
self.installedStickerPacks[packId] = pack
status_stickers.saveInstalledStickerPacks(self.installedStickerPacks)
proc removeRecentStickers*(self: StickersModel, packId: int) =
self.recentStickers.keepItIf(it.packId != packId)
status_stickers.saveRecentStickers(self.recentStickers)
proc uninstallStickerPack*(self: StickersModel, packId: int) =
if not self.installedStickerPacks.hasKey(packId):
return
let pack = self.availableStickerPacks[packId]
self.installedStickerPacks.del(packId)
status_stickers.saveInstalledStickerPacks(self.installedStickerPacks)
proc addStickerToRecent*(self: StickersModel, sticker: Sticker, save: bool = false) =
self.recentStickers.insert(sticker, 0)
self.recentStickers = self.recentStickers.deduplicate()
if self.recentStickers.len > 24:
self.recentStickers = self.recentStickers[0..23] # take top 24 most recent
if save:
status_stickers.saveRecentStickers(self.recentStickers)

View File

@ -198,7 +198,7 @@ proc getStickers*(address: EthAddress): string =
if (purchasedStickerPacks.len == 0): if (purchasedStickerPacks.len == 0):
return $(%*stickers) return $(%*stickers)
# TODO find a way to keep those in memory so as not to reload it each time # TODO find a way to keep those in memory so as not to reload it each time
let availableStickerPacks = status_chat.getAvailableStickerPacks() let availableStickerPacks = status_stickers.getAvailableStickerPacks()
var index = 0 var index = 0
for stickerId in purchasedStickerPacks: for stickerId in purchasedStickerPacks: