mirror of
https://github.com/end-4/dots-hyprland.git
synced 2026-06-06 07:19:27 -05:00
sidebar: ai: loading skeleton
This commit is contained in:
@@ -10,7 +10,7 @@ let configOptions = {
|
||||
'enhancements': true,
|
||||
'useHistory': true,
|
||||
'writingCursor': " ...", // Warning: Using weird characters can mess up Markdown rendering
|
||||
'proxyUrl': '', // Can be "socks5://127.0.0.1:9050" or "http://127.0.0.1:8080" for example. Leave it blank if you don't need it.
|
||||
'proxyUrl': null, // Can be "socks5://127.0.0.1:9050" or "http://127.0.0.1:8080" for example. Leave it blank if you don't need it.
|
||||
},
|
||||
'animations': {
|
||||
'choreographyDelay': 35,
|
||||
|
||||
@@ -3,7 +3,7 @@ import GtkSource from "gi://GtkSource?version=3.0";
|
||||
import App from 'resource:///com/github/Aylur/ags/app.js';
|
||||
import Widget from 'resource:///com/github/Aylur/ags/widget.js';
|
||||
import * as Utils from 'resource:///com/github/Aylur/ags/utils.js';
|
||||
const { Box, Button, Label, Icon, Scrollable } = Widget;
|
||||
const { Box, Button, Label, Icon, Scrollable, Stack } = Widget;
|
||||
const { execAsync, exec } = Utils;
|
||||
import { MaterialIcon } from '../../.commonwidgets/materialicon.js';
|
||||
import md2pango from '../../.miscutils/md2pango.js';
|
||||
@@ -77,7 +77,7 @@ const TextBlock = (content = '') => Label({
|
||||
|
||||
Utils.execAsync(['bash', '-c', `rm ${LATEX_DIR}/*`])
|
||||
.then(() => Utils.execAsync(['bash', '-c', `mkdir -p ${LATEX_DIR}`]))
|
||||
.catch(() => { });
|
||||
.catch(() => { });
|
||||
const Latex = (content = '') => {
|
||||
const latexViewArea = Box({
|
||||
// vscroll: 'never',
|
||||
@@ -286,7 +286,25 @@ const MessageContent = (content) => {
|
||||
}
|
||||
|
||||
export const ChatMessage = (message, modelName = 'Model') => {
|
||||
const TextSkeleton = (extraClassName = '') => Box({
|
||||
className: `sidebar-chat-message-skeletonline ${extraClassName}`,
|
||||
})
|
||||
const messageContentBox = MessageContent(message.content);
|
||||
const messageLoadingSkeleton = Box({
|
||||
vertical: true,
|
||||
className: 'spacing-v-5',
|
||||
children: Array.from({ length: 3 }, (_, id) => TextSkeleton(`sidebar-chat-message-skeletonline-offset${id}`)),
|
||||
})
|
||||
const messageArea = Stack({
|
||||
homogeneous: message.role !== 'user',
|
||||
transition: 'crossfade',
|
||||
transitionDuration: userOptions.animations.durationLarge,
|
||||
children: {
|
||||
'thinking': messageLoadingSkeleton,
|
||||
'message': messageContentBox,
|
||||
},
|
||||
shown: message.thinking ? 'thinking' : 'message',
|
||||
});
|
||||
const thisMessage = Box({
|
||||
className: 'sidebar-chat-message',
|
||||
homogeneous: true,
|
||||
@@ -302,11 +320,15 @@ export const ChatMessage = (message, modelName = 'Model') => {
|
||||
useMarkup: true,
|
||||
label: (message.role == 'user' ? USERNAME : modelName),
|
||||
}),
|
||||
messageContentBox,
|
||||
Box({
|
||||
homogeneous: true,
|
||||
className: 'sidebar-chat-messagearea',
|
||||
children: [messageArea]
|
||||
})
|
||||
],
|
||||
setup: (self) => self
|
||||
.hook(message, (self, isThinking) => {
|
||||
messageContentBox.toggleClassName('thinking', message.thinking);
|
||||
messageArea.shown = message.thinking ? 'thinking' : 'message';
|
||||
}, 'notify::thinking')
|
||||
.hook(message, (self) => { // Message update
|
||||
messageContentBox.attribute.fullUpdate(messageContentBox, message.content, message.role != 'user');
|
||||
|
||||
@@ -98,28 +98,6 @@ $elevation_margin: 0.476rem;
|
||||
margin: $elevation_margin;
|
||||
}
|
||||
|
||||
@keyframes flyin-top {
|
||||
from {
|
||||
margin-top: -2.795rem;
|
||||
}
|
||||
|
||||
to {
|
||||
margin-top: 0rem;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes flyin-bottom {
|
||||
from {
|
||||
margin-top: 4.841rem;
|
||||
margin-bottom: -4.841rem;
|
||||
}
|
||||
|
||||
to {
|
||||
margin-bottom: 0rem;
|
||||
margin-top: 0rem;
|
||||
}
|
||||
}
|
||||
|
||||
@mixin menu_decel {
|
||||
transition: 300ms cubic-bezier(0.1, 1, 0, 1);
|
||||
}
|
||||
@@ -163,12 +141,15 @@ $elevation_margin: 0.476rem;
|
||||
@mixin element_decel {
|
||||
transition: 300ms cubic-bezier(0, 0.55, 0.45, 1);
|
||||
}
|
||||
|
||||
@mixin element_bounceOut {
|
||||
transition: transform 200ms cubic-bezier(0.34, 1.56, 0.64, 1);
|
||||
}
|
||||
|
||||
@mixin element_accel {
|
||||
transition: 300ms cubic-bezier(0.55, 0, 1, 0.45);
|
||||
}
|
||||
|
||||
@mixin element_easeInOut {
|
||||
transition: 300ms cubic-bezier(0.85, 0, 0.15, 1);
|
||||
}
|
||||
|
||||
@@ -539,13 +539,59 @@ $colorpicker_rounding: 0.341rem;
|
||||
background-color: mix($primary, $hovercolor, 40%);
|
||||
}
|
||||
|
||||
.sidebar-chat-messagearea {
|
||||
margin: 0.341rem;
|
||||
}
|
||||
|
||||
.sidebar-chat-message {
|
||||
margin: 0.682rem;
|
||||
@include normal-rounding;
|
||||
@include group-padding;
|
||||
background-color: $layer1;
|
||||
}
|
||||
|
||||
$skeleton-accent: mix($secondary, $onSecondary, 50%);
|
||||
|
||||
@keyframes sidebar-chat-message-skeletonline-anim {
|
||||
0% {
|
||||
background-position: 175% 0%;
|
||||
}
|
||||
|
||||
100% {
|
||||
background-position: 50% 0%;
|
||||
}
|
||||
}
|
||||
|
||||
.sidebar-chat-message-skeletonline {
|
||||
border-radius: $rounding_verysmall;
|
||||
min-height: 1.364rem;
|
||||
background-color: $layer2;
|
||||
}
|
||||
|
||||
.sidebar-chat-message-skeletonline-offset0 {
|
||||
background-repeat: no-repeat;
|
||||
background: linear-gradient(to right, $layer3 0%, $skeleton-accent 25%, $layer3 50%, $layer3 100%);
|
||||
background-size: 500% 500%;
|
||||
animation: sidebar-chat-message-skeletonline-anim 3s linear;
|
||||
animation-iteration-count: infinite;
|
||||
}
|
||||
|
||||
.sidebar-chat-message-skeletonline-offset1 {
|
||||
background-repeat: no-repeat;
|
||||
background: linear-gradient(to right, $layer3 0%, $layer3 50%, $skeleton-accent 75%, $layer3 100%);
|
||||
background-size: 500% 500%;
|
||||
animation: sidebar-chat-message-skeletonline-anim 3s linear;
|
||||
animation-iteration-count: infinite;
|
||||
}
|
||||
|
||||
.sidebar-chat-message-skeletonline-offset2 {
|
||||
margin-right: 5.795rem;
|
||||
background-repeat: no-repeat;
|
||||
background: linear-gradient(to right, $layer3 0%, $layer3 25%, $skeleton-accent 50%, $layer3 75%, $layer3 100%);
|
||||
background-size: 500% 500%;
|
||||
animation: sidebar-chat-message-skeletonline-anim 3s linear;
|
||||
animation-iteration-count: infinite;
|
||||
}
|
||||
|
||||
.sidebar-chat-indicator {
|
||||
@include element_decel;
|
||||
@include full-rounding;
|
||||
|
||||
@@ -62,11 +62,11 @@ class GeminiMessage extends Service {
|
||||
|
||||
_role = '';
|
||||
_parts = [{ text: '' }];
|
||||
_thinking = false;
|
||||
_thinking;
|
||||
_done = false;
|
||||
_rawData = '';
|
||||
|
||||
constructor(role, content, thinking = false, done = false) {
|
||||
constructor(role, content, thinking = true, done = false) {
|
||||
super();
|
||||
this._role = role;
|
||||
this._parts = [{ text: content }];
|
||||
@@ -97,8 +97,8 @@ class GeminiMessage extends Service {
|
||||
get label() { return this._parserState.parsed + this._parserState.stack.join('') }
|
||||
|
||||
get thinking() { return this._thinking }
|
||||
set thinking(thinking) {
|
||||
this._thinking = thinking;
|
||||
set thinking(value) {
|
||||
this._thinking = value;
|
||||
this.notify('thinking')
|
||||
this.emit('changed')
|
||||
}
|
||||
@@ -116,7 +116,7 @@ class GeminiMessage extends Service {
|
||||
|
||||
parseSection() {
|
||||
if (this._thinking) {
|
||||
this._thinking = false;
|
||||
this.thinking = false;
|
||||
this._parts[0].text = '';
|
||||
}
|
||||
const parsedData = JSON.parse(this._rawData);
|
||||
@@ -273,12 +273,12 @@ class GeminiService extends Service {
|
||||
}
|
||||
|
||||
addMessage(role, message) {
|
||||
this._messages.push(new GeminiMessage(role, message));
|
||||
this._messages.push(new GeminiMessage(role, message, false));
|
||||
this.emit('newMsg', this._messages.length - 1);
|
||||
}
|
||||
|
||||
send(msg) {
|
||||
this._messages.push(new GeminiMessage('user', msg));
|
||||
this._messages.push(new GeminiMessage('user', msg, false));
|
||||
this.emit('newMsg', this._messages.length - 1);
|
||||
const aiResponse = new GeminiMessage('model', 'thinking...', true, false)
|
||||
|
||||
|
||||
@@ -76,10 +76,10 @@ class GPTMessage extends Service {
|
||||
|
||||
_role = '';
|
||||
_content = '';
|
||||
_thinking = false;
|
||||
_thinking;
|
||||
_done = false;
|
||||
|
||||
constructor(role, content, thinking = false, done = false) {
|
||||
constructor(role, content, thinking = true, done = false) {
|
||||
super();
|
||||
this._role = role;
|
||||
this._content = content;
|
||||
@@ -103,8 +103,8 @@ class GPTMessage extends Service {
|
||||
get label() { return this._parserState.parsed + this._parserState.stack.join('') }
|
||||
|
||||
get thinking() { return this._thinking }
|
||||
set thinking(thinking) {
|
||||
this._thinking = thinking;
|
||||
set thinking(value) {
|
||||
this._thinking = value;
|
||||
this.notify('thinking')
|
||||
this.emit('changed')
|
||||
}
|
||||
@@ -202,6 +202,7 @@ class GPTService extends Service {
|
||||
}
|
||||
|
||||
readResponse(stream, aiResponse) {
|
||||
aiResponse.thinking = false;
|
||||
stream.read_line_async(
|
||||
0, null,
|
||||
(stream, res) => {
|
||||
@@ -234,7 +235,7 @@ class GPTService extends Service {
|
||||
}
|
||||
|
||||
send(msg) {
|
||||
this._messages.push(new GPTMessage('user', msg));
|
||||
this._messages.push(new GPTMessage('user', msg, false, true));
|
||||
this.emit('newMsg', this._messages.length - 1);
|
||||
const aiResponse = new GPTMessage('assistant', 'thinking...', true, false)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user