booru: more anims, add konachan

This commit is contained in:
end-4
2024-04-04 21:45:20 +07:00
parent 3d823c8947
commit 2ed9ed4b91
4 changed files with 98 additions and 83 deletions
@@ -61,6 +61,7 @@ export const ConfigToggle = ({
}); });
const interactionWrapper = Button({ const interactionWrapper = Button({
attribute: { attribute: {
enabled: enabled,
toggle: (newValue) => { toggle: (newValue) => {
enabled.value = !enabled.value; enabled.value = !enabled.value;
onChange(interactionWrapper, enabled.value); onChange(interactionWrapper, enabled.value);
+69 -66
View File
@@ -1,10 +1,7 @@
// TODO: execAsync(['identify', '-format', '{"w":%w,"h":%h}', imagePath])
// to detect img dimensions
const { Gdk, GdkPixbuf, Gio, GLib, Gtk } = imports.gi; const { Gdk, GdkPixbuf, Gio, GLib, Gtk } = imports.gi;
import Widget from 'resource:///com/github/Aylur/ags/widget.js'; import Widget from 'resource:///com/github/Aylur/ags/widget.js';
import * as Utils from 'resource:///com/github/Aylur/ags/utils.js'; import * as Utils from 'resource:///com/github/Aylur/ags/utils.js';
const { Box, Button, Label, Overlay, Revealer, Scrollable, Stack } = Widget; const { Box, Button, EventBox, Label, Overlay, Revealer, Scrollable, Stack } = Widget;
const { execAsync, exec } = Utils; const { execAsync, exec } = Utils;
import { fileExists } from '../../.miscutils/files.js'; import { fileExists } from '../../.miscutils/files.js';
import { MaterialIcon } from '../../.commonwidgets/materialicon.js'; import { MaterialIcon } from '../../.commonwidgets/materialicon.js';
@@ -13,15 +10,6 @@ import { setupCursorHover, setupCursorHoverInfo } from '../../.widgetutils/curso
import BooruService from '../../../services/booru.js'; import BooruService from '../../../services/booru.js';
import { chatEntry } from '../apiwidgets.js'; import { chatEntry } from '../apiwidgets.js';
import { ConfigToggle } from '../../.commonwidgets/configwidgets.js'; import { ConfigToggle } from '../../.commonwidgets/configwidgets.js';
const Grid = Widget.subclass(Gtk.Grid, "AgsGrid");
async function getImageViewerApp(preferredApp) {
Utils.execAsync(['bash', '-c', `command -v ${preferredApp}`])
.then((output) => {
if (output != '') return preferredApp;
else return 'xdg-open';
});
}
const IMAGE_REVEAL_DELAY = 13; // Some wait for inits n other weird stuff const IMAGE_REVEAL_DELAY = 13; // Some wait for inits n other weird stuff
const USER_CACHE_DIR = GLib.get_user_cache_dir(); const USER_CACHE_DIR = GLib.get_user_cache_dir();
@@ -71,7 +59,7 @@ const BooruInfo = () => {
className: 'txt-smallie txt-subtext', className: 'txt-smallie txt-subtext',
wrap: true, wrap: true,
justify: Gtk.Justification.CENTER, justify: Gtk.Justification.CENTER,
label: 'Powered by yande.re', label: 'Powered by yande.re and konachan',
}), }),
Button({ Button({
className: 'txt-subtext txt-norm icon-material', className: 'txt-subtext txt-norm icon-material',
@@ -108,6 +96,9 @@ export const BooruSettings = () => MarginRevealer({
onChange: (self, newValue) => { onChange: (self, newValue) => {
BooruService.nsfw = newValue; BooruService.nsfw = newValue;
}, },
extraSetup: (self) => self.hook(BooruService, (self) => {
self.attribute.enabled.value = BooruService.nsfw;
}, 'notify::nsfw')
}), }),
] ]
}) })
@@ -129,7 +120,7 @@ const booruWelcome = Box({
}) })
}); });
const BooruPage = (taglist) => { const BooruPage = (taglist, serviceName = 'Booru') => {
const PageState = (icon, name) => Box({ const PageState = (icon, name) => Box({
className: 'spacing-h-5 txt', className: 'spacing-h-5 txt',
children: [ children: [
@@ -181,6 +172,7 @@ const BooruPage = (taglist) => {
cr.paint(); cr.paint();
}); });
self.queue_draw(); self.queue_draw();
imageRevealer.revealChild = true;
} }
// Show // Show
// const downloadCommand = `wget -O '${imagePath}' '${data.preview_url}'`; // const downloadCommand = `wget -O '${imagePath}' '${data.preview_url}'`;
@@ -198,27 +190,42 @@ const BooruPage = (taglist) => {
Utils.timeout(1000, () => self.attribute.update(self, data)); Utils.timeout(1000, () => self.attribute.update(self, data));
} }
}); });
const imageActions = Box({ const imageActions = Revealer({
vpack: 'start', transition: 'crossfade',
className: 'sidebar-booru-image-actions spacing-h-3', transitionDuration: userOptions.animations.durationLarge,
children: [ child: Box({
Box({ hexpand: true }), vpack: 'start',
ImageAction({ className: 'sidebar-booru-image-actions spacing-h-3',
name: 'Go to file url', children: [
icon: 'file_open', Box({ hexpand: true }),
action: () => execAsync(['xdg-open', `${data.file_url}`]).catch(print), ImageAction({
}), name: 'Go to file url',
ImageAction({ icon: 'file_open',
name: 'Go to source', action: () => execAsync(['xdg-open', `${data.file_url}`]).catch(print),
icon: 'open_in_new', }),
action: () => execAsync(['xdg-open', `${data.source}`]).catch(print), ImageAction({
}), name: 'Go to source',
] icon: 'open_in_new',
action: () => execAsync(['xdg-open', `${data.source}`]).catch(print),
}),
]
})
}); });
return Overlay({ const imageOverlay = Overlay({
passThrough: true,
child: imageBox, child: imageBox,
overlays: [imageActions] overlays: [imageActions]
});
const imageRevealer = Revealer({
transition: 'slide_down',
transitionDuration: userOptions.animations.durationLarge,
child: EventBox({
onHover: () => { imageActions.revealChild = true },
onHoverLost: () => { imageActions.revealChild = false },
child: imageOverlay,
})
}) })
return imageRevealer;
} }
const downloadState = Stack({ const downloadState = Stack({
homogeneous: false, homogeneous: false,
@@ -238,22 +245,31 @@ const BooruPage = (taglist) => {
child: downloadState, child: downloadState,
}); });
const pageHeading = Box({ const pageHeading = Box({
homogeneous: false, vertical: true,
children: [ children: [
Scrollable({ Label({
hexpand: true, hpack: 'start',
vscroll: 'never', className: `sidebar-booru-provider`,
hscroll: 'automatic', label: `${serviceName}`,
child: Box({
hpack: 'fill',
className: 'spacing-h-5',
children: [
...taglist.map((tag) => CommandButton(tag)),
Box({ hexpand: true }),
]
})
}), }),
downloadIndicator, Box({
children: [
Scrollable({
hexpand: true,
vscroll: 'never',
hscroll: 'automatic',
child: Box({
hpack: 'fill',
className: 'spacing-h-5',
children: [
...taglist.map((tag) => CommandButton(tag)),
Box({ hexpand: true }),
]
})
}),
downloadIndicator,
]
})
] ]
}); });
const pageImages = Box({ const pageImages = Box({
@@ -308,25 +324,6 @@ const BooruPage = (taglist) => {
pageImages.children[minIndex].pack_start(PreviewImage(data[i], minIndex), false, false, 0) pageImages.children[minIndex].pack_start(PreviewImage(data[i], minIndex), false, false, 0)
pageImages.children[minIndex].attribute.height += 1 / data[i].aspect_ratio; // we want height/width pageImages.children[minIndex].attribute.height += 1 / data[i].aspect_ratio; // we want height/width
} }
// Show all
// for(let i = 0; i < imageColumns; i++) {
// pageImages.children[i].show_all();
// }
pageImages.show_all();
// each image: PreviewImage(data[i * imageColumns + j])
// Add stuff
// for (let i = 0; i < imageRows; i++) {
// for (let j = 0; j < imageColumns; j++) {
// if (i * imageColumns + j >= Math.min(userOptions.sidebar.imageBooruCount, data.length)) break;
// pageImages.attach(
// PreviewImage(data[i * imageColumns + j]),
// j, i, 1, 1
// );
// }
// }
pageImages.show_all(); pageImages.show_all();
// Reveal stuff // Reveal stuff
@@ -360,7 +357,7 @@ const booruContent = Box({
setup: (self) => self setup: (self) => self
.hook(BooruService, (box, id) => { .hook(BooruService, (box, id) => {
if (id === undefined) return; if (id === undefined) return;
const newPage = BooruPage(BooruService.queries[id]); const newPage = BooruPage(BooruService.queries[id].taglist, BooruService.queries[id].providerName);
box.add(newPage); box.add(newPage);
box.show_all(); box.show_all();
box.attribute.map.set(id, newPage); box.attribute.map.set(id, newPage);
@@ -453,6 +450,12 @@ export const sendMessage = (text) => {
// Commands // Commands
if (text.startsWith('/')) { if (text.startsWith('/')) {
if (text.startsWith('/clear')) clearChat(); if (text.startsWith('/clear')) clearChat();
else if (text.startsWith('/safe')) BooruService.nsfw = false;
else if (text.startsWith('/lewd')) BooruService.nsfw = true;
else if (text.startsWith('/mode')) {
const firstSpaceIndex = text.indexOf(' ');
BooruService.mode = text.slice(firstSpaceIndex + 1);
}
} }
else BooruService.fetch(text); else BooruService.fetch(text);
} }
+13 -14
View File
@@ -9,8 +9,7 @@ $sidebar_chat_textboxareaColor: mix($onSurfaceVariant, $surfaceVariant, 40%);
@include elevation-border; @include elevation-border;
@include elevation2; @include elevation2;
border-radius: $rounding_large - $elevation_margin + 0.068rem; border-radius: $rounding_large - $elevation_margin + 0.068rem;
min-width: 27.818rem; // COMMENT THIS LATER IF TEXT WRAP IS USED min-width: 27.818rem;
// min-height: 29.591rem;
background-color: $background; background-color: $background;
padding: 1.023rem; padding: 1.023rem;
} }
@@ -30,8 +29,7 @@ $sidebar_chat_textboxareaColor: mix($onSurfaceVariant, $surfaceVariant, 40%);
@include elevation-border; @include elevation-border;
@include elevation2; @include elevation2;
border-radius: $rounding_large - $elevation_margin + 0.068rem; border-radius: $rounding_large - $elevation_margin + 0.068rem;
min-width: 27.818rem; // COMMENT THIS LATER IF TEXT WRAP IS USED min-width: 27.818rem;
// min-height: 29.591rem;
background-color: $background; background-color: $background;
padding: 1.023rem; padding: 1.023rem;
} }
@@ -123,7 +121,6 @@ $sidebar_chat_textboxareaColor: mix($onSurfaceVariant, $surfaceVariant, 40%);
} }
.sidebar-navrail { .sidebar-navrail {
// background-color: $surface;
padding: 0rem $rounding_medium; padding: 0rem $rounding_medium;
} }
@@ -505,13 +502,8 @@ $colorpicker_rounding: 0.341rem;
color: $onSurfaceVariant; color: $onSurfaceVariant;
} }
// .sidebar-chat-providerswitcher-list {
// margin: 0.341rem 0rem;
// }
.sidebar-chat-viewport { .sidebar-chat-viewport {
@include element_decel; @include element_decel;
// margin: 0.682rem 0rem;
padding: 0.682rem 0rem; padding: 0.682rem 0rem;
} }
@@ -592,7 +584,6 @@ $colorpicker_rounding: 0.341rem;
@include small-rounding; @include small-rounding;
padding: 0.341rem 0.818rem; padding: 0.341rem 0.818rem;
margin: 0.341rem; margin: 0.341rem;
// margin-left: 0rem;
background-color: $layer2; background-color: $layer2;
color: $onLayer2; color: $onLayer2;
} }
@@ -631,7 +622,6 @@ $colorpicker_rounding: 0.341rem;
.sidebar-chat-codeblock { .sidebar-chat-codeblock {
@include normal-rounding; @include normal-rounding;
// @include elevation2;
background-color: $layer2; background-color: $layer2;
color: $onLayer2; color: $onLayer2;
margin: 0rem 0.682rem; margin: 0rem 0.682rem;
@@ -807,8 +797,7 @@ $waifu_image_overlay_transparency: 0.7;
@include full-rounding; @include full-rounding;
min-width: 1.875rem; min-width: 1.875rem;
min-height: 1.875rem; min-height: 1.875rem;
background-color: rgba(0, 0, 0, background-color: rgba(0, 0, 0, $waifu_image_overlay_transparency ); // Fixed cuz on image
$waifu_image_overlay_transparency ); // Fixed cuz on image
color: rgba(255, 255, 255, $waifu_image_overlay_transparency); color: rgba(255, 255, 255, $waifu_image_overlay_transparency);
} }
@@ -821,6 +810,16 @@ $waifu_image_overlay_transparency: 0.7;
background-color: rgba(60, 60, 60, $waifu_image_overlay_transparency); background-color: rgba(60, 60, 60, $waifu_image_overlay_transparency);
} }
.sidebar-booru-provider {
@include titlefont;
@include small-rounding;
padding: 0.341rem 0.818rem;
margin: 0.341rem;
font-weight: bold;
background-color: $primary;
color: $onPrimary;
}
.sidebar-booru-imagegrid { .sidebar-booru-imagegrid {
@include normal-rounding; @include normal-rounding;
} }
+15 -3
View File
@@ -3,8 +3,13 @@ import * as Utils from 'resource:///com/github/Aylur/ags/utils.js';
const APISERVICES = { const APISERVICES = {
'yandere': { 'yandere': {
name: 'yande.re',
endpoint: 'https://yande.re/post.json', endpoint: 'https://yande.re/post.json',
} },
'konachan': {
name: 'Konachan',
endpoint: 'https://konachan.net/post.json',
},
} }
const getWorkingImageSauce = (url) => { const getWorkingImageSauce = (url) => {
@@ -43,6 +48,8 @@ class BooruService extends Service {
'clear': [], 'clear': [],
'newResponse': ['int'], 'newResponse': ['int'],
'updateResponse': ['int'], 'updateResponse': ['int'],
}, {
'nsfw': ['boolean'],
}); });
} }
@@ -58,7 +65,7 @@ class BooruService extends Service {
} }
get nsfw() { return this._nsfw } get nsfw() { return this._nsfw }
set nsfw(value) { this._nsfw = value; } set nsfw(value) { this._nsfw = value; this.notify('nsfw'); }
get mode() { return this._mode } get mode() { return this._mode }
set mode(value) { set mode(value) {
@@ -82,7 +89,10 @@ class BooruService extends Service {
else taglist.push(thisArg); else taglist.push(thisArg);
} }
const newMessageId = this._queries.length; const newMessageId = this._queries.length;
this._queries.push(taglist.length == 0 ? ['*', `${page}`] : [...taglist, `${page}`]); this._queries.push({
providerName: APISERVICES[this._mode].name,
taglist: taglist.length == 0 ? ['*', `${page}`] : [...taglist, `${page}`],
});
this.emit('newResponse', newMessageId); this.emit('newResponse', newMessageId);
const params = { const params = {
'tags': taglist.join('+'), 'tags': taglist.join('+'),
@@ -97,12 +107,14 @@ class BooruService extends Service {
headers: APISERVICES[this._mode].headers, headers: APISERVICES[this._mode].headers,
}; };
let status = 0; let status = 0;
// console.log(`${APISERVICES[this._mode].endpoint}?${paramString}`);
Utils.fetch(`${APISERVICES[this._mode].endpoint}?${paramString}`, options) Utils.fetch(`${APISERVICES[this._mode].endpoint}?${paramString}`, options)
.then(result => { .then(result => {
status = result.status; status = result.status;
return result.text(); return result.text();
}) })
.then((dataString) => { // Store interesting stuff and emit .then((dataString) => { // Store interesting stuff and emit
// console.log(dataString);
const parsedData = JSON.parse(dataString); const parsedData = JSON.parse(dataString);
// console.log(parsedData) // console.log(parsedData)
this._responses.push(parsedData.map(obj => { this._responses.push(parsedData.map(obj => {