forked from Shinonome/dots-hyprland
booru: proper danbooru support, fix gelbooru
This commit is contained in:
@@ -113,12 +113,14 @@ Singleton {
|
|||||||
property color colOnLayer1Inactive: mix(colOnLayer1, colLayer1, 0.45);
|
property color colOnLayer1Inactive: mix(colOnLayer1, colLayer1, 0.45);
|
||||||
property color colLayer2: mix(m3colors.m3surfaceContainer, m3colors.m3surfaceContainerHigh, 0.55);
|
property color colLayer2: mix(m3colors.m3surfaceContainer, m3colors.m3surfaceContainerHigh, 0.55);
|
||||||
property color colOnLayer2: m3colors.m3onSurface;
|
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 colLayer3: mix(m3colors.m3surfaceContainerHigh, m3colors.m3onSurface, 0.96);
|
||||||
property color colOnLayer3: m3colors.m3onSurface;
|
property color colOnLayer3: m3colors.m3onSurface;
|
||||||
property color colLayer1Hover: mix(colLayer1, colOnLayer1, 0.88);
|
property color colLayer1Hover: mix(colLayer1, colOnLayer1, 0.88);
|
||||||
property color colLayer1Active: mix(colLayer1, colOnLayer1, 0.77);
|
property color colLayer1Active: mix(colLayer1, colOnLayer1, 0.77);
|
||||||
property color colLayer2Hover: mix(colLayer2, colOnLayer2, 0.90);
|
property color colLayer2Hover: mix(colLayer2, colOnLayer2, 0.90);
|
||||||
property color colLayer2Active: mix(colLayer2, colOnLayer2, 0.80);
|
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 colLayer3Hover: mix(colLayer3, colOnLayer3, 0.90);
|
||||||
property color colLayer3Active: mix(colLayer3, colOnLayer3, 0.80);
|
property color colLayer3Active: mix(colLayer3, colOnLayer3, 0.80);
|
||||||
property color colPrimaryHover: mix(m3colors.m3primary, colLayer1Hover, 0.85)
|
property color colPrimaryHover: mix(m3colors.m3primary, colLayer1Hover, 0.85)
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ ToolTip {
|
|||||||
property bool extraVisibleCondition: true
|
property bool extraVisibleCondition: true
|
||||||
property bool alternativeVisibleCondition: false
|
property bool alternativeVisibleCondition: false
|
||||||
property bool internalVisibleCondition: false
|
property bool internalVisibleCondition: false
|
||||||
padding: 7
|
padding: 5
|
||||||
|
|
||||||
visible: ((extraVisibleCondition && (parent.hovered === undefined || parent?.hovered) && internalVisibleCondition)) || alternativeVisibleCondition
|
visible: ((extraVisibleCondition && (parent.hovered === undefined || parent?.hovered) && internalVisibleCondition)) || alternativeVisibleCondition
|
||||||
|
|
||||||
@@ -50,6 +50,7 @@ ToolTip {
|
|||||||
StyledText {
|
StyledText {
|
||||||
id: tooltipTextObject
|
id: tooltipTextObject
|
||||||
text: content
|
text: content
|
||||||
|
font.pixelSize: Appearance.font.pixelSize.smaller
|
||||||
color: Appearance.colors.colOnTooltip
|
color: Appearance.colors.colOnTooltip
|
||||||
wrapMode: Text.Wrap
|
wrapMode: Text.Wrap
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import "root:/services"
|
|||||||
import "root:/modules/common"
|
import "root:/modules/common"
|
||||||
import "root:/modules/common/widgets"
|
import "root:/modules/common/widgets"
|
||||||
import "./anime/"
|
import "./anime/"
|
||||||
|
import Qt.labs.platform
|
||||||
import QtQuick
|
import QtQuick
|
||||||
import QtQuick.Controls
|
import QtQuick.Controls
|
||||||
import QtQuick.Layouts
|
import QtQuick.Layouts
|
||||||
@@ -15,6 +16,14 @@ Item {
|
|||||||
id: root
|
id: root
|
||||||
property var panelWindow
|
property var panelWindow
|
||||||
property var inputField: tagInputField
|
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) {
|
function handleInput(inputText) {
|
||||||
if (inputText.startsWith("/")) {
|
if (inputText.startsWith("/")) {
|
||||||
@@ -28,9 +37,15 @@ Item {
|
|||||||
const newProvider = args[0];
|
const newProvider = args[0];
|
||||||
Booru.setProvider(newProvider);
|
Booru.setProvider(newProvider);
|
||||||
}
|
}
|
||||||
else if (command == "lewd" || command == "nsfw") {
|
else if (command == "nsfw") {
|
||||||
ConfigOptions.sidebar.booru.allowNsfw = !ConfigOptions.sidebar.booru.allowNsfw
|
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 {
|
else {
|
||||||
@@ -105,6 +120,9 @@ Item {
|
|||||||
delegate: BooruResponse {
|
delegate: BooruResponse {
|
||||||
responseData: modelData
|
responseData: modelData
|
||||||
tagInputField: root.inputField
|
tagInputField: root.inputField
|
||||||
|
previewDownloadPath: root.previewDownloadPath
|
||||||
|
downloadPath: root.downloadPath
|
||||||
|
nsfwPath: root.nsfwPath
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -164,34 +182,78 @@ Item {
|
|||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
TextArea { // The actual input field widget
|
|
||||||
id: tagInputField
|
RowLayout {
|
||||||
wrapMode: TextArea.Wrap
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.topMargin: 5
|
Layout.topMargin: 5
|
||||||
padding: 10
|
spacing: 0
|
||||||
color: activeFocus ? Appearance.m3colors.m3onSurface : Appearance.m3colors.m3onSurfaceVariant
|
TextArea { // The actual input field widget
|
||||||
renderType: Text.NativeRendering
|
id: tagInputField
|
||||||
selectedTextColor: Appearance.m3colors.m3onPrimary
|
wrapMode: TextArea.Wrap
|
||||||
selectionColor: Appearance.m3colors.m3primary
|
Layout.fillWidth: true
|
||||||
placeholderText: qsTr("Enter tags")
|
padding: 10
|
||||||
placeholderTextColor: Appearance.m3colors.m3outline
|
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) => {
|
Keys.onPressed: (event) => {
|
||||||
if ((event.key === Qt.Key_Enter || event.key === Qt.Key_Return)) {
|
if ((event.key === Qt.Key_Enter || event.key === Qt.Key_Return)) {
|
||||||
if (event.modifiers & Qt.ShiftModifier) {
|
if (event.modifiers & Qt.ShiftModifier) {
|
||||||
// Insert newline
|
// Insert newline
|
||||||
tagInputField.insert(tagInputField.cursorPosition, "\n")
|
tagInputField.insert(tagInputField.cursorPosition, "\n")
|
||||||
event.accepted = true
|
event.accepted = true
|
||||||
} else { // Accept text
|
} 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
|
const inputText = tagInputField.text
|
||||||
root.handleInput(inputText)
|
root.handleInput(inputText)
|
||||||
tagInputField.clear()
|
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 {
|
Item {
|
||||||
implicitHeight: providerRowLayout.implicitHeight + 5 * 2
|
implicitHeight: providerRowLayout.implicitHeight + 5 * 2
|
||||||
implicitWidth: providerRowLayout.implicitWidth + 10 * 2
|
implicitWidth: providerRowLayout.implicitWidth + 10 * 2
|
||||||
// radius: Appearance.rounding.small
|
|
||||||
// color: Appearance.colors.colLayer1
|
|
||||||
|
|
||||||
RowLayout {
|
RowLayout {
|
||||||
id: providerRowLayout
|
id: providerRowLayout
|
||||||
@@ -249,7 +309,7 @@ Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
font.pixelSize: Appearance.font.pixelSize.small
|
font.pixelSize: Appearance.font.pixelSize.large
|
||||||
color: Appearance.colors.colOnLayer1
|
color: Appearance.colors.colOnLayer1
|
||||||
text: "•"
|
text: "•"
|
||||||
}
|
}
|
||||||
@@ -267,13 +327,13 @@ Item {
|
|||||||
Layout.leftMargin: 10
|
Layout.leftMargin: 10
|
||||||
Layout.alignment: Qt.AlignVCenter
|
Layout.alignment: Qt.AlignVCenter
|
||||||
font.pixelSize: Appearance.font.pixelSize.smaller
|
font.pixelSize: Appearance.font.pixelSize.smaller
|
||||||
color: Appearance.colors.coloOnLayer1
|
color: Appearance.colors.colOnLayer1
|
||||||
text: qsTr("NSFW")
|
text: qsTr("NSFW")
|
||||||
}
|
}
|
||||||
StyledSwitch {
|
StyledSwitch {
|
||||||
id: nsfwSwitch
|
id: nsfwSwitch
|
||||||
enabled: Booru.currentProvider !== "zerochan"
|
enabled: Booru.currentProvider !== "zerochan"
|
||||||
scale: 0.75
|
scale: 0.6
|
||||||
Layout.alignment: Qt.AlignVCenter
|
Layout.alignment: Qt.AlignVCenter
|
||||||
checked: (ConfigOptions.sidebar.booru.allowNsfw && Booru.currentProvider !== "zerochan")
|
checked: (ConfigOptions.sidebar.booru.allowNsfw && Booru.currentProvider !== "zerochan")
|
||||||
onCheckedChanged: {
|
onCheckedChanged: {
|
||||||
@@ -294,9 +354,9 @@ Item {
|
|||||||
buttonText: modelData.name
|
buttonText: modelData.name
|
||||||
background: Rectangle {
|
background: Rectangle {
|
||||||
radius: Appearance.rounding.small
|
radius: Appearance.rounding.small
|
||||||
color: (tagButton.down ? Appearance.colors.colLayer1Active :
|
color: tagButton.down ? Appearance.colors.colLayer2Active :
|
||||||
tagButton.hovered ? Appearance.colors.colLayer1Hover :
|
tagButton.hovered ? Appearance.colors.colLayer2Hover :
|
||||||
Appearance.transparentize(Appearance.colors.colLayer1, 1))
|
Appearance.colors.colLayer2
|
||||||
|
|
||||||
Behavior on color {
|
Behavior on color {
|
||||||
ColorAnimation {
|
ColorAnimation {
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
import "root:/"
|
import "root:/"
|
||||||
import "root:/modules/common"
|
import "root:/modules/common"
|
||||||
import "root:/modules/common/widgets"
|
import "root:/modules/common/widgets"
|
||||||
|
import Qt.labs.platform
|
||||||
import QtQuick
|
import QtQuick
|
||||||
import QtQuick.Controls
|
import QtQuick.Controls
|
||||||
import QtQuick.Layouts
|
import QtQuick.Layouts
|
||||||
|
import Quickshell.Io
|
||||||
import Quickshell.Hyprland
|
import Quickshell.Hyprland
|
||||||
import Qt5Compat.GraphicalEffects
|
import Qt5Compat.GraphicalEffects
|
||||||
|
|
||||||
@@ -11,10 +13,31 @@ Button {
|
|||||||
id: root
|
id: root
|
||||||
property var imageData
|
property var imageData
|
||||||
property var rowHeight
|
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: {
|
Process {
|
||||||
// console.log("Image data changed:", imageData)
|
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
|
padding: 0
|
||||||
implicitWidth: imageObject.width
|
implicitWidth: imageObject.width
|
||||||
|
|||||||
@@ -17,11 +17,15 @@ Rectangle {
|
|||||||
property var responseData
|
property var responseData
|
||||||
property var tagInputField
|
property var tagInputField
|
||||||
|
|
||||||
|
property string previewDownloadPath
|
||||||
|
property string downloadPath
|
||||||
|
property string nsfwPath
|
||||||
|
|
||||||
onResponseDataChanged: {
|
onResponseDataChanged: {
|
||||||
console.log("Response data changed:", responseData)
|
console.log("Response data changed:", responseData)
|
||||||
}
|
}
|
||||||
|
|
||||||
property real availableWidth: parent?.width
|
property real availableWidth: parent.width ?? 0
|
||||||
property real rowTooShortThreshold: 100
|
property real rowTooShortThreshold: 100
|
||||||
property real imageSpacing: 5
|
property real imageSpacing: 5
|
||||||
property real responsePadding: 5
|
property real responsePadding: 5
|
||||||
@@ -65,7 +69,7 @@ Rectangle {
|
|||||||
visible: root.responseData.page != "" && root.responseData.page > 0
|
visible: root.responseData.page != "" && root.responseData.page > 0
|
||||||
implicitWidth: Math.max(pageNumber.implicitWidth + 10 * 2, 30)
|
implicitWidth: Math.max(pageNumber.implicitWidth + 10 * 2, 30)
|
||||||
implicitHeight: pageNumber.implicitHeight + 5 * 2
|
implicitHeight: pageNumber.implicitHeight + 5 * 2
|
||||||
Layout.alignment: Qt.AlignTop
|
Layout.alignment: Qt.AlignVCenter
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
id: pageNumber
|
id: pageNumber
|
||||||
@@ -205,6 +209,10 @@ Rectangle {
|
|||||||
delegate: BooruImage {
|
delegate: BooruImage {
|
||||||
imageData: modelData
|
imageData: modelData
|
||||||
rowHeight: imageRow.rowHeight
|
rowHeight: imageRow.rowHeight
|
||||||
|
manualDownload: root.responseData.provider == "danbooru"
|
||||||
|
previewDownloadPath: root.previewDownloadPath
|
||||||
|
downloadPath: root.downloadPath
|
||||||
|
nsfwPath: root.nsfwPath
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 responses: []
|
||||||
property var getWorkingImageSource: (url) => {
|
property var getWorkingImageSource: (url) => {
|
||||||
if (url.includes('pximg.net')) {
|
if (url.includes('pximg.net')) {
|
||||||
@@ -203,7 +204,12 @@ Singleton {
|
|||||||
else {
|
else {
|
||||||
params.push("tags=" + encodeURIComponent(tagString))
|
params.push("tags=" + encodeURIComponent(tagString))
|
||||||
params.push("limit=" + limit)
|
params.push("limit=" + limit)
|
||||||
params.push("page=" + page)
|
if (currentProvider == "gelbooru") {
|
||||||
|
params.push("pid=" + page)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
params.push("page=" + page)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
var url = baseUrl
|
var url = baseUrl
|
||||||
if (baseUrl.indexOf("?") === -1) {
|
if (baseUrl.indexOf("?") === -1) {
|
||||||
@@ -224,7 +230,7 @@ Singleton {
|
|||||||
if (xhr.readyState === XMLHttpRequest.DONE && xhr.status === 200) {
|
if (xhr.readyState === XMLHttpRequest.DONE && xhr.status === 200) {
|
||||||
try {
|
try {
|
||||||
// console.log("[Booru] Raw response length: " + xhr.responseText.length)
|
// 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)
|
var response = JSON.parse(xhr.responseText)
|
||||||
|
|
||||||
// Access nested properties based on listAccess
|
// Access nested properties based on listAccess
|
||||||
@@ -243,11 +249,18 @@ Singleton {
|
|||||||
"tags": tags,
|
"tags": tags,
|
||||||
"page": page,
|
"page": page,
|
||||||
"images": response,
|
"images": response,
|
||||||
"message": ""
|
"message": response.length > 0 ? "" : root.failMessage
|
||||||
}]
|
}]
|
||||||
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log("[Booru] Failed to parse response: " + 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) {
|
else if (xhr.readyState === XMLHttpRequest.DONE) {
|
||||||
|
|||||||
Reference in New Issue
Block a user