fix: handle bookmarks syncing signals properly
Bookmarks were only synced when devices were synced, but not when bookmarks were added/removed/updated. To account for this, there's are new messenger APIs in status-go proposed here: https://github.com/status-im/status-go/pull/2709 Based on those APIs, desktop can now add/remove/update bookmarks and the changes are automatically synced to other devices in real-time. This commit also ensures that changes from other devices with regards to bookmarks are handled and updated on the current device. Partially addresses #5201
This commit is contained in:
parent
1046d6ab4d
commit
858caeca73
|
@ -153,7 +153,7 @@ proc newAppController*(statusFoundation: StatusFoundation): AppController =
|
||||||
)
|
)
|
||||||
result.transactionService = transaction_service.newService(statusFoundation.events, statusFoundation.threadpool,
|
result.transactionService = transaction_service.newService(statusFoundation.events, statusFoundation.threadpool,
|
||||||
result.walletAccountService, result.networkService, result.settingsService, result.tokenService)
|
result.walletAccountService, result.networkService, result.settingsService, result.tokenService)
|
||||||
result.bookmarkService = bookmark_service.newService()
|
result.bookmarkService = bookmark_service.newService(statusFoundation.events)
|
||||||
result.profileService = profile_service.newService(result.contactsService, result.settingsService)
|
result.profileService = profile_service.newService(result.contactsService, result.settingsService)
|
||||||
result.stickersService = stickers_service.newService(
|
result.stickersService = stickers_service.newService(
|
||||||
statusFoundation.events,
|
statusFoundation.events,
|
||||||
|
|
|
@ -4,12 +4,14 @@ import base
|
||||||
|
|
||||||
import ../../../../app_service/service/message/dto/[message, pinned_message_update, reaction, removed_message]
|
import ../../../../app_service/service/message/dto/[message, pinned_message_update, reaction, removed_message]
|
||||||
import ../../../../app_service/service/chat/dto/[chat]
|
import ../../../../app_service/service/chat/dto/[chat]
|
||||||
|
import ../../../../app_service/service/bookmarks/dto/[bookmark]
|
||||||
import ../../../../app_service/service/community/dto/[community]
|
import ../../../../app_service/service/community/dto/[community]
|
||||||
import ../../../../app_service/service/activity_center/dto/[notification]
|
import ../../../../app_service/service/activity_center/dto/[notification]
|
||||||
import ../../../../app_service/service/contacts/dto/[contacts, status_update]
|
import ../../../../app_service/service/contacts/dto/[contacts, status_update]
|
||||||
import ../../../../app_service/service/devices/dto/[device]
|
import ../../../../app_service/service/devices/dto/[device]
|
||||||
|
|
||||||
type MessageSignal* = ref object of Signal
|
type MessageSignal* = ref object of Signal
|
||||||
|
bookmarks*: seq[BookmarkDto]
|
||||||
messages*: seq[MessageDto]
|
messages*: seq[MessageDto]
|
||||||
pinnedMessages*: seq[PinnedMessageUpdateDto]
|
pinnedMessages*: seq[PinnedMessageUpdateDto]
|
||||||
chats*: seq[ChatDto]
|
chats*: seq[ChatDto]
|
||||||
|
@ -52,6 +54,11 @@ proc fromEvent*(T: type MessageSignal, event: JsonNode): MessageSignal =
|
||||||
var currentStatus = event["event"]["currentStatus"].toStatusUpdateDto()
|
var currentStatus = event["event"]["currentStatus"].toStatusUpdateDto()
|
||||||
signal.currentStatus.add(currentStatus)
|
signal.currentStatus.add(currentStatus)
|
||||||
|
|
||||||
|
if event["event"]{"bookmarks"} != nil:
|
||||||
|
for jsonBookmark in event["event"]["bookmarks"]:
|
||||||
|
var bookmark = jsonBookmark.toBookmarkDto()
|
||||||
|
signal.bookmarks.add(bookmark)
|
||||||
|
|
||||||
if event["event"]{"installations"} != nil:
|
if event["event"]{"installations"} != nil:
|
||||||
for jsonDevice in event["event"]["installations"]:
|
for jsonDevice in event["event"]["installations"]:
|
||||||
signal.devices.add(jsonDevice.toDeviceDto())
|
signal.devices.add(jsonDevice.toDeviceDto())
|
||||||
|
|
|
@ -3,16 +3,20 @@ import result
|
||||||
import io_interface
|
import io_interface
|
||||||
|
|
||||||
import ../../../../../app_service/service/bookmarks/service as bookmark_service
|
import ../../../../../app_service/service/bookmarks/service as bookmark_service
|
||||||
|
import ../../../../core/eventemitter
|
||||||
|
|
||||||
type
|
type
|
||||||
Controller* = ref object of RootObj
|
Controller* = ref object of RootObj
|
||||||
delegate: io_interface.AccessInterface
|
delegate: io_interface.AccessInterface
|
||||||
|
events: EventEmitter
|
||||||
bookmarkService: bookmark_service.Service
|
bookmarkService: bookmark_service.Service
|
||||||
|
|
||||||
proc newController*(delegate: io_interface.AccessInterface,
|
proc newController*(delegate: io_interface.AccessInterface,
|
||||||
|
events: EventEmitter,
|
||||||
bookmarkService: bookmark_service.Service):
|
bookmarkService: bookmark_service.Service):
|
||||||
Controller =
|
Controller =
|
||||||
result = Controller()
|
result = Controller()
|
||||||
|
result.events = events
|
||||||
result.delegate = delegate
|
result.delegate = delegate
|
||||||
result.bookmarkService = bookmarkService
|
result.bookmarkService = bookmarkService
|
||||||
|
|
||||||
|
@ -20,7 +24,17 @@ proc delete*(self: Controller) =
|
||||||
discard
|
discard
|
||||||
|
|
||||||
proc init*(self: Controller) =
|
proc init*(self: Controller) =
|
||||||
discard
|
self.events.on(SIGNAL_BOOKMARK_REMOVED) do(e: Args):
|
||||||
|
let args = BookmarkRemovedArgs(e)
|
||||||
|
self.delegate.onBookmarkDeleted(args.url)
|
||||||
|
|
||||||
|
self.events.on(SIGNAL_BOOKMARK_ADDED) do(e: Args):
|
||||||
|
let args = BookmarkArgs(e)
|
||||||
|
self.delegate.onBoomarkStored(args.bookmark.url, args.bookmark.name, args.bookmark.imageUrl)
|
||||||
|
|
||||||
|
self.events.on(SIGNAL_BOOKMARK_UPDATED) do(e: Args):
|
||||||
|
let args = BookmarkArgs(e)
|
||||||
|
self.delegate.onBookmarkUpdated(args.bookmark.url, args.bookmark.url, args.bookmark.name, args.bookmark.imageUrl)
|
||||||
|
|
||||||
proc getBookmarks*(self: Controller): seq[bookmark_service.BookmarkDto] =
|
proc getBookmarks*(self: Controller): seq[bookmark_service.BookmarkDto] =
|
||||||
return self.bookmarkService.getBookmarks()
|
return self.bookmarkService.getBookmarks()
|
||||||
|
|
|
@ -6,6 +6,7 @@ import view
|
||||||
import controller
|
import controller
|
||||||
import ../../../../global/global_singleton
|
import ../../../../global/global_singleton
|
||||||
import ../../../../../app_service/service/bookmarks/service as bookmark_service
|
import ../../../../../app_service/service/bookmarks/service as bookmark_service
|
||||||
|
import ../../../../core/eventemitter
|
||||||
|
|
||||||
export io_interface
|
export io_interface
|
||||||
|
|
||||||
|
@ -17,13 +18,13 @@ type
|
||||||
moduleLoaded: bool
|
moduleLoaded: bool
|
||||||
controller: Controller
|
controller: Controller
|
||||||
|
|
||||||
proc newModule*(delegate: delegate_interface.AccessInterface, bookmarkService: bookmark_service.Service): Module =
|
proc newModule*(delegate: delegate_interface.AccessInterface, events: EventEmitter, bookmarkService: bookmark_service.Service): Module =
|
||||||
result = Module()
|
result = Module()
|
||||||
result.delegate = delegate
|
result.delegate = delegate
|
||||||
result.view = view.newView(result)
|
result.view = view.newView(result)
|
||||||
result.viewVariant = newQVariant(result.view)
|
result.viewVariant = newQVariant(result.view)
|
||||||
result.moduleLoaded = false
|
result.moduleLoaded = false
|
||||||
result.controller = controller.newController(result, bookmarkService)
|
result.controller = controller.newController(result, events, bookmarkService)
|
||||||
|
|
||||||
method delete*(self: Module) =
|
method delete*(self: Module) =
|
||||||
self.view.delete
|
self.view.delete
|
||||||
|
@ -32,6 +33,7 @@ method delete*(self: Module) =
|
||||||
|
|
||||||
method load*(self: Module) =
|
method load*(self: Module) =
|
||||||
singletonInstance.engine.setRootContextProperty("bookmarkModule", self.viewVariant)
|
singletonInstance.engine.setRootContextProperty("bookmarkModule", self.viewVariant)
|
||||||
|
self.controller.init()
|
||||||
self.view.load()
|
self.view.load()
|
||||||
|
|
||||||
method isLoaded*(self: Module): bool =
|
method isLoaded*(self: Module): bool =
|
||||||
|
|
|
@ -42,7 +42,7 @@ proc newModule*(delegate: delegate_interface.AccessInterface,
|
||||||
result.viewVariant = newQVariant(result.view)
|
result.viewVariant = newQVariant(result.view)
|
||||||
result.moduleLoaded = false
|
result.moduleLoaded = false
|
||||||
result.providerModule = provider_module.newModule(result, events, settingsService, providerService)
|
result.providerModule = provider_module.newModule(result, events, settingsService, providerService)
|
||||||
result.bookmarkModule = bookmark_module.newModule(result, bookmarkService)
|
result.bookmarkModule = bookmark_module.newModule(result, events, bookmarkService)
|
||||||
result.dappsModule = dapps_module.newModule(result, dappPermissionsService, walletAccountService)
|
result.dappsModule = dapps_module.newModule(result, dappPermissionsService, walletAccountService)
|
||||||
result.currentAccountModule = current_account_module.newModule(result, events, walletAccountService)
|
result.currentAccountModule = current_account_module.newModule(result, events, walletAccountService)
|
||||||
|
|
||||||
|
|
|
@ -6,9 +6,13 @@ type BookmarkDto* = object
|
||||||
name*: string
|
name*: string
|
||||||
url*: string
|
url*: string
|
||||||
imageUrl*: string
|
imageUrl*: string
|
||||||
|
removed*: bool
|
||||||
|
deletedAt*: int
|
||||||
|
|
||||||
proc toBookmarkDto*(jsonObj: JsonNode): BookmarkDto =
|
proc toBookmarkDto*(jsonObj: JsonNode): BookmarkDto =
|
||||||
result = BookmarkDto()
|
result = BookmarkDto()
|
||||||
discard jsonObj.getProp("name", result.name)
|
discard jsonObj.getProp("name", result.name)
|
||||||
discard jsonObj.getProp("url", result.url)
|
discard jsonObj.getProp("url", result.url)
|
||||||
discard jsonObj.getProp("imageUrl", result.imageUrl)
|
discard jsonObj.getProp("imageUrl", result.imageUrl)
|
||||||
|
discard jsonObj.getProp("removed", result.removed)
|
||||||
|
discard jsonObj.getProp("deletedAt", result.deletedAt)
|
||||||
|
|
|
@ -1,47 +1,95 @@
|
||||||
import Tables, json, sequtils, strformat, chronicles
|
import Tables, json, sequtils, strformat, chronicles, strutils
|
||||||
import result
|
import result
|
||||||
include ../../common/json_utils
|
include ../../common/json_utils
|
||||||
import ./dto/bookmark as bookmark_dto
|
import ./dto/bookmark as bookmark_dto
|
||||||
|
import ../../../app/core/eventemitter
|
||||||
|
import ../../../app/core/signals/types
|
||||||
import ../../../backend/backend
|
import ../../../backend/backend
|
||||||
|
import ../../../backend/browser
|
||||||
|
|
||||||
export bookmark_dto
|
export bookmark_dto
|
||||||
|
|
||||||
logScope:
|
logScope:
|
||||||
topics = "bookmarks-service"
|
topics = "bookmarks-service"
|
||||||
|
|
||||||
|
const SIGNAL_BOOKMARK_ADDED* = "bookmarkAdded"
|
||||||
|
const SIGNAL_BOOKMARK_REMOVED* = "bookmarkRemoved"
|
||||||
|
const SIGNAL_BOOKMARK_UPDATED* = "bookmarkUpdated"
|
||||||
|
|
||||||
type
|
type
|
||||||
Service* = ref object of RootObj
|
Service* = ref object of RootObj
|
||||||
bookmarks: Table[string, BookmarkDto] # [url, BookmarkDto]
|
bookmarks: Table[string, BookmarkDto] # [url, BookmarkDto]
|
||||||
|
events: EventEmitter
|
||||||
|
|
||||||
type R = Result[BookmarkDto, string]
|
type R = Result[BookmarkDto, string]
|
||||||
|
|
||||||
|
type
|
||||||
|
BookmarkArgs* = ref object of Args
|
||||||
|
bookmark*: BookmarkDto
|
||||||
|
|
||||||
|
type
|
||||||
|
BookmarkRemovedArgs* = ref object of Args
|
||||||
|
url*: string
|
||||||
|
|
||||||
proc delete*(self: Service) =
|
proc delete*(self: Service) =
|
||||||
discard
|
discard
|
||||||
|
|
||||||
proc newService*(): Service =
|
proc newService*(events: EventEmitter): Service =
|
||||||
result = Service()
|
result = Service()
|
||||||
|
result.events = events
|
||||||
result.bookmarks = initTable[string, BookmarkDto]()
|
result.bookmarks = initTable[string, BookmarkDto]()
|
||||||
|
|
||||||
proc init*(self: Service) =
|
proc init*(self: Service) =
|
||||||
try:
|
try:
|
||||||
let response = backend.getBookmarks()
|
let response = backend.getBookmarks()
|
||||||
for bookmark in response.result.getElems().mapIt(it.toBookmarkDto()):
|
for bookmark in response.result.getElems().mapIt(it.toBookmarkDto()):
|
||||||
|
if not bookmark.removed:
|
||||||
self.bookmarks[bookmark.url] = bookmark
|
self.bookmarks[bookmark.url] = bookmark
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
let errDescription = e.msg
|
let errDescription = e.msg
|
||||||
error "error: ", errDescription
|
error "error: ", errDescription
|
||||||
|
|
||||||
|
self.events.on(SignalType.Message.event) do(e: Args):
|
||||||
|
var receivedData = MessageSignal(e)
|
||||||
|
if receivedData.bookmarks.len > 0:
|
||||||
|
for bookmark in receivedData.bookmarks:
|
||||||
|
let url = bookmark.url
|
||||||
|
if bookmark.removed and not self.bookmarks.hasKey(url):
|
||||||
|
return
|
||||||
|
|
||||||
|
if self.bookmarks.hasKey(url) and bookmark.removed:
|
||||||
|
self.bookmarks.del(url)
|
||||||
|
self.events.emit(SIGNAL_BOOKMARK_REMOVED, BookmarkRemovedArgs(url: url))
|
||||||
|
return
|
||||||
|
|
||||||
|
let emitUpdateEvent = self.bookmarks.hasKey(url)
|
||||||
|
|
||||||
|
self.bookmarks[url] = BookmarkDto()
|
||||||
|
self.bookmarks[url].url = bookmark.url
|
||||||
|
self.bookmarks[url].name = bookmark.name
|
||||||
|
self.bookmarks[url].imageUrl = bookmark.imageUrl
|
||||||
|
self.bookmarks[url].removed = bookmark.removed
|
||||||
|
|
||||||
|
if emitUpdateEvent:
|
||||||
|
self.events.emit(SIGNAL_BOOKMARK_UPDATED, BookmarkArgs(bookmark: self.bookmarks[url]))
|
||||||
|
return
|
||||||
|
|
||||||
|
self.events.emit(SIGNAL_BOOKMARK_ADDED, BookmarkArgs(bookmark: self.bookmarks[url]))
|
||||||
|
|
||||||
proc getBookmarks*(self: Service): seq[BookmarkDto] =
|
proc getBookmarks*(self: Service): seq[BookmarkDto] =
|
||||||
return toSeq(self.bookmarks.values)
|
return toSeq(self.bookmarks.values)
|
||||||
|
|
||||||
proc storeBookmark*(self: Service, url, name: string): R =
|
proc storeBookmark*(self: Service, url, name: string): R =
|
||||||
try:
|
try:
|
||||||
let response = backend.storeBookmark(backend.Bookmark(name: name, url: url)).result
|
if not url.isEmptyOrWhitespace:
|
||||||
|
let response = browser.addBookmark(backend.Bookmark(name: name, url: url)).result
|
||||||
self.bookmarks[url] = BookmarkDto()
|
self.bookmarks[url] = BookmarkDto()
|
||||||
self.bookmarks[url].url = url
|
self.bookmarks[url].url = url
|
||||||
self.bookmarks[url].name = name
|
self.bookmarks[url].name = name
|
||||||
discard response.getProp("imageUrl", self.bookmarks[url].imageUrl)
|
discard response.getProp("imageUrl", self.bookmarks[url].imageUrl)
|
||||||
|
discard response.getProp("removed", self.bookmarks[url].removed)
|
||||||
|
discard response.getProp("deletedAt", self.bookmarks[url].deletedAt)
|
||||||
result.ok self.bookmarks[url]
|
result.ok self.bookmarks[url]
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
let errDescription = e.msg
|
let errDescription = e.msg
|
||||||
|
@ -52,7 +100,7 @@ proc deleteBookmark*(self: Service, url: string): bool =
|
||||||
try:
|
try:
|
||||||
if not self.bookmarks.hasKey(url):
|
if not self.bookmarks.hasKey(url):
|
||||||
return
|
return
|
||||||
discard backend.deleteBookmark(url)
|
discard browser.removeBookmark(url).result
|
||||||
self.bookmarks.del(url)
|
self.bookmarks.del(url)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
let errDescription = e.msg
|
let errDescription = e.msg
|
||||||
|
@ -65,12 +113,14 @@ proc updateBookmark*(self: Service, oldUrl, newUrl, newName: string): R =
|
||||||
if not self.bookmarks.hasKey(oldUrl):
|
if not self.bookmarks.hasKey(oldUrl):
|
||||||
return
|
return
|
||||||
|
|
||||||
let response = backend.updateBookmark(oldUrl, backend.Bookmark(name: newName, url: newUrl)).result
|
let response = browser.updateBookmark(oldUrl, backend.Bookmark(name: newName, url: newUrl)).result
|
||||||
self.bookmarks.del(oldUrl)
|
self.bookmarks.del(oldUrl)
|
||||||
self.bookmarks[newUrl] = BookmarkDto()
|
self.bookmarks[newUrl] = BookmarkDto()
|
||||||
self.bookmarks[newUrl].url = newUrl
|
self.bookmarks[newUrl].url = newUrl
|
||||||
self.bookmarks[newUrl].name = newName
|
self.bookmarks[newUrl].name = newName
|
||||||
discard response.getProp("imageUrl", self.bookmarks[newurl].imageUrl)
|
discard response.getProp("imageUrl", self.bookmarks[newurl].imageUrl)
|
||||||
|
discard response.getProp("removed", self.bookmarks[newurl].removed)
|
||||||
|
discard response.getProp("deletedAt", self.bookmarks[newurl].deletedAt)
|
||||||
result.ok self.bookmarks[newUrl]
|
result.ok self.bookmarks[newUrl]
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
let errDescription = e.msg
|
let errDescription = e.msg
|
||||||
|
|
|
@ -16,6 +16,9 @@ type
|
||||||
Bookmark* = ref object of RootObj
|
Bookmark* = ref object of RootObj
|
||||||
name* {.serializedFieldName("name").}: string
|
name* {.serializedFieldName("name").}: string
|
||||||
url* {.serializedFieldName("url").}: string
|
url* {.serializedFieldName("url").}: string
|
||||||
|
imageUrl* {.serializedFieldName("imageUrl").}: string
|
||||||
|
removed* {.serializedFieldName("removed").}: bool
|
||||||
|
deletedAt* {.serializedFieldName("deletedAt").}: int
|
||||||
|
|
||||||
Permission* = ref object of RootObj
|
Permission* = ref object of RootObj
|
||||||
dapp* {.serializedFieldName("dapp").}: string
|
dapp* {.serializedFieldName("dapp").}: string
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
import json, strutils
|
||||||
|
import core, utils
|
||||||
|
import response_type
|
||||||
|
import ./backend
|
||||||
|
|
||||||
|
export response_type
|
||||||
|
|
||||||
|
|
||||||
|
proc addBookmark*(bookmark: backend.Bookmark): RpcResponse[JsonNode] {.raises: [Exception].} =
|
||||||
|
result = callPrivateRPC("addBookmark".prefix, %*[{
|
||||||
|
"url": bookmark.url,
|
||||||
|
"name": bookmark.name,
|
||||||
|
"imageUrl": bookmark.imageUrl,
|
||||||
|
"removed": bookmark.removed,
|
||||||
|
"deletedAt": bookmark.deletedAt
|
||||||
|
}])
|
||||||
|
|
||||||
|
proc removeBookmark*(url: string): RpcResponse[JsonNode] {.raises: [Exception].} =
|
||||||
|
result = callPrivateRPC("removeBookmark".prefix, %*[url])
|
||||||
|
|
||||||
|
proc updateBookmark*(oldUrl: string, bookmark: backend.Bookmark): RpcResponse[JsonNode] {.raises: [Exception].} =
|
||||||
|
result = callPrivateRPC("updateBookmark".prefix, %*[oldUrl, {
|
||||||
|
"url": bookmark.url,
|
||||||
|
"name": bookmark.name,
|
||||||
|
"imageUrl": bookmark.imageUrl,
|
||||||
|
"removed": bookmark.removed,
|
||||||
|
"deletedAt": bookmark.deletedAt
|
||||||
|
}])
|
|
@ -1 +1 @@
|
||||||
Subproject commit 961526556b98feec3a1584d93fbde6ac62fcb9ed
|
Subproject commit 4f722b6fe8215fa02f54e02cb454b402e1728c8f
|
Loading…
Reference in New Issue