From 2d238efd1033f7692b8267230410184abdd655b9 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Fri, 29 Dec 2023 13:30:25 +0700 Subject: [PATCH] ags: sync --- .config/ags/lib/advancedrevealers.js | 76 +++++++ .config/ags/lib/doublerevealer.js | 24 --- .config/ags/lib/notification.js | 200 +++++++++++------- .config/ags/lib/statusicons.js | 6 +- .config/ags/scripts/record-script.sh | 8 +- .../scripts/templates/gradience/preset.json | 40 ++-- .../ags/scripts/templates/hypr/colors.conf | 2 +- .config/ags/scss/_bar.scss | 7 +- .config/ags/scss/_colors.scss | 2 +- .config/ags/scss/_lib_classes.scss | 40 ++++ .config/ags/scss/_lib_mixins.scss | 12 ++ .config/ags/scss/_notifications.scss | 26 ++- .config/ags/scss/_osd.scss | 4 + .config/ags/services/waifus.js | 170 +++++++++++++++ .config/ags/style.css | 56 +++-- .config/ags/widgets/bar/tray.js | 13 +- .../ags/widgets/indicators/indicatorvalues.js | 18 +- .config/ags/widgets/indicators/main.js | 3 + .config/ags/widgets/overview/overview.js | 2 +- .config/ags/widgets/sideleft/apis/chatgpt.js | 18 +- .../sideleft/apis/chatgpt_chatmessage.js | 15 +- .config/ags/widgets/sideleft/apis/waifu.js | 19 +- .config/ags/widgets/sideleft/apiwidgets.js | 3 + .config/ags/widgets/sideleft/sideleft.js | 2 + 24 files changed, 586 insertions(+), 180 deletions(-) create mode 100644 .config/ags/lib/advancedrevealers.js delete mode 100644 .config/ags/lib/doublerevealer.js create mode 100644 .config/ags/services/waifus.js diff --git a/.config/ags/lib/advancedrevealers.js b/.config/ags/lib/advancedrevealers.js new file mode 100644 index 000000000..e90aa8297 --- /dev/null +++ b/.config/ags/lib/advancedrevealers.js @@ -0,0 +1,76 @@ +const { Gdk, Gtk } = imports.gi; +import { App, Service, Utils, Variable, Widget } from '../imports.js'; +const { Box, Button, Entry, EventBox, Icon, Label, Revealer, Scrollable, Stack } = Widget; + +export const MarginRevealer = ({ + transition = 'slide_down', + child, + revealChild, + showClass = 'element-show', // These are for animation curve + hideClass = 'element-hide', // Don't put margins in these classes! + extraProperties = [], + ...rest +}) => { + child.toggleClassName(`${revealChild ? showClass : hideClass}`, true); + if(!revealChild) child.css = 'min-height: 2px;'; + const widget = Scrollable({ + properties: [ + ['revealChild', true], // It'll be set to false after init if it's supposed to hide + ['transition', transition], + ['show', (self) => { + if (self._revealChild) return; + child.toggleClassName(hideClass, false); + child.toggleClassName(showClass, true); + self._revealChild = true; + child.css = 'margin: 0px;'; + }], + ['hide', (self) => { + if (!self._revealChild) return; + child.toggleClassName(hideClass, true); + child.toggleClassName(showClass, false); + self._revealChild = false; + if (self._transition == 'slide_left') + child.css = `margin-right: -${child.get_allocated_width()}px;`; + else if (self._transition == 'slide_right') + child.css = `margin-left: -${child.get_allocated_width()}px;`; + else if (self._transition == 'slide_up') + child.css = `margin-bottom: -${child.get_allocated_height()}px;`; + else if (self._transition == 'slide_down') + child.css = `margin-top: -${child.get_allocated_height()}px;`; + }], + ['toggle', (self) => { + if (self._revealChild) self._hide(self); + else self._show(self); + }], + ...extraProperties, + ], + child: child, + setup: (self) => { + self.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.NEVER); + }, + ...rest, + }); + return widget; +} + +// TODO: Allow reveal update. Currently this just helps at declaration +export const DoubleRevealer = ({ + transition1 = 'slide_right', + transition2 = 'slide_left', + duration1 = 150, + duration2 = 150, + child, + revealChild, +}) => { + return Revealer({ + transition: transition1, + transitionDuration: duration1, + revealChild: revealChild, + child: Revealer({ + transition: transition2, + transitionDuration: duration2, + revealChild: revealChild, + child: child, + }) + }) +} diff --git a/.config/ags/lib/doublerevealer.js b/.config/ags/lib/doublerevealer.js deleted file mode 100644 index fe2855dc4..000000000 --- a/.config/ags/lib/doublerevealer.js +++ /dev/null @@ -1,24 +0,0 @@ -const { Gdk, Gtk } = imports.gi; -import { App, Service, Utils, Variable, Widget } from '../imports.js'; - -// TODO: Allow reveal update. Currently this just helps at declaration -export const DoubleRevealer = ({ - transition1 = 'slide_right', - transition2 = 'slide_left', - duration1 = 150, - duration2 = 150, - child, - revealChild, -}) => { - return Widget.Revealer({ - transition: transition1, - transitionDuration: duration1, - revealChild: revealChild, - child: Widget.Revealer({ - transition: transition2, - transitionDuration: duration2, - revealChild: revealChild, - child: child, - }) - }) -} \ No newline at end of file diff --git a/.config/ags/lib/notification.js b/.config/ags/lib/notification.js index a7decbcf2..93d6d70a0 100644 --- a/.config/ags/lib/notification.js +++ b/.config/ags/lib/notification.js @@ -7,6 +7,7 @@ const { Box, EventBox, Icon, Overlay, Label, Button, Revealer } = Widget; import { MaterialIcon } from "./materialicon.js"; import { setupCursorHover } from "./cursorhover.js"; import { AnimatedCircProg } from "./animatedcircularprogress.js"; +import { MarginRevealer } from './advancedrevealers.js'; function guessMessageType(summary) { if (summary.includes('recording')) return 'screen_record'; @@ -43,16 +44,15 @@ const NotificationIcon = (notifObject) => { icon = notifObject.appEntry; return Box({ - valign: Gtk.Align.CENTER, + vpack: 'center', hexpand: false, className: `notif-icon notif-icon-material-${notifObject.urgency}`, homogeneous: true, children: [ (icon != 'NO_ICON' ? Icon({ + vpack: 'center', icon: icon, - halign: Gtk.Align.CENTER, hexpand: true, - valign: Gtk.Align.CENTER, setup: (self) => Utils.timeout(1, () => { const styleContext = self.get_parent().get_style_context(); const width = styleContext.get_property('min-width', Gtk.StateFlags.NORMAL); @@ -81,7 +81,7 @@ export default ({ ) const destroyWithAnims = () => { widget.sensitive = false; - notificationBox.setCss(rightAnim1); + notificationBox.setCss(middleClickClose); Utils.timeout(200, () => { wholeThing.revealChild = false; }); @@ -125,82 +125,124 @@ export default ({ }); const display = Gdk.Display.get_default(); + const notifTextPreview = Revealer({ + transition: 'slide_down', + transitionDuration: 300, + revealChild: true, + child: Label({ + xalign: 0, + className: `txt-smallie notif-body-${notifObject.urgency}`, + useMarkup: true, + xalign: 0, + justify: Gtk.Justification.LEFT, + maxWidthChars: 24, + truncate: 'end', + label: notifObject.body.split("\n")[0], + }), + }); + const notifTextExpanded = Revealer({ + transition: 'slide_up', + transitionDuration: 300, + revealChild: false, + child: Label({ + xalign: 0, + className: `txt-smallie notif-body-${notifObject.urgency}`, + useMarkup: true, + xalign: 0, + justify: Gtk.Justification.LEFT, + maxWidthChars: 24, + wrap: true, + label: notifObject.body, + }), + }); + const notifIcon = Box({ + vpack: 'start', + homogeneous: true, + children: [ + Overlay({ + child: NotificationIcon(notifObject), + overlays: [ + AnimatedCircProg({ + className: `notif-circprog-${notifObject.urgency}`, + valign: Gtk.Align.CENTER, + initFrom: (isPopup ? 100 : 0), + initTo: 0, + initAnimTime: popupTimeout, + }) + ] + }), + ] + }); + const notifText = Box({ + valign: Gtk.Align.CENTER, + vertical: true, + hexpand: true, + children: [ + Box({ + children: [ + Label({ + xalign: 0, + className: 'txt-small txt-semibold titlefont', + justify: Gtk.Justification.LEFT, + hexpand: true, + maxWidthChars: 24, + truncate: 'end', + ellipsize: 3, + // wrap: true, + useMarkup: notifObject.summary.startsWith('<'), + label: notifObject.summary, + }), + Label({ + valign: Gtk.Align.CENTER, + className: 'txt-smaller txt-semibold', + justify: Gtk.Justification.RIGHT, + setup: (label) => { + // Let's ignore how it won't work for Jan1 cuz I'm lazy + const messageTime = GLib.DateTime.new_from_unix_local(notifObject.time); + if (messageTime.get_day_of_year() == GLib.DateTime.new_now_local().get_day_of_year()) { + label.label = messageTime.format('%H:%M'); + } + else if (messageTime.get_day_of_year() == GLib.DateTime.new_now_local().get_day_of_year() - 1) { + label.label = messageTime.format('Yesterday'); + } + else { + label.label = messageTime.format('%d/%m'); + } + } + }), + ] + }), + notifTextPreview, + notifTextExpanded, + ] + }); + const notifExpandButton = Button({ + vpack: 'start', + className: 'notif-expand-btn', + onClicked: (self) => { + if (notifTextPreview.revealChild) { // Expanding... + notifTextPreview.revealChild = false; + notifTextExpanded.revealChild = true; + self.child.label = 'expand_less'; + } + else { + notifTextPreview.revealChild = true; + notifTextExpanded.revealChild = false; + self.child.label = 'expand_more'; + } + }, + child: MaterialIcon('expand_more', 'norm', { + vpack: 'center', + }), + setup: setupCursorHover, + }); const notificationContent = Box({ ...props, className: `${isPopup ? 'popup-' : ''}notif-${notifObject.urgency} spacing-h-10`, children: [ - NotificationIcon(notifObject), - Box({ - valign: Gtk.Align.CENTER, - vertical: true, - hexpand: true, - children: [ - Box({ - children: [ - Label({ - xalign: 0, - className: 'txt-small txt-semibold titlefont', - justify: Gtk.Justification.LEFT, - hexpand: true, - maxWidthChars: 24, - truncate: 'end', - ellipsize: 3, - wrap: true, - useMarkup: notifObject.summary.startsWith('<'), - label: notifObject.summary, - }), - Label({ - valign: Gtk.Align.CENTER, - className: 'txt-smaller txt-semibold', - justify: Gtk.Justification.RIGHT, - setup: (label) => { - // Let's ignore how it won't work for Jan1 cuz I'm lazy - const messageTime = GLib.DateTime.new_from_unix_local(notifObject.time); - if (messageTime.get_day_of_year() == GLib.DateTime.new_now_local().get_day_of_year()) { - label.label = messageTime.format('%H:%M'); - } - else if (messageTime.get_day_of_year() == GLib.DateTime.new_now_local().get_day_of_year() - 1) { - label.label = messageTime.format('Yesterday'); - } - else { - label.label = messageTime.format('%d/%m'); - } - } - }), - ] - }), - Label({ - xalign: 0, - className: `txt-smallie notif-body-${notifObject.urgency}`, - useMarkup: true, - xalign: 0, - justify: Gtk.Justification.LEFT, - wrap: true, - label: notifObject.body, - }), - ] - }), - Overlay({ - child: AnimatedCircProg({ - className: `notif-circprog-${notifObject.urgency}`, - valign: Gtk.Align.CENTER, - initFrom: (isPopup ? 100 : 0), - initTo: 0, - initAnimTime: popupTimeout, - }), - overlays: [ - Button({ - className: 'notif-close-btn', - onClicked: () => { - destroyWithAnims() - }, - child: MaterialIcon('close', 'large', { - valign: Gtk.Align.CENTER, - }), - setup: setupCursorHover, - }), - ] - }), + notifIcon, + notifText, + notifExpandButton, // what is this? i think it should be at the bottom not on the right // Box({ @@ -236,10 +278,16 @@ export default ({ margin-right: -${Number(maxOffset + endMargin)}rem; opacity: 0;`; + const middleClickClose = `transition: 200ms cubic-bezier(0.85, 0, 0.15, 1); + margin-left: ${Number(maxOffset + endMargin)}rem; + margin-right: -${Number(maxOffset + endMargin)}rem; + opacity: 0;`; + const notificationBox = Box({ properties: [ ['leftAnim1', leftAnim1], ['rightAnim1', rightAnim1], + ['middleClickClose', middleClickClose], ['ready', false], ], homogeneous: true, diff --git a/.config/ags/lib/statusicons.js b/.config/ags/lib/statusicons.js index 21eebe2db..d0db10ebd 100644 --- a/.config/ags/lib/statusicons.js +++ b/.config/ags/lib/statusicons.js @@ -145,7 +145,11 @@ export const NetworkIndicator = () => Widget.Stack({ ['wired', NetworkWiredIndicator()], ], connections: [[Network, stack => { - let primary = Network.primary || 'fallback'; + if(!Network.primary) { + stack.shown = 'wifi'; + return; + } + const primary = Network.primary || 'fallback'; if (primary == 'wifi' || primary == 'wired') stack.shown = primary; else diff --git a/.config/ags/scripts/record-script.sh b/.config/ags/scripts/record-script.sh index ddcef8071..1881e0c2a 100755 --- a/.config/ags/scripts/record-script.sh +++ b/.config/ags/scripts/record-script.sh @@ -8,13 +8,13 @@ cd ~/Videos || exit if [[ "$(pidof wf-recorder)" == "" ]]; then notify-send "Starting recording" 'recording_'"$(getdate)"'.mp4' -a 'record-script.sh' if [[ "$1" == "--sound" ]]; then - wf-recorder -f './recording_'"$(getdate)"'.mp4' -t --geometry "$(slurp)" --audio=alsa_output.pci-0000_08_00.6.analog-stereo.monitor + wf-recorder --pixel-format yuv420p -f './recording_'"$(getdate)"'.mp4' -t --geometry "$(slurp)" --audio=alsa_output.pci-0000_08_00.6.analog-stereo.monitor elif [[ "$1" == "--fullscreen-sound" ]]; then - wf-recorder -f './recording_'"$(getdate)"'.mp4' -t --audio=alsa_output.pci-0000_08_00.6.analog-stereo.monitor + wf-recorder --pixel-format yuv420p -f './recording_'"$(getdate)"'.mp4' -t --audio=alsa_output.pci-0000_08_00.6.analog-stereo.monitor elif [[ "$1" == "--fullscreen" ]]; then - wf-recorder -f './recording_'"$(getdate)"'.mp4' -t + wf-recorder --pixel-format yuv420p -f './recording_'"$(getdate)"'.mp4' -t else - wf-recorder -f './recording_'"$(getdate)"'.mp4' -t --geometry "$(slurp)" + wf-recorder --pixel-format yuv420p -f './recording_'"$(getdate)"'.mp4' -t --geometry "$(slurp)" fi else /usr/bin/kill --signal SIGINT wf-recorder diff --git a/.config/ags/scripts/templates/gradience/preset.json b/.config/ags/scripts/templates/gradience/preset.json index 5402658e6..d23d5efb5 100644 --- a/.config/ags/scripts/templates/gradience/preset.json +++ b/.config/ags/scripts/templates/gradience/preset.json @@ -87,34 +87,34 @@ "BLACK_500": "#393634", "BLACK_700": "#33302F", "BLACK_900": "#2B2928", - "accent_bg_color": "#e2e2e2", - "accent_fg_color": "#000000", - "accent_color": "#e2e2e2", - "destructive_bg_color": "#e2e2e2", - "destructive_fg_color": "#000000", - "destructive_color": "#e2e2e2", + "accent_bg_color": "#d6baff", + "accent_fg_color": "#3d1c70", + "accent_color": "#d6baff", + "destructive_bg_color": "#ffb4a9", + "destructive_fg_color": "#680003", + "destructive_color": "#ffb4a9", "success_bg_color": "#81C995", "success_fg_color": "rgba(0, 0, 0, 0.87)", "warning_bg_color": "#FDD633", "warning_fg_color": "rgba(0, 0, 0, 0.87)", - "error_bg_color": "#e2e2e2", - "error_fg_color": "#000000", - "window_bg_color": "#000000", - "window_fg_color": "#e2e2e2", - "view_bg_color": "#000000", - "view_fg_color": "#e2e2e2", + "error_bg_color": "#ffb4a9", + "error_fg_color": "#680003", + "window_bg_color": "#111012", + "window_fg_color": "#e7e1e6", + "view_bg_color": "#1d1b1e", + "view_fg_color": "#e7e1e6", "headerbar_bg_color": "mix(@dialog_bg_color, @window_bg_color, 0.5)", - "headerbar_fg_color": "#e2e2e2", - "headerbar_border_color": "#313131", + "headerbar_fg_color": "#eadef7", + "headerbar_border_color": "#4b4358", "headerbar_backdrop_color": "@headerbar_bg_color", "headerbar_shade_color": "rgba(0, 0, 0, 0.09)", - "card_bg_color": "#000000", - "card_fg_color": "#e2e2e2", + "card_bg_color": "#111012", + "card_fg_color": "#eadef7", "card_shade_color": "rgba(0, 0, 0, 0.09)", - "dialog_bg_color": "#313131", - "dialog_fg_color": "#e2e2e2", - "popover_bg_color": "#313131", - "popover_fg_color": "#e2e2e2", + "dialog_bg_color": "#4b4358", + "dialog_fg_color": "#eadef7", + "popover_bg_color": "#4b4358", + "popover_fg_color": "#eadef7", "thumbnail_bg_color": "#1a1b26", "thumbnail_fg_color": "#AEE5FA", "shade_color": "rgba(0, 0, 0, 0.36)", diff --git a/.config/ags/scripts/templates/hypr/colors.conf b/.config/ags/scripts/templates/hypr/colors.conf index 232c664ee..6a9ec6051 100755 --- a/.config/ags/scripts/templates/hypr/colors.conf +++ b/.config/ags/scripts/templates/hypr/colors.conf @@ -1,6 +1,6 @@ # Auto generated color theme for image at: [Local wallpaper] general { - col.active_border = rgba({{ $primaryContainer }}FF) + col.active_border = rgba({{ $onPrimary }}FF) col.inactive_border = rgba({{ $secondaryContainer }}CC) } diff --git a/.config/ags/scss/_bar.scss b/.config/ags/scss/_bar.scss index 7ba2303b4..27229888f 100644 --- a/.config/ags/scss/_bar.scss +++ b/.config/ags/scss/_bar.scss @@ -464,13 +464,14 @@ $notchOnPrimary: $onPrimary; .bar-systray { @include full-rounding; - min-height: 1.909rem; - min-width: 1.909rem; + margin: 0.137rem 0rem; + padding: 0rem 0.682rem; } .bar-systray-item { @include full-rounding; - min-width: 1.909rem; + min-height: 1.032rem; + min-width: 1.032rem; } .bar-statusicons { diff --git a/.config/ags/scss/_colors.scss b/.config/ags/scss/_colors.scss index 4c1317cd6..5a510350d 100755 --- a/.config/ags/scss/_colors.scss +++ b/.config/ags/scss/_colors.scss @@ -125,4 +125,4 @@ $term3: $onPrimaryContainer; $term4: $onPrimaryContainer; $term5: $onSecondaryContainer; $term6: $primary; -$term7: $onSurfaceVariant; \ No newline at end of file +$term7: $onSurfaceVariant; diff --git a/.config/ags/scss/_lib_classes.scss b/.config/ags/scss/_lib_classes.scss index 4b7e0ca7c..791a7a1c7 100644 --- a/.config/ags/scss/_lib_classes.scss +++ b/.config/ags/scss/_lib_classes.scss @@ -214,6 +214,14 @@ margin-right: 0rem; } +.spacing-h-15>scrolledwindow>* { + margin-right: 1.023rem; +} + +.spacing-h-15>scrolledwindow:last-child>* { + margin-right: 0rem; +} + .spacing-v-5>box { margin-bottom: 0.341rem; } @@ -238,6 +246,14 @@ margin-bottom: 0rem; } +.spacing-v-5-revealer>scrolledwindow>* { + margin-bottom: 0.341rem; +} + +.spacing-v-5-revealer>scrolledwindow:last-child>* { + margin-bottom: 0rem; +} + .spacing-h-5>* { margin-right: 0.341rem; } @@ -262,6 +278,14 @@ margin-right: 0rem; } +.spacing-h-5>scrolledwindow>* { + margin-right: 0.341rem; +} + +.spacing-h-5>scrolledwindow:last-child>* { + margin-right: 0rem; +} + .spacing-v-minus5>* { margin-bottom: -0.341rem; } @@ -286,6 +310,14 @@ margin-right: 0rem; } +.spacing-h-10>scrolledwindow>* { + margin-right: 0.682rem; +} + +.spacing-h-10>scrolledwindow:last-child>* { + margin-right: 0rem; +} + .spacing-h-10>flowboxchild>* { margin-right: 0.682rem; } @@ -439,4 +471,12 @@ .menu-decel { @include menu_decel; +} + +.element-show { + @include element_easeInOut; +} + +.element-hide { + @include element_easeInOut; } \ No newline at end of file diff --git a/.config/ags/scss/_lib_mixins.scss b/.config/ags/scss/_lib_mixins.scss index 3beb1718e..b43dc52e1 100644 --- a/.config/ags/scss/_lib_mixins.scss +++ b/.config/ags/scss/_lib_mixins.scss @@ -161,6 +161,18 @@ $elevation_margin: 0.476rem; transition: 150ms cubic-bezier(0.3, 0, 0.8, 0.15); } +@mixin element_decel { + transition: 300ms cubic-bezier(0, 0.55, 0.45, 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); +} + @function tint($color, $percentage) { @return mix(rgb(245, 250, 255), $color, $percentage); } diff --git a/.config/ags/scss/_notifications.scss b/.config/ags/scss/_notifications.scss index 38e6b397d..7ac21aee9 100644 --- a/.config/ags/scss/_notifications.scss +++ b/.config/ags/scss/_notifications.scss @@ -93,17 +93,18 @@ $notif_surface: $t_background; color: $secondaryContainer; } -.notif-close-btn { +.notif-expand-btn { @include notif-rounding; - padding: 0rem 0.136rem; + min-width: 1.841rem; + min-height: 1.841rem; } -.notif-close-btn:hover, -.notif-close-btn:focus { +.notif-expand-btn:hover, +.notif-expand-btn:focus { background: $hovercolor; } -.notif-close-btn:active { +.notif-expand-btn:active { background: $activecolor; } @@ -123,14 +124,17 @@ $notif_surface: $t_background; .osd-notif { @include notif-rounding; - background-color: transparentize($background, $transparentize_surface_amount_subtract_surface); + background-color: transparentize( + $background, + $transparentize_surface_amount_subtract_surface + ); min-width: 30.682rem; } .notif-circprog-low { transition: 0ms linear; min-width: 0.136rem; // line width - min-height: 1.770rem; + min-height: 3.409rem; padding: 0rem; color: $onSecondaryContainer; } @@ -138,7 +142,7 @@ $notif_surface: $t_background; .notif-circprog-normal { transition: 0ms linear; min-width: 0.136rem; // line width - min-height: 1.770rem; + min-height: 3.409rem; padding: 0rem; color: $onSecondaryContainer; } @@ -146,7 +150,7 @@ $notif_surface: $t_background; .notif-circprog-critical { transition: 0ms linear; min-width: 0.136rem; // line width - min-height: 1.770rem; + min-height: 3.409rem; padding: 0rem; - color: $onSecondaryContainer; -} \ No newline at end of file + color: $secondaryContainer; +} diff --git a/.config/ags/scss/_osd.scss b/.config/ags/scss/_osd.scss index 6c6e2dde2..9d04f8d48 100644 --- a/.config/ags/scss/_osd.scss +++ b/.config/ags/scss/_osd.scss @@ -1,3 +1,7 @@ +// .osd-window { + // margin-top: 2.727rem; +// } + .osd-bg { min-width: 8.864rem; min-height: 3.409rem; diff --git a/.config/ags/services/waifus.js b/.config/ags/services/waifus.js new file mode 100644 index 000000000..3674713e6 --- /dev/null +++ b/.config/ags/services/waifus.js @@ -0,0 +1,170 @@ +import { Utils, Widget } from '../imports.js'; +import Service from 'resource:///com/github/Aylur/ags/service.js'; +import Gio from 'gi://Gio'; +import GLib from 'gi://GLib'; +import Soup from 'gi://Soup?version=3.0'; +import { fileExists } from './messages.js'; + +class WaifuResponse extends Service { + static { + Service.register(this, + { + 'delta': ['string'], + }, + { + 'content': ['string'], + 'thinking': ['boolean'], + 'done': ['boolean'], + }); + } + + _role = ''; + _content = ''; + _thinking = false; + _done = false; + + constructor(role, content, thinking = false, done = false) { + super(); + this._role = role; + this._content = content; + this._thinking = thinking; + this._done = done; + } + + get done() { return this._done } + set done(isDone) { this._done = isDone; this.notify('done') } + + get role() { return this._role } + set role(role) { this._role = role; this.emit('changed') } + + get content() { return this._content } + set content(content) { + this._content = content; + this.notify('content') + this.emit('changed') + } + + get label() { return this._parserState.parsed + this._parserState.stack.join('') } + + get thinking() { return this._thinking } + set thinking(thinking) { + this._thinking = thinking; + this.notify('thinking') + this.emit('changed') + } + + addDelta(delta) { + if (this.thinking) { + this.thinking = false; + this.content = delta; + } + else { + this.content += delta; + } + this.emit('delta', delta); + } +} + +class WaifuService extends Service { + _endpoints = { + 'im': 'https://api.waifu.im/search', + 'nekos': 'https://nekos.life/api/neko', + 'pics': 'https://api.waifu.pics/sfw/', + } + _headers = { + 'im': { 'Accept-Version': 'v5' }, + 'nekos': {}, + 'pics': {}, + } + _url = 'https://api.waifu.im/search'; + _mode = 'im'; // Allowed: im + _responses = []; + _nsfw = false; + _minHeight = 600; + + static { + Service.register(this, { + 'initialized': [], + 'clear': [], + 'newResponse': ['string'], + }); + } + + constructor() { + super(); + this.emit('initialized'); + } + + clear() { + this._responses = []; + this.emit('clear'); + } + + get mode() { return this._mode } + set mode(value) { + this._mode = value; + this._url = this._endpoints[this._mode]; + } + get nsfw() { return this._nsfw } + set nsfw(value) { this._nsfw = value } + get responses() { return this._responses } + + readResponseRecursive(stream, response) { + stream.read_line_async( + 0, null, + (stream, res) => { + if (!stream) return; + const [bytes] = stream.read_line_finish(res); + const line = this._decoder.decode(bytes); + if (line && line != '') { + let data = line.substr(6); + if (data == '[DONE]') return; + try { + const result = JSON.parse(data); + if (result.choices[0].finish_reason === 'stop') { + response.done = true; + return; + } + response.addDelta(result.choices[0].delta.content); + } + catch { + response.addDelta(line + '\n'); + } + } + this.readResponseRecursive(stream, response); + }); + } + + fetch(msg) { + const taglist = msg.split(' '); + this.emit('newResponse', msg); + this._responses.push(msg); + + const params = { + 'included_tags': taglist, + 'height': `>=${this._minHeight}`, + 'nsfw': this._nsfw, + }; + + const session = new Soup.Session(); + const message = new Soup.Message({ + method: 'GET', + uri: GLib.Uri.parse(this._url, GLib.UriFlags.NONE), + }); + session.send_message(message, (session, message) => { + if (message.status_code === 200) { + const responseBody = message.response_body.data; + const data = JSON.parse(responseBody); + // Process the response data as needed + console.log(data); + log(data); + } else { + logError('Request failed with status code: ' + message.status_code); + } + }); + + } +} + +export default new WaifuService(); + diff --git a/.config/ags/style.css b/.config/ags/style.css index 53f3aec50..8d7f9d373 100644 --- a/.config/ags/style.css +++ b/.config/ags/style.css @@ -159,6 +159,12 @@ .spacing-h-15 > revealer:last-child > * { margin-right: 0rem; } +.spacing-h-15 > scrolledwindow > * { + margin-right: 1.023rem; } + +.spacing-h-15 > scrolledwindow:last-child > * { + margin-right: 0rem; } + .spacing-v-5 > box { margin-bottom: 0.341rem; } @@ -177,6 +183,12 @@ .spacing-v-5-revealer > revealer:last-child > * { margin-bottom: 0rem; } +.spacing-v-5-revealer > scrolledwindow > * { + margin-bottom: 0.341rem; } + +.spacing-v-5-revealer > scrolledwindow:last-child > * { + margin-bottom: 0rem; } + .spacing-h-5 > * { margin-right: 0.341rem; } @@ -195,6 +207,12 @@ .spacing-h-5 > revealer:last-child > * { margin-right: 0rem; } +.spacing-h-5 > scrolledwindow > * { + margin-right: 0.341rem; } + +.spacing-h-5 > scrolledwindow:last-child > * { + margin-right: 0rem; } + .spacing-v-minus5 > * { margin-bottom: -0.341rem; } @@ -213,6 +231,12 @@ .spacing-h-10 > revealer:last-child > * { margin-right: 0rem; } +.spacing-h-10 > scrolledwindow > * { + margin-right: 0.682rem; } + +.spacing-h-10 > scrolledwindow:last-child > * { + margin-right: 0rem; } + .spacing-h-10 > flowboxchild > * { margin-right: 0.682rem; } @@ -330,6 +354,12 @@ .menu-decel { transition: 300ms cubic-bezier(0.1, 1, 0, 1); } +.element-show { + transition: 300ms cubic-bezier(0.85, 0, 0.15, 1); } + +.element-hide { + transition: 300ms cubic-bezier(0.85, 0, 0.15, 1); } + * { caret-color: #d6baff; } * selection { @@ -844,13 +874,14 @@ tooltip { .bar-systray { border-radius: 9999px; -gtk-outline-radius: 9999px; - min-height: 1.909rem; - min-width: 1.909rem; } + margin: 0.137rem 0rem; + padding: 0rem 0.682rem; } .bar-systray-item { border-radius: 9999px; -gtk-outline-radius: 9999px; - min-width: 1.909rem; } + min-height: 1.032rem; + min-width: 1.032rem; } .bar-statusicons { border-radius: 9999px; @@ -2089,16 +2120,17 @@ tooltip { background-color: #eadef7; color: #4b4358; } -.notif-close-btn { +.notif-expand-btn { border-radius: 1.159rem; -gtk-outline-radius: 1.159rem; - padding: 0rem 0.136rem; } + min-width: 1.841rem; + min-height: 1.841rem; } -.notif-close-btn:hover, -.notif-close-btn:focus { +.notif-expand-btn:hover, +.notif-expand-btn:focus { background: rgba(128, 128, 128, 0.3); } -.notif-close-btn:active { +.notif-expand-btn:active { background: rgba(128, 128, 128, 0.7); } .notif-closeall-btn { @@ -2122,23 +2154,23 @@ tooltip { .notif-circprog-low { transition: 0ms linear; min-width: 0.136rem; - min-height: 1.770rem; + min-height: 3.409rem; padding: 0rem; color: #eadef7; } .notif-circprog-normal { transition: 0ms linear; min-width: 0.136rem; - min-height: 1.770rem; + min-height: 3.409rem; padding: 0rem; color: #eadef7; } .notif-circprog-critical { transition: 0ms linear; min-width: 0.136rem; - min-height: 1.770rem; + min-height: 3.409rem; padding: 0rem; - color: #eadef7; } + color: #4b4358; } .osd-music { transition: 300ms cubic-bezier(0.1, 1, 0, 1); diff --git a/.config/ags/widgets/bar/tray.js b/.config/ags/widgets/bar/tray.js index 0d0ded80d..885bec07f 100644 --- a/.config/ags/widgets/bar/tray.js +++ b/.config/ags/widgets/bar/tray.js @@ -10,7 +10,13 @@ const SysTrayItem = item => Button({ className: 'bar-systray-item', child: Icon({ hpack: 'center', - binds: [['icon', item, 'icon']] + binds: [['icon', item, 'icon']], + setup: (self) => Utils.timeout(1, () => { + const styleContext = self.get_parent().get_style_context(); + const width = styleContext.get_property('min-width', Gtk.StateFlags.NORMAL); + const height = styleContext.get_property('min-height', Gtk.StateFlags.NORMAL); + self.size = Math.max(width, height, 1); // im too lazy to add another box lol + }), }), binds: [['tooltipMarkup', item, 'tooltip-markup']], onClicked: btn => item.menu.popup_at_widget(btn, Gravity.SOUTH, Gravity.NORTH, null), @@ -19,8 +25,7 @@ const SysTrayItem = item => Button({ export const Tray = (props = {}) => { const trayContent = Box({ - vpack: 'center', - className: 'bar-systray bar-group', + className: 'bar-systray bar-group spacing-h-10', properties: [ ['items', new Map()], ['onAdded', (box, id) => { @@ -31,7 +36,7 @@ export const Tray = (props = {}) => { return; const widget = SysTrayItem(item); box._items.set(id, widget); - box.pack_start(widget, false, false, 0); + box.add(widget); box.show_all(); if (box._items.size === 1) trayRevealer.revealChild = true; diff --git a/.config/ags/widgets/indicators/indicatorvalues.js b/.config/ags/widgets/indicators/indicatorvalues.js index e4d587809..74c4f641d 100644 --- a/.config/ags/widgets/indicators/indicatorvalues.js +++ b/.config/ags/widgets/indicators/indicatorvalues.js @@ -2,34 +2,32 @@ const { GLib, Gtk } = imports.gi; import { App, Service, Utils, Widget } from '../../imports.js'; import Audio from 'resource:///com/github/Aylur/ags/service/audio.js'; -import Notifications from 'resource:///com/github/Aylur/ags/service/notifications.js'; -const { Box, EventBox, Icon, Scrollable, Label, Button, Revealer } = Widget; +const { Box, Label, ProgressBar, Revealer } = Widget; import Brightness from '../../services/brightness.js'; import Indicator from '../../services/indicator.js'; -import Notification from '../../lib/notification.js'; -const OsdValue = (name, labelConnections, progressConnections, props = {}) => Widget.Box({ // Volume +const OsdValue = (name, labelConnections, progressConnections, props = {}) => Box({ // Volume ...props, vertical: true, className: 'osd-bg osd-value', hexpand: true, children: [ - Widget.Box({ + Box({ vexpand: true, children: [ - Widget.Label({ + Label({ xalign: 0, yalign: 0, hexpand: true, className: 'osd-label', label: `${name}`, }), - Widget.Label({ + Label({ hexpand: false, className: 'osd-value-txt', label: '100', connections: labelConnections, }), ] }), - Widget.ProgressBar({ + ProgressBar({ className: 'osd-progress', hexpand: true, vertical: false, @@ -58,14 +56,14 @@ const volumeIndicator = OsdValue('Volume', }]], ); -export default () => Widget.Revealer({ +export default () => Revealer({ transition: 'slide_down', connections: [ [Indicator, (revealer, value) => { revealer.revealChild = (value > -1); }, 'popup'], ], - child: Widget.Box({ + child: Box({ hpack: 'center', vertical: false, children: [ diff --git a/.config/ags/widgets/indicators/main.js b/.config/ags/widgets/indicators/main.js index ee74f8a56..b2204a15b 100644 --- a/.config/ags/widgets/indicators/main.js +++ b/.config/ags/widgets/indicators/main.js @@ -10,6 +10,7 @@ export default (monitor) => Widget.Window({ monitor, className: 'indicator', layer: 'overlay', + // exclusivity: 'ignore', visible: true, anchor: ['top'], child: Widget.EventBox({ @@ -18,6 +19,7 @@ export default (monitor) => Widget.Window({ }, child: Widget.Box({ vertical: true, + className: 'osd-window', css: 'min-height: 2px;', children: [ IndicatorValues(), @@ -28,3 +30,4 @@ export default (monitor) => Widget.Window({ }) }), }); + diff --git a/.config/ags/widgets/overview/overview.js b/.config/ags/widgets/overview/overview.js index 5a62f2f94..aca13a286 100644 --- a/.config/ags/widgets/overview/overview.js +++ b/.config/ags/widgets/overview/overview.js @@ -4,7 +4,7 @@ import Applications from 'resource:///com/github/Aylur/ags/service/applications. import Hyprland from 'resource:///com/github/Aylur/ags/service/hyprland.js'; const { execAsync, exec } = Utils; import { setupCursorHover, setupCursorHoverGrab } from "../../lib/cursorhover.js"; -import { DoubleRevealer } from "../../lib/doublerevealer.js"; +import { DoubleRevealer } from "../../lib/advancedrevealers.js"; import { execAndClose, expandTilde, hasUnterminatedBackslash, startsWithNumber, launchCustomCommand, ls } from './miscfunctions.js'; import { CalculationResultButton, CustomCommandButton, DirectoryButton, diff --git a/.config/ags/widgets/sideleft/apis/chatgpt.js b/.config/ags/widgets/sideleft/apis/chatgpt.js index 314877326..898a6a3fb 100644 --- a/.config/ags/widgets/sideleft/apis/chatgpt.js +++ b/.config/ags/widgets/sideleft/apis/chatgpt.js @@ -8,6 +8,7 @@ import { setupCursorHover, setupCursorHoverInfo } from "../../../lib/cursorhover import { SystemMessage, ChatMessage } from "./chatgpt_chatmessage.js"; import { ConfigToggle, ConfigSegmentedSelection, ConfigGap } from '../../../lib/configwidgets.js'; import { markdownTest } from '../../../lib/md2pango.js'; +import { MarginRevealer } from '../../../lib/advancedrevealers.js'; export const chatGPTTabIcon = Box({ hpack: 'center', @@ -60,16 +61,15 @@ const chatGPTInfo = Box({ ] }) -export const chatGPTSettings = Revealer({ +export const chatGPTSettings = MarginRevealer({ transition: 'slide_down', - transitionDuration: 150, revealChild: true, connections: [ [ChatGPT, (self) => Utils.timeout(200, () => { - self.revealChild = false; + self._hide(self); }), 'newMsg'], [ChatGPT, (self) => Utils.timeout(200, () => { - self.revealChild = true; + self._show(self); }), 'clear'], ], child: Box({ @@ -249,6 +249,16 @@ export const chatGPTSendMessage = (text) => { if (text.startsWith('/')) { if (text.startsWith('/clear')) clearChat(); else if (text.startsWith('/model')) chatContent.add(SystemMessage(`Currently using \`${ChatGPT.modelName}\``, '/model', chatGPTView)) + else if (text.startsWith('/prompt')) { + const firstSpaceIndex = text.indexOf(' '); + const prompt = text.slice(firstSpaceIndex + 1); + if (firstSpaceIndex == -1 || prompt.length < 1) { + chatContent.add(SystemMessage(`Usage: \`/prompt MESSAGE\``, '/prompt', chatGPTView)) + } + else { + ChatGPT.addMessage('user', prompt) + } + } else if (text.startsWith('/key')) { const parts = text.split(' '); if (parts.length == 1) chatContent.add(SystemMessage( diff --git a/.config/ags/widgets/sideleft/apis/chatgpt_chatmessage.js b/.config/ags/widgets/sideleft/apis/chatgpt_chatmessage.js index 8a5a25faa..99faf5368 100644 --- a/.config/ags/widgets/sideleft/apis/chatgpt_chatmessage.js +++ b/.config/ags/widgets/sideleft/apis/chatgpt_chatmessage.js @@ -9,7 +9,7 @@ import GtkSource from "gi://GtkSource?version=3.0"; const CUSTOM_SOURCEVIEW_SCHEME_PATH = `${App.configDir}/data/sourceviewtheme.xml`; const CUSTOM_SCHEME_ID = 'custom'; const USERNAME = GLib.get_user_name(); -const CHATGPT_CURSOR = ' >> '; +const CHATGPT_CURSOR = ' (o) '; const MESSAGE_SCROLL_DELAY = 13; // In milliseconds, the time before an updated message scrolls to bottom /////////////////////// Custom source view colorscheme ///////////////////////// @@ -92,10 +92,6 @@ const CodeBlock = (content = '', lang = 'txt') => { }), Button({ className: 'sidebar-chat-codeblock-topbar-btn', - onClicked: (self) => { - // execAsync(['bash', '-c', `wl-copy '${content}'`, `&`]).catch(print); - execAsync([`wl-copy`, `${sourceView.label}`]).catch(print); - }, child: Box({ className: 'spacing-h-5', children: [ @@ -104,8 +100,13 @@ const CodeBlock = (content = '', lang = 'txt') => { label: 'Copy', }) ] - }) - }) + }), + onClicked: (self) => { + const copyContent = sourceView.get_buffer().get_text(0, 0, 0); // TODO: fix this + console.log(copyContent); + execAsync([`wl-copy`, `${copyContent}`]).catch(print); + }, + }), ] }) // Source view diff --git a/.config/ags/widgets/sideleft/apis/waifu.js b/.config/ags/widgets/sideleft/apis/waifu.js index 34cfb0214..e4e7dd631 100644 --- a/.config/ags/widgets/sideleft/apis/waifu.js +++ b/.config/ags/widgets/sideleft/apis/waifu.js @@ -4,6 +4,7 @@ const { Box, Button, Entry, EventBox, Icon, Label, Revealer, Scrollable, Stack } const { execAsync, exec } = Utils; import { MaterialIcon } from "../../../lib/materialicon.js"; import { setupCursorHover, setupCursorHoverInfo } from "../../../lib/cursorhover.js"; +import WaifuService from '../../../services/waifus.js'; export const waifuTabIcon = Box({ hpack: 'center', @@ -14,12 +15,27 @@ export const waifuTabIcon = Box({ ] }); +const waifuContent = Box({ + className: 'spacing-v-15', + vertical: true, + connections: [ + [WaifuService, (box, id) => { + const message = WaifuService.responses[id]; + if (!message) return; + box.add(Label({ + label: message, + })) + }, 'newResponse'], + ] +}); + export const waifuView = Scrollable({ className: 'sidebar-chat-viewport', vexpand: true, child: Box({ vertical: true, children: [ + waifuContent, ] }), setup: (scrolledWindow) => { @@ -45,11 +61,12 @@ export const waifuCommands = Box({ // command do something }, setup: setupCursorHover, - label: '/A command button', + label: '/call', }), ] }); export const waifuCallAPI = (text) => { // Do something on send + WaifuService.fetch(text); } \ No newline at end of file diff --git a/.config/ags/widgets/sideleft/apiwidgets.js b/.config/ags/widgets/sideleft/apiwidgets.js index 88d1539d5..573b65dab 100644 --- a/.config/ags/widgets/sideleft/apiwidgets.js +++ b/.config/ags/widgets/sideleft/apiwidgets.js @@ -15,6 +15,7 @@ const APIS = [ contentWidget: chatGPTView, commandBar: chatGPTCommands, tabIcon: chatGPTTabIcon, + placeholderText: 'Message ChatGPT', }, { name: 'Waifus', @@ -22,6 +23,7 @@ const APIS = [ contentWidget: waifuView, commandBar: waifuCommands, tabIcon: waifuTabIcon, + placeholderText: 'Enter tags', }, ]; let currentApiId = 0; @@ -80,6 +82,7 @@ function switchToTab(id) { APIS[id].tabIcon.toggleClassName('sidebar-chat-apiswitcher-icon-enabled', true); apiContentStack.shown = APIS[id].name; apiCommandStack.shown = APIS[id].name; + chatEntry.placeholderText = APIS[id].placeholderText, currentApiId = id; } const apiSwitcher = Box({ diff --git a/.config/ags/widgets/sideleft/sideleft.js b/.config/ags/widgets/sideleft/sideleft.js index 32150a8e3..12ea47330 100644 --- a/.config/ags/widgets/sideleft/sideleft.js +++ b/.config/ags/widgets/sideleft/sideleft.js @@ -172,6 +172,8 @@ export default () => Box({ if (event.get_keyval()[1] == Gdk.KEY_p) pinButton._toggle(pinButton); // Switch sidebar tab + else if (event.get_keyval()[1] === Gdk.KEY_Tab) + switchToTab((currentTabId + 1) % contents.length); else if (event.get_keyval()[1] === Gdk.KEY_Page_Up) switchToTab(Math.max(currentTabId - 1), 0); else if (event.get_keyval()[1] === Gdk.KEY_Page_Down)