feat: add basic bookmark support
This commit is contained in:
parent
ba06d46d68
commit
a13f1f2043
|
@ -0,0 +1,26 @@
|
||||||
|
import NimQml, chronicles
|
||||||
|
import ../../status/status
|
||||||
|
import ../../status/libstatus/types as status_types
|
||||||
|
import view
|
||||||
|
|
||||||
|
logScope:
|
||||||
|
topics = "browser"
|
||||||
|
|
||||||
|
type BrowserController* = ref object
|
||||||
|
status*: Status
|
||||||
|
view*: BrowserView
|
||||||
|
variant*: QVariant
|
||||||
|
|
||||||
|
proc newController*(status: Status): BrowserController =
|
||||||
|
result = BrowserController()
|
||||||
|
result.status = status
|
||||||
|
result.view = newBrowserView(status)
|
||||||
|
result.variant = newQVariant(result.view)
|
||||||
|
|
||||||
|
proc delete*(self: BrowserController) =
|
||||||
|
delete self.variant
|
||||||
|
delete self.view
|
||||||
|
|
||||||
|
proc init*(self: BrowserController) =
|
||||||
|
self.view.init()
|
||||||
|
discard
|
|
@ -0,0 +1,44 @@
|
||||||
|
import NimQml, json, chronicles
|
||||||
|
import ../../status/status
|
||||||
|
import ../../status/libstatus/types as status_types
|
||||||
|
import ../../status/libstatus/settings as status_settings
|
||||||
|
import views/bookmark_list
|
||||||
|
|
||||||
|
QtObject:
|
||||||
|
type BrowserView* = ref object of QObject
|
||||||
|
status*: Status
|
||||||
|
bookmarks*: BookmarkList
|
||||||
|
|
||||||
|
proc setup(self: BrowserView) =
|
||||||
|
self.QObject.setup
|
||||||
|
|
||||||
|
proc delete(self: BrowserView) =
|
||||||
|
self.QObject.delete
|
||||||
|
self.bookmarks.delete
|
||||||
|
|
||||||
|
proc newBrowserView*(status: Status): BrowserView =
|
||||||
|
new(result, delete)
|
||||||
|
result.bookmarks = newBookmarkList()
|
||||||
|
result.status = status
|
||||||
|
result.setup
|
||||||
|
|
||||||
|
proc init*(self: BrowserView) =
|
||||||
|
var bookmarks: seq[Bookmark] = @[]
|
||||||
|
try:
|
||||||
|
let bookmarksJSON = status_settings.getSetting[string](Setting.Bookmarks, "[]").parseJson
|
||||||
|
for bookmark in bookmarksJSON:
|
||||||
|
bookmarks.add(Bookmark(url: bookmark["url"].getStr, name: bookmark["name"].getStr, image: ""))
|
||||||
|
except:
|
||||||
|
# Bad JSON. Just use the empty array
|
||||||
|
discard
|
||||||
|
self.bookmarks.setNewData(bookmarks)
|
||||||
|
|
||||||
|
proc getBookmarks*(self: BrowserView): QVariant {.slot.} =
|
||||||
|
return newQVariant(self.bookmarks)
|
||||||
|
|
||||||
|
QtProperty[QVariant] bookmarks:
|
||||||
|
read = getBookmarks
|
||||||
|
|
||||||
|
proc addBookmark*(self: BrowserView, url: string, name: string) {.slot.} =
|
||||||
|
self.bookmarks.addBookmarkItemToList(Bookmark(url: url, name: name, image: ""))
|
||||||
|
discard status_settings.saveSetting(Setting.Bookmarks, $(%self.bookmarks.bookmarks))
|
|
@ -0,0 +1,78 @@
|
||||||
|
import NimQml, Tables
|
||||||
|
import sequtils as sequtils
|
||||||
|
|
||||||
|
|
||||||
|
type Bookmark* = ref object
|
||||||
|
name*: string
|
||||||
|
url*: string
|
||||||
|
image*: string
|
||||||
|
|
||||||
|
type
|
||||||
|
BookmarkRoles {.pure.} = enum
|
||||||
|
Name = UserRole + 1,
|
||||||
|
Url = UserRole + 2
|
||||||
|
Image = UserRole + 3
|
||||||
|
|
||||||
|
QtObject:
|
||||||
|
type
|
||||||
|
BookmarkList* = ref object of QAbstractListModel
|
||||||
|
bookmarks*: seq[Bookmark]
|
||||||
|
|
||||||
|
proc setup(self: BookmarkList) = self.QAbstractListModel.setup
|
||||||
|
|
||||||
|
proc delete(self: BookmarkList) =
|
||||||
|
self.bookmarks = @[]
|
||||||
|
self.QAbstractListModel.delete
|
||||||
|
|
||||||
|
proc newBookmarkList*(): BookmarkList =
|
||||||
|
new(result, delete)
|
||||||
|
result.bookmarks = @[]
|
||||||
|
result.setup
|
||||||
|
|
||||||
|
|
||||||
|
method rowCount*(self: BookmarkList, index: QModelIndex = nil): int = self.bookmarks.len
|
||||||
|
|
||||||
|
method data(self: BookmarkList, index: QModelIndex, role: int): QVariant =
|
||||||
|
if not index.isValid:
|
||||||
|
return
|
||||||
|
if index.row < 0 or index.row >= self.bookmarks.len:
|
||||||
|
return
|
||||||
|
|
||||||
|
let bookmarkItem = self.bookmarks[index.row]
|
||||||
|
|
||||||
|
let bookmarkItemRole = role.BookmarkRoles
|
||||||
|
case bookmarkItemRole:
|
||||||
|
of BookmarkRoles.Name: result = newQVariant(bookmarkItem.name)
|
||||||
|
of BookmarkRoles.Url: result = newQVariant(bookmarkItem.url)
|
||||||
|
of BookmarkRoles.Image: result = newQVariant(bookmarkItem.image)
|
||||||
|
|
||||||
|
method roleNames(self: BookmarkList): Table[int, string] =
|
||||||
|
{
|
||||||
|
BookmarkRoles.Name.int:"name",
|
||||||
|
BookmarkRoles.Url.int:"url",
|
||||||
|
BookmarkRoles.Image.int: "image",
|
||||||
|
}.toTable
|
||||||
|
|
||||||
|
proc addBookmarkItemToList*(self: BookmarkList, bookmark: Bookmark) =
|
||||||
|
self.beginInsertRows(newQModelIndex(), self.bookmarks.len, self.bookmarks.len)
|
||||||
|
self.bookmarks.add(bookmark)
|
||||||
|
self.endInsertRows()
|
||||||
|
|
||||||
|
# proc getBookmarkIndexByUrl*(self: BookmarkList, bookmark: Bookmark)
|
||||||
|
|
||||||
|
proc removeBookmarkItemFromList*(self: BookmarkList, index: int) =
|
||||||
|
self.beginRemoveRows(newQModelIndex(), index, index)
|
||||||
|
self.bookmarks.delete(index)
|
||||||
|
self.endRemoveRows()
|
||||||
|
|
||||||
|
|
||||||
|
proc setNewData*(self: BookmarkList, bookmarkList: seq[Bookmark]) =
|
||||||
|
self.beginResetModel()
|
||||||
|
self.bookmarks = bookmarkList
|
||||||
|
self.endResetModel()
|
||||||
|
|
||||||
|
proc getBookmarkByUrl*(self: BookmarkList, url: string): Bookmark =
|
||||||
|
for bookmark in self.bookmarks:
|
||||||
|
if bookmark.url == url:
|
||||||
|
return bookmark
|
||||||
|
|
|
@ -4,6 +4,7 @@ import app/chat/core as chat
|
||||||
import app/wallet/core as wallet
|
import app/wallet/core as wallet
|
||||||
import app/node/core as node
|
import app/node/core as node
|
||||||
import app/utilsView/core as utilsView
|
import app/utilsView/core as utilsView
|
||||||
|
import app/browser/core as browserView
|
||||||
import app/profile/core as profile
|
import app/profile/core as profile
|
||||||
import app/onboarding/core as onboarding
|
import app/onboarding/core as onboarding
|
||||||
import app/login/core as login
|
import app/login/core as login
|
||||||
|
@ -78,6 +79,9 @@ proc mainProc() =
|
||||||
var utilsController = utilsView.newController(status)
|
var utilsController = utilsView.newController(status)
|
||||||
engine.setRootContextProperty("utilsModel", utilsController.variant)
|
engine.setRootContextProperty("utilsModel", utilsController.variant)
|
||||||
|
|
||||||
|
var browserController = browserView.newController(status)
|
||||||
|
engine.setRootContextProperty("browserModel", browserController.variant)
|
||||||
|
|
||||||
proc changeLanguage(locale: string) =
|
proc changeLanguage(locale: string) =
|
||||||
engine.setTranslationPackage(joinPath(i18nPath, fmt"qml_{locale}.qm"))
|
engine.setTranslationPackage(joinPath(i18nPath, fmt"qml_{locale}.qm"))
|
||||||
|
|
||||||
|
@ -102,6 +106,7 @@ proc mainProc() =
|
||||||
provider.init()
|
provider.init()
|
||||||
chat.init()
|
chat.init()
|
||||||
utilsController.init()
|
utilsController.init()
|
||||||
|
browserController.init()
|
||||||
|
|
||||||
wallet.checkPendingTransactions()
|
wallet.checkPendingTransactions()
|
||||||
wallet.start()
|
wallet.start()
|
||||||
|
@ -125,6 +130,7 @@ proc mainProc() =
|
||||||
chat.delete()
|
chat.delete()
|
||||||
profile.delete()
|
profile.delete()
|
||||||
utilsController.delete()
|
utilsController.delete()
|
||||||
|
browserController.delete()
|
||||||
|
|
||||||
|
|
||||||
# Initialize only controllers whose init functions
|
# Initialize only controllers whose init functions
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import core, ./types, ../signals/types as statusgo_types, ./accounts/constants, ./utils
|
import core, ./types, ../signals/types as statusgo_types, ./accounts/constants, ./utils
|
||||||
import json, tables, sugar, sequtils, strutils
|
import json, tables, sugar, sequtils, chronicles
|
||||||
import json_serialization
|
import json_serialization
|
||||||
import locks
|
import locks
|
||||||
|
|
||||||
|
@ -28,6 +28,7 @@ proc getSettings*(useCached: bool = true, keepSensitiveData: bool = false): Json
|
||||||
withLock settingsLock:
|
withLock settingsLock:
|
||||||
if useCached and not dirty and not keepSensitiveData:
|
if useCached and not dirty and not keepSensitiveData:
|
||||||
result = settings
|
result = settings
|
||||||
|
# debug "setting", settings
|
||||||
else:
|
else:
|
||||||
result = callPrivateRPC("settings_getSettings").parseJSON()["result"]
|
result = callPrivateRPC("settings_getSettings").parseJSON()["result"]
|
||||||
if (keepSensitiveData):
|
if (keepSensitiveData):
|
||||||
|
|
|
@ -150,6 +150,7 @@ type
|
||||||
|
|
||||||
Setting* {.pure.} = enum
|
Setting* {.pure.} = enum
|
||||||
Appearance = "appearance",
|
Appearance = "appearance",
|
||||||
|
Bookmarks = "bookmarks",
|
||||||
Currency = "currency"
|
Currency = "currency"
|
||||||
EtherscanLink = "etherscan-link"
|
EtherscanLink = "etherscan-link"
|
||||||
InstallationId = "installation-id"
|
InstallationId = "installation-id"
|
||||||
|
|
|
@ -11,6 +11,7 @@ import "../../../shared"
|
||||||
import "../../../shared/status"
|
import "../../../shared/status"
|
||||||
import "../../../imports"
|
import "../../../imports"
|
||||||
import "../Chat/ChatColumn/ChatComponents"
|
import "../Chat/ChatColumn/ChatComponents"
|
||||||
|
import "./components"
|
||||||
|
|
||||||
// Code based on https://code.qt.io/cgit/qt/qtwebengine.git/tree/examples/webengine/quicknanobrowser/BrowserWindow.qml?h=5.15
|
// Code based on https://code.qt.io/cgit/qt/qtwebengine.git/tree/examples/webengine/quicknanobrowser/BrowserWindow.qml?h=5.15
|
||||||
// Licensed under BSD
|
// Licensed under BSD
|
||||||
|
@ -612,37 +613,35 @@ Rectangle {
|
||||||
anchors.topMargin: 60
|
anchors.topMargin: 60
|
||||||
}
|
}
|
||||||
|
|
||||||
Row {
|
Item {
|
||||||
anchors.horizontalCenter: emptyPageImage.horizontalCenter
|
anchors.horizontalCenter: emptyPageImage.horizontalCenter
|
||||||
anchors.top: emptyPageImage.bottom
|
anchors.top: emptyPageImage.bottom
|
||||||
anchors.topMargin: 30
|
anchors.topMargin: 30
|
||||||
Item {
|
width: parent.width - Style.current.bigPadding * 2
|
||||||
width: bookmarkItem.width
|
|
||||||
height: bookmarkItem.height
|
|
||||||
Item {
|
|
||||||
id: bookmarkItem
|
|
||||||
width: childrenRect.width
|
|
||||||
height: childrenRect.height
|
|
||||||
SVGImage {
|
|
||||||
id: bookmarkImage
|
|
||||||
source: "../../img/globe.svg"
|
|
||||||
width: 48
|
|
||||||
height: 48
|
|
||||||
}
|
|
||||||
|
|
||||||
StyledText {
|
ListView {
|
||||||
text: "site.com"
|
id: bookmarkList
|
||||||
anchors.horizontalCenter: bookmarkImage.horizontalCenter
|
model: browserModel.bookmarks
|
||||||
anchors.top: bookmarkImage.bottom
|
spacing: Style.current.padding
|
||||||
anchors.topMargin: Style.current.halfPadding
|
orientation : ListView.Horizontal
|
||||||
}
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
anchors.horizontalCenterOffset: -(addBookmarkBtn.width + spacing) /2
|
||||||
|
width: Math.min(childrenRect.width, parent.width - addBookmarkBtn.width - spacing)
|
||||||
|
delegate: BookmarkButton {
|
||||||
|
text: name
|
||||||
|
onClicked: Qt.openUrlExternally(url)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BookmarkButton {
|
||||||
|
id: addBookmarkBtn
|
||||||
|
text: qsTr("Add favorite")
|
||||||
|
onClicked: {
|
||||||
|
// TODO add a popup
|
||||||
|
browserModel.addBookmark("https://dap.ps/", "dap.ps")
|
||||||
}
|
}
|
||||||
MouseArea {
|
anchors.left: bookmarkList.right
|
||||||
anchors.fill: bookmarkItem
|
anchors.leftMargin: bookmarkList.spacing
|
||||||
cursorShape: Qt.PointingHandCursor
|
|
||||||
onClicked: console.log('Go to bookmark')
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
import QtQuick 2.13
|
||||||
|
import "../../../../shared"
|
||||||
|
import "../../../../shared/status"
|
||||||
|
import "../../../../imports"
|
||||||
|
|
||||||
|
Item {
|
||||||
|
property url source: "../../../img/globe.svg"
|
||||||
|
property string text
|
||||||
|
signal clicked
|
||||||
|
|
||||||
|
id: root
|
||||||
|
width: 74
|
||||||
|
height: bookmarkImage.height + bookmarkName.height + Style.current.halfPadding
|
||||||
|
|
||||||
|
SVGImage {
|
||||||
|
id: bookmarkImage
|
||||||
|
source: root.source
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
width: 48
|
||||||
|
height: 48
|
||||||
|
}
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
id: bookmarkName
|
||||||
|
text: root.text
|
||||||
|
width: parent.width
|
||||||
|
anchors.top: bookmarkImage.bottom
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
wrapMode: Text.WordWrap
|
||||||
|
anchors.topMargin: Style.current.halfPadding
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
cursorShape: Qt.PointingHandCursor
|
||||||
|
onClicked: root.clicked()
|
||||||
|
}
|
||||||
|
}
|
|
@ -130,6 +130,7 @@ DISTFILES += \
|
||||||
app/AppLayouts/Browser/DownloadBar.qml \
|
app/AppLayouts/Browser/DownloadBar.qml \
|
||||||
app/AppLayouts/Browser/DownloadElement.qml \
|
app/AppLayouts/Browser/DownloadElement.qml \
|
||||||
app/AppLayouts/Browser/FaviconImage.qml \
|
app/AppLayouts/Browser/FaviconImage.qml \
|
||||||
|
app/AppLayouts/Browser/components/BookmarkButton.qml \
|
||||||
app/AppLayouts/Chat/ChatColumn/ChatComponents/ChatCommandButton.qml \
|
app/AppLayouts/Chat/ChatColumn/ChatComponents/ChatCommandButton.qml \
|
||||||
app/AppLayouts/Chat/ChatColumn/ChatComponents/ChatCommandModal.qml \
|
app/AppLayouts/Chat/ChatColumn/ChatComponents/ChatCommandModal.qml \
|
||||||
app/AppLayouts/Chat/ChatColumn/ChatComponents/ChatCommandsPopup.qml \
|
app/AppLayouts/Chat/ChatColumn/ChatComponents/ChatCommandsPopup.qml \
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit d04e54e54e8ea85c9bd35aff5482e064f5ee76b0
|
Subproject commit b2d8f7f416a276f1e03282cd95cf43b187e12c5f
|
Loading…
Reference in New Issue