forked from Shinonome/dots-hyprland
161 lines
5.3 KiB
JavaScript
161 lines
5.3 KiB
JavaScript
const { Gdk, 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 { 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/*'`);
|
|
|
|
const CommandButton = (command) => Button({
|
|
className: 'sidebar-chat-chip sidebar-chat-chip-action txt txt-small',
|
|
onClicked: () => sendMessage(command),
|
|
setup: setupCursorHover,
|
|
label: command,
|
|
});
|
|
|
|
export const waifuTabIcon = Box({
|
|
hpack: 'center',
|
|
className: 'sidebar-chat-apiswitcher-icon',
|
|
homogeneous: true,
|
|
children: [
|
|
MaterialIcon('photo_library', 'norm'),
|
|
]
|
|
});
|
|
|
|
const WaifuImage = (taglist) => {
|
|
const colorIndicator = Box({
|
|
className: `sidebar-chat-indicator`,
|
|
});
|
|
const downloadIndicator = Label({
|
|
className: 'sidebar-waifu-txt txt-smallie txt',
|
|
xalign: 0,
|
|
label: 'Downloading image...',
|
|
});
|
|
const blockHeading = Box({
|
|
className: 'sidebar-waifu-content',
|
|
vertical: true,
|
|
children: [
|
|
Box({
|
|
children: taglist.map((tag) => CommandButton(tag))
|
|
}),
|
|
downloadIndicator,
|
|
]
|
|
});
|
|
const blockImage = Box({
|
|
hpack: 'start',
|
|
className: 'sidebar-waifu-image',
|
|
})
|
|
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}`;
|
|
// Start download
|
|
Utils.execAsync(['bash', '-c', `wget -O '${imagePath}' '${url}'`])
|
|
.then(() => {
|
|
blockImage.css = `background-image:url('${imagePath}');`;
|
|
downloadIndicator.destroy();
|
|
})
|
|
.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',
|
|
children: [
|
|
blockHeading,
|
|
blockImage,
|
|
]
|
|
})
|
|
],
|
|
setup: (self) => Utils.timeout(MESSAGE_SCROLL_DELAY, () => {
|
|
var adjustment = waifuView.get_vadjustment();
|
|
adjustment.set_value(adjustment.get_upper() - adjustment.get_page_size());
|
|
})
|
|
});
|
|
return thisBlock;
|
|
}
|
|
|
|
const waifuContent = Box({
|
|
className: 'spacing-v-15',
|
|
vertical: true,
|
|
vexpand: true,
|
|
properties: [
|
|
['map', new Map()],
|
|
],
|
|
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();
|
|
box._map.set(id, newImageBlock);
|
|
}, 'newResponse'],
|
|
[WaifuService, (box, id) => {
|
|
if (id === undefined) return;
|
|
const data = WaifuService.responses[id];
|
|
if (!data) return;
|
|
const imageBlock = box._map.get(id);
|
|
imageBlock._update(data);
|
|
}, 'updateResponse'],
|
|
]
|
|
});
|
|
|
|
export const waifuView = Scrollable({
|
|
className: 'sidebar-chat-viewport',
|
|
vexpand: true,
|
|
child: Box({
|
|
vertical: true,
|
|
children: [
|
|
waifuContent,
|
|
]
|
|
}),
|
|
setup: (scrolledWindow) => {
|
|
// Show scrollbar
|
|
scrolledWindow.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC);
|
|
const vScrollbar = scrolledWindow.get_vscrollbar();
|
|
vScrollbar.get_style_context().add_class('sidebar-scrollbar');
|
|
// Avoid click-to-scroll-widget-to-view behavior
|
|
Utils.timeout(1, () => {
|
|
const viewport = scrolledWindow.child;
|
|
viewport.set_focus_vadjustment(new Gtk.Adjustment(undefined));
|
|
})
|
|
}
|
|
});
|
|
|
|
export const waifuCommands = Box({
|
|
className: 'spacing-h-5',
|
|
children: [
|
|
Box({ hexpand: true }),
|
|
CommandButton('/clear'),
|
|
]
|
|
});
|
|
|
|
export const sendMessage = (text) => {
|
|
// Do something on send
|
|
// Commands
|
|
if (text.startsWith('/')) {
|
|
if (text.startsWith('/clear')) {
|
|
const kids = waifuContent.get_children();
|
|
for (let i = 0; i < kids.length; i++) {
|
|
const child = kids[i];
|
|
child.destroy();
|
|
}
|
|
}
|
|
}
|
|
else WaifuService.fetch(text);
|
|
} |