feat: add popup menu to add favorites on sites themselves
This commit is contained in:
parent
ff0a96c02b
commit
f7cc0cf78d
|
@ -33,12 +33,34 @@ QtObject:
|
||||||
discard
|
discard
|
||||||
self.bookmarks.setNewData(bookmarks)
|
self.bookmarks.setNewData(bookmarks)
|
||||||
|
|
||||||
|
proc bookmarksChanged*(self: BrowserView) {.signal.}
|
||||||
|
|
||||||
proc getBookmarks*(self: BrowserView): QVariant {.slot.} =
|
proc getBookmarks*(self: BrowserView): QVariant {.slot.} =
|
||||||
return newQVariant(self.bookmarks)
|
return newQVariant(self.bookmarks)
|
||||||
|
|
||||||
QtProperty[QVariant] bookmarks:
|
QtProperty[QVariant] bookmarks:
|
||||||
read = getBookmarks
|
read = getBookmarks
|
||||||
|
notify = bookmarksChanged
|
||||||
|
|
||||||
proc addBookmark*(self: BrowserView, url: string, name: string) {.slot.} =
|
proc addBookmark*(self: BrowserView, url: string, name: string) {.slot.} =
|
||||||
self.bookmarks.addBookmarkItemToList(Bookmark(url: url, name: name, image: ""))
|
self.bookmarks.addBookmarkItemToList(Bookmark(url: url, name: name, image: ""))
|
||||||
discard status_settings.saveSetting(Setting.Bookmarks, $(%self.bookmarks.bookmarks))
|
discard status_settings.saveSetting(Setting.Bookmarks, $(%self.bookmarks.bookmarks))
|
||||||
|
self.bookmarksChanged()
|
||||||
|
|
||||||
|
proc removeBookmark*(self: BrowserView, url: string) {.slot.} =
|
||||||
|
let index = self.bookmarks.getBookmarkIndexByUrl(url)
|
||||||
|
if index == -1:
|
||||||
|
return
|
||||||
|
self.bookmarks.removeBookmarkItemFromList(index)
|
||||||
|
discard status_settings.saveSetting(Setting.Bookmarks, $(%self.bookmarks.bookmarks))
|
||||||
|
self.bookmarksChanged()
|
||||||
|
|
||||||
|
proc modifyBookmark*(self: BrowserView, ogUrl: string, newUrl: string, newName: string) {.slot.} =
|
||||||
|
let index = self.bookmarks.getBookmarkIndexByUrl(ogUrl)
|
||||||
|
if index == -1:
|
||||||
|
# Somehow we don't know this URL. Let's just add it as a new one
|
||||||
|
self.addBookmark(newUrl, newName)
|
||||||
|
return
|
||||||
|
self.bookmarks.modifyBookmarkItemFromList(index, newUrl, newName)
|
||||||
|
discard status_settings.saveSetting(Setting.Bookmarks, $(%self.bookmarks.bookmarks))
|
||||||
|
self.bookmarksChanged()
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import NimQml, Tables
|
import NimQml, Tables, chronicles
|
||||||
import sequtils as sequtils
|
import sequtils as sequtils
|
||||||
|
|
||||||
|
|
||||||
|
@ -29,9 +29,17 @@ QtObject:
|
||||||
result.bookmarks = @[]
|
result.bookmarks = @[]
|
||||||
result.setup
|
result.setup
|
||||||
|
|
||||||
|
|
||||||
method rowCount*(self: BookmarkList, index: QModelIndex = nil): int = self.bookmarks.len
|
method rowCount*(self: BookmarkList, index: QModelIndex = nil): int = self.bookmarks.len
|
||||||
|
|
||||||
|
proc rowData(self: BookmarkList, index: int, column: string): string {.slot.} =
|
||||||
|
if (index > self.bookmarks.len - 1):
|
||||||
|
return
|
||||||
|
let bookmark = self.bookmarks[index]
|
||||||
|
case column:
|
||||||
|
of "name": result = bookmark.name
|
||||||
|
of "url": result = bookmark.url
|
||||||
|
of "image": result = bookmark.image
|
||||||
|
|
||||||
method data(self: BookmarkList, index: QModelIndex, role: int): QVariant =
|
method data(self: BookmarkList, index: QModelIndex, role: int): QVariant =
|
||||||
if not index.isValid:
|
if not index.isValid:
|
||||||
return
|
return
|
||||||
|
@ -58,21 +66,27 @@ QtObject:
|
||||||
self.bookmarks.add(bookmark)
|
self.bookmarks.add(bookmark)
|
||||||
self.endInsertRows()
|
self.endInsertRows()
|
||||||
|
|
||||||
# proc getBookmarkIndexByUrl*(self: BookmarkList, bookmark: Bookmark)
|
|
||||||
|
|
||||||
proc removeBookmarkItemFromList*(self: BookmarkList, index: int) =
|
proc removeBookmarkItemFromList*(self: BookmarkList, index: int) =
|
||||||
self.beginRemoveRows(newQModelIndex(), index, index)
|
self.beginRemoveRows(newQModelIndex(), index, index)
|
||||||
self.bookmarks.delete(index)
|
self.bookmarks.delete(index)
|
||||||
self.endRemoveRows()
|
self.endRemoveRows()
|
||||||
|
|
||||||
|
proc modifyBookmarkItemFromList*(self: BookmarkList, index: int, url: string, name: string) =
|
||||||
|
let topLeft = self.createIndex(index, index, nil)
|
||||||
|
let bottomRight = self.createIndex(index, index, nil)
|
||||||
|
self.bookmarks[index] = Bookmark(url: url, name: name, image: "")
|
||||||
|
self.dataChanged(topLeft, bottomRight, @[BookmarkRoles.Name.int, BookmarkRoles.Url.int])
|
||||||
|
|
||||||
proc setNewData*(self: BookmarkList, bookmarkList: seq[Bookmark]) =
|
proc setNewData*(self: BookmarkList, bookmarkList: seq[Bookmark]) =
|
||||||
self.beginResetModel()
|
self.beginResetModel()
|
||||||
self.bookmarks = bookmarkList
|
self.bookmarks = bookmarkList
|
||||||
self.endResetModel()
|
self.endResetModel()
|
||||||
|
|
||||||
proc getBookmarkByUrl*(self: BookmarkList, url: string): Bookmark =
|
proc getBookmarkIndexByUrl*(self: BookmarkList, url: string): int {.slot.} =
|
||||||
|
var i = 0
|
||||||
for bookmark in self.bookmarks:
|
for bookmark in self.bookmarks:
|
||||||
if bookmark.url == url:
|
if bookmark.url == url:
|
||||||
return bookmark
|
return i
|
||||||
|
i = i + 1
|
||||||
|
return -1
|
||||||
|
|
||||||
|
|
|
@ -1,21 +1,52 @@
|
||||||
import QtQuick 2.13
|
import QtQuick 2.13
|
||||||
import QtQuick.Controls 2.13
|
import QtQuick.Controls 2.13
|
||||||
import QtQuick.Layouts 1.13
|
import QtQuick.Layouts 1.13
|
||||||
|
import QtGraphicalEffects 1.13
|
||||||
import "../../../imports"
|
import "../../../imports"
|
||||||
import "../../../shared"
|
import "../../../shared"
|
||||||
|
import "../../../shared/status"
|
||||||
|
|
||||||
ModalPopup {
|
ModalPopup {
|
||||||
property string urlError: ""
|
property string urlError: ""
|
||||||
property string nameError: ""
|
property string nameError: ""
|
||||||
|
property string ogUrl
|
||||||
|
property string ogName
|
||||||
|
property bool modifiyModal: false
|
||||||
|
|
||||||
id: popup
|
id: popup
|
||||||
width: 480
|
width: modifiyModal ? 345 : 480
|
||||||
height: 480
|
height: modifiyModal ? 345 : 480
|
||||||
|
|
||||||
|
modal: !modifiyModal
|
||||||
|
|
||||||
|
background: Rectangle {
|
||||||
|
id: bgPopup
|
||||||
|
color: Style.current.background
|
||||||
|
radius: Style.current.radius
|
||||||
|
layer.enabled: true
|
||||||
|
layer.effect: DropShadow{
|
||||||
|
width: bgPopup.width
|
||||||
|
height: bgPopup.height
|
||||||
|
x: bgPopup.x
|
||||||
|
y: bgPopup.y + 10
|
||||||
|
visible: bgPopup.visible
|
||||||
|
source: bgPopup
|
||||||
|
horizontalOffset: 0
|
||||||
|
verticalOffset: 5
|
||||||
|
radius: 10
|
||||||
|
samples: 15
|
||||||
|
color: "#22000000"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
onOpened: {
|
onOpened: {
|
||||||
urlInput.forceActiveFocus(Qt.MouseFocusReason)
|
urlInput.forceActiveFocus(Qt.MouseFocusReason)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onClosed: {
|
||||||
|
reset()
|
||||||
|
}
|
||||||
|
|
||||||
function validate() {
|
function validate() {
|
||||||
urlError = ""
|
urlError = ""
|
||||||
if (!urlInput.text) {
|
if (!urlInput.text) {
|
||||||
|
@ -29,7 +60,19 @@ ModalPopup {
|
||||||
return !urlError && !nameError
|
return !urlError && !nameError
|
||||||
}
|
}
|
||||||
|
|
||||||
title: qsTr("Add favorite")
|
function reset() {
|
||||||
|
modifiyModal = false
|
||||||
|
urlError = ""
|
||||||
|
nameError = ""
|
||||||
|
ogUrl = ""
|
||||||
|
ogName = ""
|
||||||
|
x = Math.round(((parent ? parent.width : 0) - width) / 2)
|
||||||
|
y = Math.round(((parent ? parent.height : 0) - height) / 2)
|
||||||
|
}
|
||||||
|
|
||||||
|
title: modifiyModal ?
|
||||||
|
qsTr("Favorite added") :
|
||||||
|
qsTr("Add favorite")
|
||||||
|
|
||||||
Column {
|
Column {
|
||||||
width: parent.width
|
width: parent.width
|
||||||
|
@ -41,6 +84,7 @@ ModalPopup {
|
||||||
placeholderText: qsTr("Paste URL")
|
placeholderText: qsTr("Paste URL")
|
||||||
pasteFromClipboard: true
|
pasteFromClipboard: true
|
||||||
validationError: popup.urlError
|
validationError: popup.urlError
|
||||||
|
text: popup.ogUrl
|
||||||
}
|
}
|
||||||
|
|
||||||
Input {
|
Input {
|
||||||
|
@ -48,22 +92,51 @@ ModalPopup {
|
||||||
label: qsTr("Name")
|
label: qsTr("Name")
|
||||||
placeholderText: qsTr("Name the website")
|
placeholderText: qsTr("Name the website")
|
||||||
validationError: popup.nameError
|
validationError: popup.nameError
|
||||||
|
text: popup.ogName
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
footer: StyledButton {
|
footer: Item {
|
||||||
|
width: parent.width
|
||||||
|
height: parent.height
|
||||||
|
|
||||||
|
StatusButton {
|
||||||
|
id: removeBtn
|
||||||
|
anchors.right: addBtn.left
|
||||||
|
anchors.rightMargin: Style.current.padding
|
||||||
|
visible: popup.modifiyModal
|
||||||
|
text: qsTr("Remove")
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
color: Style.current.danger
|
||||||
|
bgColor: Utils.setColorAlpha(Style.current.danger, 0.1)
|
||||||
|
bgHoverColor: Utils.setColorAlpha(Style.current.danger, 0.2)
|
||||||
|
onClicked: {
|
||||||
|
browserModel.removeBookmark(popup.ogUrl)
|
||||||
|
popup.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StatusButton {
|
||||||
id: addBtn
|
id: addBtn
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.rightMargin: Style.current.smallPadding
|
anchors.rightMargin: Style.current.smallPadding
|
||||||
label: qsTr("Add")
|
text: popup.modifiyModal ?
|
||||||
|
qsTr("Done") :
|
||||||
|
qsTr("Add")
|
||||||
anchors.bottom: parent.bottom
|
anchors.bottom: parent.bottom
|
||||||
onClicked: {
|
onClicked: {
|
||||||
if (!validate()) {
|
if (!validate()) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!popup.modifiyModal) {
|
||||||
browserModel.addBookmark(urlInput.text, nameInput.text)
|
browserModel.addBookmark(urlInput.text, nameInput.text)
|
||||||
|
} else if (popup.ogName !== nameInput.text || popup.ogUrl !== urlInput.text) {
|
||||||
|
browserModel.modifyBookmark(popup.ogUrl, urlInput.text, nameInput.text)
|
||||||
|
}
|
||||||
|
|
||||||
popup.close()
|
popup.close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -77,7 +77,30 @@ Rectangle {
|
||||||
Layout.leftMargin: -root.innerMargin/2
|
Layout.leftMargin: -root.innerMargin/2
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: browserModel
|
||||||
|
onBookmarksChanged: {
|
||||||
|
addressBar.currentFavorite = getCurrentFavorite()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
StyledTextField {
|
StyledTextField {
|
||||||
|
property var currentFavorite: getCurrentFavorite()
|
||||||
|
|
||||||
|
function getCurrentFavorite() {
|
||||||
|
if (!currentWebView || !currentWebView.url) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
const index = browserModel.bookmarks.getBookmarkIndexByUrl(currentWebView.url)
|
||||||
|
if (index === -1) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
url: currentWebView.url,
|
||||||
|
name: browserModel.bookmarks.rowData(index, 'name')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
id: addressBar
|
id: addressBar
|
||||||
height: 40
|
height: 40
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
@ -100,7 +123,30 @@ Rectangle {
|
||||||
}
|
}
|
||||||
|
|
||||||
StatusIconButton {
|
StatusIconButton {
|
||||||
id: chatCommandsBtn
|
id: addFavoriteBtn
|
||||||
|
visible: !!currentWebView && !!currentWebView.url
|
||||||
|
icon.name: !!addressBar.currentFavorite ? "browser/favoriteActive" : "browser/favorite"
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
anchors.right: reloadBtn.left
|
||||||
|
anchors.rightMargin: Style.current.halfPadding
|
||||||
|
onClicked: {
|
||||||
|
if (!addressBar.currentFavorite) {
|
||||||
|
browserModel.addBookmark(currentWebView.url, currentWebView.title)
|
||||||
|
}
|
||||||
|
|
||||||
|
addFavoriteModal.modifiyModal = true
|
||||||
|
addFavoriteModal.x = addFavoriteBtn.x + addFavoriteBtn.width / 2 - addFavoriteBtn.width / 2
|
||||||
|
addFavoriteModal.y = root.y + root.height + 4
|
||||||
|
addFavoriteModal.ogUrl = addressBar.currentFavorite ? addressBar.currentFavorite.url : currentWebView.url
|
||||||
|
addFavoriteModal.ogName = addressBar.currentFavorite ? addressBar.currentFavorite.name : currentWebView.title
|
||||||
|
addFavoriteModal.open()
|
||||||
|
}
|
||||||
|
width: 24
|
||||||
|
height: 24
|
||||||
|
}
|
||||||
|
|
||||||
|
StatusIconButton {
|
||||||
|
id: reloadBtn
|
||||||
icon.name: currentWebView && currentWebView.loading ? "close" : "browser/refresh"
|
icon.name: currentWebView && currentWebView.loading ? "close" : "browser/refresh"
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
|
|
|
@ -633,7 +633,7 @@ Rectangle {
|
||||||
width: Math.min(childrenRect.width, parent.width - addBookmarkBtn.width - spacing)
|
width: Math.min(childrenRect.width, parent.width - addBookmarkBtn.width - spacing)
|
||||||
delegate: BookmarkButton {
|
delegate: BookmarkButton {
|
||||||
text: name
|
text: name
|
||||||
onClicked: Qt.openUrlExternally(url)
|
onClicked: currentWebView.url = url
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M14.7778 8.37542L12.4622 2.80798C12.2914 2.39734 11.7096 2.39734 11.5388 2.80799L9.22321 8.37542L3.2127 8.85727C2.76938 8.89282 2.58961 9.44607 2.92738 9.7354L7.50676 13.6581L6.10768 19.5234C6.00449 19.956 6.47512 20.2979 6.85466 20.0661L12.0005 16.923L17.1463 20.0661C17.5259 20.2979 17.9965 19.956 17.8933 19.5234L16.4942 13.6581L21.0736 9.7354C21.4114 9.44607 21.2316 8.89282 20.7883 8.85727L14.7778 8.37542ZM17.8153 10.5514C17.9842 10.4067 17.8943 10.1301 17.6727 10.1123L14.6579 9.87062C14.0972 9.82567 13.6088 9.47081 13.3928 8.95146L12.2313 6.15894C12.1459 5.95362 11.8551 5.95362 11.7697 6.15894L10.6082 8.95146C10.3922 9.47081 9.90377 9.82567 9.34308 9.87062L6.32832 10.1123C6.10666 10.1301 6.01678 10.4067 6.18566 10.5514L8.48259 12.5189C8.90977 12.8849 9.09633 13.459 8.96582 14.0062L8.26407 16.9481C8.21247 17.1644 8.44779 17.3353 8.63756 17.2194L11.2186 15.6429C11.6986 15.3497 12.3024 15.3497 12.7824 15.6429L15.3634 17.2194C15.5532 17.3353 15.7885 17.1644 15.7369 16.9481L15.0352 14.0062C14.9047 13.459 15.0912 12.8849 15.5184 12.5189L17.8153 10.5514Z" fill="#4360DF"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.2 KiB |
|
@ -0,0 +1,3 @@
|
||||||
|
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M14.7773 8.37542L12.4617 2.80798C12.2909 2.39734 11.7091 2.39734 11.5383 2.80799L9.22272 8.37542L3.21222 8.85727C2.76889 8.89282 2.58913 9.44607 2.92689 9.7354L7.50627 13.6581L6.10719 19.5234C6.004 19.956 6.47463 20.2979 6.85418 20.0661L12 16.923L17.1458 20.0661C17.5254 20.2979 17.996 19.956 17.8928 19.5234L16.4938 13.6581L21.0731 9.7354C21.4109 9.44607 21.2311 8.89282 20.7878 8.85727L14.7773 8.37542Z" fill="#4360DF"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 575 B |
|
@ -10,6 +10,8 @@ Button {
|
||||||
property string size: "large"
|
property string size: "large"
|
||||||
property string state: "default"
|
property string state: "default"
|
||||||
property color color: Style.current.buttonForegroundColor
|
property color color: Style.current.buttonForegroundColor
|
||||||
|
property color bgColor: Style.current.buttonBackgroundColor
|
||||||
|
property color bgHoverColor: Qt.darker(control.bgColor, 1.1)
|
||||||
property int iconRotation: 0
|
property int iconRotation: 0
|
||||||
|
|
||||||
id: control
|
id: control
|
||||||
|
@ -89,11 +91,11 @@ Button {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
color: {
|
color: {
|
||||||
if (type === "secondary") {
|
if (type === "secondary") {
|
||||||
return hovered ? Style.current.buttonBackgroundColor : "transparent"
|
return hovered ? control.bgColor : "transparent"
|
||||||
}
|
}
|
||||||
return !enabled ? Style.current.buttonDisabledBackgroundColor :
|
return !enabled ? Style.current.buttonDisabledBackgroundColor :
|
||||||
hovered ? Qt.darker(Style.current.buttonBackgroundColor, 1.1) :
|
hovered ? control.bgHoverColor :
|
||||||
Style.current.buttonBackgroundColor
|
control.bgColor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue