ags: sync

This commit is contained in:
end-4
2024-01-05 02:23:51 +07:00
parent 28ae26a5b5
commit 2f8bf36831
13 changed files with 347 additions and 301 deletions
+1 -1
View File
@@ -38,7 +38,7 @@ export const Keybinds = () => Widget.Box({
children: category.binds.map((keybinds, i) => Widget.Box({ // Binds
vertical: false,
children: keybinds.keys.map((key, i) => Widget.Label({ // Specific keys
className: `${key == 'OR' || key == '+' ? 'cheatsheet-key-notkey' : 'cheatsheet-key'} txt-small`,
className: `${['OR', '+'].includes(key) ? 'cheatsheet-key-notkey' : 'cheatsheet-key'} txt-small`,
label: key,
}))
}))
@@ -83,7 +83,7 @@ const keyboardItself = (kbJson) => {
children: row.map(key => {
return Button({
className: `osk-key osk-key-${key.shape}`,
hexpand: (key.shape == "space" || key.shape == "expand"),
hexpand: ["space", "expand"].includes(key.shape),
label: key.label,
setup: (button) => {
let pressed = false;
+96 -88
View File
@@ -40,8 +40,6 @@ const searchPromptTexts = [
'Type to search',
]
const overviewTick = Variable(false);
function truncateTitle(str) {
let lastDash = -1;
let found = -1; // 0: em dash, 1: en dash, 2: minus, 3: vertical bar, 4: middle dot
@@ -108,7 +106,6 @@ const ContextWorkspaceArray = ({ label, actionFunc, thisWorkspace }) => Widget.M
button.connect("activate", () => {
// execAsync([`${onClickBinary}`, `${thisWorkspace}`, `${i}`]).catch(print);
actionFunc(thisWorkspace, i);
overviewTick.value = !overviewTick.value;
});
submenu.append(button);
}
@@ -247,7 +244,6 @@ const workspace = index => {
setup: (eventbox) => {
eventbox.drag_dest_set(Gtk.DestDefaults.ALL, TARGET, Gdk.DragAction.COPY);
eventbox.connect('drag-data-received', (_w, _c, _x, _y, data) => {
overviewTick.value = !overviewTick.value;
Hyprland.sendMessage(`dispatch movetoworkspacesilent ${index},address:${data.get_text()}`)
});
},
@@ -298,6 +294,7 @@ const arr = (s, n) => {
const OverviewRow = ({ startWorkspace, workspaces, windowName = 'overview' }) => Widget.Box({
children: arr(startWorkspace, workspaces).map(workspace),
properties: [['update', box => {
if (!App.getWindow(windowName).visible) return;
execAsync('hyprctl -j clients').then(clients => {
const json = JSON.parse(clients);
const children = box.get_children();
@@ -308,19 +305,18 @@ const OverviewRow = ({ startWorkspace, workspaces, windowName = 'overview' }) =>
}).catch(print);
}]],
setup: (box) => box._update(box),
connections: [
// Update on change
[overviewTick, box => { if (!App.getWindow(windowName).visible) return; Utils.timeout(2, () => box._update(box)); }],
[Hyprland, box => { if (!App.getWindow(windowName).visible) return; box._update(box); }, 'client-added'],
[Hyprland, box => { if (!App.getWindow(windowName).visible) return; box._update(box); }, 'client-removed'],
// Update on show
[App, (box, name, visible) => { // Update on open
if (name == 'overview' && visible) {
box._update(box);
}
}],
],
setup: (box) => {
box
.hook(Hyprland, (box, name, data) => {
if (["changefloatingmode", "movewindow"].includes(name))
box._update(box);
}, 'event')
.hook(Hyprland, (box) => box._update(box), 'client-added')
.hook(Hyprland, (box) => box._update(box), 'client-removed')
.hook(App, (box, name, visible) => { // Update on open
if (name == 'overview' && visible) box._update(box);
})
},
});
@@ -393,7 +389,7 @@ export const SearchAndWindows = () => {
const text = self.text;
if (text.length == 0) return;
const isAction = text.startsWith('>');
const isDir = (entry.text[0] == '/' || entry.text[0] == '~');
const isDir = (['/', '~'].includes(entry.text[0]));
if (startsWithNumber(text)) { // Eval on typing is dangerous, this is a workaround
try {
@@ -434,72 +430,68 @@ export const SearchAndWindows = () => {
execAsync(['bash', '-c', `xdg-open 'https://www.google.com/search?q=${text} -site:quora.com' &`]).catch(print); // quora is useless
}
},
// Actually onChange but this is ta workaround for a bug
connections: [
['notify::text', (entry) => { // This is when you type
const isAction = entry.text[0] == '>';
const isDir = (entry.text[0] == '/' || entry.text[0] == '~');
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
if (entry.text == '') {
resultsRevealer.set_reveal_child(false);
overviewRevealer.set_reveal_child(true);
entryPromptRevealer.set_reveal_child(true);
entryIconRevealer.set_reveal_child(false);
entry.toggleClassName('overview-search-box-extended', false);
}
else {
const text = entry.text;
resultsRevealer.set_reveal_child(true);
overviewRevealer.set_reveal_child(false);
entryPromptRevealer.set_reveal_child(false);
entryIconRevealer.set_reveal_child(true);
entry.toggleClassName('overview-search-box-extended', true);
_appSearchResults = Applications.query(text);
onChange: (entry) => {
const isAction = entry.text[0] == '>';
const isDir = (['/', '~'].includes(entry.text[0]));
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
if (entry.text == '') {
resultsRevealer.set_reveal_child(false);
overviewRevealer.set_reveal_child(true);
entryPromptRevealer.set_reveal_child(true);
entryIconRevealer.set_reveal_child(false);
entry.toggleClassName('overview-search-box-extended', false);
return;
}
const text = entry.text;
resultsRevealer.set_reveal_child(true);
overviewRevealer.set_reveal_child(false);
entryPromptRevealer.set_reveal_child(false);
entryIconRevealer.set_reveal_child(true);
entry.toggleClassName('overview-search-box-extended', true);
_appSearchResults = Applications.query(text);
// Calculate
if (startsWithNumber(text)) { // Eval on typing is dangerous, this is a small workaround.
try {
const fullResult = eval(text);
resultsBox.add(CalculationResultButton({ result: fullResult, text: text }));
} catch (e) {
// console.log(e);
}
}
if (isDir) {
var contents = [];
contents = ls({ path: text, silent: true });
contents.forEach((item) => {
resultsBox.add(DirectoryButton(item));
})
}
if (isAction) { // Eval on typing is dangerous, this is a workaround.
resultsBox.add(CustomCommandButton({ text: entry.text }));
}
// Add application entries
let appsToAdd = MAX_RESULTS;
_appSearchResults.forEach(app => {
if (appsToAdd == 0) return;
resultsBox.add(DesktopEntryButton(app));
appsToAdd--;
});
// Fallbacks
// if the first word is an actual command
if (!isAction && !hasUnterminatedBackslash(text) && exec(`bash -c "command -v ${text.split(' ')[0]}"`) != '') {
resultsBox.add(ExecuteCommandButton({ command: entry.text, terminal: entry.text.startsWith('sudo') }));
}
// Add fallback: search
resultsBox.add(SearchButton({ text: entry.text }));
resultsBox.show_all();
// Calculate
if (startsWithNumber(text)) { // Eval on typing is dangerous, this is a small workaround.
try {
const fullResult = eval(text);
resultsBox.add(CalculationResultButton({ result: fullResult, text: text }));
} catch (e) {
// console.log(e);
}
}]
],
}
if (isDir) {
var contents = [];
contents = ls({ path: text, silent: true });
contents.forEach((item) => {
resultsBox.add(DirectoryButton(item));
})
}
if (isAction) { // Eval on typing is dangerous, this is a workaround.
resultsBox.add(CustomCommandButton({ text: entry.text }));
}
// Add application entries
let appsToAdd = MAX_RESULTS;
_appSearchResults.forEach(app => {
if (appsToAdd == 0) return;
resultsBox.add(DesktopEntryButton(app));
appsToAdd--;
});
// Fallbacks
// if the first word is an actual command
if (!isAction && !hasUnterminatedBackslash(text) && exec(`bash -c "command -v ${text.split(' ')[0]}"`) != '') {
resultsBox.add(ExecuteCommandButton({ command: entry.text, terminal: entry.text.startsWith('sudo') }));
}
// Add fallback: search
resultsBox.add(SearchButton({ text: entry.text }));
resultsBox.show_all();
},
});
return Widget.Box({
@@ -524,21 +516,37 @@ export const SearchAndWindows = () => {
overviewRevealer,
resultsRevealer,
],
connections: [
[App, (_b, name, visible) => {
setup: (self) => self
.hook(App, (_b, name, visible) => {
if (name == 'overview' && !visible) {
entryPromptRevealer.child.label = searchPromptTexts[Math.floor(Math.random() * searchPromptTexts.length)];
resultsBox.children = [];
entry.set_text('');
}
}],
['key-press-event', (widget, event) => { // Typing
})
.on('key-press-event', (widget, event) => { // Typing
if (event.get_keyval()[1] >= 32 && event.get_keyval()[1] <= 126 && widget != entry) {
Utils.timeout(1, () => entry.grab_focus());
entry.set_text(entry.text + String.fromCharCode(event.get_keyval()[1]));
entry.set_position(-1);
}
}],
],
})
,
// connections: [
// [App, (_b, name, visible) => {
// if (name == 'overview' && !visible) {
// entryPromptRevealer.child.label = searchPromptTexts[Math.floor(Math.random() * searchPromptTexts.length)];
// resultsBox.children = [];
// entry.set_text('');
// }
// }],
// ['key-press-event', (widget, event) => { // Typing
// if (event.get_keyval()[1] >= 32 && event.get_keyval()[1] <= 126 && widget != entry) {
// Utils.timeout(1, () => entry.grab_focus());
// entry.set_text(entry.text + String.fromCharCode(event.get_keyval()[1]));
// entry.set_position(-1);
// }
// }],
// ],
});
};
+105 -62
View File
@@ -6,56 +6,103 @@ const { GLib, Gtk } = imports.gi;
import { Service, Utils, Widget } from '../../imports.js';
import Notifications from 'resource:///com/github/Aylur/ags/service/notifications.js';
const { lookUpIcon, timeout } = Utils;
const { Box, Icon, Scrollable, Label, Button, Revealer } = Widget;
const { Box, Button, Icon, Label, Revealer, Scrollable, Stack } = Widget;
import { MaterialIcon } from "../../lib/materialicon.js";
import { setupCursorHover } from "../../lib/cursorhover.js";
import { ConfigToggle, ConfigSegmentedSelection, ConfigGap } from '../../lib/configwidgets.js';
import Notification from "../../lib/notification.js";
const NotificationList = Box({
vertical: true,
vpack: 'start',
className: 'spacing-v-5-revealer',
connections: [
[Notifications, (box, id) => {
if (box.children.length == 0) {
Notifications.notifications
.forEach(n => {
box.pack_end(Notification({
notifObject: n,
isPopup: false,
}), false, false, 0)
});
box.show_all();
}
else if (id) {
export default (props) => {
const dndToggle = ConfigToggle({
hpack: 'center',
icon: 'notifications_paused',
name: 'Do not disturb',
desc: "Don't pop up notifications",
initValue: Notifications.dnd,
onChange: (self, newValue) => {
Notifications.dnd = newValue;
silenceButton.toggleClassName('notif-listaction-btn-enabled', Notifications.dnd);
},
});
const notifEmptyContent = Box({
homogeneous: true,
children: [Box({
vertical: true,
vpack: 'center',
className: 'txt spacing-v-10',
children: [
Box({
vertical: true,
className: 'spacing-v-5',
children: [
MaterialIcon('notifications_active', 'badonkers'),
Label({ label: 'No notifications', className: 'txt-small' }),
]
}),
dndToggle,
]
})]
});
const notificationList = Box({
vertical: true,
vpack: 'start',
className: 'spacing-v-5-revealer',
connections: [
[Notifications, (box, id) => {
if (box.get_children().length == 0) { // On init there's no notif, or 1st notif
Notifications.notifications
.forEach(n => {
box.pack_end(Notification({
notifObject: n,
isPopup: false,
}), false, false, 0)
});
box.show_all();
return;
}
// 2nd or later notif
const notif = Notifications.getNotification(id);
const NewNotif = Notification({
notifObject: notif,
isPopup: false,
});
if (NewNotif) {
box.pack_end(NewNotif, false, false, 0);
box.show_all();
}
}
}, 'notified'],
[Notifications, (box, id) => {
if (!id) return;
for (const ch of box.children) {
if (ch._id === id) {
ch._destroyWithAnims();
}, 'notified'],
[Notifications, (box, id) => {
if (!id) return;
for (const ch of box.children) {
if (ch._id === id) {
ch._destroyWithAnims();
}
}
}
}, 'closed'],
[Notifications, box => box.visible = Notifications.notifications.length > 0],
],
});
export default (props) => {
}, 'closed'],
],
});
const ListActionButton = (icon, name, action) => Button({
className: 'notif-listaction-btn',
onClicked: action,
child: Box({
className: 'spacing-h-5',
children: [
MaterialIcon(icon, 'norm'),
Label({
className: 'txt-small',
label: name,
})
]
}),
setup: setupCursorHover,
});
const silenceButton = ListActionButton('notifications_paused', 'Silence', (self) => {
Notifications.dnd = !Notifications.dnd;
dndToggle._toggle(Notifications.dnd)
self.toggleClassName('notif-listaction-btn-enabled', Notifications.dnd);
});
const clearButton = ListActionButton('clear_all', 'Clear', () => Notifications.clear());
const listTitle = Revealer({
revealChild: false,
connections: [[Notifications, (revealer) => {
@@ -63,7 +110,7 @@ export default (props) => {
}]],
child: Box({
vpack: 'start',
className: 'sidebar-group-invisible txt',
className: 'sidebar-group-invisible txt spacing-h-5',
children: [
Label({
hexpand: true,
@@ -71,40 +118,36 @@ export default (props) => {
className: 'txt-title-small',
label: 'Notifications',
}),
Button({
className: 'notif-closeall-btn',
onClicked: () => {
Notifications.clear();
},
child: Box({
className: 'spacing-h-5',
children: [
MaterialIcon('clear_all', 'norm'),
Label({
className: 'txt-small',
label: 'Clear',
})
]
}),
setup: button => {
setupCursorHover(button);
},
})
silenceButton,
clearButton,
]
})
});
const listContents = Scrollable({
const notifList = Scrollable({
hexpand: true,
hscroll: 'never',
vscroll: 'automatic',
child: Box({
vexpand: true,
children: [NotificationList],
})
// homogeneous: true,
children: [notificationList],
}),
setup: (self) => {
const vScrollbar = self.get_vscrollbar();
vScrollbar.get_style_context().add_class('sidebar-scrollbar');
}
});
const listContents = Stack({
transition: 'crossfade',
transitionDuration: 150,
items: [
['empty', notifEmptyContent],
['list', notifList]
],
setup: (self) => self
.hook(Notifications, (self) => self.shown = (Notifications.notifications.length > 0 ? 'list' : 'empty'))
,
});
listContents.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC);
const vScrollbar = listContents.get_vscrollbar();
vScrollbar.get_style_context().add_class('sidebar-scrollbar');
return Box({
...props,
className: 'sidebar-group-invisible spacing-v-5',
@@ -27,7 +27,7 @@ export const ToggleIconWifi = (props = {}) => Widget.Button({
child: NetworkIndicator(),
connections: [
[Network, button => {
button.toggleClassName('sidebar-button-active', Network.wifi?.internet == 'connected' || Network.wired?.internet == 'connected')
button.toggleClassName('sidebar-button-active', [Network.wifi?.internet, Network.wired?.internet].includes('connected'))
}],
[Network, button => {
button.tooltipText = (`${Network.wifi?.ssid} | Right-click to configure` || 'Unknown');