From 5543efac7ac4b87dc92985eac3448aadde401309 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Tue, 29 Apr 2025 10:44:44 +0200 Subject: [PATCH] booru: more sexy --- .../common/widgets/NotificationWidget.qml | 4 +- .../modules/common/widgets/StyledSwitch.qml | 71 +++++ .../quickshell/modules/sidebarLeft/Anime.qml | 271 +++++++++++++----- .../modules/sidebarLeft/SidebarLeft.qml | 9 +- .../modules/sidebarLeft/anime/BooruImage.qml | 24 +- .../sidebarLeft/anime/BooruResponse.qml | 47 ++- .../sidebarLeft/anime/BooruTagButton.qml | 2 - .../sidebarRight/CenterWidgetGroup.qml | 8 + .../modules/sidebarRight/todo/TaskList.qml | 4 +- .config/quickshell/services/Booru.qml | 36 ++- 10 files changed, 363 insertions(+), 113 deletions(-) create mode 100644 .config/quickshell/modules/common/widgets/StyledSwitch.qml diff --git a/.config/quickshell/modules/common/widgets/NotificationWidget.qml b/.config/quickshell/modules/common/widgets/NotificationWidget.qml index f912c9cef..c6d12bc83 100644 --- a/.config/quickshell/modules/common/widgets/NotificationWidget.qml +++ b/.config/quickshell/modules/common/widgets/NotificationWidget.qml @@ -445,7 +445,7 @@ Item { ? `` + `${notificationObject.body.replace(/\n/g, "
")}` : notificationObject.body.replace(/ { Qt.openUrlExternally(link) Hyprland.dispatch("global quickshell:sidebarRightClose") } @@ -453,7 +453,7 @@ Item { anchors.fill: parent acceptedButtons: Qt.NoButton // Only for hover hoverEnabled: true - cursorShape: notificationBodyText.hoveredLink !== "" ? Qt.PointingHandCursor : Qt.ArrowCursor + cursorShape: parent.hoveredLink !== "" ? Qt.PointingHandCursor : Qt.ArrowCursor } } } diff --git a/.config/quickshell/modules/common/widgets/StyledSwitch.qml b/.config/quickshell/modules/common/widgets/StyledSwitch.qml new file mode 100644 index 000000000..c0b0a4ffb --- /dev/null +++ b/.config/quickshell/modules/common/widgets/StyledSwitch.qml @@ -0,0 +1,71 @@ +import "root:/modules/common/" +import QtQuick +import QtQuick.Layouts +import QtQuick.Controls +import Qt5Compat.GraphicalEffects + +Switch { + id: root + property real scale: 1 + implicitHeight: 32 * root.scale + implicitWidth: 52 * root.scale + + // Custom track styling + background: Rectangle { + width: parent.width + height: parent.height + radius: Appearance.rounding.full + color: root.checked ? Appearance.m3colors.m3primary : Appearance.m3colors.m3surfaceContainerHighest + border.width: 2 * root.scale + border.color: root.checked ? Appearance.m3colors.m3primary : Appearance.m3colors.m3outline + + Behavior on color { + ColorAnimation { + duration: Appearance.animation.elementDecel.duration + easing.type: Appearance.animation.elementDecel.type + } + } + Behavior on border.color { + ColorAnimation { + duration: Appearance.animation.elementDecel.duration + easing.type: Appearance.animation.elementDecel.type + } + } + } + + // Custom thumb styling + indicator: Rectangle { + width: root.pressed ? (28 * root.scale) : root.checked ? (24 * root.scale) : (16 * root.scale) + height: root.pressed ? (28 * root.scale) : root.checked ? (24 * root.scale) : (16 * root.scale) + radius: Appearance.rounding.full + color: root.checked ? Appearance.m3colors.m3onPrimary : Appearance.m3colors.m3outline + anchors.verticalCenter: parent.verticalCenter + anchors.left: parent.left + anchors.leftMargin: root.checked ? (root.pressed ? (22 * root.scale) : 24 * root.scale) : (root.pressed ? (2 * root.scale) : 8 * root.scale) + + Behavior on anchors.leftMargin { + NumberAnimation { + duration: Appearance.animation.elementDecel.duration + easing.type: Appearance.animation.elementDecel.type + } + } + Behavior on width { + NumberAnimation { + duration: Appearance.animation.elementDecel.duration + easing.type: Appearance.animation.elementDecel.type + } + } + Behavior on height { + NumberAnimation { + duration: Appearance.animation.elementDecel.duration + easing.type: Appearance.animation.elementDecel.type + } + } + Behavior on color { + ColorAnimation { + duration: Appearance.animation.elementDecel.duration + easing.type: Appearance.animation.elementDecel.type + } + } + } +} diff --git a/.config/quickshell/modules/sidebarLeft/Anime.qml b/.config/quickshell/modules/sidebarLeft/Anime.qml index 56db81ec0..79aa9fa46 100644 --- a/.config/quickshell/modules/sidebarLeft/Anime.qml +++ b/.config/quickshell/modules/sidebarLeft/Anime.qml @@ -16,14 +16,48 @@ Item { property var panelWindow property var inputField: tagInputField + function handleInput(inputText) { + if (inputText.startsWith("/")) { + // Handle special commands + const command = inputText.split(" ")[0].substring(1); + const args = inputText.split(" ").slice(1); + if (command === "clear") { + Booru.clearResponses(); + } + else if (command === "mode") { + const newProvider = args[0]; + Booru.setProvider(newProvider); + } + else if (command == "lewd" || command == "nsfw") { + ConfigOptions.sidebar.booru.allowNsfw = !ConfigOptions.sidebar.booru.allowNsfw + } + + } + else { + // Create tag list + const tagList = inputText.split(/\s+/); + let pageIndex = 1; + for (let i = 0; i < tagList.length; ++i) { // Detect page number + if (/^\d+$/.test(tagList[i])) { + pageIndex = parseInt(tagList[i], 10); + tagList.splice(i, 1); + break; + } + } + Booru.makeRequest(tagList, ConfigOptions.sidebar.booru.allowNsfw, ConfigOptions.sidebar.booru.limit, pageIndex); + } + } + Keys.onPressed: (event) => { tagInputField.forceActiveFocus() - if (event.key === Qt.Key_PageUp) { - booruResponseListView.contentY = Math.max(0, booruResponseListView.contentY - booruResponseListView.height / 2) - event.accepted = true - } else if (event.key === Qt.Key_PageDown) { - booruResponseListView.contentY = Math.min(booruResponseListView.contentHeight - booruResponseListView.height, booruResponseListView.contentY + booruResponseListView.height / 2) - event.accepted = true + if (event.modifiers === Qt.NoModifier) { + if (event.key === Qt.Key_PageUp) { + booruResponseListView.contentY = Math.max(0, booruResponseListView.contentY - booruResponseListView.height / 2) + event.accepted = true + } else if (event.key === Qt.Key_PageDown) { + booruResponseListView.contentY = Math.min(booruResponseListView.contentHeight - booruResponseListView.height / 2, booruResponseListView.contentY + booruResponseListView.height / 2) + event.accepted = true + } } } @@ -37,46 +71,75 @@ Item { id: columnLayout anchors.fill: parent - ListView { // Booru responses - id: booruResponseListView + Item { Layout.fillWidth: true Layout.fillHeight: true - clip: true - layer.enabled: true - layer.effect: OpacityMask { - maskSource: Rectangle { - width: swipeView.width - height: swipeView.height - radius: Appearance.rounding.small + ListView { // Booru responses + id: booruResponseListView + anchors.fill: parent + clip: true + layer.enabled: true + layer.effect: OpacityMask { + maskSource: Rectangle { + width: swipeView.width + height: swipeView.height + radius: Appearance.rounding.small + } + } + + Behavior on contentY { + NumberAnimation { + id: scrollAnim + duration: Appearance.animation.elementDecel.duration + easing.type: Appearance.animation.elementDecel.type + } + } + + spacing: 10 + model: ScriptModel { + values: Booru.responses + } + delegate: BooruResponse { + responseData: modelData + tagInputField: root.inputField } } - Behavior on contentY { - NumberAnimation { - id: scrollAnim - duration: Appearance.animation.elementDecel.duration - easing.type: Appearance.animation.elementDecel.type - } - } + Item { // Placeholder when list is empty + visible: Booru.responses.length === 0 + anchors.fill: parent - spacing: 10 - model: ScriptModel { - values: Booru.responses - } - delegate: BooruResponse { - responseData: modelData - tagInputField: root.inputField + ColumnLayout { + anchors.centerIn: parent + spacing: 5 + + MaterialSymbol { + Layout.alignment: Qt.AlignHCenter + font.pixelSize: 55 + color: Appearance.m3colors.m3outline + text: "bookmark_heart" + } + StyledText { + Layout.alignment: Qt.AlignHCenter + font.pixelSize: Appearance.font.pixelSize.normal + color: Appearance.m3colors.m3outline + horizontalAlignment: Text.AlignHCenter + text: "Anime boorus" + } + } } } - Rectangle { - id: tagInputFieldContainer + Rectangle { // Tag input field + id: tagInputContainer Layout.fillWidth: true radius: Appearance.rounding.small color: Appearance.colors.colLayer1 - implicitWidth: tagInputField.implicitWidth - implicitHeight: Math.max(tagInputField.implicitHeight, 45) + implicitWidth: tagInputColumnLayout.implicitWidth + implicitHeight: Math.max(tagInputColumnLayout.implicitHeight, 45) clip: true + border.color: Appearance.m3colors.m3outlineVariant + border.width: 1 Behavior on implicitHeight { NumberAnimation { @@ -85,56 +148,118 @@ Item { } } - TextArea { - id: tagInputField + ColumnLayout { + id: tagInputColumnLayout anchors.left: parent.left anchors.right: parent.right anchors.verticalCenter: parent.verticalCenter - wrapMode: TextArea.Wrap + TextArea { // The actual input field widget + id: tagInputField + wrapMode: TextArea.Wrap + Layout.fillWidth: true + Layout.topMargin: 5 + padding: 10 + color: activeFocus ? Appearance.m3colors.m3onSurface : Appearance.m3colors.m3onSurfaceVariant + renderType: Text.NativeRendering + selectedTextColor: Appearance.m3colors.m3onPrimary + selectionColor: Appearance.m3colors.m3primary + placeholderText: qsTr("Enter tags") + placeholderTextColor: Appearance.m3colors.m3outline - padding: 10 - color: activeFocus ? Appearance.m3colors.m3onSurface : Appearance.m3colors.m3onSurfaceVariant - renderType: Text.NativeRendering - selectedTextColor: Appearance.m3colors.m3onPrimary - selectionColor: Appearance.m3colors.m3primary - placeholderText: qsTr("Enter tags") - placeholderTextColor: Appearance.m3colors.m3outline + background: Item {} - Keys.onPressed: (event) => { - if ((event.key === Qt.Key_Enter || event.key === Qt.Key_Return)) { - if (event.modifiers & Qt.ShiftModifier) { - // Insert newline - tagInputField.insert(tagInputField.cursorPosition, "\n") - event.accepted = true - } else { - const inputText = tagInputField.text - if (inputText.startsWith("/")) { - // Handle special commands - const command = inputText.split(" ")[0].substring(1); - if (command === "clear") { - Booru.clearResponses(); - } - else if (command === "mode") { - const newProvider = inputText.split(" ")[1]; - Booru.setProvider(newProvider); - Booru.addSystemMessage(`Provider set to ${Booru.providers[newProvider].name}`); + Keys.onPressed: (event) => { + if ((event.key === Qt.Key_Enter || event.key === Qt.Key_Return)) { + if (event.modifiers & Qt.ShiftModifier) { + // Insert newline + tagInputField.insert(tagInputField.cursorPosition, "\n") + event.accepted = true + } else { // Accept text + const inputText = tagInputField.text + root.handleInput(inputText) + tagInputField.clear() + event.accepted = true + } + } + } + } + + RowLayout { // Controls + id: commandButtonsRow + spacing: 5 + Layout.bottomMargin: 5 + Layout.leftMargin: 5 + Layout.rightMargin: 5 + + property var commands: [ + { + name: "/mode", + sendDirectly: false, + }, + { + name: "/clear", + sendDirectly: true, + }, + ] + + Rectangle { + implicitWidth: switchesRow.implicitWidth + + RowLayout { + id: switchesRow + spacing: 5 + anchors.centerIn: parent + + StyledText { + Layout.fillHeight: true + Layout.leftMargin: 10 + Layout.alignment: Qt.AlignVCenter + font.pixelSize: Appearance.font.pixelSize.smaller + color: Appearance.colors.coloOnLayer1 + text: qsTr("NSFW") + } + StyledSwitch { + id: nsfwSwitch + scale: 0.75 + Layout.alignment: Qt.AlignVCenter + checked: ConfigOptions.sidebar.booru.allowNsfw + onCheckedChanged: { + ConfigOptions.sidebar.booru.allowNsfw = checked } } - else { - // Create tag list - const tagList = inputText.split(/\s+/); - let pageIndex = 1; - for (let i = 0; i < tagList.length; ++i) { // Detect page number - if (/^\d+$/.test(tagList[i])) { - pageIndex = parseInt(tagList[i], 10); - tagList.splice(i, 1); - break; + } + } + + Item { Layout.fillWidth: true } + + Repeater { // Command buttons + id: commandRepeater + model: commandButtonsRow.commands + delegate: BooruTagButton { + id: tagButton + buttonText: modelData.name + background: Rectangle { + radius: Appearance.rounding.small + color: (tagButton.down ? Appearance.colors.colLayer1Active : + tagButton.hovered ? Appearance.colors.colLayer1Hover : + Appearance.transparentize(Appearance.colors.colLayer1, 1)) + + Behavior on color { + ColorAnimation { + duration: Appearance.animation.elementDecel.duration + easing.type: Appearance.animation.elementDecel.type } } - Booru.makeRequest(tagList, ConfigOptions.sidebar.booru.allowNsfw, ConfigOptions.sidebar.booru.limit, pageIndex); } - tagInputField.clear() - event.accepted = true + onClicked: { + if(modelData.sendDirectly) { + root.handleInput(modelData.name) + } else { + tagInputField.text = modelData.name + " " + tagInputField.cursorPosition = tagInputField.text.length + tagInputField.forceActiveFocus() + } + } } } } diff --git a/.config/quickshell/modules/sidebarLeft/SidebarLeft.qml b/.config/quickshell/modules/sidebarLeft/SidebarLeft.qml index 7dfaaa42a..71f7713f1 100644 --- a/.config/quickshell/modules/sidebarLeft/SidebarLeft.qml +++ b/.config/quickshell/modules/sidebarLeft/SidebarLeft.qml @@ -90,9 +90,16 @@ Scope { // Scope if (event.modifiers === Qt.ControlModifier) { if (event.key === Qt.Key_PageDown) { sidebarRoot.currentTab = Math.min(sidebarRoot.currentTab + 1, root.tabButtonList.length - 1) - } else if (event.key === Qt.Key_PageUp) { + } + else if (event.key === Qt.Key_PageUp) { sidebarRoot.currentTab = Math.max(sidebarRoot.currentTab - 1, 0) } + else if (event.key === Qt.Key_Tab) { + sidebarRoot.currentTab = (sidebarRoot.currentTab + 1) % root.tabButtonList.length; + } + else if (event.key === Qt.Key_Backtab) { + sidebarRoot.currentTab = (sidebarRoot.currentTab - 1 + root.tabButtonList.length) % root.tabButtonList.length; + } event.accepted = true; } } diff --git a/.config/quickshell/modules/sidebarLeft/anime/BooruImage.qml b/.config/quickshell/modules/sidebarLeft/anime/BooruImage.qml index 8442754e9..6bd450a42 100644 --- a/.config/quickshell/modules/sidebarLeft/anime/BooruImage.qml +++ b/.config/quickshell/modules/sidebarLeft/anime/BooruImage.qml @@ -12,7 +12,13 @@ Button { property var imageData property var rowHeight + // onImageDataChanged: { + // console.log("Image data changed:", imageData) + // } + padding: 0 + implicitWidth: imageObject.width + implicitHeight: imageObject.height PointingHandInteraction {} @@ -21,27 +27,27 @@ Button { } background: Rectangle { - implicitWidth: imageData.width - implicitHeight: imageData.height + implicitWidth: imageObject.width + implicitHeight: imageObject.height radius: Appearance.rounding.small color: Appearance.colors.colLayer2 } contentItem: Image { - id: imageData + id: imageObject anchors.fill: parent - sourceSize.width: imageRow.rowHeight * modelData.aspect_ratio - sourceSize.height: imageRow.rowHeight + sourceSize.width: root.rowHeight * modelData.aspect_ratio + sourceSize.height: root.rowHeight fillMode: Image.PreserveAspectFit source: modelData.preview_url - width: imageRow.rowHeight * modelData.aspect_ratio - height: imageRow.rowHeight + width: root.rowHeight * modelData.aspect_ratio + height: root.rowHeight layer.enabled: true layer.effect: OpacityMask { maskSource: Rectangle { - width: imageData.width - height: imageData.height + width: imageObject.width + height: imageObject.height radius: Appearance.rounding.small } } diff --git a/.config/quickshell/modules/sidebarLeft/anime/BooruResponse.qml b/.config/quickshell/modules/sidebarLeft/anime/BooruResponse.qml index 6dd5c3498..42aaf8117 100644 --- a/.config/quickshell/modules/sidebarLeft/anime/BooruResponse.qml +++ b/.config/quickshell/modules/sidebarLeft/anime/BooruResponse.qml @@ -14,9 +14,13 @@ import Qt5Compat.GraphicalEffects Rectangle { id: root - property var responseData + property var responseData: {} property var tagInputField + onResponseDataChanged: { + console.log("Response data changed:", responseData) + } + property real availableWidth: parent?.width property real rowTooShortThreshold: 100 property real imageSpacing: 5 @@ -38,9 +42,8 @@ Rectangle { anchors.margins: responsePadding spacing: root.imageSpacing - // Provider name - RowLayout { - Rectangle { + RowLayout { // Header + Rectangle { // Provider name id: providerNameWrapper color: Appearance.m3colors.m3secondaryContainer radius: Appearance.rounding.small @@ -52,31 +55,33 @@ Rectangle { id: providerName anchors.centerIn: parent font.pixelSize: Appearance.font.pixelSize.large + font.weight: Font.DemiBold color: Appearance.m3colors.m3onSecondaryContainer text: Booru.providers[root.responseData.provider].name } } Item { Layout.fillWidth: true } - Rectangle { + Rectangle { // Page number + visible: root.responseData.page != "" && root.responseData.page > 0 color: Appearance.colors.colLayer2 radius: Appearance.rounding.small - implicitWidth: Math.max(pageNumber.implicitWidth + 10 * 2, 20) + implicitWidth: Math.max(pageNumber.implicitWidth + 10 * 2, 30) implicitHeight: pageNumber.implicitHeight + 5 * 2 - Layout.alignment: Qt.AlignVCenter + Layout.alignment: Qt.AlignTop StyledText { id: pageNumber anchors.centerIn: parent - font.pixelSize: Appearance.font.pixelSize.small + font.pixelSize: Appearance.font.pixelSize.smaller color: Appearance.colors.colOnLayer2 text: `Page ${root.responseData.page}` } } } - // Tags - Flickable { + Flickable { // Tag strip id: tagsFlickable + visible: root.responseData.tags.length > 0 Layout.alignment: Qt.AlignLeft Layout.fillWidth: { console.log(root.responseData) @@ -128,6 +133,28 @@ Rectangle { } } + StyledText { // Message + id: messageText + Layout.fillWidth: true + visible: root.responseData.message.length > 0 + font.pixelSize: Appearance.font.pixelSize.small + color: Appearance.colors.colOnLayer1 + text: root.responseData.message + wrapMode: Text.WordWrap + Layout.margins: responsePadding + textFormat: Text.MarkdownText + onLinkActivated: (link) => { + Qt.openUrlExternally(link) + Hyprland.dispatch("global quickshell:sidebarLeftClose") + } + MouseArea { + anchors.fill: parent + acceptedButtons: Qt.NoButton // Only for hover + hoverEnabled: true + cursorShape: parent.hoveredLink !== "" ? Qt.PointingHandCursor : Qt.ArrowCursor + } + } + Repeater { model: { // Group two images every row, ensuring they are of the same height diff --git a/.config/quickshell/modules/sidebarLeft/anime/BooruTagButton.qml b/.config/quickshell/modules/sidebarLeft/anime/BooruTagButton.qml index 02ed3883c..0154cdd23 100644 --- a/.config/quickshell/modules/sidebarLeft/anime/BooruTagButton.qml +++ b/.config/quickshell/modules/sidebarLeft/anime/BooruTagButton.qml @@ -22,8 +22,6 @@ Button { color: (button.down ? Appearance.colors.colSurfaceContainerHighestActive : button.hovered ? Appearance.colors.colSurfaceContainerHighestHover : Appearance.m3colors.m3surfaceContainerHighest) - - } contentItem: StyledText { diff --git a/.config/quickshell/modules/sidebarRight/CenterWidgetGroup.qml b/.config/quickshell/modules/sidebarRight/CenterWidgetGroup.qml index 1503ef107..3a4ed520f 100644 --- a/.config/quickshell/modules/sidebarRight/CenterWidgetGroup.qml +++ b/.config/quickshell/modules/sidebarRight/CenterWidgetGroup.qml @@ -28,6 +28,14 @@ Rectangle { } event.accepted = true; } + if (event.modifiers === Qt.ControlModifier) { + if (event.key === Qt.Key_Tab) { + root.currentTab = (root.currentTab + 1) % root.tabButtonList.length; + } else if (event.key === Qt.Key_Backtab) { + root.currentTab = (root.currentTab - 1 + root.tabButtonList.length) % root.tabButtonList.length; + } + event.accepted = true; + } } ColumnLayout { diff --git a/.config/quickshell/modules/sidebarRight/todo/TaskList.qml b/.config/quickshell/modules/sidebarRight/todo/TaskList.qml index f68dadaec..401ed1010 100644 --- a/.config/quickshell/modules/sidebarRight/todo/TaskList.qml +++ b/.config/quickshell/modules/sidebarRight/todo/TaskList.qml @@ -146,8 +146,8 @@ Item { } } } - // Placeholder when list is empty - Item { + + Item { // Placeholder when list is empty visible: taskList.length === 0 anchors.fill: parent diff --git a/.config/quickshell/services/Booru.qml b/.config/quickshell/services/Booru.qml index 4f4bf8549..1357d4f17 100644 --- a/.config/quickshell/services/Booru.qml +++ b/.config/quickshell/services/Booru.qml @@ -10,6 +10,13 @@ import QtQuick; Singleton { id: root + Connections { + target: ConfigOptions.sidebar.booru + function onAllowNsfwChanged() { + root.addSystemMessage(ConfigOptions.sidebar.booru.allowNsfw ? qsTr("Tiddies enabled") : qsTr("No horny")) + } + } + property var responses: [] property var getWorkingImageSource: (url) => { if (url.includes('pximg.net')) { @@ -42,7 +49,7 @@ Singleton { "sample_url": item.sample_url ?? item.file_url, "file_url": item.file_url, "file_ext": item.file_ext, - "source": getWorkingImageSource(item.source), + "source": getWorkingImageSource(item.source) ?? item.file_url, } }) } @@ -67,7 +74,7 @@ Singleton { "sample_url": item.sample_url ?? item.file_url, "file_url": item.file_url, "file_ext": item.file_ext, - "source": getWorkingImageSource(item.source), + "source": getWorkingImageSource(item.source) ?? item.file_url, } }) } @@ -92,7 +99,7 @@ Singleton { "sample_url": item.thumbnail, "file_url": item.thumbnail, "file_ext": "avif", - "source": getWorkingImageSource(item.source), + "source": getWorkingImageSource(item.source) ?? item.thumbnail, "character": item.tag } }) @@ -118,7 +125,7 @@ Singleton { "sample_url": item.file_url ?? item.large_file_url, "file_url": item.large_file_url, "file_ext": item.file_ext, - "source": getWorkingImageSource(item.source), + "source": getWorkingImageSource(item.source) ?? item.file_url, } }) } @@ -143,7 +150,7 @@ Singleton { "sample_url": item.sample_url ?? item.file_url, "file_url": item.file_url, "file_ext": item.file_url.split('.').pop(), - "source": getWorkingImageSource(item.source), + "source": getWorkingImageSource(item.source) ?? item.file_url, } }) } @@ -155,8 +162,11 @@ Singleton { function setProvider(provider) { if (providerList.indexOf(provider) !== -1) { currentProvider = provider + root.addSystemMessage(qsTr("Provider set to ") + providers[provider].name + + (provider == "zerochan" ? qsTr(". Notes for Zerochan:\n- You must enter a color\n- Set your zerochan username in `sidebar.booru.zerochan.username` config option. You [might be banned for not doing so](https://www.zerochan.net/api#:~:text=The%20request%20may%20still%20be%20completed%20successfully%20without%20this%20custom%20header%2C%20but%20your%20project%20may%20be%20banned%20for%20being%20anonymous.)!") : "")) } else { console.log("[Booru] Invalid provider: " + provider) + root.addSystemMessage(qsTr("Invalid provider. Supported providers: \n- ") + providerList.join("\n- ")) } } @@ -165,13 +175,13 @@ Singleton { } function addSystemMessage(message) { - responses.push({ + responses = [...responses, { "provider": "system", "tags": [], - "page": 1, + "page": -1, "images": [], "message": `${message}` - }) + }] } function constructRequestUrl(tags, nsfw=true, limit=20, page=1) { @@ -214,7 +224,7 @@ Singleton { if (xhr.readyState === XMLHttpRequest.DONE && xhr.status === 200) { try { // console.log("[Booru] Raw response length: " + xhr.responseText.length) - console.log("[Booru] Raw response: " + xhr.responseText) + // console.log("[Booru] Raw response: " + xhr.responseText) var response = JSON.parse(xhr.responseText) // Access nested properties based on listAccess @@ -227,16 +237,14 @@ Singleton { } } response = providers[currentProvider].mapFunc(response) - console.log("[Booru] Scoped & mapped response: " + JSON.stringify(response)) - var newResponses = root.responses.slice() // make a shallow copy - newResponses.push({ + // console.log("[Booru] Scoped & mapped response: " + JSON.stringify(response)) + root.responses = [...root.responses, { "provider": currentProvider, "tags": tags, "page": page, "images": response, "message": "" - }) - root.responses = newResponses + }] } catch (e) { console.log("[Booru] Failed to parse response: " + e)