booru: show provider and command description

This commit is contained in:
end-4
2025-05-03 21:31:31 +02:00
parent a2722478ba
commit bc8b01a6f6
3 changed files with 89 additions and 25 deletions
@@ -0,0 +1,5 @@
function format(str, ...args) {
return str.replace(/{(\d+)}/g, (match, index) =>
typeof args[index] !== 'undefined' ? args[index] : match
);
}
@@ -3,6 +3,7 @@ import "root:/services"
import "root:/modules/common"
import "root:/modules/common/widgets"
import "root:/modules/common/functions/fuzzysort.js" as Fuzzy
import "root:/modules/common/functions/string_utils.js" as StringUtils
import "./anime/"
import Qt.labs.platform
import QtQuick
@@ -55,36 +56,29 @@ Item {
}
},
{
name: "nsfw",
description: qsTr("Toggle NSFW mode"),
name: "next",
description: qsTr("Get the next page of results"),
execute: () => {
ConfigOptions.sidebar.booru.allowNsfw = !ConfigOptions.sidebar.booru.allowNsfw;
if (Booru.responses.length > 0) {
const lastResponse = Booru.responses[Booru.responses.length - 1];
root.handleInput(`${lastResponse.tags.join(" ")} ${parseInt(lastResponse.page) + 1}`);
}
}
},
{
name: "safe",
description: qsTr("Set NSFW mode to false"),
description: qsTr("Disable NSFW content"),
execute: () => {
ConfigOptions.sidebar.booru.allowNsfw = false;
}
},
{
name: "lewd",
description: qsTr("Set NSFW mode to true"),
description: qsTr("Allow NSFW content"),
execute: () => {
ConfigOptions.sidebar.booru.allowNsfw = true;
}
},
{
name: "next",
description: qsTr("Get the next page of results"),
execute: () => {
if (Booru.responses.length > 0) {
const lastResponse = Booru.responses[Booru.responses.length - 1];
root.handleInput(lastResponse.tags.join(" ") + ` ${parseInt(lastResponse.page) + 1}`);
}
}
}
]
function handleInput(inputText) {
@@ -233,10 +227,47 @@ Item {
}
}
Item { // Tag suggestion description
opacity: tagDescriptionText.text.length > 0 ? 1 : 0
visible: opacity > 0
Layout.fillWidth: true
implicitHeight: tagDescriptionBackground.implicitHeight
Behavior on opacity {
NumberAnimation {
duration: Appearance.animation.elementMoveFast.duration
easing.type: Appearance.animation.elementMoveFast.type
easing.bezierCurve: Appearance.animation.elementMoveFast.bezierCurve
}
}
Rectangle {
id: tagDescriptionBackground
color: Appearance.colors.colTooltip
anchors.left: parent.left
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
implicitHeight: tagDescriptionText.implicitHeight + 5 * 2
radius: Appearance.rounding.verysmall
StyledText {
id: tagDescriptionText
anchors.left: parent.left
anchors.right: parent.right
anchors.leftMargin: 10
anchors.rightMargin: 10
anchors.verticalCenter: parent.verticalCenter
font.pixelSize: Appearance.font.pixelSize.smaller
color: Appearance.colors.colOnTooltip
wrapMode: Text.Wrap
text: root.suggestionList[tagSuggestions.selectedIndex]?.description ?? ""
}
}
}
Flow { // Tag suggestions
id: tagSuggestions
visible: root.suggestionList.length > 0 &&
tagInputField.text.length > 0
visible: root.suggestionList.length > 0 && tagInputField.text.length > 0
property int selectedIndex: 0
Layout.fillWidth: true
spacing: 5
@@ -249,7 +280,7 @@ Item {
}
delegate: BooruTagButton {
id: tagButton
// buttonText: `${modelData.name}_{${modelData.count}}`
background: Rectangle {
radius: Appearance.rounding.small
color: tagSuggestions.selectedIndex === index ? Appearance.colors.colLayer2Hover :
@@ -270,7 +301,7 @@ Item {
StyledText {
font.pixelSize: Appearance.font.pixelSize.small
color: Appearance.m3colors.m3onSurface
text: modelData.name
text: modelData.displayName ?? modelData.name
}
StyledText {
visible: modelData.count !== undefined
@@ -279,6 +310,12 @@ Item {
text: modelData.count ?? ""
}
}
onHoveredChanged: {
if (tagButton.hovered) {
tagSuggestions.selectedIndex = index;
}
}
onClicked: {
tagSuggestions.acceptTag(modelData.name)
}
@@ -344,7 +381,7 @@ Item {
renderType: Text.NativeRendering
selectedTextColor: Appearance.m3colors.m3onPrimary
selectionColor: Appearance.m3colors.m3primary
placeholderText: qsTr("Enter tags")
placeholderText: StringUtils.format(qsTr('Enter tags, or "{0}" for commands'), root.commandPrefix)
placeholderTextColor: Appearance.m3colors.m3outline
background: Item {}
@@ -379,10 +416,11 @@ Item {
all: true,
key: "name"
})
console.log(JSON.stringify(providerResults))
root.suggestionList = providerResults.map(provider => {
return {
name: `${tagInputField.text.trim().split(" ").length == 1 ? (root.commandPrefix + "mode ") : ""}${provider.target}`,
displayName: `${Booru.providers[provider.target].name}`,
description: `${Booru.providers[provider.target].description}`,
}
})
searchTimer.stop();
@@ -393,6 +431,7 @@ Item {
root.suggestionList = root.allCommands.filter(cmd => cmd.name.startsWith(tagInputField.text.substring(1))).map(cmd => {
return {
name: `${root.commandPrefix}${cmd.name}`,
description: `${cmd.description}`,
}
})
searchTimer.stop();
@@ -517,6 +556,7 @@ Item {
}
StyledToolTip {
id: toolTip
extraVisibleCondition: false
alternativeVisibleCondition: mouseArea.containsMouse // Show tooltip when hovered
content: qsTr("The current API used. Endpoint: ") + Booru.providers[Booru.currentProvider].url + qsTr("\nSet with /mode PROVIDER")
}
@@ -534,7 +574,7 @@ Item {
text: "•"
}
Rectangle {
Rectangle { // NSFW toggle
implicitWidth: switchesRow.implicitWidth
RowLayout {
@@ -542,13 +582,22 @@ Item {
spacing: 5
anchors.centerIn: parent
MouseArea {
anchors.fill: parent
hoverEnabled: true
PointingHandInteraction {}
onClicked: {
nsfwSwitch.checked = !nsfwSwitch.checked
}
}
StyledText {
Layout.fillHeight: true
Layout.leftMargin: 10
Layout.alignment: Qt.AlignVCenter
font.pixelSize: Appearance.font.pixelSize.smaller
color: Appearance.colors.colOnLayer1
text: qsTr("NSFW")
color: nsfwSwitch.enabled ? Appearance.colors.colOnLayer1 : Appearance.m3colors.m3outline
text: qsTr("Allow NSFW")
}
StyledSwitch {
id: nsfwSwitch
+11 -1
View File
@@ -35,6 +35,7 @@ Singleton {
"name": "yande.re",
"url": "https://yande.re",
"api": "https://yande.re/post.json",
"description": "All-rounder | Good quality, decent quantity",
"mapFunc": (response) => {
return response.map(item => {
return {
@@ -68,6 +69,7 @@ Singleton {
"name": "Konachan",
"url": "https://konachan.com",
"api": "https://konachan.com/post.json",
"description": "For desktop wallpapers | Good quality",
"mapFunc": (response) => {
return response.map(item => {
return {
@@ -101,6 +103,7 @@ Singleton {
"name": "Zerochan",
"url": "https://www.zerochan.net",
"api": "https://www.zerochan.net/?json",
"description": "Clean stuff | Excellent quality, no NSFW",
"mapFunc": (response) => {
response = response.items
return response.map(item => {
@@ -127,6 +130,7 @@ Singleton {
"name": "Danbooru",
"url": "https://danbooru.donmai.us",
"api": "https://danbooru.donmai.us/posts.json",
"description": "The popular one | Best quantity, but quality can vary wildly",
"mapFunc": (response) => {
return response.map(item => {
return {
@@ -161,6 +165,7 @@ Singleton {
"name": "Gelbooru",
"url": "https://gelbooru.com",
"api": "https://gelbooru.com/index.php?page=dapi&s=post&q=index&json=1",
"description": "The hentai one | Great quantity, a lot of NSFW, quality varies wildly",
"mapFunc": (response) => {
response = response.post
return response.map(item => {
@@ -195,6 +200,7 @@ Singleton {
"name": "waifu.im",
"url": "https://waifu.im",
"api": "https://api.waifu.im/search",
"description": "Waifus only | Excellent quality, limited quantity",
"mapFunc": (response) => {
response = response.images
return response.map(item => {
@@ -226,6 +232,7 @@ Singleton {
property var currentProvider: ConfigOptions.sidebar.booru.defaultProvider
function setProvider(provider) {
provider = provider.toLowerCase()
if (providerList.indexOf(provider) !== -1) {
currentProvider = provider
root.addSystemMessage(qsTr("Provider set to ") + providers[provider].name
@@ -254,7 +261,10 @@ Singleton {
var baseUrl = provider.api
var tagString = tags.join(" ")
if (!nsfw && !(["zerochan", "waifu.im"].includes(currentProvider))) {
tagString += " rating:safe"
if (currentProvider == "gelbooru")
tagString += " rating:general";
else
tagString += " rating:safe";
}
var params = []
// Tags & limit