diff --git a/.config/ags/scss/_lib_classes.scss b/.config/ags/scss/_lib_classes.scss index ad586d2aa..9340a362b 100644 --- a/.config/ags/scss/_lib_classes.scss +++ b/.config/ags/scss/_lib_classes.scss @@ -21,12 +21,11 @@ } .test { - background-image: linear-gradient(45deg, - #F4D609 0%, #F4D609 10%, #212121 10%, #212121 20%, - #F4D609 20%, #F4D609 30%, #212121 30%, #212121 40%, - #F4D609 40%, #F4D609 50%, #212121 50%, #212121 60%, - #F4D609 60%, #F4D609 70%, #212121 70%, #212121 80%, - #F4D609 80%, #F4D609 90%, #212121 90%, #212121 100%); + background-image: linear-gradient( + 45deg, #f4d609 0%, #f4d609 10%, #212121 10%, #212121 20%, #f4d609 20%, #f4d609 30%, #212121 30%, + #212121 40%, #f4d609 40%, #f4d609 50%, #212121 50%, #212121 60%, #f4d609 60%, + #f4d609 70%, #212121 70%, #212121 80%, #f4d609 80%, #f4d609 90%, #212121 90%, #212121 100% + ); background-repeat: repeat; } @@ -186,183 +185,190 @@ min-height: 0.545rem; } -.spacing-h-3>* { +.spacing-h-3 > * { margin-right: 0.205rem; } -.spacing-h-3>*:last-child { +.spacing-h-3 > *:last-child { margin-right: 0rem; } -.spacing-v-15>* { +.spacing-v-3 > * { + margin-bottom: 0.205rem; +} + +.spacing-v-3 > *:last-child { + margin-bottom: 0rem; +} + +.spacing-v-15 > * { margin-bottom: 1.023rem; } -.spacing-v-15>*:last-child { +.spacing-v-15 > *:last-child { margin-bottom: 0rem; } -.spacing-h-15>* { +.spacing-h-15 > * { margin-right: 1.023rem; } -.spacing-h-15>*:last-child { +.spacing-h-15 > *:last-child { margin-right: 0rem; } -.spacing-h-15>revealer>* { +.spacing-h-15 > revealer > * { margin-right: 1.023rem; } -.spacing-h-15>revealer:last-child>* { +.spacing-h-15 > revealer:last-child > * { margin-right: 0rem; } -.spacing-h-15>scrolledwindow>* { +.spacing-h-15 > scrolledwindow > * { margin-right: 1.023rem; } -.spacing-h-15>scrolledwindow:last-child>* { +.spacing-h-15 > scrolledwindow:last-child > * { margin-right: 0rem; } -.spacing-v-5>box { +.spacing-v-5 > box { margin-bottom: 0.341rem; } -.spacing-v-5>box:last-child { +.spacing-v-5 > box:last-child { margin-bottom: 0rem; } -.spacing-v-5>* { +.spacing-v-5 > * { margin-bottom: 0.341rem; } -.spacing-v-5>*:last-child { +.spacing-v-5 > *:last-child { margin-bottom: 0rem; } -.spacing-v-5-revealer>revealer>* { +.spacing-v-5-revealer > revealer > * { margin-bottom: 0.341rem; } -.spacing-v-5-revealer>revealer:last-child>* { +.spacing-v-5-revealer > revealer:last-child > * { margin-bottom: 0rem; } -.spacing-v-5-revealer>scrolledwindow>* { +.spacing-v-5-revealer > scrolledwindow > * { margin-bottom: 0.341rem; } -.spacing-v-5-revealer>scrolledwindow:last-child>* { +.spacing-v-5-revealer > scrolledwindow:last-child > * { margin-bottom: 0rem; } -.spacing-h-4>* { +.spacing-h-4 > * { margin-right: 0.273rem; } -.spacing-h-4>*:last-child { +.spacing-h-4 > *:last-child { margin-right: 0rem; } -.spacing-h-5>* { +.spacing-h-5 > * { margin-right: 0.341rem; } -.spacing-h-5>*:last-child { +.spacing-h-5 > *:last-child { margin-right: 0rem; } -.spacing-h-5>widget>* { +.spacing-h-5 > widget > * { margin-right: 0.341rem; } -.spacing-h-5>widget:last-child>* { +.spacing-h-5 > widget:last-child > * { margin-right: 0rem; } -.spacing-h-5>revealer>* { +.spacing-h-5 > revealer > * { margin-right: 0.341rem; } -.spacing-h-5>revealer:last-child>* { +.spacing-h-5 > revealer:last-child > * { margin-right: 0rem; } -.spacing-h-5>scrolledwindow>* { +.spacing-h-5 > scrolledwindow > * { margin-right: 0.341rem; } -.spacing-h-5>scrolledwindow:last-child>* { +.spacing-h-5 > scrolledwindow:last-child > * { margin-right: 0rem; } -.spacing-v-minus5>* { +.spacing-v-minus5 > * { margin-bottom: -0.341rem; } -.spacing-v-minus5>*:last-child { +.spacing-v-minus5 > *:last-child { margin-bottom: 0rem; } -.spacing-h-10>* { +.spacing-h-10 > * { margin-right: 0.682rem; } -.spacing-h-10>*:last-child { +.spacing-h-10 > *:last-child { margin-right: 0rem; } -.spacing-h-10>revealer>* { +.spacing-h-10 > revealer > * { margin-right: 0.682rem; } -.spacing-h-10>revealer:last-child>* { +.spacing-h-10 > revealer:last-child > * { margin-right: 0rem; } -.spacing-h-10>scrolledwindow>* { +.spacing-h-10 > scrolledwindow > * { margin-right: 0.682rem; } -.spacing-h-10>scrolledwindow:last-child>* { +.spacing-h-10 > scrolledwindow:last-child > * { margin-right: 0rem; } -.spacing-h-10>flowboxchild>* { +.spacing-h-10 > flowboxchild > * { margin-right: 0.682rem; } -.spacing-h-10>flowboxchild:last-child>* { +.spacing-h-10 > flowboxchild:last-child > * { margin-right: 0rem; } -.spacing-v-10>* { +.spacing-v-10 > * { margin-bottom: 0.682rem; } -.spacing-v-10>*:last-child { +.spacing-v-10 > *:last-child { margin-bottom: 0rem; } -.spacing-h-20>* { +.spacing-h-20 > * { margin-right: 1.364rem; } -.spacing-h-20>*:last-child { +.spacing-h-20 > *:last-child { margin-right: 0rem; } -.spacing-v-20>* { +.spacing-v-20 > * { margin-bottom: 1.364rem; } -.spacing-v-20>*:last-child { +.spacing-v-20 > *:last-child { margin-bottom: 0rem; } - .anim-enter { @include anim-enter; } @@ -429,51 +435,51 @@ color: transparent; } -.spacing-h--5>box { +.spacing-h--5 > box { margin-right: -0.341rem; } -.spacing-h--5>box:last-child { +.spacing-h--5 > box:last-child { margin-right: 0rem; } -.spacing-v--5>* { +.spacing-v--5 > * { margin-bottom: -0.341rem; } -.spacing-v--5>*:last-child { +.spacing-v--5 > *:last-child { margin-bottom: 0rem; } -.spacing-h--10>* { +.spacing-h--10 > * { margin-left: -1.364rem; } -.spacing-h--10>*:first-child { +.spacing-h--10 > *:first-child { margin-left: 0rem; } -.spacing-v--10>* { +.spacing-v--10 > * { margin-bottom: -0.682rem; } -.spacing-v--10>*:last-child { +.spacing-v--10 > *:last-child { margin-bottom: 0rem; } -.spacing-v--10>* { +.spacing-v--10 > * { margin-bottom: -0.682rem; } -.spacing-v--10>*:last-child { +.spacing-v--10 > *:last-child { margin-bottom: 0rem; } -.spacing-h--20>* { +.spacing-h--20 > * { margin-left: -1.364rem; } -.spacing-h--20>*:first-child { +.spacing-h--20 > *:first-child { margin-left: 0rem; } @@ -491,4 +497,12 @@ .element-hide { @include element_easeInOut; -} \ No newline at end of file +} + +.element-decel { + @include element_decel; +} + +.element-accel { + @include element_accel; +} diff --git a/.config/ags/scss/_sidebars.scss b/.config/ags/scss/_sidebars.scss index 7321978bf..4503e7d61 100644 --- a/.config/ags/scss/_sidebars.scss +++ b/.config/ags/scss/_sidebars.scss @@ -759,16 +759,13 @@ $onChatgpt: $onPrimary; margin-left: -0.136rem; padding-left: 0.818rem; } - .sidebar-waifu-content { margin-left: 0.682rem; } - .sidebar-waifu-txt { @include readingfont; margin-left: 0.682rem; } - .sidebar-waifu-image { margin-left: 0.682rem; @include normal-rounding; @@ -776,3 +773,21 @@ $onChatgpt: $onPrimary; background-repeat: no-repeat; background-position: center; } +.sidebar-waifu-image-actions { + padding: 0.313rem; +} +$waifu_image_overlay_transparency: 0.7; +.sidebar-waifu-image-action { + @include full-rounding; + min-width: 1.875rem; + min-height: 1.875rem; + background-color: rgba(0, 0, 0, $waifu_image_overlay_transparency); // Fixed cuz on image + color: rgba(255, 255, 255, $waifu_image_overlay_transparency); +} +.sidebar-waifu-image-action:hover, +.sidebar-waifu-image-action:focus { + background-color: rgba(30, 30, 30, $waifu_image_overlay_transparency); +} +.sidebar-waifu-image-action:active { + background-color: rgba(60, 60, 60, $waifu_image_overlay_transparency); +} diff --git a/.config/ags/services/waifus.js b/.config/ags/services/waifus.js index f7f9b28c9..f1e167b00 100644 --- a/.config/ags/services/waifus.js +++ b/.config/ags/services/waifus.js @@ -5,6 +5,20 @@ import GLib from 'gi://GLib'; import Soup from 'gi://Soup?version=3.0'; import { fileExists } from './messages.js'; +// Usage from my python waifu fetcher, for reference +// Usage: waifu-get.py [OPTION]... [TAG]... +// Options: +// --segs\tForce NSFW images +// --im\tUse waifu.im API. You can use many tags +// --pics\tUse waifu.pics API. Use 1 tag only. +// --nekos\tUse nekos.life (old) API. No tags. + +// Tags: +// waifu.im (type): +// maid waifu marin-kitagawa mori-calliope raiden-shogun oppai selfies uniform +// waifu.im (nsfw tags): +// ecchi hentai ero ass paizuri oral milf + function paramStringFromObj(params) { return Object.entries(params) .map(([key, value]) => { @@ -38,6 +52,7 @@ class WaifuService extends Service { _queries = []; _nsfw = false; _minHeight = 600; + _status = 0; static { Service.register(this, { @@ -81,17 +96,21 @@ class WaifuService extends Service { 'nsfw': this._nsfw, }; const paramString = paramStringFromObj(params); - console.log(paramString); // Fetch const options = { method: 'GET', headers: this._headers[this._mode], }; + var status = 0; Utils.fetch(`${this._baseUrl}?${paramString}`, options) - .then(result => result.text()) // Parse + .then(result => { + status = result.status; + return result.text(); + }) .then((dataString) => { // Store interesting stuff and emit const parsedData = JSON.parse(dataString); if (!parsedData.images) this._responses.push({ + status: status, signature: -1, url: '', source: '', @@ -104,6 +123,7 @@ class WaifuService extends Service { else { const imageData = parsedData.images[0]; this._responses.push({ + status: status, signature: imageData?.signature || -1, url: imageData?.url || undefined, source: imageData?.source, diff --git a/.config/ags/style.css b/.config/ags/style.css index 4582f992e..fefa3cfee 100644 --- a/.config/ags/style.css +++ b/.config/ags/style.css @@ -16,7 +16,7 @@ margin-top: 0rem; } } .test { - background-image: linear-gradient(45deg, #F4D609 0%, #F4D609 10%, #212121 10%, #212121 20%, #F4D609 20%, #F4D609 30%, #212121 30%, #212121 40%, #F4D609 40%, #F4D609 50%, #212121 50%, #212121 60%, #F4D609 60%, #F4D609 70%, #212121 70%, #212121 80%, #F4D609 80%, #F4D609 90%, #212121 90%, #212121 100%); + background-image: linear-gradient(45deg, #f4d609 0%, #f4d609 10%, #212121 10%, #212121 20%, #f4d609 20%, #f4d609 30%, #212121 30%, #212121 40%, #f4d609 40%, #f4d609 50%, #212121 50%, #212121 60%, #f4d609 60%, #f4d609 70%, #212121 70%, #212121 80%, #f4d609 80%, #f4d609 90%, #212121 90%, #212121 100%); background-repeat: repeat; } .test-size { @@ -144,6 +144,12 @@ .spacing-h-3 > *:last-child { margin-right: 0rem; } +.spacing-v-3 > * { + margin-bottom: 0.205rem; } + +.spacing-v-3 > *:last-child { + margin-bottom: 0rem; } + .spacing-v-15 > * { margin-bottom: 1.023rem; } @@ -369,6 +375,12 @@ .element-hide { transition: 300ms cubic-bezier(0.85, 0, 0.15, 1); } +.element-decel { + transition: 300ms cubic-bezier(0, 0.55, 0.45, 1); } + +.element-accel { + transition: 300ms cubic-bezier(0.55, 0, 1, 0.45); } + * { caret-color: #ffc4f5; } * selection { @@ -2001,6 +2013,24 @@ tooltip { background-repeat: no-repeat; background-position: center; } +.sidebar-waifu-image-actions { + padding: 0.313rem; } + +.sidebar-waifu-image-action { + border-radius: 9999px; + -gtk-outline-radius: 9999px; + min-width: 1.875rem; + min-height: 1.875rem; + background-color: rgba(0, 0, 0, 0.7); + color: rgba(255, 255, 255, 0.7); } + +.sidebar-waifu-image-action:hover, +.sidebar-waifu-image-action:focus { + background-color: rgba(30, 30, 30, 0.7); } + +.sidebar-waifu-image-action:active { + background-color: rgba(60, 60, 60, 0.7); } + .session-bg { margin-top: -2.727rem; background-color: rgba(16, 13, 16, 0.64); } diff --git a/.config/ags/widgets/sideleft/apis/chatgpt.js b/.config/ags/widgets/sideleft/apis/chatgpt.js index 8faf03831..62679add4 100644 --- a/.config/ags/widgets/sideleft/apis/chatgpt.js +++ b/.config/ags/widgets/sideleft/apis/chatgpt.js @@ -201,6 +201,11 @@ export const chatGPTView = Scrollable({ const viewport = scrolledWindow.child; viewport.set_focus_vadjustment(new Gtk.Adjustment(undefined)); }) + // Always scroll to bottom with new content + const adjustment = scrolledWindow.get_vadjustment(); + adjustment.connect("changed", () => { + adjustment.set_value(adjustment.get_upper() - adjustment.get_page_size()); + }) } }); diff --git a/.config/ags/widgets/sideleft/apis/chatgpt_chatmessage.js b/.config/ags/widgets/sideleft/apis/chatgpt_chatmessage.js index 2532ea459..65c228d67 100644 --- a/.config/ags/widgets/sideleft/apis/chatgpt_chatmessage.js +++ b/.config/ags/widgets/sideleft/apis/chatgpt_chatmessage.js @@ -10,7 +10,6 @@ const CUSTOM_SOURCEVIEW_SCHEME_PATH = `${App.configDir}/data/sourceviewtheme.xml const CUSTOM_SCHEME_ID = 'custom'; const USERNAME = GLib.get_user_name(); const CHATGPT_CURSOR = ' (o) '; -const MESSAGE_SCROLL_DELAY = 13; // In milliseconds, the time before an updated message scrolls to bottom /////////////////////// Custom source view colorscheme ///////////////////////// @@ -125,7 +124,11 @@ const CodeBlock = (content = '', lang = 'txt') => { Box({ className: 'sidebar-chat-codeblock-code', homogeneous: true, - children: [sourceView,], + children: [Scrollable({ + vscroll: 'never', + hscroll: 'automatic', + child: sourceView, + })], }) ] }) @@ -246,11 +249,6 @@ export const ChatMessage = (message, scrolledWindow) => { }, 'notify::thinking'], [message, (self) => { // Message update messageContentBox._fullUpdate(messageContentBox, message.content, message.role != 'user'); - Utils.timeout(MESSAGE_SCROLL_DELAY, () => { - if (!scrolledWindow) return; - var adjustment = scrolledWindow.get_vadjustment(); - adjustment.set_value(adjustment.get_upper() - adjustment.get_page_size()); - }); }, 'notify::content'], [message, (label, isDone) => { // Remove the cursor messageContentBox._fullUpdate(messageContentBox, message.content, false); @@ -285,11 +283,6 @@ export const SystemMessage = (content, commandName, scrolledWindow) => { ], }) ], - setup: (self) => Utils.timeout(MESSAGE_SCROLL_DELAY, () => { - if (!scrolledWindow) return; - var adjustment = scrolledWindow.get_vadjustment(); - adjustment.set_value(adjustment.get_upper() - adjustment.get_page_size()); - }) }); return thisMessage; } diff --git a/.config/ags/widgets/sideleft/apis/waifu.js b/.config/ags/widgets/sideleft/apis/waifu.js index b4bb650be..e89cb41c7 100644 --- a/.config/ags/widgets/sideleft/apis/waifu.js +++ b/.config/ags/widgets/sideleft/apis/waifu.js @@ -1,13 +1,12 @@ -const { Gdk, GLib, Gtk, Pango } = imports.gi; +const { Gdk, Gio, GLib, Gtk, Pango } = imports.gi; import { App, Utils, Widget } from '../../../imports.js'; const { Box, Button, Entry, EventBox, Icon, Label, Revealer, Scrollable, Stack } = Widget; const { execAsync, exec } = Utils; import { MaterialIcon } from "../../../lib/materialicon.js"; +import { MarginRevealer } from '../../../lib/advancedrevealers.js'; import { setupCursorHover, setupCursorHoverInfo } from "../../../lib/cursorhover.js"; import WaifuService from '../../../services/waifus.js'; -const MESSAGE_SCROLL_DELAY = 13; // In milliseconds, the time before an updated message scrolls to bottom - // Create cache folder and clear pics from previous session Utils.exec(`bash -c 'mkdir -p ${GLib.get_user_cache_dir()}/ags/media/waifus'`); Utils.exec(`bash -c 'rm ${GLib.get_user_cache_dir()}/ags/media/waifus/*'`); @@ -29,62 +28,146 @@ export const waifuTabIcon = Box({ }); const WaifuImage = (taglist) => { + var imagePath = ''; + var blockImageData = {}; + const ImageState = (icon, name) => Box({ + className: 'spacing-h-5', + children: [ + Box({ hexpand: true }), + Label({ + className: 'sidebar-waifu-txt txt-smallie txt', + xalign: 0, + label: name, + }), + MaterialIcon(icon, 'norm'), + ] + }) + const ImageAction = ({ name, icon, action }) => Button({ + className: 'sidebar-waifu-image-action txt-norm icon-material', + tooltipText: name, + label: icon, + onClicked: action, + setup: setupCursorHover, + }) const colorIndicator = Box({ className: `sidebar-chat-indicator`, }); - const downloadIndicator = Label({ - className: 'sidebar-waifu-txt txt-smallie txt', - xalign: 0, - label: 'Downloading image...', + const downloadState = Stack({ + homogeneous: false, + transition: 'slide_up_down', + transitionDuration: 150, + items: [ + ['api', ImageState('api', 'Calling API')], + ['download', ImageState('downloading', 'Downloading image')], + ['done', ImageState('done', 'Finished!')], + ['error', ImageState('error', 'Error')], + ] + }); + const downloadIndicator = MarginRevealer({ + vpack: 'center', + transition: 'slide_left', + revealChild: true, + child: downloadState, }); const blockHeading = Box({ - className: 'sidebar-waifu-content', - vertical: true, + hpack: 'fill', + className: 'sidebar-waifu-content spacing-h-5', children: [ - Box({ - children: taglist.map((tag) => CommandButton(tag)) - }), + ...taglist.map((tag) => CommandButton(tag)), + Box({ hexpand: true }), downloadIndicator, ] }); - const blockImage = Box({ - hpack: 'start', - className: 'sidebar-waifu-image', + const blockImageActions = Box({ + className: 'sidebar-waifu-image-actions spacing-h-3', + children: [ + Box({ hexpand: true }), + ImageAction({ + name: 'Go to source', + icon: 'link', + action: () => execAsync(['xdg-open', `${blockImageData.source}`]).catch(print), + }), + ImageAction({ + name: 'Hoard', + icon: 'save', + action: () => execAsync(['bash', '-c', `mkdir -p ~/Pictures/waifus && cp ${imagePath} ~/Pictures/waifus`]).catch(print), + }), + ImageAction({ + name: 'Open externally', + icon: 'open_in_new', + action: () => execAsync(['xdg-open', `${imagePath}`]).catch(print), + }), + ] }) + const blockImage = Box({ + className: 'test', + hpack: 'start', + vertical: true, + className: 'sidebar-waifu-image', + homogeneous: true, + children: [ + Revealer({ + transition: 'crossfade', + revealChild: false, + child: Box({ + vertical: true, + children: [blockImageActions], + }) + }) + ] + }) + const blockImageRevealer = Revealer({ + transition: 'slide_down', + transitionDuration: 150, + revealChild: false, + child: blockImage, + }); const thisBlock = Box({ className: 'sidebar-chat-message', properties: [ ['update', (imageData) => { - const { signature, url, source, dominant_color, is_nsfw, width, height, tags } = imageData; - const imagePath = `${GLib.get_user_cache_dir()}/ags/media/waifus/${signature}`; + blockImageData = imageData; + const { status, signature, url, source, dominant_color, is_nsfw, width, height, tags } = blockImageData; + if (status != 200) { + downloadState.shown = 'error'; + return; + } + imagePath = `${GLib.get_user_cache_dir()}/ags/media/waifus/${signature}`; + downloadState.shown = 'download'; + // Width allocation + const widgetWidth = Math.min(Math.floor(waifuContent.get_allocated_width() * 0.75), width); + blockImage.set_size_request(widgetWidth, Math.ceil(widgetWidth * height / width)); // Start download - Utils.execAsync(['bash', '-c', `wget -O '${imagePath}' '${url}'`]) - .then(() => { - blockImage.css = `background-image:url('${imagePath}');`; - downloadIndicator.destroy(); - }) + const showImage = () => { + downloadState.shown = 'done'; + blockImage.css = `background-image:url('${imagePath}');`; + blockImage.get_children()[0].revealChild = true; + Utils.timeout(blockImageRevealer.transitionDuration, + () => blockImageRevealer.revealChild = true + ); + downloadIndicator._hide(downloadIndicator); + } + if (Gio.File.new_for_path(imagePath).query_exists(null)) showImage(); + else Utils.execAsync(['bash', '-c', `wget -O '${imagePath}' '${url}'`]) + .then(showImage) .catch(print); colorIndicator.css = `background-color: ${dominant_color};`; - // Width allocation - const widgetWidth = Math.floor(waifuContent.get_allocated_width() * 0.75); // idk tbh - blockImage.set_size_request(widgetWidth, Math.ceil(widgetWidth * height / width)); }], ], children: [ colorIndicator, Box({ vertical: true, - className: 'spacing-v-10', + className: 'spacing-v-5', children: [ blockHeading, - blockImage, + Box({ + vertical: true, + children: [blockImageRevealer], + }) ] }) ], - setup: (self) => Utils.timeout(MESSAGE_SCROLL_DELAY, () => { - var adjustment = waifuView.get_vadjustment(); - adjustment.set_value(adjustment.get_upper() - adjustment.get_page_size()); - }) }); return thisBlock; } @@ -99,7 +182,6 @@ const waifuContent = Box({ connections: [ [WaifuService, (box, id) => { if (id === undefined) return; - console.log('new', WaifuService.queries[id]); const newImageBlock = WaifuImage(WaifuService.queries[id]); box.add(newImageBlock); box.show_all(); @@ -134,9 +216,29 @@ export const waifuView = Scrollable({ const viewport = scrolledWindow.child; viewport.set_focus_vadjustment(new Gtk.Adjustment(undefined)); }) + // Always scroll to bottom with new content + const adjustment = scrolledWindow.get_vadjustment(); + adjustment.connect("changed", () => { + adjustment.set_value(adjustment.get_upper() - adjustment.get_page_size()); + }) } }); +// const waifuTags = Box({ +// className: 'spacing-h-5', +// children: [ +// Box({ hexpand: true }), +// CommandButton('waifu'), +// CommandButton('maid'), +// CommandButton('uniform'), +// CommandButton('oppai'), +// CommandButton('selfies'), +// CommandButton('marin-kitagawa'), +// CommandButton('raiden-shogun'), +// CommandButton('mori-calliope'), +// ] +// }); + export const waifuCommands = Box({ className: 'spacing-h-5', children: [ @@ -156,6 +258,22 @@ export const sendMessage = (text) => { child.destroy(); } } + else if (text.startsWith('/test')) { + const newImage = WaifuImage(['/test']); + waifuContent.add(newImage); + Utils.timeout(13, () => newImage._update({ // Needs timeout or inits won't make it + // This is an image uploaded to my github repo + status: 200, + url: 'https://picsum.photos/400/600', + signature: 0, + source: 'https://picsum.photos/400/600', + dominant_color: '#9392A6', + is_nsfw: false, + width: 300, + height: 200, + tags: ['/test'], + })); + } } else WaifuService.fetch(text); } \ No newline at end of file