booru: proper danbooru support, fix gelbooru

This commit is contained in:
end-4
2025-04-29 22:26:45 +02:00
parent f72e480e91
commit f2b523545b
6 changed files with 145 additions and 38 deletions
@@ -113,12 +113,14 @@ Singleton {
property color colOnLayer1Inactive: mix(colOnLayer1, colLayer1, 0.45);
property color colLayer2: mix(m3colors.m3surfaceContainer, m3colors.m3surfaceContainerHigh, 0.55);
property color colOnLayer2: m3colors.m3onSurface;
property color colOnLayer2Disabled: mix(colOnLayer2, m3colors.m3background, 0.4);
property color colLayer3: mix(m3colors.m3surfaceContainerHigh, m3colors.m3onSurface, 0.96);
property color colOnLayer3: m3colors.m3onSurface;
property color colLayer1Hover: mix(colLayer1, colOnLayer1, 0.88);
property color colLayer1Active: mix(colLayer1, colOnLayer1, 0.77);
property color colLayer2Hover: mix(colLayer2, colOnLayer2, 0.90);
property color colLayer2Active: mix(colLayer2, colOnLayer2, 0.80);
property color colLayer2Disabled: mix(colLayer2, m3colors.m3background, 0.8);
property color colLayer3Hover: mix(colLayer3, colOnLayer3, 0.90);
property color colLayer3Active: mix(colLayer3, colOnLayer3, 0.80);
property color colPrimaryHover: mix(m3colors.m3primary, colLayer1Hover, 0.85)
@@ -9,7 +9,7 @@ ToolTip {
property bool extraVisibleCondition: true
property bool alternativeVisibleCondition: false
property bool internalVisibleCondition: false
padding: 7
padding: 5
visible: ((extraVisibleCondition && (parent.hovered === undefined || parent?.hovered) && internalVisibleCondition)) || alternativeVisibleCondition
@@ -50,6 +50,7 @@ ToolTip {
StyledText {
id: tooltipTextObject
text: content
font.pixelSize: Appearance.font.pixelSize.smaller
color: Appearance.colors.colOnTooltip
wrapMode: Text.Wrap
}
@@ -3,6 +3,7 @@ import "root:/services"
import "root:/modules/common"
import "root:/modules/common/widgets"
import "./anime/"
import Qt.labs.platform
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
@@ -15,6 +16,14 @@ Item {
id: root
property var panelWindow
property var inputField: tagInputField
property string previewDownloadPath: `${StandardPaths.standardLocations(StandardPaths.CacheLocation)[0]}/media/waifus`.replace("file://", "")
property string downloadPath: (StandardPaths.standardLocations(StandardPaths.PicturesLocation)[0] + "/homework").replace("file://", "")
property string nsfwPath: (StandardPaths.standardLocations(StandardPaths.PicturesLocation)[0] + "/homework/🌶️").replace("file://", "")
Component.onCompleted: {
Hyprland.dispatch(`exec rm -rf ${previewDownloadPath}`)
Hyprland.dispatch(`exec mkdir -p ${previewDownloadPath}`)
}
function handleInput(inputText) {
if (inputText.startsWith("/")) {
@@ -28,9 +37,15 @@ Item {
const newProvider = args[0];
Booru.setProvider(newProvider);
}
else if (command == "lewd" || command == "nsfw") {
else if (command == "nsfw") {
ConfigOptions.sidebar.booru.allowNsfw = !ConfigOptions.sidebar.booru.allowNsfw
}
else if (command == "safe") {
ConfigOptions.sidebar.booru.allowNsfw = false
}
else if (command == "lewd") {
ConfigOptions.sidebar.booru.allowNsfw = true
}
}
else {
@@ -105,6 +120,9 @@ Item {
delegate: BooruResponse {
responseData: modelData
tagInputField: root.inputField
previewDownloadPath: root.previewDownloadPath
downloadPath: root.downloadPath
nsfwPath: root.nsfwPath
}
}
@@ -164,34 +182,78 @@ Item {
anchors.left: parent.left
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
TextArea { // The actual input field widget
id: tagInputField
wrapMode: TextArea.Wrap
Layout.fillWidth: true
RowLayout {
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
spacing: 0
TextArea { // The actual input field widget
id: tagInputField
wrapMode: TextArea.Wrap
Layout.fillWidth: true
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 {}
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 { // Accept text
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
}
}
}
}
Button { // Send button
id: sendButton
Layout.alignment: Qt.AlignTop
Layout.rightMargin: 5
implicitWidth: 40
implicitHeight: 40
enabled: tagInputField.text.length > 0
MouseArea {
anchors.fill: parent
cursorShape: sendButton.enabled ? Qt.PointingHandCursor : Qt.ArrowCursor
onClicked: {
const inputText = tagInputField.text
root.handleInput(inputText)
tagInputField.clear()
event.accepted = true
}
}
background: Rectangle {
radius: Appearance.rounding.small
color: sendButton.enabled ? (sendButton.down ? Appearance.colors.colPrimaryActive :
sendButton.hovered ? Appearance.colors.colPrimaryHover :
Appearance.m3colors.m3primary) : Appearance.colors.colLayer2Disabled
Behavior on color {
ColorAnimation {
duration: Appearance.animation.elementDecel.duration
easing.type: Appearance.animation.elementDecel.type
}
}
}
contentItem: MaterialSymbol {
anchors.centerIn: parent
text: "send"
horizontalAlignment: Text.AlignHCenter
font.pixelSize: Appearance.font.pixelSize.larger
color: sendButton.enabled ? Appearance.m3colors.m3onPrimary : Appearance.colors.colOnLayer2Disabled
}
}
}
@@ -216,8 +278,6 @@ Item {
Item {
implicitHeight: providerRowLayout.implicitHeight + 5 * 2
implicitWidth: providerRowLayout.implicitWidth + 10 * 2
// radius: Appearance.rounding.small
// color: Appearance.colors.colLayer1
RowLayout {
id: providerRowLayout
@@ -249,7 +309,7 @@ Item {
}
StyledText {
font.pixelSize: Appearance.font.pixelSize.small
font.pixelSize: Appearance.font.pixelSize.large
color: Appearance.colors.colOnLayer1
text: "•"
}
@@ -267,13 +327,13 @@ Item {
Layout.leftMargin: 10
Layout.alignment: Qt.AlignVCenter
font.pixelSize: Appearance.font.pixelSize.smaller
color: Appearance.colors.coloOnLayer1
color: Appearance.colors.colOnLayer1
text: qsTr("NSFW")
}
StyledSwitch {
id: nsfwSwitch
enabled: Booru.currentProvider !== "zerochan"
scale: 0.75
scale: 0.6
Layout.alignment: Qt.AlignVCenter
checked: (ConfigOptions.sidebar.booru.allowNsfw && Booru.currentProvider !== "zerochan")
onCheckedChanged: {
@@ -294,9 +354,9 @@ Item {
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))
color: tagButton.down ? Appearance.colors.colLayer2Active :
tagButton.hovered ? Appearance.colors.colLayer2Hover :
Appearance.colors.colLayer2
Behavior on color {
ColorAnimation {
@@ -1,9 +1,11 @@
import "root:/"
import "root:/modules/common"
import "root:/modules/common/widgets"
import Qt.labs.platform
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import Quickshell.Io
import Quickshell.Hyprland
import Qt5Compat.GraphicalEffects
@@ -11,10 +13,31 @@ Button {
id: root
property var imageData
property var rowHeight
property bool manualDownload: false
property string previewDownloadPath
property string downloadPath
property string nsfwPath
property string fileName: decodeURIComponent((imageData.file_url).substring((imageData.file_url).lastIndexOf('/') + 1))
// onImageDataChanged: {
// console.log("Image data changed:", imageData)
// }
Process {
id: downloadProcess
running: false
command: ["bash", "-c", `curl '${imageData.preview_url}' -o '${previewDownloadPath}/${root.fileName}' && echo 'done'`]
stdout: SplitParser {
onRead: (data) => {
console.log("Download output:", data)
if(data.includes("done")) {
imageObject.source = `${previewDownloadPath}/${root.fileName}`
}
}
}
}
Component.onCompleted: {
if (root.manualDownload) {
downloadProcess.running = true
}
}
padding: 0
implicitWidth: imageObject.width
@@ -17,11 +17,15 @@ Rectangle {
property var responseData
property var tagInputField
property string previewDownloadPath
property string downloadPath
property string nsfwPath
onResponseDataChanged: {
console.log("Response data changed:", responseData)
}
property real availableWidth: parent?.width
property real availableWidth: parent.width ?? 0
property real rowTooShortThreshold: 100
property real imageSpacing: 5
property real responsePadding: 5
@@ -65,7 +69,7 @@ Rectangle {
visible: root.responseData.page != "" && root.responseData.page > 0
implicitWidth: Math.max(pageNumber.implicitWidth + 10 * 2, 30)
implicitHeight: pageNumber.implicitHeight + 5 * 2
Layout.alignment: Qt.AlignTop
Layout.alignment: Qt.AlignVCenter
StyledText {
id: pageNumber
@@ -205,6 +209,10 @@ Rectangle {
delegate: BooruImage {
imageData: modelData
rowHeight: imageRow.rowHeight
manualDownload: root.responseData.provider == "danbooru"
previewDownloadPath: root.previewDownloadPath
downloadPath: root.downloadPath
nsfwPath: root.nsfwPath
}
}
}
+16 -3
View File
@@ -17,6 +17,7 @@ Singleton {
}
}
property string failMessage: qsTr("That didn't work. Tips:\n- Check your tags and NSFW settings\n- If you don't have a tag in mind, type a page number")
property var responses: []
property var getWorkingImageSource: (url) => {
if (url.includes('pximg.net')) {
@@ -203,7 +204,12 @@ Singleton {
else {
params.push("tags=" + encodeURIComponent(tagString))
params.push("limit=" + limit)
params.push("page=" + page)
if (currentProvider == "gelbooru") {
params.push("pid=" + page)
}
else {
params.push("page=" + page)
}
}
var url = baseUrl
if (baseUrl.indexOf("?") === -1) {
@@ -224,7 +230,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
@@ -243,11 +249,18 @@ Singleton {
"tags": tags,
"page": page,
"images": response,
"message": ""
"message": response.length > 0 ? "" : root.failMessage
}]
} catch (e) {
console.log("[Booru] Failed to parse response: " + e)
root.responses = [...root.responses, {
"provider": currentProvider,
"tags": tags,
"page": page,
"images": [],
"message": root.failMessage
}]
}
}
else if (xhr.readyState === XMLHttpRequest.DONE) {