feat: add popup menu to add favorites on sites themselves

This commit is contained in:
Jonathan Rainville 2020-10-29 15:02:32 -04:00 committed by Iuri Matias
parent ff0a96c02b
commit f7cc0cf78d
8 changed files with 189 additions and 26 deletions

View File

@ -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()

View File

@ -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

View File

@ -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()
} }
} }
} }
}

View File

@ -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

View File

@ -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
} }
} }

View File

@ -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

View File

@ -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

View File

@ -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
} }
} }