ags: sync

This commit is contained in:
end-4
2023-12-31 01:12:29 +07:00
parent 7bede724a5
commit 5e43761875
62 changed files with 2688 additions and 1468 deletions
+14 -21
View File
@@ -1,12 +1,11 @@
"strict mode"; "strict mode";
// Import // Import
import { App, Utils } from './imports.js'; import { App, Utils } from './imports.js';
import { firstRunWelcome } from './services/messages.js';
// Widgets // Widgets
import Bar from './widgets/bar/main.js'; import Bar from './widgets/bar/main.js';
import Cheatsheet from './widgets/cheatsheet/main.js'; import Cheatsheet from './widgets/cheatsheet/main.js';
import DesktopBackground from './widgets/desktopbackground/main.js'; // import DesktopBackground from './widgets/desktopbackground/main.js';
import Dock from './widgets/dock/main.js'; // import Dock from './widgets/dock/main.js';
import { CornerTopleft, CornerTopright, CornerBottomleft, CornerBottomright } from './widgets/screencorners/main.js'; import { CornerTopleft, CornerTopright, CornerBottomleft, CornerBottomright } from './widgets/screencorners/main.js';
import Indicator from './widgets/indicators/main.js'; import Indicator from './widgets/indicators/main.js';
import Osk from './widgets/onscreenkeyboard/main.js'; import Osk from './widgets/onscreenkeyboard/main.js';
@@ -15,18 +14,20 @@ import Session from './widgets/session/main.js';
import SideLeft from './widgets/sideleft/main.js'; import SideLeft from './widgets/sideleft/main.js';
import SideRight from './widgets/sideright/main.js'; import SideRight from './widgets/sideright/main.js';
// Longer than actual anim time (see styles) to make sure widgets animate fully const CLOSE_ANIM_TIME = 210; // Longer than actual anim time (see styles) to make sure widgets animate fully
const CLOSE_ANIM_TIME = 210;
// Init cache and check first run // Init cache
Utils.exec(`bash -c 'mkdir -p ~/.cache/ags/user/colorschemes'`); Utils.exec(`bash -c 'mkdir -p ~/.cache/ags/user/colorschemes'`);
// SCSS compilation // SCSS compilation
Utils.exec(`bash -c 'echo "" > ${App.configDir}/scss/_musicwal.scss'`); // reset music styles Utils.exec(`bash -c 'echo "" > ${App.configDir}/scss/_musicwal.scss'`); // reset music styles
Utils.exec(`bash -c 'echo "" > ${App.configDir}/scss/_musicmaterial.scss'`); // reset music styles Utils.exec(`bash -c 'echo "" > ${App.configDir}/scss/_musicmaterial.scss'`); // reset music styles
Utils.exec(`sassc ${App.configDir}/scss/main.scss ${App.configDir}/style.css`); function applyStyle() {
App.resetCss(); Utils.exec(`sassc ${App.configDir}/scss/main.scss ${App.configDir}/style.css`);
App.applyCss(`${App.configDir}/style.css`); App.resetCss();
App.applyCss(`${App.configDir}/style.css`);
console.log('[LOG] Styles loaded')
}
applyStyle();
// Config object // Config object
export default { export default {
@@ -38,13 +39,12 @@ export default {
'osk': CLOSE_ANIM_TIME, 'osk': CLOSE_ANIM_TIME,
}, },
windows: [ windows: [
// Bar() is below
CornerTopleft(), CornerTopleft(),
CornerTopright(), CornerTopright(),
CornerBottomleft(), CornerBottomleft(),
CornerBottomright(), CornerBottomright(),
DesktopBackground(), // DesktopBackground(),
Dock(), // Buggy // Dock(), // Buggy
Overview(), Overview(),
Indicator(), Indicator(),
Cheatsheet(), Cheatsheet(),
@@ -52,13 +52,6 @@ export default {
SideRight(), SideRight(),
Osk(), // On-screen keyboard Osk(), // On-screen keyboard
Session(), // Power menu, if that's what you like to call it Session(), // Power menu, if that's what you like to call it
Bar(),
], ],
}; };
// We don't want context menus of the bar's tray go under the rounded corner below,
// So bar is returned after 1ms, making it get spawned after the corner
// And having an Utils.timeout in that window array just gives an error
// Not having it in default export is fine since we don't need to toggle it
Bar();
// uwu
+1 -1
View File
@@ -111,4 +111,4 @@ export const oskLayouts = {
] ]
] ]
} }
} }
+1 -1
View File
@@ -29,7 +29,7 @@
<style name="current-line" background="#3E3D32"/> <style name="current-line" background="#3E3D32"/>
<style name="current-line-number" background="#eeeeec"/> <style name="current-line-number" background="#eeeeec"/>
<style name="draw-spaces" foreground="#babdb6"/> <style name="draw-spaces" foreground="#babdb6"/>
<style name="background-pattern" background="#rgba(0,0,0,0)"/> <style name="background-pattern" background="#000000"/>
<!-- Bracket Matching --> <!-- Bracket Matching -->
<!-- <style name="bracket-match" foreground="white" background="grey"/> --> <!-- <style name="bracket-match" foreground="white" background="grey"/> -->
+81
View File
@@ -0,0 +1,81 @@
const { Gdk, Gtk } = imports.gi;
import { App, SCREEN_WIDTH, SCREEN_HEIGHT, 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, they don't really hide
hideClass = 'element-hide', // Don't put margins in these classes!
extraProperties = [],
...rest
}) => {
const widget = Scrollable({
...rest,
css: `min-height: 0px;`,
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;
self.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.NEVER);
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) => {
console.log('toggle');
if (self._revealChild) self._hide(self);
else self._show(self);
}],
...extraProperties,
],
setup: (self) => {
if (!revealChild)
self.set_policy(Gtk.PolicyType.ALWAYS, Gtk.PolicyType.ALWAYS);
else
self.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.NEVER);
self.child = child;
},
});
child.toggleClassName(`${revealChild ? showClass : hideClass}`, true);
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,
})
})
}
+74 -12
View File
@@ -4,7 +4,7 @@ import { MaterialIcon } from './materialicon.js';
import { setupCursorHover } from './cursorhover.js'; import { setupCursorHover } from './cursorhover.js';
const { Box, Button, Entry, EventBox, Icon, Label, Revealer, Scrollable, Stack } = Widget; const { Box, Button, Entry, EventBox, Icon, Label, Revealer, Scrollable, Stack } = Widget;
export const ConfigToggle = ({ icon, name, desc = '', initValue, onChange, ...props }) => { export const ConfigToggle = ({ icon, name, desc = '', initValue, onChange, ...rest }) => {
let value = initValue; let value = initValue;
const toggleIcon = Label({ const toggleIcon = Label({
className: `icon-material txt-bold ${value ? '' : 'txt-poof'}`, className: `icon-material txt-bold ${value ? '' : 'txt-poof'}`,
@@ -37,25 +37,87 @@ export const ConfigToggle = ({ icon, name, desc = '', initValue, onChange, ...pr
] ]
}); });
const interactionWrapper = Button({ const interactionWrapper = Button({
...props,
child: widgetContent, child: widgetContent,
setup: setupCursorHover,
onClicked: () => { // mouse up/kb press onClicked: () => { // mouse up/kb press
value = !value; value = !value;
toggleIcon.toggleClassName('switch-fg-toggling-false', false); toggleIcon.toggleClassName('switch-fg-toggling-false', false);
toggleIcon.label = `${value ? 'check' : ''}`; if (!value) {
toggleIcon.toggleClassName('txt-poof', !value); toggleIcon.label = '';
toggleIcon.toggleClassName('txt-poof', true);
}
toggleButtonIndicator.toggleClassName('switch-fg-true', value); toggleButtonIndicator.toggleClassName('switch-fg-true', value);
toggleButton.toggleClassName('switch-bg-true', value); toggleButton.toggleClassName('switch-bg-true', value);
if(value) Utils.timeout(1, () => {
toggleIcon.label = 'check';
toggleIcon.toggleClassName('txt-poof', false);
})
onChange(interactionWrapper, value); onChange(interactionWrapper, value);
}, },
setup: (button) => { setup: (button) => {
button.connect('pressed', () => { // mouse down setupCursorHover(button),
toggleIcon.toggleClassName('txt-poof', true); button.connect('pressed', () => { // mouse down
toggleIcon.toggleClassName('switch-fg-true', false); toggleIcon.toggleClassName('txt-poof', true);
if(!value) toggleIcon.toggleClassName('switch-fg-toggling-false', true); toggleIcon.toggleClassName('switch-fg-true', false);
}); if (!value) toggleIcon.toggleClassName('switch-fg-toggling-false', true);
} });
},
...rest,
}); });
return interactionWrapper; return interactionWrapper;
} }
export const ConfigSegmentedSelection = ({
icon, name, desc = '',
options = [{ name: 'Option 1', value: 0 }, { name: 'Option 2', value: 1 }],
initIndex = 0,
onChange,
...rest
}) => {
let lastSelected = initIndex;
let value = options[initIndex].value;
const widget = Box({
tooltipText: desc,
className: 'segment-container',
// homogeneous: true,
children: options.map((option, id) => {
const selectedIcon = Revealer({
revealChild: id == initIndex,
transition: 'slide_right',
transitionDuration: 150,
child: MaterialIcon('check', 'norm')
});
return Button({
setup: setupCursorHover,
className: `segment-btn ${id == initIndex ? 'segment-btn-enabled' : ''}`,
child: Box({
hpack: 'center',
className: 'spacing-h-5',
children: [
selectedIcon,
Label({
label: option.name,
})
]
}),
onClicked: (self) => {
value = option.value;
const kids = widget.get_children();
kids[lastSelected].toggleClassName('segment-btn-enabled', false);
kids[lastSelected].get_children()[0].get_children()[0].revealChild = false;
lastSelected = id;
self.toggleClassName('segment-btn-enabled', true);
selectedIcon.revealChild = true;
onChange(option.value, option.name);
}
})
}),
...rest,
});
return widget;
}
export const ConfigGap = ({ vertical = true, size = 5, ...rest }) => Box({
className: `gap-${vertical ? 'v' : 'h'}-${size}`,
...rest,
})
-24
View File
@@ -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,
})
})
}
+11 -8
View File
@@ -12,12 +12,11 @@ let sub_h1, sub_h2, sub_h3, sub_h4, sub_h5
// m2p_sections defines how to detect special markdown sections. // m2p_sections defines how to detect special markdown sections.
// These expressions scan the full line to detect headings, lists, and code. // These expressions scan the full line to detect headings, lists, and code.
const m2p_sections = [ const m2p_sections = [
// h1 is actually 210% on github, but it's unecessary large imo sub_h1 = { name: H1, re: /^(#\s+)(.*)(\s*)$/, sub: "<span font_weight='bold' size='170%'>$2</span>" },
sub_h1 = { name: H1, re: /^(#\s+)(.*)(\s*)$/, sub: "<span font_weight='bold' size='150%'>$2</span>" }, sub_h2 = { name: H2, re: /^(##\s+)(.*)(\s*)$/, sub: "<span font_weight='bold' size='150%'>$2</span>" },
sub_h2 = { name: H2, re: /^(##\s+)(.*)(\s*)$/, sub: "<span font_weight='bold' size='125%'>$2</span>" }, sub_h3 = { name: H3, re: /^(###\s+)(.*)(\s*)$/, sub: "<span font_weight='bold' size='125%'>$2</span>" },
sub_h3 = { name: H3, re: /^(###\s+)(.*)(\s*)$/, sub: "<span font_weight='bold' size='100%'>$2</span>" }, sub_h4 = { name: H4, re: /^(####\s+)(.*)(\s*)$/, sub: "<span font_weight='bold' size='100%'>$2</span>" },
sub_h4 = { name: H4, re: /^(####\s+)(.*)(\s*)$/, sub: "<span font_weight='bold' size='90%'>$2</span>" }, sub_h5 = { name: H5, re: /^(#####\s+)(.*)(\s*)$/, sub: "<span font_weight='bold' size='90%'>$2</span>" },
sub_h5 = { name: H5, re: /^(#####\s+)(.*)(\s*)$/, sub: "<span font_weight='bold' size='80%'>$2</span>" },
{ name: BULLET, re: /^(\s*)([\*\-]\s)(.*)(\s*)$/, sub: "$1• $3" }, { name: BULLET, re: /^(\s*)([\*\-]\s)(.*)(\s*)$/, sub: "$1• $3" },
{ name: NUMBERING, re: /^(\s*[0-9]+\.\s)(.*)(\s*)$/, sub: " $1$2" }, { name: NUMBERING, re: /^(\s*[0-9]+\.\s)(.*)(\s*)$/, sub: " $1$2" },
] ]
@@ -29,7 +28,7 @@ const m2p_styles = [
{ name: EMPH, re: /\*(\S.*?\S)\*/g, sub: "<i>$1</i>" }, { name: EMPH, re: /\*(\S.*?\S)\*/g, sub: "<i>$1</i>" },
// { name: EMPH, re: /_(\S.*?\S)_/g, sub: "<i>$1</i>" }, // { name: EMPH, re: /_(\S.*?\S)_/g, sub: "<i>$1</i>" },
{ name: HEXCOLOR, re: /#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})/g, sub: `<span bgcolor='#$1' fgcolor='#000000' font_family='${monospaceFonts}'> #$1 </span>` }, { name: HEXCOLOR, re: /#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})/g, sub: `<span bgcolor='#$1' fgcolor='#000000' font_family='${monospaceFonts}'> #$1 </span>` },
{ name: INLCODE, re: /(`)([^`]*)(`)/g, sub: `<span font_weight='bold' font_family='${monospaceFonts}' bgcolor='#000000' fgcolor='#ffffff'> $2 </span>` }, { name: INLCODE, re: /(`)([^`]*)(`)/g, sub: `<span font_weight='bold' font_family='${monospaceFonts}'> $2 </span>` },
// { name: UND, re: /(__|\*\*)(\S[\s\S]*?\S)(__|\*\*)/g, sub: "<u>$2</u>" }, // { name: UND, re: /(__|\*\*)(\S[\s\S]*?\S)(__|\*\*)/g, sub: "<u>$2</u>" },
] ]
@@ -226,7 +225,11 @@ if (__is_nodejs_main) {
console.log(`Usage: ${process.argv[1]} FILE [FILE...]`) console.log(`Usage: ${process.argv[1]} FILE [FILE...]`)
process.exit(0) process.exit(0)
} }
args.forEach((f) => process.stdout.write(convert(readFile(f)))) for (let i = 0; i < args.length; i++) {
const f = args[i];
process.stdout.write(convert(readFile(f)));
}
} }
export const markdownTest = `# Heading 1 export const markdownTest = `# Heading 1
+196 -120
View File
@@ -7,6 +7,7 @@ const { Box, EventBox, Icon, Overlay, Label, Button, Revealer } = Widget;
import { MaterialIcon } from "./materialicon.js"; import { MaterialIcon } from "./materialicon.js";
import { setupCursorHover } from "./cursorhover.js"; import { setupCursorHover } from "./cursorhover.js";
import { AnimatedCircProg } from "./animatedcircularprogress.js"; import { AnimatedCircProg } from "./animatedcircularprogress.js";
import { MarginRevealer } from './advancedrevealers.js';
function guessMessageType(summary) { function guessMessageType(summary) {
if (summary.includes('recording')) return 'screen_record'; if (summary.includes('recording')) return 'screen_record';
@@ -43,21 +44,20 @@ const NotificationIcon = (notifObject) => {
icon = notifObject.appEntry; icon = notifObject.appEntry;
return Box({ return Box({
valign: Gtk.Align.CENTER, vpack: 'center',
hexpand: false, hexpand: false,
className: `notif-icon notif-icon-material-${notifObject.urgency}`, className: `notif-icon notif-icon-material-${notifObject.urgency}`,
homogeneous: true, homogeneous: true,
children: [ children: [
(icon != 'NO_ICON' ? (icon != 'NO_ICON' ?
Icon({ Icon({
vpack: 'center',
icon: icon, icon: icon,
halign: Gtk.Align.CENTER, hexpand: true,
valign: Gtk.Align.CENTER,
setup: (self) => Utils.timeout(1, () => { setup: (self) => Utils.timeout(1, () => {
const styleContext = self.get_parent().get_style_context(); const styleContext = self.get_parent().get_style_context();
const width = styleContext.get_property('min-width', Gtk.StateFlags.NORMAL); const width = styleContext.get_property('min-width', Gtk.StateFlags.NORMAL);
const height = styleContext.get_property('min-height', Gtk.StateFlags.NORMAL); const height = styleContext.get_property('min-height', Gtk.StateFlags.NORMAL);
self.size = Math.max(width * 0.9, height * 0.9, 1); // im too lazy to add another box lol self.size = Math.max(width * 0.7, height * 0.7, 1); // im too lazy to add another box lol
}), }),
}) })
: :
@@ -81,7 +81,7 @@ export default ({
) )
const destroyWithAnims = () => { const destroyWithAnims = () => {
widget.sensitive = false; widget.sensitive = false;
notificationBox.setCss(rightAnim1); notificationBox.setCss(middleClickClose);
Utils.timeout(200, () => { Utils.timeout(200, () => {
wholeThing.revealChild = false; wholeThing.revealChild = false;
}); });
@@ -125,103 +125,153 @@ export default ({
}); });
const display = Gdk.Display.get_default(); const display = Gdk.Display.get_default();
const notifTextPreview = Revealer({
transition: 'slide_down',
transitionDuration: 120,
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: 120,
revealChild: false,
child: Box({
vertical: true,
className: 'spacing-v-10',
children: [
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,
}),
Box({
homogeneous: true,
className: 'notif-actions',
children: [
Button({
className: `notif-action notif-action-${notifObject.urgency}`,
label: 'Close',
onClicked: () => destroyWithAnims(),
}),
...notifObject.actions.map(action => Widget.Button({
className: `notif-action notif-action-${notifObject.urgency}`,
onClicked: () => notifObject.invoke(action.id),
label: action.label,
}))
],
})
]
}),
});
const notifIcon = Box({
vpack: 'start',
homogeneous: true,
children: [
Overlay({
child: NotificationIcon(notifObject),
overlays: isPopup ? [AnimatedCircProg({
className: `notif-circprog-${notifObject.urgency}`,
vpack: 'center', hpack: 'center',
initFrom: (isPopup ? 100 : 0),
initTo: 0,
initAnimTime: popupTimeout,
})] : [],
}),
]
});
let notifTime = '';
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())
notifTime = messageTime.format('%H:%M');
else if (messageTime.get_day_of_year() == GLib.DateTime.new_now_local().get_day_of_year() - 1)
notifTime = 'Yesterday';
else
notifTime = messageTime.format('%d/%m');
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,
useMarkup: notifObject.summary.startsWith('<'),
label: notifObject.summary,
}),
Label({
vpack: 'center',
justification: 'right',
className: 'txt-smaller txt-semibold',
label: notifTime,
}),
]
}),
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';
expanded = true;
}
else {
notifTextPreview.revealChild = true;
notifTextExpanded.revealChild = false;
self.child.label = 'expand_more';
expanded = false;
}
},
child: MaterialIcon('expand_more', 'norm', {
vpack: 'center',
}),
setup: setupCursorHover,
});
const notificationContent = Box({ const notificationContent = Box({
...props, ...props,
className: `${isPopup ? 'popup-' : ''}notif-${notifObject.urgency} spacing-h-10`, className: `${isPopup ? 'popup-' : ''}notif-${notifObject.urgency} spacing-h-10`,
children: [ children: [
NotificationIcon(notifObject), notifIcon,
Box({ notifText,
valign: Gtk.Align.CENTER, notifExpandButton,
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,
}),
]
}),
// what is this? i think it should be at the bottom not on the right
// Box({
// className: 'actions',
// children: actions.map(action => Button({
// className: 'action-button',
// onClicked: () => Notifications.invoke(id, action.id),
// hexpand: true,
// child: Label(action.label),
// })),
// }),
] ]
}) })
// Gesture stuff // Gesture stuff
const gesture = Gtk.GestureDrag.new(widget); const gesture = Gtk.GestureDrag.new(widget);
var initialDir = 0; var initDirX = 0;
var initDirVertical = -1; // -1: unset, 0: horizontal, 1: vertical
var expanded = false;
// in px // in px
const startMargin = 0; const startMargin = 0;
const dragThreshold = 100; const MOVE_THRESHOLD = 10;
const DRAG_CONFIRM_THRESHOLD = 100;
// in rem // in rem
const maxOffset = 10.227; const maxOffset = 10.227;
const endMargin = 20.455; const endMargin = 20.455;
@@ -236,57 +286,83 @@ export default ({
margin-right: -${Number(maxOffset + endMargin)}rem; margin-right: -${Number(maxOffset + endMargin)}rem;
opacity: 0;`; 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({ const notificationBox = Box({
properties: [ attribute: {
['leftAnim1', leftAnim1], 'leftAnim1': leftAnim1,
['rightAnim1', rightAnim1], 'rightAnim1': rightAnim1,
['ready', false], 'middleClickClose': middleClickClose,
], 'ready': false,
},
homogeneous: true, homogeneous: true,
children: [notificationContent], children: [notificationContent],
connections: [ setup: (self) => self
[gesture, self => { .hook(gesture, self => {
var offset = gesture.get_offset()[1]; var offset_x = gesture.get_offset()[1];
if (initialDir == 0 && offset != 0) var offset_y = gesture.get_offset()[2];
initialDir = (offset > 0 ? 1 : -1) if (initDirVertical == -1) {
if (Math.abs(offset_y) > MOVE_THRESHOLD)
initDirVertical = 1;
if (initDirX == 0 && Math.abs(offset_x) > MOVE_THRESHOLD) {
initDirVertical = 0;
initDirX = (offset_x > 0 ? 1 : -1);
}
}
if (offset > 0) { if (initDirVertical == 0 && offset_x > MOVE_THRESHOLD) {
if (initialDir < 0) if (initDirX < 0)
self.setCss(`margin-left: 0px; margin-right: 0px;`); self.setCss(`margin-left: 0px; margin-right: 0px;`);
else else
self.setCss(` self.setCss(`
margin-left: ${Number(offset + startMargin)}px; margin-left: ${Number(offset_x + startMargin - MOVE_THRESHOLD)}px;
margin-right: -${Number(offset + startMargin)}px; margin-right: -${Number(offset_x + startMargin - MOVE_THRESHOLD)}px;
`); `);
} }
else if (offset < 0) { else if (initDirVertical == 0 && offset_x < -MOVE_THRESHOLD) {
if (initialDir > 0) if (initDirX > 0)
self.setCss(`margin-left: 0px; margin-right: 0px;`); self.setCss(`margin-left: 0px; margin-right: 0px;`);
else { else {
offset = Math.abs(offset); offset_x = Math.abs(offset_x);
self.setCss(` self.setCss(`
margin-right: ${Number(offset + startMargin)}px; margin-right: ${Number(offset_x + startMargin - MOVE_THRESHOLD)}px;
margin-left: -${Number(offset + startMargin)}px; margin-left: -${Number(offset_x + startMargin - MOVE_THRESHOLD)}px;
`); `);
} }
} }
wholeThing._dragging = Math.abs(offset) > 10; wholeThing._dragging = Math.abs(offset_x) > 10;
if (widget.window) if (widget.window)
widget.window.set_cursor(Gdk.Cursor.new_from_name(display, 'grabbing')); widget.window.set_cursor(Gdk.Cursor.new_from_name(display, 'grabbing'));
}, 'drag-update'],
[gesture, self => { if (initDirVertical == 1 && offset_y > MOVE_THRESHOLD && !expanded) {
notifTextPreview.revealChild = false;
notifTextExpanded.revealChild = true;
expanded = true;
notifExpandButton.child.label = 'expand_less';
}
else if (initDirVertical == 1 && offset_y < -MOVE_THRESHOLD && expanded) {
notifTextPreview.revealChild = true;
notifTextExpanded.revealChild = false;
expanded = false;
notifExpandButton.child.label = 'expand_more';
}
}, 'drag-update')
.hook(gesture, self => {
if (!self._ready) { if (!self._ready) {
wholeThing.revealChild = true; wholeThing.revealChild = true;
self._ready = true; self._ready = true;
return; return;
} }
const offset = gesture.get_offset()[1]; const offset_h = gesture.get_offset()[1];
if (Math.abs(offset) > dragThreshold && offset * initialDir > 0) { if (Math.abs(offset_h) > DRAG_CONFIRM_THRESHOLD && offset_h * initDirX > 0) {
if (offset > 0) { if (offset_h > 0) {
self.setCss(rightAnim1); self.setCss(rightAnim1);
widget.sensitive = false; widget.sensitive = false;
} }
@@ -313,10 +389,10 @@ export default ({
wholeThing._dragging = false; wholeThing._dragging = false;
} }
initialDir = 0; initDirX = 0;
}, 'drag-end'], initDirVertical = -1;
}, 'drag-end')
], ,
}) })
widget.add(notificationBox); widget.add(notificationBox);
wholeThing.child.children = [widget]; wholeThing.child.children = [widget];
+7 -5
View File
@@ -17,11 +17,13 @@ export default ({
child: Box({ child: Box({
className: `${showClassName} ${hideClassName}`, className: `${showClassName} ${hideClassName}`,
connections: [[App, (self, currentName, visible) => { setup: (self) => self
if (currentName === name) { .hook(App, (self, currentName, visible) => {
self.toggleClassName(hideClassName, !visible); if (currentName === name) {
} self.toggleClassName(hideClassName, !visible);
}]], }
})
,
child: child, child: child,
}), }),
}); });
+44 -38
View File
@@ -27,18 +27,18 @@ export const NotificationIndicator = (notifCenterName = 'sideright') => {
transition: 150, transition: 150,
transition: 'slide_left', transition: 'slide_left',
revealChild: false, revealChild: false,
connections: [ setup: (self) => self
[Notifications, (self, id) => { .hook(Notifications, (self, id) => {
if (!id || Notifications.dnd) return; if (!id || Notifications.dnd) return;
if (!Notifications.getNotification(id)) return; if (!Notifications.getNotification(id)) return;
self.revealChild = true; self.revealChild = true;
}, 'notified'], }, 'notified')
[App, (self, currentName, visible) => { .hook(App, (self, currentName, visible) => {
if (visible && currentName === notifCenterName) { if (visible && currentName === notifCenterName) {
self.revealChild = false; self.revealChild = false;
} }
}], })
], ,
child: Widget.Box({ child: Widget.Box({
children: [ children: [
MaterialIcon('notifications', 'norm'), MaterialIcon('notifications', 'norm'),
@@ -50,20 +50,20 @@ export const NotificationIndicator = (notifCenterName = 'sideright') => {
['update', (self) => self.label = `${self._unreadCount}`], ['update', (self) => self.label = `${self._unreadCount}`],
['unreadCount', 0], ['unreadCount', 0],
], ],
connections: [ setup: (self) => self
[Notifications, (self, id) => { .hook(Notifications, (self, id) => {
if (!id || Notifications.dnd) return; if (!id || Notifications.dnd) return;
if (!Notifications.getNotification(id)) return; if (!Notifications.getNotification(id)) return;
self._increment(self); self._increment(self);
self._update(self); self._update(self);
}, 'notified'], }, 'notified')
[App, (self, currentName, visible) => { .hook(App, (self, currentName, visible) => {
if (visible && currentName === notifCenterName) { if (visible && currentName === notifCenterName) {
self._markread(self); self._markread(self);
self._update(self); self._update(self);
} }
}], })
] ,
}) })
] ]
}) })
@@ -77,7 +77,11 @@ export const BluetoothIndicator = () => Widget.Stack({
['true', Widget.Label({ className: 'txt-norm icon-material', label: 'bluetooth' })], ['true', Widget.Label({ className: 'txt-norm icon-material', label: 'bluetooth' })],
['false', Widget.Label({ className: 'txt-norm icon-material', label: 'bluetooth_disabled' })], ['false', Widget.Label({ className: 'txt-norm icon-material', label: 'bluetooth_disabled' })],
], ],
connections: [[Bluetooth, stack => { stack.shown = String(Bluetooth.enabled); }]], setup: (self) => self
.hook(Bluetooth, stack => {
stack.shown = String(Bluetooth.enabled);
})
,
}); });
@@ -90,7 +94,7 @@ const NetworkWiredIndicator = () => Widget.Stack({
['connected', Widget.Label({ className: 'txt-norm icon-material', label: 'lan' })], ['connected', Widget.Label({ className: 'txt-norm icon-material', label: 'lan' })],
['connecting', Widget.Label({ className: 'txt-norm icon-material', label: 'settings_ethernet' })], ['connecting', Widget.Label({ className: 'txt-norm icon-material', label: 'settings_ethernet' })],
], ],
connections: [[Network, stack => { setup: (self) => self.hook(Network, stack => {
if (!Network.wired) if (!Network.wired)
return; return;
@@ -101,15 +105,15 @@ const NetworkWiredIndicator = () => Widget.Stack({
stack.shown = 'disconnected'; stack.shown = 'disconnected';
else else
stack.shown = 'fallback'; stack.shown = 'fallback';
}]], }),
}); });
const SimpleNetworkIndicator = () => Widget.Icon({ const SimpleNetworkIndicator = () => Widget.Icon({
connections: [[Network, self => { setup: (self) => self.hook(Network, self => {
const icon = Network[Network.primary || 'wifi']?.iconName; const icon = Network[Network.primary || 'wifi']?.iconName;
self.icon = icon || ''; self.icon = icon || '';
self.visible = icon; self.visible = icon;
}]], }),
}); });
const NetworkWifiIndicator = () => Widget.Stack({ const NetworkWifiIndicator = () => Widget.Stack({
@@ -124,7 +128,7 @@ const NetworkWifiIndicator = () => Widget.Stack({
['3', Widget.Label({ className: 'txt-norm icon-material', label: 'network_wifi_3_bar' })], ['3', Widget.Label({ className: 'txt-norm icon-material', label: 'network_wifi_3_bar' })],
['4', Widget.Label({ className: 'txt-norm icon-material', label: 'signal_wifi_4_bar' })], ['4', Widget.Label({ className: 'txt-norm icon-material', label: 'signal_wifi_4_bar' })],
], ],
connections: [[Network, (stack) => { setup: (self) => self.hook(Network, (stack) => {
if (!Network.wifi) { if (!Network.wifi) {
return; return;
} }
@@ -134,7 +138,7 @@ const NetworkWifiIndicator = () => Widget.Stack({
else if (Network.wifi.internet == 'disconnected' || Network.wifi.internet == 'connecting') { else if (Network.wifi.internet == 'disconnected' || Network.wifi.internet == 'connecting') {
stack.shown = Network.wifi.internet; stack.shown = Network.wifi.internet;
} }
}]], }),
}); });
export const NetworkIndicator = () => Widget.Stack({ export const NetworkIndicator = () => Widget.Stack({
@@ -144,13 +148,17 @@ export const NetworkIndicator = () => Widget.Stack({
['wifi', NetworkWifiIndicator()], ['wifi', NetworkWifiIndicator()],
['wired', NetworkWiredIndicator()], ['wired', NetworkWiredIndicator()],
], ],
connections: [[Network, stack => { setup: (self) => self.hook(Network, stack => {
let primary = Network.primary || 'fallback'; if (!Network.primary) {
stack.shown = 'wifi';
return;
}
const primary = Network.primary || 'fallback';
if (primary == 'wifi' || primary == 'wired') if (primary == 'wifi' || primary == 'wired')
stack.shown = primary; stack.shown = primary;
else else
stack.shown = 'fallback'; stack.shown = 'fallback';
}]], }),
}); });
const KeyboardLayout = ({ useFlag } = {}) => { const KeyboardLayout = ({ useFlag } = {}) => {
@@ -188,22 +196,20 @@ const KeyboardLayout = ({ useFlag } = {}) => {
...languageStackArray, ...languageStackArray,
['undef', Widget.Label({ label: '?' })] ['undef', Widget.Label({ label: '?' })]
], ],
connections: [ setup: (self) => self.hook(Hyprland, (stack, kbName, layoutName) => {
[Hyprland, (stack, kbName, layoutName) => { if (!kbName) {
if (!kbName) { return;
return; }
} var lang = languages.find(lang => layoutName.includes(lang.name));
var lang = languages.find(lang => layoutName.includes(lang.name)); if (lang) {
if (lang) { widgetContent.shown = lang.layout;
widgetContent.shown = lang.layout; }
} else { // Attempt to support langs not listed
else { // Attempt to support langs not listed lang = languageStackArray.find(lang => isLanguageMatch(lang[0], layoutName));
lang = languageStackArray.find(lang => isLanguageMatch(lang[0], layoutName)); if (!lang) stack.shown = 'undef';
if (!lang) stack.shown = 'undef'; else stack.shown = lang[0];
else stack.shown = lang[0]; }
} }, 'keyboard-layout'),
}, 'keyboard-layout']
],
}); });
widgetRevealer.child = widgetContent; widgetRevealer.child = widgetContent;
return widgetRevealer; return widgetRevealer;
@@ -50,7 +50,9 @@ else:
# exit() # exit()
colorscheme=0 colorscheme=0
darkmode = True
if("-l" in sys.argv): if("-l" in sys.argv):
darkmode = False
colorscheme = newtheme.get('schemes').get('light') colorscheme = newtheme.get('schemes').get('light')
print('$darkmode: false;') print('$darkmode: false;')
else: else:
@@ -85,8 +87,9 @@ inverseSurface = hexFromArgb(colorscheme.get_inverseSurface())
inverseOnSurface = hexFromArgb(colorscheme.get_inverseOnSurface()) inverseOnSurface = hexFromArgb(colorscheme.get_inverseOnSurface())
inversePrimary = hexFromArgb(colorscheme.get_inversePrimary()) inversePrimary = hexFromArgb(colorscheme.get_inversePrimary())
# post proccessing # make material less boring
background = darken(background, 0.6) if darkmode:
background = darken(background, 0.6)
print('$primary: ' + primary + ';') print('$primary: ' + primary + ';')
print('$onPrimary: ' + onPrimary + ';') print('$onPrimary: ' + onPrimary + ';')
+4 -4
View File
@@ -8,13 +8,13 @@ cd ~/Videos || exit
if [[ "$(pidof wf-recorder)" == "" ]]; then if [[ "$(pidof wf-recorder)" == "" ]]; then
notify-send "Starting recording" 'recording_'"$(getdate)"'.mp4' -a 'record-script.sh' notify-send "Starting recording" 'recording_'"$(getdate)"'.mp4' -a 'record-script.sh'
if [[ "$1" == "--sound" ]]; then 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 & disown
elif [[ "$1" == "--fullscreen-sound" ]]; then 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 & disown
elif [[ "$1" == "--fullscreen" ]]; then elif [[ "$1" == "--fullscreen" ]]; then
wf-recorder -f './recording_'"$(getdate)"'.mp4' -t wf-recorder --pixel-format yuv420p -f './recording_'"$(getdate)"'.mp4' -t & disown
else else
wf-recorder -f './recording_'"$(getdate)"'.mp4' -t --geometry "$(slurp)" wf-recorder --pixel-format yuv420p -f './recording_'"$(getdate)"'.mp4' -t --geometry "$(slurp)" & disown
fi fi
else else
/usr/bin/kill --signal SIGINT wf-recorder /usr/bin/kill --signal SIGINT wf-recorder
@@ -87,9 +87,9 @@
"BLACK_500": "#393634", "BLACK_500": "#393634",
"BLACK_700": "#33302F", "BLACK_700": "#33302F",
"BLACK_900": "#2B2928", "BLACK_900": "#2B2928",
"accent_bg_color": "#c4c0ff", "accent_bg_color": "#ffabf1",
"accent_fg_color": "#251a8c", "accent_fg_color": "#551251",
"accent_color": "#c4c0ff", "accent_color": "#ffabf1",
"destructive_bg_color": "#ffb4a9", "destructive_bg_color": "#ffb4a9",
"destructive_fg_color": "#680003", "destructive_fg_color": "#680003",
"destructive_color": "#ffb4a9", "destructive_color": "#ffb4a9",
@@ -99,22 +99,22 @@
"warning_fg_color": "rgba(0, 0, 0, 0.87)", "warning_fg_color": "rgba(0, 0, 0, 0.87)",
"error_bg_color": "#ffb4a9", "error_bg_color": "#ffb4a9",
"error_fg_color": "#680003", "error_fg_color": "#680003",
"window_bg_color": "#101012", "window_bg_color": "#120F11",
"window_fg_color": "#e5e1e6", "window_fg_color": "#eae0e4",
"view_bg_color": "#1c1b1f", "view_bg_color": "#1f1a1d",
"view_fg_color": "#e5e1e6", "view_fg_color": "#eae0e4",
"headerbar_bg_color": "mix(@dialog_bg_color, @window_bg_color, 0.5)", "headerbar_bg_color": "mix(@dialog_bg_color, @window_bg_color, 0.5)",
"headerbar_fg_color": "#e3dff9", "headerbar_fg_color": "#f8daee",
"headerbar_border_color": "#464559", "headerbar_border_color": "#554050",
"headerbar_backdrop_color": "@headerbar_bg_color", "headerbar_backdrop_color": "@headerbar_bg_color",
"headerbar_shade_color": "rgba(0, 0, 0, 0.09)", "headerbar_shade_color": "rgba(0, 0, 0, 0.09)",
"card_bg_color": "#101012", "card_bg_color": "#120F11",
"card_fg_color": "#e3dff9", "card_fg_color": "#f8daee",
"card_shade_color": "rgba(0, 0, 0, 0.09)", "card_shade_color": "rgba(0, 0, 0, 0.09)",
"dialog_bg_color": "#464559", "dialog_bg_color": "#554050",
"dialog_fg_color": "#e3dff9", "dialog_fg_color": "#f8daee",
"popover_bg_color": "#464559", "popover_bg_color": "#554050",
"popover_fg_color": "#e3dff9", "popover_fg_color": "#f8daee",
"thumbnail_bg_color": "#1a1b26", "thumbnail_bg_color": "#1a1b26",
"thumbnail_fg_color": "#AEE5FA", "thumbnail_fg_color": "#AEE5FA",
"shade_color": "rgba(0, 0, 0, 0.36)", "shade_color": "rgba(0, 0, 0, 0.36)",
@@ -1,6 +1,7 @@
# Auto generated color theme for image at: [Local wallpaper] $SLURP_COMMAND="$(slurp -d -c {{ $onSecondaryContainer }}BB -b {{ $secondaryContainer }}22 -s 00000000)"
general { general {
col.active_border = rgba({{ $primaryContainer }}FF) col.active_border = rgba({{ $onPrimary }}FF)
col.inactive_border = rgba({{ $secondaryContainer }}CC) col.inactive_border = rgba({{ $secondaryContainer }}CC)
} }
+96 -164
View File
@@ -1,27 +1,20 @@
// Made to be pixel-perfect with 11pt font size // Made to be pixel-perfect with 11pt font size
// 1rem = 11pt = 14.6666666667px // 1rem = 11pt = 14.6666666667px
// Init
$black: black; $black: black;
$white: white; $white: white;
$notchSecondaryContainer: $secondaryContainer; $bar_ws_width: 1.774rem;
$notchOnSecondaryContainer: $onSecondaryContainer; $bar_subgroup_bg: mix($surfaceVariant, $primary, 89%);
$notchPrimary: $primary;
$notchOnPrimary: $onPrimary;
// Check dark mode. Set colors accordingly for the fake snotch that's always black
@if $darkmode ==true { @if $darkmode ==true {
$notchSecondaryContainer: $secondaryContainer; $bar_subgroup_bg: $surfaceVariant;
$notchOnSecondaryContainer: $onSecondaryContainer;
$notchPrimary: $primary;
$notchOnPrimary: $onPrimary;
} }
@else { @mixin bar-group-rounding {
$notchSecondaryContainer: $onSecondaryContainer; @include small-rounding;
$notchOnSecondaryContainer: $secondaryContainer; }
$notchPrimary: $primaryContainer;
$notchOnPrimary: $onPrimaryContainer; .bar-height {
min-height: 2.727rem;
} }
.bar-bg { .bar-bg {
@@ -34,31 +27,17 @@ $notchOnPrimary: $onPrimary;
} }
.bar-group-margin { .bar-group-margin {
padding: 0.2rem; padding: 0.273rem 0rem;
} }
.bar-group { .bar-group {
// @include elevation-border; background-color: $l_l_t_surfaceVariant;
background-color: $t_surface;
}
.bar-group-center {
border-bottom-left-radius: 1.364rem;
border-bottom-right-radius: 1.364rem;
padding: 0.2rem;
// background-color: $t_surface;
background-color: $black; // Hard code: fake notch
}
.corner-bar-group {
border-radius: 1.364rem; // Half of bar height
border-width: 0.068rem;
// background-color: $t_surface;
background-color: $black; // Hard code: fake notch
} }
.bar-group-pad { .bar-group-pad {
padding: 0rem 1.023rem; // padding: 0rem 1.023rem;
padding: 0.205rem;
// padding-left: 0.341rem;
} }
.bar-group-pad-less { .bar-group-pad-less {
@@ -67,12 +46,12 @@ $notchOnPrimary: $onPrimary;
.bar-group-pad-system { .bar-group-pad-system {
padding-left: 1.023rem; padding-left: 1.023rem;
padding-right: 0.547rem; padding-right: 0.341rem;
} }
.bar-group-pad-music { .bar-group-pad-music {
padding-right: 1.023rem; padding-right: 1.023rem;
// padding-left: 0.273rem; padding-left: 0.341rem;
} }
.bar-group-pad-left { .bar-group-pad-left {
@@ -94,7 +73,7 @@ $notchOnPrimary: $onPrimary;
} }
.bar-group-standalone { .bar-group-standalone {
border-radius: 1.364rem; @include bar-group-rounding;
-gtk-outline-radius: 1.364rem; -gtk-outline-radius: 1.364rem;
} }
@@ -123,7 +102,25 @@ $notchOnPrimary: $onPrimary;
} }
.bar-ws-width { .bar-ws-width {
min-width: 18.614rem; min-width: 18.341rem;
}
.bar-ws {
min-width: $bar_ws_width;
color: mix($onBackground, $background, 40%);
@if $darkmode ==true {
color: mix($onBackground, $background, 45%);
}
}
.bar-ws-active {
background-color: $secondaryContainer;
color: $onSecondaryContainer;
}
.bar-ws-occupied {
background-color: $bar_subgroup_bg;
color: $onSurfaceVariant;
} }
.bar-separator { .bar-separator {
@@ -137,7 +134,6 @@ $notchOnPrimary: $onPrimary;
.bar-clock { .bar-clock {
@include titlefont; @include titlefont;
font-size: 1.2727rem; font-size: 1.2727rem;
color: $onBackground;
} }
.bar-date { .bar-date {
@@ -146,95 +142,13 @@ $notchOnPrimary: $onPrimary;
color: $onBackground; color: $onBackground;
} }
.bar-ws {
min-height: 1.636rem;
min-width: 1.772rem;
font-size: 1.091rem;
@include mainfont;
border-top: 0.068rem solid;
border-bottom: 0.068rem solid;
border-color: transparent;
color: $white;
}
.bar-ws-active-box {
transition: 100ms cubic-bezier(0.05, 0.7, 0.1, 1);
}
.bar-ws-active {
min-height: 1.5rem;
min-width: 1.5rem;
font-size: 1.091rem;
@include mainfont;
background-color: $notchPrimary;
color: $notchOnPrimary;
border-radius: 999px;
margin: 0.068rem;
// background-color: red;
}
.bar-ws-active-middledecor {
min-width: 0.682rem;
min-height: 0.682rem;
border-radius: 9999px;
background-color: $black;
margin: 0rem 0.409rem;
}
.bar-ws-occupied {
background-color: $notchSecondaryContainer;
color: $notchOnSecondaryContainer;
min-width: 1.772rem;
border-top: 0.068rem solid $notchOnSecondaryContainer;
border-bottom: 0.068rem solid $notchOnSecondaryContainer;
}
.bar-ws-occupied-left {
background-color: $notchSecondaryContainer;
color: $notchOnSecondaryContainer;
min-width: 1.704rem;
border-top-left-radius: 999px;
border-bottom-left-radius: 999px;
border-left: 0.068rem solid $notchOnSecondaryContainer;
border-top: 0.068rem solid $notchOnSecondaryContainer;
border-bottom: 0.068rem solid $notchOnSecondaryContainer;
border-right: 0px solid transparent;
}
.bar-ws-occupied-right {
background-color: $notchSecondaryContainer;
color: $notchOnSecondaryContainer;
min-width: 1.704rem;
border-top-right-radius: 999px;
border-bottom-right-radius: 999px;
border-right: 0.068rem solid $notchOnSecondaryContainer;
border-top: 0.068rem solid $notchOnSecondaryContainer;
border-bottom: 0.068rem solid $notchOnSecondaryContainer;
border-left: 0px solid transparent;
}
.bar-ws-occupied-left-right {
@include full-rounding;
background-color: $notchSecondaryContainer;
color: $notchOnSecondaryContainer;
min-width: 1.636rem;
border: 0.068rem solid $notchOnSecondaryContainer;
}
.bar-ws-empty {
color: $onBackground;
border-color: transparent;
}
.bar-batt { .bar-batt {
@include full-rounding; @include full-rounding;
padding: 0rem 0.341rem; min-height: 1.77rem;
background-color: $t_secondaryContainer; min-width: 1.77rem;
color: $t_onSecondaryContainer; border-radius: 10rem;
// border: 1px solid $onSecondaryContainer; background-color: $secondaryContainer;
color: $onSecondaryContainer;
} }
.bar-sidemodule { .bar-sidemodule {
@@ -251,19 +165,36 @@ $notchOnPrimary: $onPrimary;
color: $onSuccessContainer; color: $onSuccessContainer;
} }
.bar-batt-prog-low { .bar-batt-circprog {
@include fluent_decel_long;
min-width: 0.068rem; // line width
min-height: 1.636rem;
padding: 0rem;
background-color: $secondaryContainer;
color: $onSecondaryContainer;
}
.bar-batt-circprog-low {
@include fluent_decel_long;
min-width: 0.068rem; // line width
min-height: 1.636rem;
padding: 0rem;
background-color: $error; background-color: $error;
color: $errorContainer; color: $errorContainer;
} }
.bar-batt-prog-full { .bar-batt-circprog-full {
@include fluent_decel_long;
min-width: 0.068rem; // line width
min-height: 1.636rem;
padding: 0rem;
background-color: $successContainer; background-color: $successContainer;
color: $onSuccessContainer; color: $onSuccessContainer;
} }
.bar-music-playstate { .bar-music-playstate {
min-height: 1.770rem; min-height: 1.77rem;
min-width: 1.770rem; min-width: 1.77rem;
border-radius: 10rem; border-radius: 10rem;
background-color: $secondaryContainer; background-color: $secondaryContainer;
color: $onSecondaryContainer; color: $onSecondaryContainer;
@@ -272,15 +203,15 @@ $notchOnPrimary: $onPrimary;
.bar-music-circprog { .bar-music-circprog {
@include fluent_decel_long; @include fluent_decel_long;
min-width: 0.068rem; // line width min-width: 0.068rem; // line width
min-height: 1.770rem; min-height: 1.636rem;
padding: 0rem; padding: 0rem;
background-color: $secondaryContainer; background-color: $secondaryContainer;
color: $onSecondaryContainer; color: $onSecondaryContainer;
} }
.bar-music-playstate-playing { .bar-music-playstate-playing {
min-height: 1.770rem; min-height: 1.77rem;
min-width: 1.770rem; min-width: 1.77rem;
border-radius: 10rem; border-radius: 10rem;
background-color: $secondaryContainer; background-color: $secondaryContainer;
color: $onSecondaryContainer; color: $onSecondaryContainer;
@@ -363,8 +294,8 @@ $notchOnPrimary: $onPrimary;
} }
progress { progress {
min-height: 0.680rem; min-height: 0.68rem;
min-width: 0.680rem; min-width: 0.68rem;
margin: 0rem 0.137rem; margin: 0rem 0.137rem;
border-radius: 10rem; border-radius: 10rem;
background-color: $t_onSecondaryContainer; background-color: $t_onSecondaryContainer;
@@ -392,30 +323,14 @@ $notchOnPrimary: $onPrimary;
border-radius: 10rem; border-radius: 10rem;
min-width: 0.681rem; min-width: 0.681rem;
min-height: 0.681rem; min-height: 0.681rem;
background-color: $t_onSecondaryContainer; background-color: $onSurfaceVariant;
color: $secondaryContainer;
} }
.bar-batt-chargestate-charging-smaller { .bar-batt-chargestate-charging-smaller {
border-radius: 10rem; border-radius: 10rem;
min-width: 0.409rem; min-width: 0.409rem;
min-height: 0.409rem; min-height: 0.409rem;
background-color: $t_onSecondaryContainer; background-color: $onSurfaceVariant;
color: $secondaryContainer;
}
.bar-batt-chargestate-low {
background-color: $errorContainer;
}
.bar-batt-chargestate-full {
background-color: $onSuccessContainer;
}
.bar-batt-percentage {
font-size: 1rem;
margin-top: -0.068rem;
font-weight: 500;
} }
.corner { .corner {
@@ -424,7 +339,7 @@ $notchOnPrimary: $onPrimary;
} }
.corner-black { .corner-black {
background-color: $black; // Hard code because fake screen corner background-color: $black; // Hard code: fake screen corner
@include large-rounding; @include large-rounding;
} }
@@ -438,17 +353,17 @@ $notchOnPrimary: $onPrimary;
padding: 0.341rem; padding: 0.341rem;
} }
.bar-space-button>box:first-child { .bar-space-button > box:first-child {
@include full-rounding; @include full-rounding;
padding: 0rem 0.682rem; padding: 0rem 0.682rem;
} }
.bar-space-button:hover>box:first-child, .bar-space-button:hover > box:first-child,
.bar-space-button:focus>box:first-child { .bar-space-button:focus > box:first-child {
background-color: $hovercolor; background-color: $hovercolor;
} }
.bar-space-button:active>box:first-child { .bar-space-button:active > box:first-child {
background-color: $activecolor; background-color: $activecolor;
} }
@@ -458,25 +373,26 @@ $notchOnPrimary: $onPrimary;
} }
} }
.bar-space-area-rightmost>box { .bar-space-area-rightmost > box {
padding-right: 2.386rem; padding-right: 2.386rem;
} }
.bar-systray { .bar-systray {
@include full-rounding; @include full-rounding;
min-height: 1.909rem; margin: 0.137rem 0rem;
min-width: 1.909rem; padding: 0rem 0.682rem;
} }
.bar-systray-item { .bar-systray-item {
@include full-rounding; @include full-rounding;
min-width: 1.909rem; min-height: 1.032rem;
min-width: 1.032rem;
} }
.bar-statusicons { .bar-statusicons {
@include full-rounding; @include full-rounding;
@include menu_decel; @include menu_decel;
margin: 0.2rem; margin: 0.273rem;
padding: 0rem 0.614rem; padding: 0rem 0.614rem;
} }
@@ -486,4 +402,20 @@ $notchOnPrimary: $onPrimary;
.bar-statusicons-active { .bar-statusicons-active {
background-color: mix($t_background, $t_onBackground, 80%); background-color: mix($t_background, $t_onBackground, 80%);
}
.bar-util-btn {
@include full-rounding;
min-height: 1.77rem;
min-width: 1.77rem;
background-color: $bar_subgroup_bg;
}
.bar-util-btn:hover,
.bar-util-btn:focus {
background-color: mix($bar_subgroup_bg, $onSurfaceVariant, 90%);
}
.bar-util-btn:active {
background-color: mix($bar_subgroup_bg, $onSurfaceVariant, 80%);
} }
+63 -19
View File
@@ -5,15 +5,18 @@ $transparency_enabled: false;
@if $transparency_enabled ==false { @if $transparency_enabled ==false {
@if $darkmode ==true { @if $darkmode ==true {
$primary: mix($primary, white, 70%);
$primaryContainer: mix($primaryContainer, white, 90%);
$background: mix(mix($background, $primary, 94%), #000000, 50%); $background: mix(mix($background, $primary, 94%), #000000, 50%);
$surface: mix($surface, $primaryContainer, 98%); $surface: mix($surface, $primaryContainer, 98%);
$surfaceVariant: mix($surfaceVariant, #000000, 55%); $surfaceVariant: mix($surfaceVariant, #000000, 75%);
// $secondaryContainer: mix($secondaryContainer, $primaryContainer, 90%);
} }
@if $darkmode ==false { @if $darkmode ==false {
$background: mix($background, $primary, 87%); $background: mix($background, $primary, 87%);
$surface: mix($surface, $primary, 93%); $surface: mix($surface, $primary, 93%);
$surfaceVariant: mix($surfaceVariant, #FFFFFF, 55%); $surfaceVariant: mix($surfaceVariant, #ffffff, 25%);
} }
} }
@@ -27,7 +30,7 @@ $transparency_enabled: false;
@if $darkmode ==false { @if $darkmode ==false {
$background: mix($background, $primary, 94%); $background: mix($background, $primary, 94%);
$surface: mix($surface, $primary, 93%); $surface: mix($surface, $primary, 93%);
$surfaceVariant: mix($surfaceVariant, #FFFFFF, 55%); $surfaceVariant: mix($surfaceVariant, #ffffff, 55%);
} }
} }
@@ -37,7 +40,8 @@ $transparentize_surface_amount_less: 0.6;
$transparentize_surface_amount_less_less: 0.55; $transparentize_surface_amount_less_less: 0.55;
$transparentize_surface_amount: 0.7; $transparentize_surface_amount: 0.7;
$transparentize_surface_amount_more: 0.8; $transparentize_surface_amount_more: 0.8;
$transparentize_surface_amount_subtract_surface: $transparentize_surface_amount - $transparentize_amount; $transparentize_surface_amount_subtract_surface: $transparentize_surface_amount -
$transparentize_amount;
@if $darkmode ==true { @if $darkmode ==true {
// Less transparency // Less transparency
@@ -46,7 +50,8 @@ $transparentize_surface_amount_subtract_surface: $transparentize_surface_amount
$transparentize_surface_amount_less_less: 0.55; $transparentize_surface_amount_less_less: 0.55;
$transparentize_surface_amount: 0.69; $transparentize_surface_amount: 0.69;
$transparentize_surface_amount_more: 0.9; $transparentize_surface_amount_more: 0.9;
$transparentize_surface_amount_subtract_surface: $transparentize_surface_amount - $transparentize_amount; $transparentize_surface_amount_subtract_surface: $transparentize_surface_amount -
$transparentize_amount;
} }
@if $transparency_enabled ==false { @if $transparency_enabled ==false {
@@ -71,33 +76,69 @@ $onSuccessContainer: #0c1f13;
$t_primary: transparentize($primary, $transparentize_amount); $t_primary: transparentize($primary, $transparentize_amount);
$t_onPrimary: transparentize($onPrimary, $transparentize_amount); $t_onPrimary: transparentize($onPrimary, $transparentize_amount);
$t_primaryContainer: transparentize($primaryContainer, $transparentize_amount); $t_primaryContainer: transparentize($primaryContainer, $transparentize_amount);
$t_onPrimaryContainer: transparentize($onPrimaryContainer, $transparentize_amount); $t_onPrimaryContainer: transparentize(
$onPrimaryContainer,
$transparentize_amount
);
$t_secondary: transparentize($secondary, $transparentize_amount); $t_secondary: transparentize($secondary, $transparentize_amount);
$t_onSecondary: transparentize($onSecondary, $transparentize_amount); $t_onSecondary: transparentize($onSecondary, $transparentize_amount);
$t_secondaryContainer: transparentize($secondaryContainer, $transparentize_amount); $t_secondaryContainer: transparentize(
$l_t_secondaryContainer: transparentize($secondaryContainer, $transparentize_surface_amount_less); $secondaryContainer,
$t_onSecondaryContainer: transparentize($onSecondaryContainer, $transparentize_amount); $transparentize_amount
);
$l_t_secondaryContainer: transparentize(
$secondaryContainer,
$transparentize_surface_amount_less
);
$t_onSecondaryContainer: transparentize(
$onSecondaryContainer,
$transparentize_amount
);
$t_t_t_onSecondaryContainer: transparentize($onSecondaryContainer, 0.93); $t_t_t_onSecondaryContainer: transparentize($onSecondaryContainer, 0.93);
$t_tertiary: transparentize($tertiary, $transparentize_amount); $t_tertiary: transparentize($tertiary, $transparentize_amount);
$t_onTertiary: transparentize($onTertiary, $transparentize_amount); $t_onTertiary: transparentize($onTertiary, $transparentize_amount);
$t_tertiaryContainer: transparentize($tertiaryContainer, $transparentize_amount); $t_tertiaryContainer: transparentize(
$t_onTertiaryContainer: transparentize($onTertiaryContainer, $transparentize_amount); $tertiaryContainer,
$transparentize_amount
);
$t_onTertiaryContainer: transparentize(
$onTertiaryContainer,
$transparentize_amount
);
$t_error: transparentize($error, $transparentize_amount); $t_error: transparentize($error, $transparentize_amount);
$t_onError: transparentize($onError, $transparentize_amount); $t_onError: transparentize($onError, $transparentize_amount);
$t_errorContainer: transparentize($errorContainer, $transparentize_amount); $t_errorContainer: transparentize($errorContainer, $transparentize_amount);
$t_onErrorContainer: transparentize($onErrorContainer, $transparentize_amount); $t_onErrorContainer: transparentize($onErrorContainer, $transparentize_amount);
$t_colorbarbg: transparentize($colorbarbg, $transparentize_amount); $t_colorbarbg: transparentize($colorbarbg, $transparentize_amount);
$t_background: transparentize($background, $transparentize_amount); $t_background: transparentize($background, $transparentize_amount);
$t_t_background: transparentize($background, $transparentize_surface_amount_more); $t_t_background: transparentize(
$background,
$transparentize_surface_amount_more
);
$t_onBackground: transparentize($onBackground, $transparentize_amount); $t_onBackground: transparentize($onBackground, $transparentize_amount);
$t_surface: transparentize($surface, $transparentize_surface_amount); $t_surface: transparentize($surface, $transparentize_surface_amount);
$t_t_surface: transparentize($surface, $transparentize_surface_amount_more); $t_t_surface: transparentize($surface, $transparentize_surface_amount_more);
$t_onSurface: transparentize($onSurface, $transparentize_surface_amount); $t_onSurface: transparentize($onSurface, $transparentize_surface_amount);
$t_surfaceVariant: transparentize($surfaceVariant, $transparentize_surface_amount); $t_surfaceVariant: transparentize(
$t_onSurfaceVariant: transparentize($onSurfaceVariant, $transparentize_surface_amount); $surfaceVariant,
$t_t_surfaceVariant: transparentize($surfaceVariant, $transparentize_surface_amount_more); $transparentize_surface_amount
$l_t_surfaceVariant: transparentize($surfaceVariant, $transparentize_surface_amount_less); );
$l_l_t_surfaceVariant: transparentize($surfaceVariant, $transparentize_surface_amount_less_less); $t_onSurfaceVariant: transparentize(
$onSurfaceVariant,
$transparentize_surface_amount
);
$t_t_surfaceVariant: transparentize(
$surfaceVariant,
$transparentize_surface_amount_more
);
$l_t_surfaceVariant: transparentize(
$surfaceVariant,
$transparentize_surface_amount_less
);
$l_l_t_surfaceVariant: transparentize(
$surfaceVariant,
$transparentize_surface_amount_less_less
);
$t_outline: transparentize($outline, $transparentize_amount); $t_outline: transparentize($outline, $transparentize_amount);
$t_shadow: transparentize($shadow, $transparentize_amount); $t_shadow: transparentize($shadow, $transparentize_amount);
$t_inverseSurface: transparentize($inverseSurface, $transparentize_amount); $t_inverseSurface: transparentize($inverseSurface, $transparentize_amount);
@@ -107,7 +148,10 @@ $t_inversePrimary: transparentize($inversePrimary, $transparentize_amount);
$t_success: transparentize($error, $transparentize_amount); $t_success: transparentize($error, $transparentize_amount);
$t_onSuccess: transparentize($onError, $transparentize_amount); $t_onSuccess: transparentize($onError, $transparentize_amount);
$t_successContainer: transparentize($errorContainer, $transparentize_amount); $t_successContainer: transparentize($errorContainer, $transparentize_amount);
$t_onSuccessContainer: transparentize($onErrorContainer, $transparentize_amount); $t_onSuccessContainer: transparentize(
$onErrorContainer,
$transparentize_amount
);
// Others // Others
$hovercolor: mix($t_surface, $t_onSurface, 50%); $hovercolor: mix($t_surface, $t_onSurface, 50%);
@@ -125,4 +169,4 @@ $term3: $onPrimaryContainer;
$term4: $onPrimaryContainer; $term4: $onPrimaryContainer;
$term5: $onSecondaryContainer; $term5: $onSecondaryContainer;
$term6: $primary; $term6: $primary;
$term7: $onSurfaceVariant; $term7: $onSurfaceVariant;
+68 -3
View File
@@ -42,7 +42,7 @@ menu {
-gtk-outline-radius: 1.159rem; -gtk-outline-radius: 1.159rem;
animation-name: appear; animation-name: appear;
animation-duration: 100ms; animation-duration: 40ms;
animation-timing-function: ease-out; animation-timing-function: ease-out;
animation-iteration-count: 1; animation-iteration-count: 1;
} }
@@ -81,12 +81,11 @@ tooltip {
} }
.configtoggle-box { .configtoggle-box {
padding: 0.205rem; padding: 0.205rem 0.341rem;
border: 0.136rem solid transparent; border: 0.136rem solid transparent;
} }
.configtoggle-box:focus { .configtoggle-box:focus {
padding: 0.205rem;
border: 0.136rem solid mix($onSurface, $surface, 40%); border: 0.136rem solid mix($onSurface, $surface, 40%);
} }
@@ -126,4 +125,70 @@ tooltip {
@include menu_decel; @include menu_decel;
min-width: 1.636rem; min-width: 1.636rem;
min-height: 0.819rem; min-height: 0.819rem;
}
.segment-container {
@include full-rounding;
border: 0.068rem solid $outline;
}
.segment-container>*:first-child {
border-top-left-radius: 9999px;
border-bottom-left-radius: 9999px;
}
.segment-container>* {
border-right: 0.068rem solid $outline;
padding: 0.341rem 0.682rem;
}
.segment-container>*:last-child {
border-right: 0rem solid transparent;
border-top-right-radius: 9999px;
border-bottom-right-radius: 9999px;
}
.segment-btn {
color: $onSurface;
}
.segment-btn:focus,
.segment-btn:hover {
background-color: $surfaceVariant;
color: $onSurfaceVariant;
}
.segment-btn-enabled {
background-color: $secondaryContainer;
color: $onSecondaryContainer;
}
.segment-btn-enabled:hover,
.segment-btn-enabled:focus {
background-color: $secondaryContainer;
color: $onSecondaryContainer;
}
.gap-v-5 {
min-height: 0.341rem;
}
.gap-h-5 {
min-width: 0.341rem;
}
.gap-v-10 {
min-height: 0.682rem;
}
.gap-h-10 {
min-width: 0.682rem;
}
.gap-v-15 {
min-height: 1.023rem;
}
.gap-h-15 {
min-width: 1.023rem;
} }
+80 -28
View File
@@ -69,6 +69,10 @@
color: $onSecondaryContainer; color: $onSecondaryContainer;
} }
.txt-onSurfaceVariant {
color: $onSurfaceVariant;
}
.txt-shadow { .txt-shadow {
text-shadow: 1px 2px 8px rgba(0, 0, 0, 0.69); text-shadow: 1px 2px 8px rgba(0, 0, 0, 0.69);
margin: 10px; margin: 10px;
@@ -214,6 +218,14 @@
margin-right: 0rem; margin-right: 0rem;
} }
.spacing-h-15>scrolledwindow>* {
margin-right: 1.023rem;
}
.spacing-h-15>scrolledwindow:last-child>* {
margin-right: 0rem;
}
.spacing-v-5>box { .spacing-v-5>box {
margin-bottom: 0.341rem; margin-bottom: 0.341rem;
} }
@@ -238,6 +250,22 @@
margin-bottom: 0rem; margin-bottom: 0rem;
} }
.spacing-v-5-revealer>scrolledwindow>* {
margin-bottom: 0.341rem;
}
.spacing-v-5-revealer>scrolledwindow:last-child>* {
margin-bottom: 0rem;
}
.spacing-h-4>* {
margin-right: 0.273rem;
}
.spacing-h-4>*:last-child {
margin-right: 0rem;
}
.spacing-h-5>* { .spacing-h-5>* {
margin-right: 0.341rem; margin-right: 0.341rem;
} }
@@ -262,6 +290,14 @@
margin-right: 0rem; margin-right: 0rem;
} }
.spacing-h-5>scrolledwindow>* {
margin-right: 0.341rem;
}
.spacing-h-5>scrolledwindow:last-child>* {
margin-right: 0rem;
}
.spacing-v-minus5>* { .spacing-v-minus5>* {
margin-bottom: -0.341rem; margin-bottom: -0.341rem;
} }
@@ -286,6 +322,14 @@
margin-right: 0rem; margin-right: 0rem;
} }
.spacing-h-10>scrolledwindow>* {
margin-right: 0.682rem;
}
.spacing-h-10>scrolledwindow:last-child>* {
margin-right: 0rem;
}
.spacing-h-10>flowboxchild>* { .spacing-h-10>flowboxchild>* {
margin-right: 0.682rem; margin-right: 0.682rem;
} }
@@ -393,43 +437,43 @@
margin-right: 0rem; margin-right: 0rem;
} }
.spacing-v--5>box { .spacing-v--5>* {
margin-bottom: -0.341rem; margin-bottom: -0.341rem;
} }
.spacing-v--5>box:last-child { .spacing-v--5>*:last-child {
margin-bottom: 0rem; margin-bottom: 0rem;
} }
.spacing-v--5>label { .spacing-h--10>* {
margin-bottom: -0.341rem;
}
.spacing-v--5>label:last-child {
margin-bottom: 0rem;
}
.spacing-v--10>box {
margin-bottom: -0.682rem;
}
.spacing-v--10>box:last-child {
margin-bottom: 0rem;
}
.spacing-v--10>label {
margin-bottom: -0.682rem;
}
.spacing-v--10>label:last-child {
margin-bottom: 0rem;
}
.spacing-h--20>box {
margin-left: -1.364rem; margin-left: -1.364rem;
} }
.spacing-h--20>box:first-child { .spacing-h--10>*:first-child {
margin-left: 0rem;
}
.spacing-v--10>* {
margin-bottom: -0.682rem;
}
.spacing-v--10>*:last-child {
margin-bottom: 0rem;
}
.spacing-v--10>* {
margin-bottom: -0.682rem;
}
.spacing-v--10>*:last-child {
margin-bottom: 0rem;
}
.spacing-h--20>* {
margin-left: -1.364rem;
}
.spacing-h--20>*:first-child {
margin-left: 0rem; margin-left: 0rem;
} }
@@ -439,4 +483,12 @@
.menu-decel { .menu-decel {
@include menu_decel; @include menu_decel;
}
.element-show {
@include element_easeInOut;
}
.element-hide {
@include element_easeInOut;
} }
+13
View File
@@ -40,6 +40,7 @@ $rounding_large: 1.705rem;
@mixin mainfont { @mixin mainfont {
// Other clean sans-serif // Other clean sans-serif
font-family: font-family:
'Rubik',
'Geist', 'Geist',
'AR One Sans', 'AR One Sans',
'Reddit Sans', 'Reddit Sans',
@@ -160,6 +161,18 @@ $elevation_margin: 0.476rem;
transition: 150ms cubic-bezier(0.3, 0, 0.8, 0.15); 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) { @function tint($color, $percentage) {
@return mix(rgb(245, 250, 255), $color, $percentage); @return mix(rgb(245, 250, 255), $color, $percentage);
} }
+23 -23
View File
@@ -1,29 +1,29 @@
$darkmode: true; $darkmode: true;
$primary: #c4c0ff; $primary: #ffabf1;
$onPrimary: #251a8c; $onPrimary: #551251;
$primaryContainer: #3d36a2; $primaryContainer: #702c69;
$onPrimaryContainer: #e3dfff; $onPrimaryContainer: #ffd6f5;
$secondary: #c7c4dd; $secondary: #dbbed2;
$onSecondary: #2f2e42; $onSecondary: #3d2b39;
$secondaryContainer: #464559; $secondaryContainer: #554050;
$onSecondaryContainer: #e3dff9; $onSecondaryContainer: #f8daee;
$tertiary: #eab9d1; $tertiary: #f5b9a6;
$onTertiary: #472639; $onTertiary: #4c2619;
$tertiaryContainer: #603c50; $tertiaryContainer: #663c2e;
$onTertiaryContainer: #ffd8eb; $onTertiaryContainer: #ffdbcf;
$error: #ffb4a9; $error: #ffb4a9;
$onError: #680003; $onError: #680003;
$errorContainer: #930006; $errorContainer: #930006;
$onErrorContainer: #ffb4a9; $onErrorContainer: #ffb4a9;
$colorbarbg: #101012; $colorbarbg: #120F11;
$background: #101012; $background: #120F11;
$onBackground: #e5e1e6; $onBackground: #eae0e4;
$surface: #1c1b1f; $surface: #1f1a1d;
$onSurface: #e5e1e6; $onSurface: #eae0e4;
$surfaceVariant: #47464f; $surfaceVariant: #4e444b;
$onSurfaceVariant: #c8c5d0; $onSurfaceVariant: #d1c2cb;
$outline: #928f9a; $outline: #9a8d95;
$shadow: #000000; $shadow: #000000;
$inverseSurface: #e5e1e6; $inverseSurface: #eae0e4;
$inverseOnSurface: #313033; $inverseOnSurface: #342f32;
$inversePrimary: #5550bb; $inversePrimary: #8c4483;
+7 -4
View File
@@ -4,11 +4,11 @@
@import './musicwal'; @import './musicwal';
@import './colors'; @import './colors';
@import './lib_mixins'; @import './lib_mixins';
$music_gradient1: mix($color1, $background, 30%); $music_gradient1: mix($color1, $background, 50%);
@if $darkmode ==true { // @if $darkmode ==true {
$music_gradient1: mix($color1, $background, 30%); // $music_gradient1: mix($color1, $background, 30%);
} // }
$music_gradient2: $color3; $music_gradient2: $color3;
$music_gradient3: $color5; $music_gradient3: $color5;
@@ -17,6 +17,9 @@ $music_extra_transparentize: 0.15;
$secondaryContainer: transparentize(mix(mix($background, $color2, 50%), $color6, 80%), 0.5); $secondaryContainer: transparentize(mix(mix($background, $color2, 50%), $color6, 80%), 0.5);
$onSecondaryContainer: mix($color7, $color2, 90%); $onSecondaryContainer: mix($color7, $color2, 90%);
@if $darkmode ==false {
$onSecondaryContainer: mix($onSecondaryContainer, black, 50%);
}
.osd-music { .osd-music {
@include menu_decel; @include menu_decel;
+29 -1
View File
@@ -1 +1,29 @@
$darkmode: true;
$primary: #ecb1ff;
$onPrimary: #4f076e;
$primaryContainer: #682886;
$onPrimaryContainer: #f9d8ff;
$secondary: #d4c0d8;
$onSecondary: #392c3d;
$secondaryContainer: #504254;
$onSecondaryContainer: #f1dcf4;
$tertiary: #f5b7b5;
$onTertiary: #4c2525;
$tertiaryContainer: #663b3a;
$onTertiaryContainer: #ffdad8;
$error: #ffb4a9;
$onError: #680003;
$errorContainer: #930006;
$onErrorContainer: #ffb4a9;
$colorbarbg: #120F12;
$background: #120F12;
$onBackground: #e8e0e5;
$surface: #1e1a1e;
$onSurface: #e8e0e5;
$surfaceVariant: #4c444d;
$onSurfaceVariant: #cec3cd;
$outline: #978e97;
$shadow: #000000;
$inverseSurface: #e8e0e5;
$inverseOnSurface: #332f33;
$inversePrimary: #8342a1;
+25
View File
@@ -1 +1,26 @@
// SCSS Variables
// Generated by 'wal'
$wallpaper: "/home/end/.cache/ags/media/c77cd3721bb54437609b42bd5254d1a16437f855";
// Special
$background: #0C0820;
$foreground: #e5c7e7;
$cursor: #e5c7e7;
// Colors
$color0: #0C0820;
$color1: #3F26DE;
$color2: #671AD9;
$color3: #A152BD;
$color4: #9E1EEA;
$color5: #E424F5;
$color6: #E65BF0;
$color7: #e5c7e7;
$color8: #a08ba1;
$color9: #3F26DE;
$color10: #671AD9;
$color11: #A152BD;
$color12: #9E1EEA;
$color13: #E424F5;
$color14: #E65BF0;
$color15: #e5c7e7;
+65 -11
View File
@@ -93,17 +93,18 @@ $notif_surface: $t_background;
color: $secondaryContainer; color: $secondaryContainer;
} }
.notif-close-btn { .notif-expand-btn {
@include notif-rounding; @include notif-rounding;
padding: 0rem 0.136rem; min-width: 1.841rem;
min-height: 1.841rem;
} }
.notif-close-btn:hover, .notif-expand-btn:hover,
.notif-close-btn:focus { .notif-expand-btn:focus {
background: $hovercolor; background: $hovercolor;
} }
.notif-close-btn:active { .notif-expand-btn:active {
background: $activecolor; background: $activecolor;
} }
@@ -123,14 +124,17 @@ $notif_surface: $t_background;
.osd-notif { .osd-notif {
@include notif-rounding; @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; min-width: 30.682rem;
} }
.notif-circprog-low { .notif-circprog-low {
transition: 0ms linear; transition: 0ms linear;
min-width: 0.136rem; // line width min-width: 0.136rem; // line width
min-height: 1.770rem; min-height: 3.136rem;
padding: 0rem; padding: 0rem;
color: $onSecondaryContainer; color: $onSecondaryContainer;
} }
@@ -138,7 +142,7 @@ $notif_surface: $t_background;
.notif-circprog-normal { .notif-circprog-normal {
transition: 0ms linear; transition: 0ms linear;
min-width: 0.136rem; // line width min-width: 0.136rem; // line width
min-height: 1.770rem; min-height: 3.136rem;
padding: 0rem; padding: 0rem;
color: $onSecondaryContainer; color: $onSecondaryContainer;
} }
@@ -146,7 +150,57 @@ $notif_surface: $t_background;
.notif-circprog-critical { .notif-circprog-critical {
transition: 0ms linear; transition: 0ms linear;
min-width: 0.136rem; // line width min-width: 0.136rem; // line width
min-height: 1.770rem; min-height: 3.136rem;
padding: 0rem; padding: 0rem;
color: $onSecondaryContainer; color: $secondaryContainer;
} }
.notif-actions {
min-height: 2.045rem;
}
.notif-action {
@include small-rounding;
}
.notif-action-low {
background-color: mix($t_onSurfaceVariant, $t_surface, 10%);
color: $onSurfaceVariant;
}
.notif-action-low:focus,
.notif-action-low:hover {
background-color: mix($t_onSurfaceVariant, $t_surface, 18%);
}
.notif-action-low:active {
background-color: mix($t_onSurfaceVariant, $t_surface, 23%);
}
.notif-action-normal {
background-color: mix($t_onSurfaceVariant, $t_surface, 10%);
color: $onSurfaceVariant;
}
.notif-action-normal:focus,
.notif-action-normal:hover {
background-color: mix($t_onSurfaceVariant, $t_surface, 18%);
}
.notif-action-normal:active {
background-color: mix($t_onSurfaceVariant, $t_surface, 23%);
}
.notif-action-critical {
background-color: mix($t_onSecondaryContainer, $t_secondaryContainer, 10%);
color: $onSurfaceVariant;
}
.notif-action-critical:focus,
.notif-action-critical:hover {
background-color: mix($t_onSecondaryContainer, $t_secondaryContainer, 18%);
}
.notif-action-critical:active {
background-color: mix($t_onSecondaryContainer, $t_secondaryContainer, 23%);
}
+14 -2
View File
@@ -1,15 +1,19 @@
// .osd-window {
// margin-top: 2.727rem;
// }
.osd-bg { .osd-bg {
min-width: 8.864rem; min-width: 8.864rem;
min-height: 3.409rem; min-height: 3.409rem;
} }
.osd-value { .osd-value {
@include elevation-border;
@include elevation2;
background-color: $t_background; background-color: $t_background;
border-radius: 1.023rem; border-radius: 1.023rem;
padding: 0.625rem 1.023rem; padding: 0.625rem 1.023rem;
padding-top: 0.313rem; padding-top: 0.313rem;
margin: 10px;
@include elevation2;
} }
.osd-progress { .osd-progress {
@@ -113,4 +117,12 @@
background-color: $background; background-color: $background;
color: $onBackground; color: $onBackground;
box { background-color: $onBackground; } box { background-color: $onBackground; }
}
.osd-show {
transition: 200ms cubic-bezier(0.1, 1, 0, 1);
}
.osd-hide {
transition: 190ms cubic-bezier(0.85, 0, 0.15, 1);
} }
+4
View File
@@ -1,3 +1,7 @@
.overview-window {
margin-top: 2.727rem;
}
.overview-search-box { .overview-search-box {
@include menu_decel; @include menu_decel;
@include large-rounding; @include large-rounding;
+59 -6
View File
@@ -12,7 +12,7 @@ $onChatgpt: $onPrimary;
@include menu_decel; @include menu_decel;
@include elevation-border; @include elevation-border;
@include elevation2; @include elevation2;
border-radius: $rounding_large - $elevation_margin; border-radius: $rounding_large - $elevation_margin + 0.068rem;
min-width: 27.818rem; // COMMENT THIS LATER IF TEXT WRAP IS USED min-width: 27.818rem; // COMMENT THIS LATER IF TEXT WRAP IS USED
// min-height: 29.591rem; // min-height: 29.591rem;
background-color: $t_background; background-color: $t_background;
@@ -33,7 +33,7 @@ $onChatgpt: $onPrimary;
@include menu_decel; @include menu_decel;
@include elevation-border; @include elevation-border;
@include elevation2; @include elevation2;
border-radius: $rounding_large - $elevation_margin; border-radius: $rounding_large - $elevation_margin + 0.068rem;
min-width: 27.818rem; // COMMENT THIS LATER IF TEXT WRAP IS USED min-width: 27.818rem; // COMMENT THIS LATER IF TEXT WRAP IS USED
// min-height: 29.591rem; // min-height: 29.591rem;
background-color: $t_background; background-color: $t_background;
@@ -332,7 +332,7 @@ $onChatgpt: $onPrimary;
.sidebar-selector-tab { .sidebar-selector-tab {
@include small-rounding; @include small-rounding;
transition: 0ms; @include menu_decel;
min-height: 2.5rem; min-height: 2.5rem;
color: $onSurface; color: $onSurface;
} }
@@ -500,9 +500,28 @@ $onChatgpt: $onPrimary;
min-height: 1.705rem; min-height: 1.705rem;
} }
.sidebar-chat-apiswitcher {
@include full-rounding;
@include group-padding;
background-color: $t_surface;
}
.sidebar-chat-apiswitcher-icon {
@include menu_decel;
@include full-rounding;
min-width: 2.182rem;
min-height: 2.182rem;
color: $onSurface;
}
.sidebar-chat-apiswitcher-icon-enabled {
background-color: $secondaryContainer;
color: $onSecondaryContainer;
}
.sidebar-chat-viewport { .sidebar-chat-viewport {
@include menu_decel; @include menu_decel;
margin: 0.682rem 0rem; // margin: 0.682rem 0rem;
padding: 0.682rem 0rem; padding: 0.682rem 0rem;
} }
@@ -645,7 +664,7 @@ $onChatgpt: $onPrimary;
margin: 0rem 3.409rem; margin: 0rem 3.409rem;
} }
.sidebar-chat-settings { .sidebar-chat-settings-toggles {
margin: 0rem 5.455rem; margin: 0rem 5.455rem;
} }
@@ -687,4 +706,38 @@ $onChatgpt: $onPrimary;
.sidebar-chat-chip-action-active { .sidebar-chat-chip-action-active {
color: $sidebar_chat_textboxareaColor; color: $sidebar_chat_textboxareaColor;
border: 0.068rem solid $sidebar_chat_textboxareaColor; border: 0.068rem solid $sidebar_chat_textboxareaColor;
} }
.sidebar-pin {
@include small-rounding;
@include menu_decel;
min-height: 2.386rem;
min-width: 2.386rem;
color: $onSurface;
}
.sidebar-pin:hover,
.sidebar-pin:focus {
background-color: mix($t_surfaceVariant, $onSurfaceVariant, 90%);
}
.sidebar-pin:active {
background-color: mix($surfaceVariant, $onSurfaceVariant, 75%);
}
.sidebar-pin-enabled {
background-color: $primary;
label {
color: $onPrimary;
}
}
.sidebar-pin-enabled:hover,
.sidebar-pin-enabled:focus {
background-color: mix($primary, $onPrimary, 90%);
}
.sidebar-pin-enabled:active {
background-color: mix($primary, $onPrimary, 80%);
}
+6
View File
@@ -32,3 +32,9 @@
.fadingRadial { .fadingRadial {
transition: 50ms cubic-bezier(0.2, 0.0, 0, 1.0); transition: 50ms cubic-bezier(0.2, 0.0, 0, 1.0);
} }
.sidebar-pinned {
margin: 0rem;
border-radius: 0rem;
border-bottom-right-radius: $rounding_large;
border: 0rem solid;
}
+6
View File
@@ -121,6 +121,7 @@ class ChatGPTService extends Service {
_assistantPrompt = false; _assistantPrompt = false;
_messages = []; _messages = [];
_cycleModels = true; _cycleModels = true;
_temperature = 0.5;
_requestCount = 0; _requestCount = 0;
_modelIndex = 0; _modelIndex = 0;
_key = ''; _key = '';
@@ -159,6 +160,9 @@ class ChatGPTService extends Service {
} }
} }
get temperature() { return this._temperature }
set temperature(value) { this._temperature = value; }
get messages() { return this._messages } get messages() { return this._messages }
get lastMessage() { return this._messages[this._messages.length - 1] } get lastMessage() { return this._messages[this._messages.length - 1] }
@@ -218,6 +222,8 @@ class ChatGPTService extends Service {
const body = { const body = {
model: CHAT_MODELS[this._modelIndex], model: CHAT_MODELS[this._modelIndex],
messages: this._messages.map(msg => { let m = { role: msg.role, content: msg.content }; return m; }), messages: this._messages.map(msg => { let m = { role: msg.role, content: msg.content }; return m; }),
temperature: this._temperature,
// temperature: 2, // <- Nuts
stream: true, stream: true,
}; };
+170
View File
@@ -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();
+646 -497
View File
File diff suppressed because it is too large Load Diff
+5 -7
View File
@@ -74,18 +74,16 @@ export const ModuleLeftSpace = () => Widget.EventBox({
Widget.Label({ Widget.Label({
xalign: 0, xalign: 0,
className: 'txt-smaller bar-topdesc txt', className: 'txt-smaller bar-topdesc txt',
connections: [[Hyprland.active.client, label => { // Hyprland.active.client setup: (self) => self.hook(Hyprland.active.client, label => { // Hyprland.active.client
label.label = Hyprland.active.client._class.length === 0 ? 'Desktop' : Hyprland.active.client._class; label.label = Hyprland.active.client._class.length === 0 ? 'Desktop' : Hyprland.active.client._class;
}]], }),
}), }),
Widget.Label({ Widget.Label({
xalign: 0, xalign: 0,
className: 'txt txt-smallie', className: 'txt txt-smallie',
connections: [ setup: (self) => self.hook(Hyprland.active.client, label => { // Hyprland.active.client
[Hyprland.active.client, label => { // Hyprland.active.client label.label = Hyprland.active.client._title.length === 0 ? `Workspace ${Hyprland.active.workspace.id}` : truncateTitle(Hyprland.active.client._title);
label.label = Hyprland.active.client._title.length === 0 ? `Workspace ${Hyprland.active.workspace.id}` : truncateTitle(Hyprland.active.client._title); }),
}]
],
}) })
] ]
}) })
+5 -5
View File
@@ -6,19 +6,19 @@ import { ModuleLeftSpace } from "./leftspace.js";
import { ModuleMusic } from "./music.js"; import { ModuleMusic } from "./music.js";
import { ModuleRightSpace } from "./rightspace.js"; import { ModuleRightSpace } from "./rightspace.js";
import { ModuleSystem } from "./system.js"; import { ModuleSystem } from "./system.js";
import { ModuleWorkspaces } from "./workspaces.js"; import ModuleWorkspaces from "./workspaces.js";
import { RoundedCorner } from "../../lib/roundedcorner.js"; import { RoundedCorner } from "../../lib/roundedcorner.js";
const left = Widget.Box({ const left = Widget.Box({
className: 'bar-sidemodule', className: 'bar-sidemodule',
children: [ModuleMusic()], children: [
ModuleMusic()
],
}); });
const center = Widget.Box({ const center = Widget.Box({
children: [ children: [
RoundedCorner('topright', { className: 'corner-bar-group' }),
ModuleWorkspaces(), ModuleWorkspaces(),
RoundedCorner('topleft', { className: 'corner-bar-group' }),
], ],
}); });
@@ -36,7 +36,7 @@ export default () => Widget.Window({
className: 'bar-bg', className: 'bar-bg',
startWidget: ModuleLeftSpace(), startWidget: ModuleLeftSpace(),
centerWidget: Widget.Box({ centerWidget: Widget.Box({
className: 'spacing-h--20', className: 'spacing-h-4',
children: [ children: [
left, left,
center, center,
+3 -3
View File
@@ -9,12 +9,12 @@ const TrackProgress = () => {
const _updateProgress = (circprog) => { const _updateProgress = (circprog) => {
const mpris = Mpris.getPlayer(''); const mpris = Mpris.getPlayer('');
if (!mpris) return; if (!mpris) return;
// Set circular progress (font size cuz that's how this hacky circprog works) // Set circular progress value
circprog.css = `font-size: ${Math.max(mpris.position / mpris.length * 100, 0)}px;` circprog.css = `font-size: ${Math.max(mpris.position / mpris.length * 100, 0)}px;`
} }
return AnimatedCircProg({ return AnimatedCircProg({
className: 'bar-music-circprog', className: 'bar-music-circprog',
vpack: 'center', vpack: 'center', hpack: 'center',
connections: [ // Update on change/once every 3 seconds connections: [ // Update on change/once every 3 seconds
[Mpris, _updateProgress], [Mpris, _updateProgress],
[3000, _updateProgress] [3000, _updateProgress]
@@ -65,7 +65,7 @@ export const ModuleMusic = () => Widget.EventBox({
Widget.Scrollable({ Widget.Scrollable({
hexpand: true, hexpand: true,
child: Widget.Label({ child: Widget.Label({
className: 'txt txt-smallie', className: 'txt-smallie txt-onSurfaceVariant',
connections: [[Mpris, label => { connections: [[Mpris, label => {
const mpris = Mpris.getPlayer(''); const mpris = Mpris.getPlayer('');
if (mpris) if (mpris)
+2 -2
View File
@@ -11,11 +11,11 @@ export const ModuleRightSpace = () => {
const barTray = Tray(); const barTray = Tray();
const barStatusIcons = StatusIcons({ const barStatusIcons = StatusIcons({
className: 'bar-statusicons', className: 'bar-statusicons',
connections: [[App, (self, currentName, visible) => { setup: (self) => self.hook(App, (self, currentName, visible) => {
if (currentName === 'sideright') { if (currentName === 'sideright') {
self.toggleClassName('bar-statusicons-active', visible); self.toggleClassName('bar-statusicons-active', visible);
} }
}]], }),
}); });
return Widget.EventBox({ return Widget.EventBox({
+130 -103
View File
@@ -1,146 +1,173 @@
// This is for the right pill of the bar. // This is for the right pill of the bar.
// For the cool memory indicator on the sidebar, see sysinfo.js // For the cool memory indicator on the sidebar, see sysinfo.js
import { Service, Utils, Widget } from '../../imports.js'; import { Service, Utils, Widget } from '../../imports.js';
const { Box, Label, Button, Overlay, Revealer, Scrollable, Stack, EventBox } = Widget;
const { exec, execAsync } = Utils; const { exec, execAsync } = Utils;
const { GLib } = imports.gi; const { GLib } = imports.gi;
import Battery from 'resource:///com/github/Aylur/ags/service/battery.js'; import Battery from 'resource:///com/github/Aylur/ags/service/battery.js';
import { MaterialIcon } from '../../lib/materialicon.js'; import { MaterialIcon } from '../../lib/materialicon.js';
import { AnimatedCircProg } from "../../lib/animatedcircularprogress.js";
const BATTERY_LOW = 20; const BATTERY_LOW = 20;
const BatBatteryProgress = () => {
const _updateProgress = (circprog) => { // Set circular progress value
circprog.css = `font-size: ${Battery.percent}px;`
circprog.toggleClassName('bar-batt-circprog-low', Battery.percent <= BATTERY_LOW);
circprog.toggleClassName('bar-batt-circprog-full', Battery.charged);
}
return AnimatedCircProg({
className: 'bar-batt-circprog',
vpack: 'center', hpack: 'center',
connections: [
[Battery, _updateProgress],
],
})
}
const BarClock = () => Widget.Box({ const BarClock = () => Widget.Box({
vpack: 'center', vpack: 'center',
className: 'spacing-h-5', className: 'spacing-h-5 txt-onSurfaceVariant',
children: [ children: [
Widget.Label({ Widget.Label({
className: 'bar-clock', className: 'bar-clock',
connections: [[5000, label => { label: GLib.DateTime.new_now_local().format("%H:%M"),
setup: (self) => self.poll(5000, label => {
label.label = GLib.DateTime.new_now_local().format("%H:%M"); label.label = GLib.DateTime.new_now_local().format("%H:%M");
}]], }),
}), }),
Widget.Label({ Widget.Label({
className: 'txt-norm txt', className: 'txt-norm',
label: '•', label: '•',
}), }),
Widget.Label({ Widget.Label({
className: 'txt-smallie txt', className: 'txt-smallie',
connections: [[5000, label => { label: GLib.DateTime.new_now_local().format("%A, %d/%m"),
setup: (self) => self.poll(5000, label => {
label.label = GLib.DateTime.new_now_local().format("%A, %d/%m"); label.label = GLib.DateTime.new_now_local().format("%A, %d/%m");
}]], }),
}), }),
], ],
}); });
const BarBattery = () => { const UtilButton = ({ name, icon, onClicked }) => Button({
const BarResourceValue = (name, icon, command) => Widget.Box({ vpack: 'center',
vpack: 'center', tooltipText: name,
className: 'bar-batt spacing-h-5', onClicked: onClicked,
children: [ className: 'bar-util-btn icon-material txt-norm',
MaterialIcon(icon, 'small'), label: `${icon}`,
Widget.ProgressBar({ // Progress })
vpack: 'center', hexpand: true,
className: 'bar-prog-batt', const Utilities = () => Scrollable({
connections: [[5000, (progress) => execAsync(['bash', '-c', command]) hexpand: true,
.then((output) => { child: Box({
progress.value = Number(output) / 100; hpack: 'center',
progress.tooltipText = `${name}: ${Number(output)}%`
})
.catch(print)
]],
}),
]
});
const batteryWidget = Widget.Box({
vpack: 'center',
hexpand: true,
className: 'spacing-h-5 bar-batt',
connections: [[Battery, box => {
box.toggleClassName('bar-batt-low', Battery.percent <= BATTERY_LOW);
box.toggleClassName('bar-batt-full', Battery.charged);
}]],
children: [
MaterialIcon('settings_heart', 'small'),
Widget.Label({ // Percentage
className: 'bar-batt-percentage',
connections: [[Battery, label => {
label.label = `${Battery.percent}`;
}]],
}),
Widget.ProgressBar({ // Progress
vpack: 'center',
hexpand: true,
className: 'bar-prog-batt',
connections: [[Battery, progress => {
progress.value = Math.abs(Battery.percent / 100); // battery could be initially negative wtf
progress.toggleClassName('bar-prog-batt-low', Battery.percent <= BATTERY_LOW);
progress.toggleClassName('bar-prog-batt-full', Battery.charged);
batteryWidget.tooltipText = `Battery: ${Battery.percent}%`
}]],
}),
Widget.Revealer({ // A dot for charging state
transitionDuration: 150,
revealChild: false,
transition: 'slide_left',
child: Widget.Box({
className: 'spacing-h-3',
children: [
Widget.Box({
vpack: 'center',
className: 'bar-batt-chargestate-charging-smaller',
connections: [[Battery, box => {
box.toggleClassName('bar-batt-chargestate-low', Battery.percent <= BATTERY_LOW);
box.toggleClassName('bar-batt-chargestate-full', Battery.charged);
}]],
}),
Widget.Box({
vpack: 'center',
className: 'bar-batt-chargestate-charging',
connections: [[Battery, box => {
box.toggleClassName('bar-batt-chargestate-low', Battery.percent <= BATTERY_LOW);
box.toggleClassName('bar-batt-chargestate-full', Battery.charged);
}]],
}),
]
}),
connections: [[Battery, revealer => {
revealer.revealChild = Battery.charging;
}]],
}),
],
});
const memUsage = Widget.Box({
className: 'spacing-h-5', className: 'spacing-h-5',
children: [ children: [
BarResourceValue('RAM usage', 'memory', `free | awk '/^Mem/ {printf("%.2f\\n", ($3/$2) * 100)}'`), UtilButton({
BarResourceValue('Swap usage', 'swap_horiz', `free | awk '/^Swap/ {printf("%.2f\\n", ($3/$2) * 100)}'`), name: 'Screen snip', icon: 'screenshot_region', onClicked: () => {
Utils.execAsync(['bash', '-c', `grim -g "$(slurp -d -c e2e2e2BB -b 31313122 -s 00000000)" - | wl-copy &`])
.catch(print)
}
}),
UtilButton({
name: 'Color picker', icon: 'colorize', onClicked: () => {
Utils.execAsync(['hyprpicker', '-a']).catch(print)
}
}),
UtilButton({
name: 'Toggle on-screen keyboard', icon: 'keyboard', onClicked: () => {
App.toggleWindow('osk');
}
}),
] ]
}) })
const widgetStack = Widget.Stack({ })
transition: 'slide_up_down',
vpack: 'center', const BarBattery = () => Box({
hexpand: true, className: 'spacing-h-4 txt-onSurfaceVariant',
items: [ children: [
['fallback', memUsage], // Revealer({ // A dot for charging state
['battery', batteryWidget], // transitionDuration: 150,
], // revealChild: false,
setup: (stack) => Utils.timeout(1, () => { // transition: 'crossfade',
if (Battery.available) stack.shown = 'battery'; // child: Widget.Box({
else stack.shown = 'fallback'; // className: 'spacing-h-3',
}) // children: [
}) // Widget.Box({
return widgetStack; // vpack: 'center',
} // className: 'bar-batt-chargestate-charging-smaller',
// setup: (self) => self.hook(Battery, box => {
// box.toggleClassName('bar-batt-chargestate-low', Battery.percent <= BATTERY_LOW);
// box.toggleClassName('bar-batt-chargestate-full', Battery.charged);
// }),
// }),
// Widget.Box({
// vpack: 'center',
// className: 'bar-batt-chargestate-charging',
// setup: (self) => self.hook(Battery, box => {
// box.toggleClassName('bar-batt-chargestate-low', Battery.percent <= BATTERY_LOW);
// box.toggleClassName('bar-batt-chargestate-full', Battery.charged);
// }),
// }),
// ]
// }),
// setup: (self) => self.hook(Battery, revealer => {
// revealer.revealChild = Battery.charging;
// }),
// }),
Stack({
transition: 'slide_up_down',
items: [
['discharging', Widget.Label({
className: 'txt-norm txt',
label: '•',
}),],
['charging', MaterialIcon('bolt', 'norm')],
],
setup: (self) => self.hook(Battery, revealer => {
self.shown = Battery.charging ? 'charging' : 'discharging';
}),
}),
Label({
className: 'txt-smallie txt-onSurfaceVariant',
setup: (self) => self.hook(Battery, label => {
label.label = `${Battery.percent}%`;
}),
}),
Overlay({
child: Widget.Box({
vpack: 'center',
className: 'bar-batt',
homogeneous: true,
children: [
MaterialIcon('settings_heart', 'small'),
],
setup: (self) => self.hook(Battery, box => {
box.toggleClassName('bar-batt-low', Battery.percent <= BATTERY_LOW);
box.toggleClassName('bar-batt-full', Battery.charged);
}),
}),
overlays: [
BatBatteryProgress(),
]
}),
]
});
export const ModuleSystem = () => Widget.EventBox({ export const ModuleSystem = () => Widget.EventBox({
onScrollUp: () => execAsync('hyprctl dispatch workspace -1'), onScrollUp: () => execAsync('hyprctl dispatch workspace -1'),
onScrollDown: () => execAsync('hyprctl dispatch workspace +1'), onScrollDown: () => execAsync('hyprctl dispatch workspace +1'),
onPrimaryClick: () => App.toggleWindow('sideright'),
child: Widget.Box({ child: Widget.Box({
className: 'bar-group-margin bar-sides', className: 'bar-group-margin bar-sides',
children: [ children: [
Widget.Box({ Widget.Box({
className: 'bar-group bar-group-standalone bar-group-pad-system spacing-h-15', className: 'bar-group bar-group-standalone bar-group-pad-system spacing-h-5',
children: [ children: [
BarClock(), BarClock(),
Utilities(),
BarBattery(), BarBattery(),
], ],
}), }),
+13 -8
View File
@@ -10,7 +10,13 @@ const SysTrayItem = item => Button({
className: 'bar-systray-item', className: 'bar-systray-item',
child: Icon({ child: Icon({
hpack: 'center', 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']], binds: [['tooltipMarkup', item, 'tooltip-markup']],
onClicked: btn => item.menu.popup_at_widget(btn, Gravity.SOUTH, Gravity.NORTH, null), 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 = {}) => { export const Tray = (props = {}) => {
const trayContent = Box({ const trayContent = Box({
vpack: 'center', className: 'bar-systray spacing-h-10',
className: 'bar-systray bar-group',
properties: [ properties: [
['items', new Map()], ['items', new Map()],
['onAdded', (box, id) => { ['onAdded', (box, id) => {
@@ -31,7 +36,7 @@ export const Tray = (props = {}) => {
return; return;
const widget = SysTrayItem(item); const widget = SysTrayItem(item);
box._items.set(id, widget); box._items.set(id, widget);
box.pack_start(widget, false, false, 0); box.add(widget);
box.show_all(); box.show_all();
if (box._items.size === 1) if (box._items.size === 1)
trayRevealer.revealChild = true; trayRevealer.revealChild = true;
@@ -46,10 +51,10 @@ export const Tray = (props = {}) => {
trayRevealer.revealChild = false; trayRevealer.revealChild = false;
}], }],
], ],
connections: [ setup: (self) => self
[SystemTray, (box, id) => box._onAdded(box, id), 'added'], .hook(SystemTray, (box, id) => box._onAdded(box, id), 'added')
[SystemTray, (box, id) => box._onRemoved(box, id), 'removed'], .hook(SystemTray, (box, id) => box._onRemoved(box, id), 'removed')
], ,
}); });
const trayRevealer = Widget.Revealer({ const trayRevealer = Widget.Revealer({
revealChild: false, revealChild: false,
+159 -90
View File
@@ -1,100 +1,169 @@
const { GLib, Gdk, Gtk } = imports.gi; const { GLib, Gdk, Gtk } = imports.gi;
const Lang = imports.lang;
const Cairo = imports.cairo;
const Pango = imports.gi.Pango;
const PangoCairo = imports.gi.PangoCairo;
import { App, Service, Utils, Widget } from '../../imports.js'; import { App, Service, Utils, Widget } from '../../imports.js';
const { Box, DrawingArea, EventBox } = Widget;
import Hyprland from 'resource:///com/github/Aylur/ags/service/hyprland.js'; import Hyprland from 'resource:///com/github/Aylur/ags/service/hyprland.js';
const WORKSPACE_SIDE_PAD = 0.546; // rem
const NUM_OF_WORKSPACES = 10; const NUM_OF_WORKSPACES = 10;
let lastWorkspace = 0; const dummyWs = Box({ className: 'bar-ws' }); // Not shown. Only for getting size props
const dummyActiveWs = Box({ className: 'bar-ws bar-ws-active' }); // Not shown. Only for getting size props
const dummyOccupiedWs = Box({ className: 'bar-ws bar-ws-occupied' }); // Not shown. Only for getting size props
const activeWorkspaceIndicator = Widget.Box({ // Font size = workspace id
css: ` const WorkspaceContents = (count = 10) => {
padding: 0rem ${WORKSPACE_SIDE_PAD}rem; return DrawingArea({
`, properties: [
children: [ ['workspaceMask', 0],
Widget.Box({ ],
vpack: 'center', css: `transition: 500ms cubic-bezier(0.1, 1, 0, 1);`,
hpack: 'start', setup: (area) => area
className: 'bar-ws-active-box', .hook(Hyprland.active.workspace, (area) =>
connections: [ area.setCss(`font-size: ${Hyprland.active.workspace.id}px;`)
[Hyprland.active.workspace, (box) => { )
const ws = Hyprland.active.workspace.id; .hook(Hyprland, (area) => {
box.setCss(` const workspaces = Hyprland.workspaces;
margin-left: ${1.774 * (ws - 1) + 0.068}rem; let workspaceMask = 0;
`); for (let i = 0; i < workspaces.length; i++) {
lastWorkspace = ws; const ws = workspaces[i];
}], if (ws.id < 0) continue; // Ignore scratchpads
], if (ws.id > count) return; // Not rendered
children: [ if (workspaces[i].windows > 0) {
Widget.Label({ workspaceMask |= (1 << ws.id);
vpack: 'center', }
className: 'bar-ws-active', }
label: ``, area._workspaceMask = workspaceMask;
}) }, 'notify::workspaces')
] .on('draw', Lang.bind(area, (area, cr) => {
}) const allocation = area.get_allocation();
] const { width, height } = allocation;
});
export const ModuleWorkspaces = () => Widget.EventBox({ const workspaceStyleContext = dummyWs.get_style_context();
onScrollUp: () => Utils.execAsync(['bash', '-c', 'hyprctl dispatch workspace -1 &']), const workspaceDiameter = workspaceStyleContext.get_property('min-width', Gtk.StateFlags.NORMAL);
onScrollDown: () => Utils.execAsync(['bash', '-c', 'hyprctl dispatch workspace +1 &']), const workspaceRadius = workspaceDiameter / 2;
const workspaceFontSize = workspaceStyleContext.get_property('font-size', Gtk.StateFlags.NORMAL) / 4 * 3;
const workspaceFontFamily = workspaceStyleContext.get_property('font-family', Gtk.StateFlags.NORMAL);
const wsbg = workspaceStyleContext.get_property('background-color', Gtk.StateFlags.NORMAL);
const wsfg = workspaceStyleContext.get_property('color', Gtk.StateFlags.NORMAL);
const occupiedWorkspaceStyleContext = dummyOccupiedWs.get_style_context();
const occupiedbg = occupiedWorkspaceStyleContext.get_property('background-color', Gtk.StateFlags.NORMAL);
const occupiedfg = occupiedWorkspaceStyleContext.get_property('color', Gtk.StateFlags.NORMAL);
const activeWorkspaceStyleContext = dummyActiveWs.get_style_context();
const activebg = activeWorkspaceStyleContext.get_property('background-color', Gtk.StateFlags.NORMAL);
const activefg = activeWorkspaceStyleContext.get_property('color', Gtk.StateFlags.NORMAL);
area.set_size_request(workspaceDiameter * count, -1);
const widgetStyleContext = area.get_style_context();
const activeWs = widgetStyleContext.get_property('font-size', Gtk.StateFlags.NORMAL);
const activeWsCenterX = -(workspaceDiameter / 2) + (workspaceDiameter * activeWs);
const activeWsCenterY = height / 2;
// Font
const layout = PangoCairo.create_layout(cr);
const fontDesc = Pango.font_description_from_string(`${workspaceFontFamily[0]} ${workspaceFontSize}`);
layout.set_font_description(fontDesc);
cr.setAntialias(Cairo.Antialias.BEST);
// Get kinda min radius for number indicators
layout.set_text("0".repeat(count.toString().length), -1);
const [layoutWidth, layoutHeight] = layout.get_pixel_size();
const indicatorRadius = Math.max(layoutWidth, layoutHeight) / 2 * 1.2; // a bit smaller than sqrt(2)*radius
const indicatorGap = workspaceRadius - indicatorRadius;
// Draw workspace numbers
for (let i = 1; i <= count; i++) {
if (area._workspaceMask & (1 << i)) {
// Draw bg highlight
cr.setSourceRGBA(occupiedbg.red, occupiedbg.green, occupiedbg.blue, occupiedbg.alpha);
const wsCenterX = -(workspaceRadius) + (workspaceDiameter * i);
const wsCenterY = height / 2;
if (!(area._workspaceMask & (1 << (i - 1)))) { // Left
cr.arc(wsCenterX, wsCenterY, workspaceRadius, 0.5 * Math.PI, 1.5 * Math.PI);
cr.fill();
}
else {
cr.rectangle(wsCenterX - workspaceRadius, wsCenterY - workspaceRadius, workspaceRadius, workspaceRadius * 2)
cr.fill();
}
if (!(area._workspaceMask & (1 << (i + 1)))) { // Right
cr.arc(wsCenterX, wsCenterY, workspaceRadius, -0.5 * Math.PI, 0.5 * Math.PI);
cr.fill();
}
else {
cr.rectangle(wsCenterX, wsCenterY - workspaceRadius, workspaceRadius, workspaceRadius * 2)
cr.fill();
}
// Set color for text
cr.setSourceRGBA(occupiedfg.red, occupiedfg.green, occupiedfg.blue, occupiedfg.alpha);
}
else
cr.setSourceRGBA(wsfg.red, wsfg.green, wsfg.blue, wsfg.alpha);
layout.set_text(`${i}`, -1);
const [layoutWidth, layoutHeight] = layout.get_pixel_size();
const x = -workspaceRadius + (workspaceDiameter * i) - (layoutWidth / 2);
const y = (height - layoutHeight) / 2;
cr.moveTo(x, y);
// cr.showText(text);
PangoCairo.show_layout(cr, layout);
cr.stroke();
}
// Draw active ws
// base
cr.setSourceRGBA(activebg.red, activebg.green, activebg.blue, activebg.alpha);
cr.arc(activeWsCenterX, activeWsCenterY, indicatorRadius, 0, 2 * Math.PI);
cr.fill();
// inner decor
cr.setSourceRGBA(activefg.red, activefg.green, activefg.blue, activefg.alpha);
cr.arc(activeWsCenterX, activeWsCenterY, indicatorRadius * 0.2, 0, 2 * Math.PI);
cr.fill();
}))
,
})
}
export default () => EventBox({
onScrollUp: () => Hyprland.sendMessage(`dispatch workspace -1`),
onScrollDown: () => Hyprland.sendMessage(`dispatch workspace +1`),
onMiddleClickRelease: () => App.toggleWindow('overview'), onMiddleClickRelease: () => App.toggleWindow('overview'),
onSecondaryClickRelease: () => App.toggleWindow('osk'), onSecondaryClickRelease: () => App.toggleWindow('osk'),
child: Widget.Box({ properties: [
['clicked', false],
],
child: Box({
homogeneous: true, homogeneous: true,
className: 'bar-ws-width', className: 'bar-group-margin',
children: [ children: [Box({
Widget.Overlay({ className: 'bar-group bar-group-standalone bar-group-pad',
passThrough: true, css: 'min-width: 2px;',
child: Widget.Box({ children: [
homogeneous: true, WorkspaceContents(10),
className: 'bar-group-center', ]
children: [Widget.Box({ })]
className: 'bar-group-standalone bar-group-pad', }),
})] setup: (self) => {
}), self.add_events(Gdk.EventMask.POINTER_MOTION_MASK);
overlays: [ self.on('motion-notify-event', (self, event) => {
Widget.Overlay({ if (!self._clicked) return;
setup: (self) => self.set_overlay_pass_through(self.get_children()[1], true), console.log('switching move');
child: Widget.Box({ const [_, cursorX, cursorY] = event.get_coords();
hpack: 'center', const widgetWidth = self.get_allocation().width;
css: ` const wsId = Math.ceil(cursorX * NUM_OF_WORKSPACES / widgetWidth);
padding: 0rem ${WORKSPACE_SIDE_PAD}rem; Hyprland.sendMessage(`dispatch workspace ${wsId}`)
`, })
// homogeneous: true, self.on('button-press-event', (self, event) => {
children: Array.from({ length: NUM_OF_WORKSPACES }, (_, i) => i + 1).map(i => Widget.Button({ if (!(event.get_button()[1] === 1)) return; // We're only interested in left-click here
onPrimaryClick: () => Utils.execAsync(['bash', '-c', `hyprctl dispatch workspace ${i} &`]).catch(print), console.log('switching');
child: Widget.Label({ self._clicked = true;
vpack: 'center', const [_, cursorX, cursorY] = event.get_coords();
label: `${i}`, const widgetWidth = self.get_allocation().width;
className: 'bar-ws txt', const wsId = Math.ceil(cursorX * NUM_OF_WORKSPACES / widgetWidth);
}), Hyprland.sendMessage(`dispatch workspace ${wsId}`);
})), })
connections: [ self.on('button-release-event', (self) => self._clicked = false);
[Hyprland, (box) => { }
// console.log('update'); })
const kids = box.children;
kids.forEach((child, i) => {
child.child.toggleClassName('bar-ws-occupied', false);
child.child.toggleClassName('bar-ws-occupied-left', false);
child.child.toggleClassName('bar-ws-occupied-right', false);
child.child.toggleClassName('bar-ws-occupied-left-right', false);
});
const occupied = Array.from({ length: NUM_OF_WORKSPACES }, (_, i) => Hyprland.getWorkspace(i + 1)?.windows > 0);
for (let i = 0; i < occupied.length; i++) {
if (!occupied[i]) continue;
const child = kids[i];
child.child.toggleClassName(`bar-ws-occupied${!occupied[i - 1] ? '-left' : ''}${!occupied[i + 1] ? '-right' : ''}`, true);
}
}, 'notify::workspaces'],
],
}),
overlays: [
activeWorkspaceIndicator,
]
})
],
})
]
})
});
+1 -1
View File
@@ -69,7 +69,7 @@ const clickOutsideToClose = Widget.EventBox({
export default () => Widget.Window({ export default () => Widget.Window({
name: 'cheatsheet', name: 'cheatsheet',
exclusivity: 'normal', exclusivity: 'ignore',
focusable: true, focusable: true,
popup: true, popup: true,
visible: false, visible: false,
@@ -138,10 +138,12 @@ export default () => Box({
}), }),
onPrimaryClickRelease: () => { onPrimaryClickRelease: () => {
const kids = resources.get_children(); const kids = resources.get_children();
for (let i = 0; i < kids.length; i++) {
kids.forEach((child, i) => { const child = kids[i];
child.get_children()[0].revealChild = !child.get_children()[0].revealChild; const firstChild = child.get_children()[0];
}); firstChild.revealChild = !firstChild.revealChild;
}
}, },
}) })
], ],
@@ -14,16 +14,18 @@ const TimeAndDate = () => Box({
Label({ Label({
className: 'bg-time-clock', className: 'bg-time-clock',
xalign: 0, xalign: 0,
connections: [[5000, label => { label: GLib.DateTime.new_now_local().format("%H:%M"),
setup: (self) => self.poll(5000, label => {
label.label = GLib.DateTime.new_now_local().format("%H:%M"); label.label = GLib.DateTime.new_now_local().format("%H:%M");
}]], }),
}), }),
Label({ Label({
className: 'bg-time-date', className: 'bg-time-date',
xalign: 0, xalign: 0,
connections: [[5000, label => { label: GLib.DateTime.new_now_local().format("%A, %d/%m/%Y"),
setup: (self) => self.poll(5000, label => {
label.label = GLib.DateTime.new_now_local().format("%A, %d/%m/%Y"); label.label = GLib.DateTime.new_now_local().format("%A, %d/%m/%Y");
}]], }),
}), }),
] ]
}) })
@@ -46,7 +48,7 @@ const QuickLaunches = () => Box({
}, },
className: 'bg-quicklaunch-btn', className: 'bg-quicklaunch-btn',
child: Label({ child: Label({
label: `${ item["name"]}`, label: `${item["name"]}`,
}), }),
setup: (self) => { setup: (self) => {
setupCursorHover(self); setupCursorHover(self);
@@ -60,7 +62,7 @@ export default () => Box({
hpack: 'start', hpack: 'start',
vpack: 'end', vpack: 'end',
vertical: true, vertical: true,
className: 'bg-time-box spacing-v-20', className: 'bg-time-box spacing-h--10',
children: [ children: [
TimeAndDate(), TimeAndDate(),
// QuickLaunches(), // QuickLaunches(),
+23 -25
View File
@@ -86,7 +86,8 @@ const Taskbar = () => Widget.Box({
return a._workspace > b._workspace; return a._workspace > b._workspace;
}], }],
['update', (box) => { ['update', (box) => {
Hyprland.clients.forEach(client => { for (let i = 0; i < Hyprland.clients.length; i++) {
const client = Hyprland.clients[i];
if (client["pid"] == -1) return; if (client["pid"] == -1) return;
const appClass = substitute(client.class); const appClass = substitute(client.class);
for (const appName of pinnedApps) { for (const appName of pinnedApps) {
@@ -101,11 +102,11 @@ const Taskbar = () => Widget.Box({
newButton._workspace = client.workspace.id; newButton._workspace = client.workspace.id;
newButton.revealChild = true; newButton.revealChild = true;
box._map.set(client.address, newButton); box._map.set(client.address, newButton);
}) }
box.children = Array.from(box._map.values()); box.children = Array.from(box._map.values());
}], }],
['add', (box, address) => { ['add', (box, address) => {
if (!address) { // Since the first active emit is undefined if (!address) { // First active emit is undefined
box._update(box); box._update(box);
return; return;
} }
@@ -137,14 +138,11 @@ const Taskbar = () => Widget.Box({
}) })
}], }],
], ],
connections: [
// [Hyprland, (box) => box._update(box)],
[Hyprland, (box, address) => box._add(box, address), 'client-added'],
[Hyprland, (box, address) => box._remove(box, address), 'client-removed'],
],
setup: (self) => { setup: (self) => {
self.hook(Hyprland, (box, address) => box._add(box, address), 'client-added')
.hook(Hyprland, (box, address) => box._remove(box, address), 'client-removed')
Utils.timeout(100, () => self._update(self)); Utils.timeout(100, () => self._update(self));
} },
}); });
const PinnedApps = () => Widget.Box({ const PinnedApps = () => Widget.Box({
@@ -165,18 +163,18 @@ const PinnedApps = () => Widget.Box({
app.launch(); app.launch();
}, },
onMiddleClick: () => app.launch(), onMiddleClick: () => app.launch(),
tooltipText: app.name,
setup: (self) => { setup: (self) => {
self.revealChild = true; self.revealChild = true;
}, self.hook(Hyprland, button => {
tooltipText: app.name, const running = Hyprland.clients
connections: [[Hyprland, button => { .find(client => client.class.toLowerCase().includes(term)) || false;
const running = Hyprland.clients
.find(client => client.class.toLowerCase().includes(term)) || false;
button.toggleClassName('nonrunning', !running); button.toggleClassName('notrunning', !running);
button.toggleClassName('focused', Hyprland.active.client.address == running.address); button.toggleClassName('focused', Hyprland.active.client.address == running.address);
button.set_tooltip_text(running ? running.title : app.name); button.set_tooltip_text(running ? running.title : app.name);
}, 'notify::clients']], }, 'notify::clients')
},
}) })
newButton.revealChild = true; newButton.revealChild = true;
return newButton; return newButton;
@@ -237,13 +235,13 @@ export default () => {
transition: 'slide_up', transition: 'slide_up',
transitionDuration: 200, transitionDuration: 200,
child: dockContent, child: dockContent,
connections: [ // setup: (self) => self
// [Hyprland, (self) => self._updateShow(self)], // .hook(Hyprland, (self) => self._updateShow(self))
// [Hyprland.active.workspace, (self) => self._updateShow(self)], // .hook(Hyprland.active.workspace, (self) => self._updateShow(self))
// [Hyprland.active.client, (self) => self._updateShow(self)], // .hook(Hyprland.active.client, (self) => self._updateShow(self))
// [Hyprland, (self) => self._updateShow(self), 'client-added'], // .hook(Hyprland, (self) => self._updateShow(self), 'client-added')
// [Hyprland, (self) => self._updateShow(self), 'client-removed'], // .hook(Hyprland, (self) => self._updateShow(self), 'client-removed')
], // ,
}) })
return EventBox({ return EventBox({
onHover: () => { onHover: () => {
@@ -50,9 +50,7 @@ export default () => Widget.Revealer({
transition: 'slide_down', transition: 'slide_down',
transitionDuration: 200, transitionDuration: 200,
child: colorschemeContent, child: colorschemeContent,
connections: [ setup: (self) => self.hook(showColorScheme, (revealer) => {
[showColorScheme, (revealer) => { revealer.revealChild = showColorScheme.value;
revealer.revealChild = showColorScheme.value; }),
}],
],
}) })
@@ -2,34 +2,33 @@
const { GLib, Gtk } = imports.gi; const { GLib, Gtk } = imports.gi;
import { App, Service, Utils, Widget } from '../../imports.js'; import { App, Service, Utils, Widget } from '../../imports.js';
import Audio from 'resource:///com/github/Aylur/ags/service/audio.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, Label, ProgressBar, Revealer } = Widget;
const { Box, EventBox, Icon, Scrollable, Label, Button, Revealer } = Widget; import { MarginRevealer } from '../../lib/advancedrevealers.js';
import Brightness from '../../services/brightness.js'; import Brightness from '../../services/brightness.js';
import Indicator from '../../services/indicator.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, ...props,
vertical: true, vertical: true,
className: 'osd-bg osd-value', className: 'osd-bg osd-value',
hexpand: true, hexpand: true,
children: [ children: [
Widget.Box({ Box({
vexpand: true, vexpand: true,
children: [ children: [
Widget.Label({ Label({
xalign: 0, yalign: 0, hexpand: true, xalign: 0, yalign: 0, hexpand: true,
className: 'osd-label', className: 'osd-label',
label: `${name}`, label: `${name}`,
}), }),
Widget.Label({ Label({
hexpand: false, className: 'osd-value-txt', hexpand: false, className: 'osd-value-txt',
label: '100', label: '100',
connections: labelConnections, connections: labelConnections,
}), }),
] ]
}), }),
Widget.ProgressBar({ ProgressBar({
className: 'osd-progress', className: 'osd-progress',
hexpand: true, hexpand: true,
vertical: false, vertical: false,
@@ -58,16 +57,20 @@ const volumeIndicator = OsdValue('Volume',
}]], }]],
); );
export default () => Widget.Revealer({ export default () => MarginRevealer({
transition: 'slide_down', transition: 'slide_down',
showClass: 'osd-show',
hideClass: 'osd-hide',
connections: [ connections: [
[Indicator, (revealer, value) => { [Indicator, (revealer, value) => {
revealer.revealChild = (value > -1); if(value > -1) revealer._show(revealer);
else revealer._hide(revealer);
}, 'popup'], }, 'popup'],
], ],
child: Widget.Box({ child: Box({
hpack: 'center', hpack: 'center',
vertical: false, vertical: false,
className: 'spacing-h--10',
children: [ children: [
brightnessIndicator, brightnessIndicator,
volumeIndicator, volumeIndicator,
+3
View File
@@ -10,6 +10,7 @@ export default (monitor) => Widget.Window({
monitor, monitor,
className: 'indicator', className: 'indicator',
layer: 'overlay', layer: 'overlay',
// exclusivity: 'ignore',
visible: true, visible: true,
anchor: ['top'], anchor: ['top'],
child: Widget.EventBox({ child: Widget.EventBox({
@@ -18,6 +19,7 @@ export default (monitor) => Widget.Window({
}, },
child: Widget.Box({ child: Widget.Box({
vertical: true, vertical: true,
className: 'osd-window',
css: 'min-height: 2px;', css: 'min-height: 2px;',
children: [ children: [
IndicatorValues(), IndicatorValues(),
@@ -28,3 +30,4 @@ export default (monitor) => Widget.Window({
}) })
}), }),
}); });
@@ -4,6 +4,7 @@ const { exec, execAsync } = Utils;
import Mpris from 'resource:///com/github/Aylur/ags/service/mpris.js'; import Mpris from 'resource:///com/github/Aylur/ags/service/mpris.js';
const { Box, EventBox, Icon, Scrollable, Label, Button, Revealer } = Widget; const { Box, EventBox, Icon, Scrollable, Label, Button, Revealer } = Widget;
import { MarginRevealer } from '../../lib/advancedrevealers.js';
import { AnimatedCircProg } from "../../lib/animatedcircularprogress.js"; import { AnimatedCircProg } from "../../lib/animatedcircularprogress.js";
import { MaterialIcon } from '../../lib/materialicon.js'; import { MaterialIcon } from '../../lib/materialicon.js';
import { showMusicControls } from '../../variables.js'; import { showMusicControls } from '../../variables.js';
@@ -343,9 +344,11 @@ const MusicControlsWidget = (player) => Box({
] ]
}) })
export default () => Widget.Revealer({ export default () => MarginRevealer({
transition: 'slide_down', transition: 'slide_down',
transitionDuration: 170, revealChild: false,
showClass: 'osd-show',
hideClass: 'osd-hide',
child: Box({ child: Box({
connections: [[Mpris, box => { connections: [[Mpris, box => {
let foundPlayer = false; let foundPlayer = false;
@@ -360,14 +363,19 @@ export default () => Widget.Revealer({
if (!foundPlayer) { if (!foundPlayer) {
box._player = null; box._player = null;
box.get_children().forEach(ch => ch.destroy()); const children = box.get_children();
for (let i = 0; i < children.length; i++) {
const child = children[i];
child.destroy();
}
return; return;
} }
}, 'notify::players']], }, 'notify::players']],
}), }),
connections: [ connections: [
[showMusicControls, (revealer) => { [showMusicControls, (revealer) => {
revealer.revealChild = showMusicControls.value; if(showMusicControls.value) revealer._show(revealer);
else revealer._hide(revealer);
}], }],
], ],
}) })
@@ -30,12 +30,10 @@ const PopupNotification = (notifObject) => Widget.Box({
const naiveNotifPopupList = Widget.Box({ const naiveNotifPopupList = Widget.Box({
vertical: true, vertical: true,
className: 'spacing-v-5', className: 'spacing-v-5',
connections: [ setup: (self) => self.hook(Notifications, (box) => {
[Notifications, (box) => { box.children = Notifications.popups.reverse()
box.children = Notifications.popups.reverse() .map(notifItem => PopupNotification(notifItem));
.map(notifItem => PopupNotification(notifItem)); }),
}],
],
}) })
const notifPopupList = Box({ const notifPopupList = Box({
@@ -72,11 +70,11 @@ const notifPopupList = Box({
// box.children = Array.from(box._map.values()).reverse(); // box.children = Array.from(box._map.values()).reverse();
}], }],
], ],
connections: [ setup: (self) => self
[Notifications, (box, id) => box._notify(box, id), 'notified'], .hook(Notifications, (box, id) => box._notify(box, id), 'notified')
[Notifications, (box, id) => box._dismiss(box, id), 'dismissed'], .hook(Notifications, (box, id) => box._dismiss(box, id), 'dismissed')
[Notifications, (box, id) => box._dismiss(box, id, true), 'closed'], .hook(Notifications, (box, id) => box._dismiss(box, id, true), 'closed')
], ,
}); });
export default () => notifPopupList; export default () => notifPopupList;
@@ -133,11 +133,11 @@ const keyboardWindow = Box({
], ],
}) })
], ],
connections: [[App, (box, name, visible) => { // Update on open setup: (self) => self.hook(App, (box, name, visible) => { // Update on open
if (name == 'osk' && visible) { if (name == 'osk' && visible) {
keyboardWindow.setCss(`margin-bottom: -0px;`); keyboardWindow.setCss(`margin-bottom: -0px;`);
} }
}],], }),
}); });
const gestureEvBox = EventBox({ child: keyboardWindow }) const gestureEvBox = EventBox({ child: keyboardWindow })
+1 -1
View File
@@ -3,7 +3,7 @@ import { SearchAndWindows } from "./overview.js";
export default () => Widget.Window({ export default () => Widget.Window({
name: 'overview', name: 'overview',
exclusivity: 'normal', exclusivity: 'ignore',
focusable: true, focusable: true,
popup: true, popup: true,
visible: false, visible: false,
+36 -9
View File
@@ -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'; import Hyprland from 'resource:///com/github/Aylur/ags/service/hyprland.js';
const { execAsync, exec } = Utils; const { execAsync, exec } = Utils;
import { setupCursorHover, setupCursorHoverGrab } from "../../lib/cursorhover.js"; 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 { execAndClose, expandTilde, hasUnterminatedBackslash, startsWithNumber, launchCustomCommand, ls } from './miscfunctions.js';
import { import {
CalculationResultButton, CustomCommandButton, DirectoryButton, CalculationResultButton, CustomCommandButton, DirectoryButton,
@@ -257,7 +257,7 @@ const workspace = index => {
child: fixed, child: fixed,
})], })],
}); });
widget.update = clients => { widget.update = (clients) => {
clients = clients.filter(({ workspace: { id } }) => id === index); clients = clients.filter(({ workspace: { id } }) => id === index);
// this is for my monitor layout // this is for my monitor layout
@@ -269,9 +269,22 @@ const workspace = index => {
return client; return client;
}); });
fixed.get_children().forEach(ch => ch.destroy()); const children = fixed.get_children();
for (let i = 0; i < children.length; i++) {
const child = children[i];
child.destroy();
}
fixed.put(WorkspaceNumber(index), 0, 0); fixed.put(WorkspaceNumber(index), 0, 0);
clients.forEach(c => c.mapped && fixed.put(client(c), c.at[0] * OVERVIEW_SCALE, c.at[1] * OVERVIEW_SCALE));
for (let i = 0; i < clients.length; i++) {
const c = clients[i];
if (c.mapped) {
fixed.put(client(c), c.at[0] * OVERVIEW_SCALE, c.at[1] * OVERVIEW_SCALE);
}
}
fixed.show_all(); fixed.show_all();
}; };
return widget; return widget;
@@ -290,7 +303,12 @@ const OverviewRow = ({ startWorkspace, workspaces, windowName = 'overview' }) =>
properties: [['update', box => { properties: [['update', box => {
execAsync('hyprctl -j clients').then(clients => { execAsync('hyprctl -j clients').then(clients => {
const json = JSON.parse(clients); const json = JSON.parse(clients);
box.get_children().forEach(ch => ch.update(json)); const children = box.get_children();
for (let i = 0; i < children.length; i++) {
const ch = children[i];
ch.update(json)
}
}).catch(print); }).catch(print);
}]], }]],
setup: (box) => box._update(box), setup: (box) => box._update(box),
@@ -312,7 +330,8 @@ const OverviewRow = ({ startWorkspace, workspaces, windowName = 'overview' }) =>
export const SearchAndWindows = () => { export const SearchAndWindows = () => {
var _appSearchResults = []; var _appSearchResults = [];
const clickOutsideToClose = Widget.EventBox({ const ClickToClose = ({ ...props }) => Widget.EventBox({
...props,
onPrimaryClick: () => App.closeWindow('overview'), onPrimaryClick: () => App.closeWindow('overview'),
onSecondaryClick: () => App.closeWindow('overview'), onSecondaryClick: () => App.closeWindow('overview'),
onMiddleClick: () => App.closeWindow('overview'), onMiddleClick: () => App.closeWindow('overview'),
@@ -375,7 +394,7 @@ export const SearchAndWindows = () => {
hpack: 'center', hpack: 'center',
onAccept: (self) => { // This is when you hit Enter onAccept: (self) => { // This is when you hit Enter
const text = self.text; const text = self.text;
if(text.length == 0) return; if (text.length == 0) return;
const isAction = text.startsWith('>'); const isAction = text.startsWith('>');
const isDir = (entry.text[0] == '/' || entry.text[0] == '~'); const isDir = (entry.text[0] == '/' || entry.text[0] == '~');
@@ -423,7 +442,11 @@ export const SearchAndWindows = () => {
['notify::text', (entry) => { // This is when you type ['notify::text', (entry) => { // This is when you type
const isAction = entry.text[0] == '>'; const isAction = entry.text[0] == '>';
const isDir = (entry.text[0] == '/' || entry.text[0] == '~'); const isDir = (entry.text[0] == '/' || entry.text[0] == '~');
resultsBox.get_children().forEach(ch => ch.destroy()); const children = resultsBox.get_children();
for (let i = 0; i < children.length; i++) {
const child = children[i];
child.destroy();
}
// check empty if so then dont do stuff // check empty if so then dont do stuff
if (entry.text == '') { if (entry.text == '') {
resultsRevealer.set_reveal_child(false); resultsRevealer.set_reveal_child(false);
@@ -485,7 +508,11 @@ export const SearchAndWindows = () => {
return Widget.Box({ return Widget.Box({
vertical: true, vertical: true,
children: [ children: [
clickOutsideToClose, ClickToClose({ // Top margin. Also works as a click-outside-to-close thing
child: Widget.Box({
className: 'bar-height',
})
}),
Widget.Box({ Widget.Box({
hpack: 'center', hpack: 'center',
children: [ children: [
+2 -2
View File
@@ -21,7 +21,7 @@ export const CornerBottomleft = () => Widget.Window({
name: 'cornerbl', name: 'cornerbl',
layer: 'top', layer: 'top',
anchor: ['bottom', 'left'], anchor: ['bottom', 'left'],
exclusivity: 'normal', exclusivity: 'ignore',
visible: true, visible: true,
child: RoundedCorner('bottomleft', { className: 'corner-black', }), child: RoundedCorner('bottomleft', { className: 'corner-black', }),
}); });
@@ -29,7 +29,7 @@ export const CornerBottomright = () => Widget.Window({
name: 'cornerbr', name: 'cornerbr',
layer: 'top', layer: 'top',
anchor: ['bottom', 'right'], anchor: ['bottom', 'right'],
exclusivity: 'normal', exclusivity: 'ignore',
visible: true, visible: true,
child: RoundedCorner('bottomright', { className: 'corner-black', }), child: RoundedCorner('bottomright', { className: 'corner-black', }),
}); });
+101 -57
View File
@@ -6,22 +6,20 @@ import ChatGPT from '../../../services/chatgpt.js';
import { MaterialIcon } from "../../../lib/materialicon.js"; import { MaterialIcon } from "../../../lib/materialicon.js";
import { setupCursorHover, setupCursorHoverInfo } from "../../../lib/cursorhover.js"; import { setupCursorHover, setupCursorHoverInfo } from "../../../lib/cursorhover.js";
import { SystemMessage, ChatMessage } from "./chatgpt_chatmessage.js"; import { SystemMessage, ChatMessage } from "./chatgpt_chatmessage.js";
import { ConfigToggle } from '../../../lib/configwidgets.js'; import { ConfigToggle, ConfigSegmentedSelection, ConfigGap } from '../../../lib/configwidgets.js';
import { markdownTest } from '../../../lib/md2pango.js'; import { markdownTest } from '../../../lib/md2pango.js';
import { MarginRevealer } from '../../../lib/advancedrevealers.js';
const chatGPTTabIcon = Icon({ export const chatGPTTabIcon = Box({
hpack: 'center', hpack: 'center',
className: 'sidebar-chat-welcome-logo', className: 'sidebar-chat-apiswitcher-icon',
icon: `${App.configDir}/assets/openai-logomark.svg`, homogeneous: true,
setup: (self) => Utils.timeout(1, () => { children: [
const styleContext = self.get_style_context(); MaterialIcon('forum', 'norm'),
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) * 116 / 180; // Why such a specific proportion? See https://openai.com/brand#logos
})
}); });
export const chatGPTInfo = Box({ const chatGPTInfo = Box({
vertical: true, vertical: true,
className: 'spacing-v-15', className: 'spacing-v-15',
children: [ children: [
@@ -63,41 +61,62 @@ export const chatGPTInfo = Box({
] ]
}) })
export const chatGPTSettings = Revealer({ export const chatGPTSettings = MarginRevealer({
transition: 'slide_down', transition: 'slide_down',
transitionDuration: 150,
revealChild: true, revealChild: true,
connections: [ connections: [
[ChatGPT, (self) => { [ChatGPT, (self) => Utils.timeout(200, () => {
self.revealChild = false; self._hide(self);
}, 'newMsg'], }), 'newMsg'],
[ChatGPT, (self) => { [ChatGPT, (self) => Utils.timeout(200, () => {
self.revealChild = true; self._show(self);
}, 'clear'], }), 'clear'],
], ],
child: Box({ child: Box({
vertical: true, vertical: true,
hpack: 'fill',
className: 'sidebar-chat-settings', className: 'sidebar-chat-settings',
children: [ children: [
ConfigToggle({ ConfigSegmentedSelection({
icon: 'cycle', hpack: 'center',
name: 'Cycle models', icon: 'casino',
desc: 'Helps avoid exceeding the API rate of 3 messages per minute.\nTurn this on if you message rapidly.', name: 'Randomness',
initValue: ChatGPT.cycleModels, desc: 'ChatGPT\'s temperature value.\n Precise = 0\n Balanced = 0.5\n Creative = 1',
onChange: (self, newValue) => { options: [
ChatGPT.cycleModels = newValue; { value: 0.00, name: 'Precise', },
}, { value: 0.50, name: 'Balanced', },
}), { value: 1.00, name: 'Creative', },
ConfigToggle({ ],
icon: 'description', initIndex: 1,
name: 'Assistant prompt', onChange: (value, name) => {
desc: 'Tells ChatGPT\n 1. It\'s a sidebar assistant on Linux\n 2. Be short and concise\n 3. Use markdown features extensively\nLeave this off for a vanilla ChatGPT experience.', ChatGPT.temperature = value;
initValue: ChatGPT.assistantPrompt,
onChange: (self, newValue) => {
ChatGPT.assistantPrompt = newValue;
}, },
}), }),
ConfigGap({ vertical: true, size: 10 }), // Note: size can only be 5, 10, or 15
Box({
vertical: true,
hpack: 'fill',
className: 'sidebar-chat-settings-toggles',
children: [
ConfigToggle({
icon: 'cycle',
name: 'Cycle models',
desc: 'Helps avoid exceeding the API rate of 3 messages per minute.\nTurn this on if you message rapidly.',
initValue: ChatGPT.cycleModels,
onChange: (self, newValue) => {
ChatGPT.cycleModels = newValue;
},
}),
ConfigToggle({
icon: 'description',
name: 'Assistant prompt',
desc: 'Tells ChatGPT\n 1. It\'s a sidebar assistant on Linux\n 2. Be short and concise\n 3. Use markdown features extensively\nLeave this off for a vanilla ChatGPT experience.',
initValue: ChatGPT.assistantPrompt,
onChange: (self, newValue) => {
ChatGPT.assistantPrompt = newValue;
},
}),
]
})
] ]
}) })
}); });
@@ -136,7 +155,7 @@ export const chatGPTWelcome = Box({
children: [ children: [
chatGPTInfo, chatGPTInfo,
openaiApiKeyInstructions, openaiApiKeyInstructions,
chatGPTSettings, chatGPTSettings, ``
] ]
}) })
}); });
@@ -148,27 +167,37 @@ export const chatContent = Box({
[ChatGPT, (box, id) => { [ChatGPT, (box, id) => {
const message = ChatGPT.messages[id]; const message = ChatGPT.messages[id];
if (!message) return; if (!message) return;
box.add(ChatMessage(message)) box.add(ChatMessage(message, chatGPTView))
}, 'newMsg'], }, 'newMsg'],
[ChatGPT, (box) => {
box.children = [chatGPTWelcome];
}, 'clear'],
[ChatGPT, (box) => {
box.children = [chatGPTWelcome];
}, 'initialized'],
] ]
}); });
const clearChat = () => {
ChatGPT.clear();
const children = chatContent.get_children();
for (let i = 0; i < children.length; i++) {
const child = children[i];
child.destroy();
}
}
export const chatGPTView = Scrollable({ export const chatGPTView = Scrollable({
className: 'sidebar-chat-viewport', className: 'sidebar-chat-viewport',
vexpand: true, vexpand: true,
child: chatContent, child: Box({
vertical: true,
children: [
chatGPTWelcome,
chatContent,
]
}),
setup: (scrolledWindow) => { setup: (scrolledWindow) => {
// Show scrollbar
scrolledWindow.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC); scrolledWindow.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC);
const vScrollbar = scrolledWindow.get_vscrollbar(); const vScrollbar = scrolledWindow.get_vscrollbar();
vScrollbar.get_style_context().add_class('sidebar-scrollbar'); vScrollbar.get_style_context().add_class('sidebar-scrollbar');
// Avoid click-to-scroll-widget-to-view behavior
Utils.timeout(1, () => { // Fix click-to-scroll-widget-to-view behavior Utils.timeout(1, () => {
const viewport = scrolledWindow.child; const viewport = scrolledWindow.child;
viewport.set_focus_vadjustment(new Gtk.Adjustment(undefined)); viewport.set_focus_vadjustment(new Gtk.Adjustment(undefined));
}) })
@@ -183,7 +212,8 @@ export const chatGPTCommands = Box({
className: 'sidebar-chat-chip sidebar-chat-chip-action txt txt-small', className: 'sidebar-chat-chip sidebar-chat-chip-action txt txt-small',
onClicked: () => chatContent.add(SystemMessage( onClicked: () => chatContent.add(SystemMessage(
`Key stored in:\n\`${ChatGPT.keyPath}\`\nTo update this key, type \`/key YOUR_API_KEY\``, `Key stored in:\n\`${ChatGPT.keyPath}\`\nTo update this key, type \`/key YOUR_API_KEY\``,
'/key')), '/key',
chatGPTView)),
setup: setupCursorHover, setup: setupCursorHover,
label: '/key', label: '/key',
}), }),
@@ -191,14 +221,15 @@ export const chatGPTCommands = Box({
className: 'sidebar-chat-chip sidebar-chat-chip-action txt txt-small', className: 'sidebar-chat-chip sidebar-chat-chip-action txt txt-small',
onClicked: () => chatContent.add(SystemMessage( onClicked: () => chatContent.add(SystemMessage(
`Currently using \`${ChatGPT.modelName}\``, `Currently using \`${ChatGPT.modelName}\``,
'/model' '/model',
chatGPTView
)), )),
setup: setupCursorHover, setup: setupCursorHover,
label: '/model', label: '/model',
}), }),
Button({ Button({
className: 'sidebar-chat-chip sidebar-chat-chip-action txt txt-small', className: 'sidebar-chat-chip sidebar-chat-chip-action txt txt-small',
onClicked: () => ChatGPT.clear(), onClicked: () => clearChat(),
setup: setupCursorHover, setup: setupCursorHover,
label: '/clear', label: '/clear',
}), }),
@@ -210,26 +241,39 @@ export const chatGPTSendMessage = (text) => {
if (text.length == 0) return; if (text.length == 0) return;
if (ChatGPT.key.length == 0) { if (ChatGPT.key.length == 0) {
ChatGPT.key = text; ChatGPT.key = text;
chatContent.add(SystemMessage(`Key saved to\n\`${ChatGPT.keyPath}\``, 'API Key')); chatContent.add(SystemMessage(`Key saved to\n\`${ChatGPT.keyPath}\``, 'API Key', chatGPTView));
text = ''; text = '';
return; return;
} }
// Commands // Commands
if (text.startsWith('/')) { if (text.startsWith('/')) {
if (text.startsWith('/clear')) ChatGPT.clear(); if (text.startsWith('/clear')) clearChat();
else if (text.startsWith('/model')) chatContent.add(SystemMessage(`Currently using \`${ChatGPT.modelName}\``, '/model')) 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')) { else if (text.startsWith('/key')) {
const parts = text.split(' '); const parts = text.split(' ');
if (parts.length == 1) chatContent.add(SystemMessage(`Key stored in:\n\`${ChatGPT.keyPath}\`\nTo update this key, type \`/key YOUR_API_KEY\``, '/key')); if (parts.length == 1) chatContent.add(SystemMessage(
`Key stored in:\n\`${ChatGPT.keyPath}\`\nTo update this key, type \`/key YOUR_API_KEY\``,
'/key',
chatGPTView));
else { else {
ChatGPT.key = parts[1]; ChatGPT.key = parts[1];
chatContent.add(SystemMessage(`Updated API Key at\n\`${ChatGPT.keyPath}\``, '/key')); chatContent.add(SystemMessage(`Updated API Key at\n\`${ChatGPT.keyPath}\``, '/key', chatGPTView));
} }
} }
else if (text.startsWith('/test')) else if (text.startsWith('/test'))
chatContent.add(SystemMessage(markdownTest, `Markdown test`)); chatContent.add(SystemMessage(markdownTest, `Markdown test`, chatGPTView));
else else
chatContent.add(SystemMessage(`Invalid command.`, 'Error')) chatContent.add(SystemMessage(`Invalid command.`, 'Error', chatGPTView))
} }
else { else {
ChatGPT.send(text); ChatGPT.send(text);
@@ -9,7 +9,7 @@ import GtkSource from "gi://GtkSource?version=3.0";
const CUSTOM_SOURCEVIEW_SCHEME_PATH = `${App.configDir}/data/sourceviewtheme.xml`; const CUSTOM_SOURCEVIEW_SCHEME_PATH = `${App.configDir}/data/sourceviewtheme.xml`;
const CUSTOM_SCHEME_ID = 'custom'; const CUSTOM_SCHEME_ID = 'custom';
const USERNAME = GLib.get_user_name(); 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 const MESSAGE_SCROLL_DELAY = 13; // In milliseconds, the time before an updated message scrolls to bottom
/////////////////////// Custom source view colorscheme ///////////////////////// /////////////////////// Custom source view colorscheme /////////////////////////
@@ -92,10 +92,6 @@ const CodeBlock = (content = '', lang = 'txt') => {
}), }),
Button({ Button({
className: 'sidebar-chat-codeblock-topbar-btn', 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({ child: Box({
className: 'spacing-h-5', className: 'spacing-h-5',
children: [ children: [
@@ -104,8 +100,13 @@ const CodeBlock = (content = '', lang = 'txt') => {
label: 'Copy', 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 // Source view
@@ -148,7 +149,11 @@ const MessageContent = (content) => {
properties: [ properties: [
['fullUpdate', (self, content, useCursor = false) => { ['fullUpdate', (self, content, useCursor = false) => {
// Clear and add first text widget // Clear and add first text widget
contentBox.get_children().forEach(ch => ch.destroy()); const children = contentBox.get_children();
for (let i = 0; i < children.length; i++) {
const child = children[i];
child.destroy();
}
contentBox.add(TextBlock()) contentBox.add(TextBlock())
// Loop lines. Put normal text in markdown parser // Loop lines. Put normal text in markdown parser
// and put code into code highlighter (TODO) // and put code into code highlighter (TODO)
@@ -214,7 +219,7 @@ const MessageContent = (content) => {
return contentBox; return contentBox;
} }
export const ChatMessage = (message) => { export const ChatMessage = (message, scrolledWindow) => {
const messageContentBox = MessageContent(message.content); const messageContentBox = MessageContent(message.content);
const thisMessage = Box({ const thisMessage = Box({
className: 'sidebar-chat-message', className: 'sidebar-chat-message',
@@ -243,7 +248,7 @@ export const ChatMessage = (message) => {
[message, (self) => { // Message update [message, (self) => { // Message update
messageContentBox._fullUpdate(messageContentBox, message.content, message.role != 'user'); messageContentBox._fullUpdate(messageContentBox, message.content, message.role != 'user');
Utils.timeout(MESSAGE_SCROLL_DELAY, () => { Utils.timeout(MESSAGE_SCROLL_DELAY, () => {
const scrolledWindow = thisMessage.get_parent().get_parent(); if (!scrolledWindow) return;
var adjustment = scrolledWindow.get_vadjustment(); var adjustment = scrolledWindow.get_vadjustment();
adjustment.set_value(adjustment.get_upper() - adjustment.get_page_size()); adjustment.set_value(adjustment.get_upper() - adjustment.get_page_size());
}); });
@@ -258,7 +263,7 @@ export const ChatMessage = (message) => {
return thisMessage; return thisMessage;
} }
export const SystemMessage = (content, commandName) => { export const SystemMessage = (content, commandName, scrolledWindow) => {
const messageContentBox = MessageContent(content); const messageContentBox = MessageContent(content);
const thisMessage = Box({ const thisMessage = Box({
className: 'sidebar-chat-message', className: 'sidebar-chat-message',
@@ -282,7 +287,7 @@ export const SystemMessage = (content, commandName) => {
}) })
], ],
setup: (self) => Utils.timeout(MESSAGE_SCROLL_DELAY, () => { setup: (self) => Utils.timeout(MESSAGE_SCROLL_DELAY, () => {
const scrolledWindow = thisMessage.get_parent().get_parent(); if (!scrolledWindow) return;
var adjustment = scrolledWindow.get_vadjustment(); var adjustment = scrolledWindow.get_vadjustment();
adjustment.set_value(adjustment.get_upper() - adjustment.get_page_size()); adjustment.set_value(adjustment.get_upper() - adjustment.get_page_size());
}) })
@@ -0,0 +1,72 @@
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';
export const waifuTabIcon = Box({
hpack: 'center',
className: 'sidebar-chat-apiswitcher-icon',
homogeneous: true,
children: [
MaterialIcon('photo_library', 'norm'),
]
});
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) => {
// 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 }),
Button({
className: 'sidebar-chat-chip sidebar-chat-chip-action txt txt-small',
onClicked: () => {
// command do something
},
setup: setupCursorHover,
label: '/call',
}),
]
});
export const waifuCallAPI = (text) => {
// Do something on send
WaifuService.fetch(text);
}
+46 -14
View File
@@ -1,10 +1,12 @@
const { Gtk, Gdk } = imports.gi;
import { App, Utils, Widget } from '../../imports.js'; import { App, Utils, Widget } from '../../imports.js';
const { Box, Button, Entry, EventBox, Icon, Label, Revealer, Scrollable, Stack } = Widget; const { Box, Button, Entry, EventBox, Icon, Label, Revealer, Scrollable, Stack } = Widget;
const { execAsync, exec } = Utils; const { execAsync, exec } = Utils;
import { setupCursorHover, setupCursorHoverInfo } from "../../lib/cursorhover.js"; import { setupCursorHover, setupCursorHoverInfo } from "../../lib/cursorhover.js";
// APIs // APIs
import ChatGPT from '../../services/chatgpt.js'; import ChatGPT from '../../services/chatgpt.js';
import { chatGPTView, chatGPTCommands, chatGPTSendMessage } from './apis/chatgpt.js'; import { chatGPTView, chatGPTCommands, chatGPTSendMessage, chatGPTTabIcon } from './apis/chatgpt.js';
import { waifuView, waifuCommands, waifuCallAPI, waifuTabIcon } from './apis/waifu.js';
const APIS = [ const APIS = [
{ {
@@ -12,20 +14,20 @@ const APIS = [
sendCommand: chatGPTSendMessage, sendCommand: chatGPTSendMessage,
contentWidget: chatGPTView, contentWidget: chatGPTView,
commandBar: chatGPTCommands, commandBar: chatGPTCommands,
tabIcon: Box({}), tabIcon: chatGPTTabIcon,
} placeholderText: 'Message ChatGPT',
},
{
name: 'Waifus',
sendCommand: waifuCallAPI,
contentWidget: waifuView,
commandBar: waifuCommands,
tabIcon: waifuTabIcon,
placeholderText: 'Enter tags',
},
]; ];
let currentApiId = 0; let currentApiId = 0;
APIS[currentApiId].tabIcon.toggleClassName('sidebar-chat-apiswitcher-icon-enabled', true);
const apiSwitcher = Box({
vertical: true,
children: [
Box({
homogeneous: true,
children: APIS.map(api => api.tabIcon),
}),
]
})
export const chatEntry = Entry({ export const chatEntry = Entry({
className: 'sidebar-chat-entry', className: 'sidebar-chat-entry',
@@ -75,7 +77,37 @@ const apiCommandStack = Stack({
items: APIS.map(api => [api.name, api.commandBar]), items: APIS.map(api => [api.name, api.commandBar]),
}) })
function switchToTab(id) {
APIS[currentApiId].tabIcon.toggleClassName('sidebar-chat-apiswitcher-icon-enabled', false);
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({
homogeneous: true,
children: [
Box({
className: 'sidebar-chat-apiswitcher spacing-h-5',
hpack: 'center',
children: APIS.map((api, id) => Button({
child: api.tabIcon,
tooltipText: api.name,
setup: setupCursorHover,
onClicked: () => {
switchToTab(id);
}
})),
}),
]
})
export default Widget.Box({ export default Widget.Box({
properties: [
['nextTab', () => switchToTab(Math.min(currentApiId + 1, APIS.length - 1))],
['prevTab', () => switchToTab(Math.max(0, currentApiId-1))],
],
vertical: true, vertical: true,
className: 'spacing-v-10', className: 'spacing-v-10',
homogeneous: false, homogeneous: false,
@@ -84,5 +116,5 @@ export default Widget.Box({
apiContentStack, apiContentStack,
apiCommandStack, apiCommandStack,
textboxArea, textboxArea,
] ],
}); });
+1
View File
@@ -5,6 +5,7 @@ export default () => PopupWindow({
focusable: true, focusable: true,
anchor: ['left', 'top', 'bottom'], anchor: ['left', 'top', 'bottom'],
name: 'sideleft', name: 'sideleft',
// exclusivity: 'exclusive',
showClassName: 'sideleft-show', showClassName: 'sideleft-show',
hideClassName: 'sideleft-hide', hideClassName: 'sideleft-hide',
child: SidebarLeft(), child: SidebarLeft(),
+3
View File
@@ -18,6 +18,9 @@ export const SidebarModule = ({
className: 'txt-small txt', className: 'txt-small txt',
label: `${name}`, label: `${name}`,
}), }),
Box({
hexpand: true,
}),
Label({ Label({
className: 'sidebar-module-btn-arrow', className: 'sidebar-module-btn-arrow',
}) })
@@ -7,6 +7,5 @@ import { SidebarModule } from './module.js';
export const QuickScripts = () => SidebarModule({ export const QuickScripts = () => SidebarModule({
name: 'Quick scripts', name: 'Quick scripts',
child: Box({ child: Box({
}) })
}) })
+146 -44
View File
@@ -7,77 +7,137 @@ import { setupCursorHover } from "../../lib/cursorhover.js";
import { NavigationIndicator } from "../../lib/navigationindicator.js"; import { NavigationIndicator } from "../../lib/navigationindicator.js";
import toolBox from './toolbox.js'; import toolBox from './toolbox.js';
import apiWidgets from './apiwidgets.js'; import apiWidgets from './apiwidgets.js';
import { chatEntry } from './apiwidgets.js'; import apiwidgets, { chatEntry } from './apiwidgets.js';
const SidebarTabButton = (stack, stackItem, navIndicator, navIndex, icon, label) => Widget.Button({ const contents = [
{
name: 'apis',
content: apiWidgets,
materialIcon: 'api',
friendlyName: 'APIs',
},
{
name: 'tools',
content: toolBox,
materialIcon: 'home_repair_service',
friendlyName: 'Tools',
},
]
let currentTabId = 0;
const contentStack = Stack({
vexpand: true,
transition: 'slide_left_right',
items: contents.map(item => [item.name, item.content]),
})
function switchToTab(id) {
const allTabs = navTabs.get_children();
const tabButton = allTabs[id];
allTabs[currentTabId].toggleClassName('sidebar-selector-tab-active', false);
allTabs[id].toggleClassName('sidebar-selector-tab-active', true);
contentStack.shown = contents[id].name;
if (tabButton) {
// Fancy highlighter line width
const buttonWidth = tabButton.get_allocated_width();
const highlightWidth = tabButton.get_children()[0].get_allocated_width();
navIndicator.css = `
font-size: ${id}px;
padding: 0px ${(buttonWidth - highlightWidth) / 2}px;
`;
}
currentTabId = id;
}
const SidebarTabButton = (navIndex) => Widget.Button({
// hexpand: true, // hexpand: true,
className: 'sidebar-selector-tab', className: 'sidebar-selector-tab',
onClicked: (self) => { onClicked: (self) => {
stack.shown = stackItem; switchToTab(navIndex);
// Add active class to self and remove for others
const allTabs = self.get_parent().get_children();
for (let i = 0; i < allTabs.length; i++) {
if (allTabs[i] != self) allTabs[i].toggleClassName('sidebar-selector-tab-active', false);
else self.toggleClassName('sidebar-selector-tab-active', true);
}
// Fancy highlighter line width
const buttonWidth = self.get_allocated_width();
const highlightWidth = self.get_children()[0].get_allocated_width();
navIndicator.css = `
font-size: ${navIndex}px;
padding: 0px ${(buttonWidth - highlightWidth) / 2}px;
`;
}, },
child: Box({ child: Box({
hpack: 'center', hpack: 'center',
className: 'spacing-h-5', className: 'spacing-h-5',
children: [ children: [
MaterialIcon(icon, 'larger'), MaterialIcon(contents[navIndex].materialIcon, 'larger'),
Label({ Label({
className: 'txt txt-smallie', className: 'txt txt-smallie',
label: label, label: `${contents[navIndex].friendlyName}`,
}) })
] ]
}), }),
setup: (button) => Utils.timeout(1, () => { setup: (button) => Utils.timeout(1, () => {
setupCursorHover(button); setupCursorHover(button);
button.toggleClassName('sidebar-selector-tab-active', defaultTab === stackItem); button.toggleClassName('sidebar-selector-tab-active', currentTabId == navIndex);
}), }),
}); });
const defaultTab = 'apis'; const navTabs = Box({
const contentStack = Stack({ homogeneous: true,
vexpand: true, children: contents.map((item, id) =>
transition: 'slide_left_right', SidebarTabButton(id, item.materialIcon, item.friendlyName)
items: [ ),
['apis', apiWidgets], });
['tools', toolBox],
],
})
const navIndicator = NavigationIndicator(2, false, { // The line thing const navIndicator = NavigationIndicator(2, false, { // The line thing
className: 'sidebar-selector-highlight', className: 'sidebar-selector-highlight',
css: 'font-size: 0px; padding: 0rem 4.773rem;', // Shushhhh css: 'font-size: 0px; padding: 0rem 4.160rem;', // Shushhhh
}) });
const navBar = Box({ const navBar = Box({
vertical: true, vertical: true,
hexpand: true,
children: [ children: [
Box({ navTabs,
homogeneous: true,
children: [
SidebarTabButton(contentStack, 'apis', navIndicator, 0, 'api', 'APIs'),
SidebarTabButton(contentStack, 'tools', navIndicator, 1, 'home_repair_service', 'Tools'),
]
}),
navIndicator, navIndicator,
] ]
});
const pinButton = Button({
properties: [
['enabled', false],
['toggle', (self) => {
self._enabled = !self._enabled;
self.toggleClassName('sidebar-pin-enabled', self._enabled);
const sideleftWindow = App.getWindow('sideleft');
const barWindow = App.getWindow('bar');
const cornerTopLeftWindow = App.getWindow('cornertl');
const sideleftContent = sideleftWindow.get_children()[0].get_children()[0].get_children()[1];
sideleftContent.toggleClassName('sidebar-pinned', self._enabled);
if (self._enabled) {
sideleftWindow.layer = 'bottom';
barWindow.layer = 'bottom';
cornerTopLeftWindow.layer = 'bottom';
sideleftWindow.exclusivity = 'exclusive';
}
else {
sideleftWindow.layer = 'top';
barWindow.layer = 'top';
cornerTopLeftWindow.layer = 'top';
sideleftWindow.exclusivity = 'normal';
}
}],
],
vpack: 'start',
className: 'sidebar-pin',
child: MaterialIcon('push_pin', 'larger'),
tooltipText: 'Pin sidebar',
onClicked: (self) => self._toggle(self),
// QoL: Focus Pin button on open. Hit keybind -> space/enter = toggle pin state
connections: [[App, (self, currentName, visible) => {
if (currentName === 'sideleft' && visible) {
self.grab_focus();
}
}]]
}) })
export default () => Box({ export default () => Box({
// vertical: true, // vertical: true,
vexpand: true, vexpand: true,
hexpand: true, hexpand: true,
css: 'min-width: 2px;',
children: [ children: [
EventBox({ EventBox({
onPrimaryClick: () => App.closeWindow('sideleft'), onPrimaryClick: () => App.closeWindow('sideleft'),
@@ -87,23 +147,65 @@ export default () => Box({
Box({ Box({
vertical: true, vertical: true,
vexpand: true, vexpand: true,
className: 'sidebar-left', className: 'sidebar-left spacing-v-10',
children: [ children: [
navBar, Box({
className: 'spacing-h-10',
children: [
navBar,
pinButton,
]
}),
contentStack, contentStack,
] ],
connections: [[App, (self, currentName, visible) => {
if (currentName === 'sideleft') {
self.toggleClassName('sidebar-pinned', pinButton._enabled && visible);
}
}]]
}), }),
], ],
connections: [ connections: [
['key-press-event', (widget, event) => { // Typing ['key-press-event', (widget, event) => { // Handle keybinds
if (event.get_keyval()[1] >= 32 && event.get_keyval()[1] <= 126 && if (event.get_state()[1] & Gdk.ModifierType.CONTROL_MASK) {
widget != chatEntry && event.get_keyval()[1] != Gdk.KEY_space) { // Pin sidebar
if (contentStack.shown == 'apis') { 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)
switchToTab(Math.min(currentTabId + 1), contents.length);
}
if (contentStack.shown == 'apis') { // If api tab is focused
// Automatically focus entry when typing
if ((
!(event.get_state()[1] & Gdk.ModifierType.CONTROL_MASK) &&
event.get_keyval()[1] >= 32 && event.get_keyval()[1] <= 126 &&
widget != chatEntry && event.get_keyval()[1] != Gdk.KEY_space)
||
((event.get_state()[1] & Gdk.ModifierType.CONTROL_MASK) &&
event.get_keyval()[1] === Gdk.KEY_v)
) {
chatEntry.grab_focus(); chatEntry.grab_focus();
chatEntry.set_text(chatEntry.text + String.fromCharCode(event.get_keyval()[1])); chatEntry.set_text(chatEntry.text + String.fromCharCode(event.get_keyval()[1]));
chatEntry.set_position(-1); chatEntry.set_position(-1);
} }
// Switch API type
else if (!(event.get_state()[1] & Gdk.ModifierType.CONTROL_MASK) &&
event.get_keyval()[1] === Gdk.KEY_Page_Down) {
const toSwitchTab = contentStack.get_visible_child();
toSwitchTab._nextTab();
}
else if (!(event.get_state()[1] & Gdk.ModifierType.CONTROL_MASK) &&
event.get_keyval()[1] === Gdk.KEY_Page_Up) {
const toSwitchTab = contentStack.get_visible_child();
toSwitchTab._prevTab();
}
} }
}], }],
], ],
}); });
+6 -4
View File
@@ -65,12 +65,14 @@ const CalendarWidget = () => {
} }
}); });
const addCalendarChildren = (box, calendarJson) => { const addCalendarChildren = (box, calendarJson) => {
const children = box.get_children();
for (let i = 0; i < children.length; i++) {
const child = children[i];
child.destroy();
}
box.children = calendarJson.map((row, i) => Widget.Box({ box.children = calendarJson.map((row, i) => Widget.Box({
// homogeneous: true,
className: 'spacing-h-5', className: 'spacing-h-5',
children: row.map((day, i) => children: row.map((day, i) => CalendarDay(day.day, day.today)),
CalendarDay(day.day, day.today)
)
})) }))
} }
function shiftCalendarXMonths(x) { function shiftCalendarXMonths(x) {
+21 -19
View File
@@ -29,17 +29,15 @@ export const ToggleIconWifi = (props = {}) => Widget.Button({
export const ToggleIconBluetooth = (props = {}) => Widget.Button({ export const ToggleIconBluetooth = (props = {}) => Widget.Button({
className: 'txt-small sidebar-iconbutton', className: 'txt-small sidebar-iconbutton',
tooltipText: 'Bluetooth | Right-click to configure', tooltipText: 'Bluetooth | Right-click to configure',
onClicked: () => { // Provided service doesn't work hmmm onClicked: () => {
const status = Bluetooth?.enabled; const status = Bluetooth?.enabled;
if (status) { if (status)
exec('rfkill block bluetooth'); exec('rfkill block bluetooth');
} else
else {
exec('rfkill unblock bluetooth'); exec('rfkill unblock bluetooth');
}
}, },
onSecondaryClickRelease: () => { onSecondaryClickRelease: () => {
execAsync(['bash', '-c', 'XDG_CURRENT_DESKTOP="gnome" gnome-control-center bluetooth', '&']); execAsync(['bash', '-c', 'blueberry &']);
}, },
child: BluetoothIndicator(), child: BluetoothIndicator(),
connections: [ connections: [
@@ -70,24 +68,28 @@ export const HyprToggleIcon = (icon, name, hyprlandConfigValue, props = {}) => W
...props, ...props,
}) })
export const ModuleNightLight = (props = {}) => Widget.Button({ export const ModuleNightLight = (props = {}) => Widget.Button({ // TODO: Make this work
properties: [
['enabled', false],
['yellowlight', undefined],
],
className: 'txt-small sidebar-iconbutton', className: 'txt-small sidebar-iconbutton',
tooltipText: 'Night Light', tooltipText: 'Night Light',
onClicked: (button) => { onClicked: (self) => {
const shaderPath = JSON.parse(exec('hyprctl -j getoption decoration:screen_shader')).str; self._enabled = !self._enabled;
if (shaderPath != "[[EMPTY]]" && shaderPath != "") { self.toggleClassName('sidebar-button-active', self._enabled);
execAsync(['bash', '-c', `hyprctl keyword decoration:screen_shader ''`]).catch(print); // if (self._enabled) Utils.execAsync(['bash', '-c', 'wlsunset & disown'])
button.toggleClassName('sidebar-button-active', false); if (self._enabled) Utils.execAsync('wlsunset')
} else Utils.execAsync('pkill wlsunset');
else {
execAsync(['bash', '-c', `hyprctl keyword decoration:screen_shader ~/.config/hypr/shaders/extradark.frag`]).catch(print);
button.toggleClassName('sidebar-button-active', true);
}
}, },
child: MaterialIcon('nightlight', 'norm'), child: MaterialIcon('nightlight', 'norm'),
setup: setupCursorHover, setup: (self) => {
setupCursorHover(self);
self._enabled = !!exec('pidof wlsunset');
self.toggleClassName('sidebar-button-active', self._enabled);
},
...props, ...props,
}) });
export const ModuleInvertColors = (props = {}) => Widget.Button({ export const ModuleInvertColors = (props = {}) => Widget.Button({
className: 'txt-small sidebar-iconbutton', className: 'txt-small sidebar-iconbutton',
+8 -7
View File
@@ -41,18 +41,18 @@ import { ModuleCalendar } from "./calendar.js";
const timeRow = Box({ const timeRow = Box({
className: 'spacing-h-5 sidebar-group-invisible-morehorizpad', className: 'spacing-h-5 sidebar-group-invisible-morehorizpad',
children: [ children: [
Widget.Label({ // Widget.Label({
className: 'txt-title txt', // className: 'txt-title txt',
connections: [[5000, label => { // connections: [[5000, label => {
label.label = GLib.DateTime.new_now_local().format("%H:%M"); // label.label = GLib.DateTime.new_now_local().format("%H:%M");
}]], // }]],
}), // }),
Widget.Label({ Widget.Label({
hpack: 'center', hpack: 'center',
className: 'txt-small txt', className: 'txt-small txt',
connections: [[5000, label => { connections: [[5000, label => {
execAsync(['bash', '-c', `uptime -p | sed -e 's/up //;s/ hours,/h/;s/ minutes/m/'`]).then(upTimeString => { execAsync(['bash', '-c', `uptime -p | sed -e 's/up //;s/ hours,/h/;s/ minutes/m/'`]).then(upTimeString => {
label.label = `• up: ${upTimeString}`; label.label = `System uptime: ${upTimeString}`;
}).catch(print); }).catch(print);
}]], }]],
}), }),
@@ -81,6 +81,7 @@ const togglesBox = Widget.Box({
export default () => Box({ export default () => Box({
vexpand: true, vexpand: true,
hexpand: true, hexpand: true,
css: 'min-width: 2px;',
children: [ children: [
EventBox({ EventBox({
onPrimaryClick: () => App.closeWindow('sideright'), onPrimaryClick: () => App.closeWindow('sideright'),