From f7cc0cf78d949775862c6b602b30ea3ed1ec3ccd Mon Sep 17 00:00:00 2001 From: Jonathan Rainville Date: Thu, 29 Oct 2020 15:02:32 -0400 Subject: [PATCH] feat: add popup menu to add favorites on sites themselves --- src/app/browser/view.nim | 22 ++++ src/app/browser/views/bookmark_list.nim | 26 ++++- .../AppLayouts/Browser/AddFavoriteModal.qml | 103 +++++++++++++++--- ui/app/AppLayouts/Browser/BrowserHeader.qml | 48 +++++++- ui/app/AppLayouts/Browser/BrowserLayout.qml | 2 +- ui/app/img/browser/favorite.svg | 3 + ui/app/img/browser/favoriteActive.svg | 3 + ui/shared/status/StatusButton.qml | 8 +- 8 files changed, 189 insertions(+), 26 deletions(-) create mode 100644 ui/app/img/browser/favorite.svg create mode 100644 ui/app/img/browser/favoriteActive.svg diff --git a/src/app/browser/view.nim b/src/app/browser/view.nim index f82add47aa..bc50c34f5d 100644 --- a/src/app/browser/view.nim +++ b/src/app/browser/view.nim @@ -33,12 +33,34 @@ QtObject: discard self.bookmarks.setNewData(bookmarks) + proc bookmarksChanged*(self: BrowserView) {.signal.} + proc getBookmarks*(self: BrowserView): QVariant {.slot.} = return newQVariant(self.bookmarks) QtProperty[QVariant] bookmarks: read = getBookmarks + notify = bookmarksChanged 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)) + 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() diff --git a/src/app/browser/views/bookmark_list.nim b/src/app/browser/views/bookmark_list.nim index c82307bbda..ea61b35b8b 100644 --- a/src/app/browser/views/bookmark_list.nim +++ b/src/app/browser/views/bookmark_list.nim @@ -1,4 +1,4 @@ -import NimQml, Tables +import NimQml, Tables, chronicles import sequtils as sequtils @@ -29,9 +29,17 @@ QtObject: result.bookmarks = @[] result.setup - 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 = if not index.isValid: return @@ -58,21 +66,27 @@ QtObject: 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 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]) = self.beginResetModel() self.bookmarks = bookmarkList 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: if bookmark.url == url: - return bookmark + return i + i = i + 1 + return -1 diff --git a/ui/app/AppLayouts/Browser/AddFavoriteModal.qml b/ui/app/AppLayouts/Browser/AddFavoriteModal.qml index 8d35f5e70b..893ab68be1 100644 --- a/ui/app/AppLayouts/Browser/AddFavoriteModal.qml +++ b/ui/app/AppLayouts/Browser/AddFavoriteModal.qml @@ -1,21 +1,52 @@ import QtQuick 2.13 import QtQuick.Controls 2.13 import QtQuick.Layouts 1.13 +import QtGraphicalEffects 1.13 import "../../../imports" import "../../../shared" +import "../../../shared/status" ModalPopup { property string urlError: "" property string nameError: "" + property string ogUrl + property string ogName + property bool modifiyModal: false id: popup - width: 480 - height: 480 + width: modifiyModal ? 345 : 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: { urlInput.forceActiveFocus(Qt.MouseFocusReason) } + onClosed: { + reset() + } + function validate() { urlError = "" if (!urlInput.text) { @@ -29,7 +60,19 @@ ModalPopup { 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 { width: parent.width @@ -41,6 +84,7 @@ ModalPopup { placeholderText: qsTr("Paste URL") pasteFromClipboard: true validationError: popup.urlError + text: popup.ogUrl } Input { @@ -48,22 +92,51 @@ ModalPopup { label: qsTr("Name") placeholderText: qsTr("Name the website") validationError: popup.nameError + text: popup.ogName } } - footer: StyledButton { - id: addBtn - anchors.right: parent.right - anchors.rightMargin: Style.current.smallPadding - label: qsTr("Add") - anchors.bottom: parent.bottom - onClicked: { - if (!validate()) { - return - } + footer: Item { + width: parent.width + height: parent.height - browserModel.addBookmark(urlInput.text, nameInput.text) - popup.close() + 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 + anchors.right: parent.right + anchors.rightMargin: Style.current.smallPadding + text: popup.modifiyModal ? + qsTr("Done") : + qsTr("Add") + anchors.bottom: parent.bottom + onClicked: { + if (!validate()) { + return + } + + if (!popup.modifiyModal) { + 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() + } } } } diff --git a/ui/app/AppLayouts/Browser/BrowserHeader.qml b/ui/app/AppLayouts/Browser/BrowserHeader.qml index bac07a16e4..da573e97ae 100644 --- a/ui/app/AppLayouts/Browser/BrowserHeader.qml +++ b/ui/app/AppLayouts/Browser/BrowserHeader.qml @@ -77,7 +77,30 @@ Rectangle { Layout.leftMargin: -root.innerMargin/2 } + Connections { + target: browserModel + onBookmarksChanged: { + addressBar.currentFavorite = getCurrentFavorite() + } + } + 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 height: 40 Layout.fillWidth: true @@ -100,7 +123,30 @@ Rectangle { } 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" anchors.verticalCenter: parent.verticalCenter anchors.right: parent.right diff --git a/ui/app/AppLayouts/Browser/BrowserLayout.qml b/ui/app/AppLayouts/Browser/BrowserLayout.qml index 4c870600ec..bc69a70921 100644 --- a/ui/app/AppLayouts/Browser/BrowserLayout.qml +++ b/ui/app/AppLayouts/Browser/BrowserLayout.qml @@ -633,7 +633,7 @@ Rectangle { width: Math.min(childrenRect.width, parent.width - addBookmarkBtn.width - spacing) delegate: BookmarkButton { text: name - onClicked: Qt.openUrlExternally(url) + onClicked: currentWebView.url = url } } diff --git a/ui/app/img/browser/favorite.svg b/ui/app/img/browser/favorite.svg new file mode 100644 index 0000000000..a9f9af2a47 --- /dev/null +++ b/ui/app/img/browser/favorite.svg @@ -0,0 +1,3 @@ + + + diff --git a/ui/app/img/browser/favoriteActive.svg b/ui/app/img/browser/favoriteActive.svg new file mode 100644 index 0000000000..79712986b9 --- /dev/null +++ b/ui/app/img/browser/favoriteActive.svg @@ -0,0 +1,3 @@ + + + diff --git a/ui/shared/status/StatusButton.qml b/ui/shared/status/StatusButton.qml index 83e802ba5f..f60f556a17 100644 --- a/ui/shared/status/StatusButton.qml +++ b/ui/shared/status/StatusButton.qml @@ -10,6 +10,8 @@ Button { property string size: "large" property string state: "default" 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 id: control @@ -89,11 +91,11 @@ Button { anchors.fill: parent color: { if (type === "secondary") { - return hovered ? Style.current.buttonBackgroundColor : "transparent" + return hovered ? control.bgColor : "transparent" } return !enabled ? Style.current.buttonDisabledBackgroundColor : - hovered ? Qt.darker(Style.current.buttonBackgroundColor, 1.1) : - Style.current.buttonBackgroundColor + hovered ? control.bgHoverColor : + control.bgColor } }