mirror of
https://github.com/xsghetti/HyprCrux.git
synced 2025-07-03 13:50:38 -04:00
updates
This commit is contained in:
parent
1f8cb3c145
commit
610604e80f
253 changed files with 27055 additions and 44 deletions
144
.config/ags/modules/sideright/centermodules/bluetooth.js
Normal file
144
.config/ags/modules/sideright/centermodules/bluetooth.js
Normal file
|
@ -0,0 +1,144 @@
|
|||
// This file is for the notification list on the sidebar
|
||||
// For the popup notifications, see onscreendisplay.js
|
||||
// The actual widget for each single notification is in ags/modules/.commonwidgets/notification.js
|
||||
import Widget from 'resource:///com/github/Aylur/ags/widget.js';
|
||||
import Bluetooth from 'resource:///com/github/Aylur/ags/service/bluetooth.js';
|
||||
import * as Utils from 'resource:///com/github/Aylur/ags/utils.js';
|
||||
const { Box, Button, Icon, Label, Scrollable, Slider, Stack } = Widget;
|
||||
const { execAsync, exec } = Utils;
|
||||
import { MaterialIcon } from '../../.commonwidgets/materialicon.js';
|
||||
import { setupCursorHover } from '../../.widgetutils/cursorhover.js';
|
||||
import { ConfigToggle } from '../../.commonwidgets/configwidgets.js';
|
||||
|
||||
// can't connect: sync_problem
|
||||
|
||||
const USE_SYMBOLIC_ICONS = true;
|
||||
|
||||
const BluetoothDevice = (device) => {
|
||||
// console.log(device);
|
||||
const deviceIcon = Icon({
|
||||
className: 'sidebar-bluetooth-appicon',
|
||||
vpack: 'center',
|
||||
tooltipText: device.name,
|
||||
setup: (self) => self.hook(device, (self) => {
|
||||
self.icon = `${device.iconName}${USE_SYMBOLIC_ICONS ? '-symbolic' : ''}`;
|
||||
}),
|
||||
});
|
||||
const deviceStatus = Box({
|
||||
hexpand: true,
|
||||
vpack: 'center',
|
||||
vertical: true,
|
||||
children: [
|
||||
Label({
|
||||
xalign: 0,
|
||||
maxWidthChars: 10,
|
||||
truncate: 'end',
|
||||
label: device.name,
|
||||
className: 'txt-small',
|
||||
setup: (self) => self.hook(device, (self) => {
|
||||
self.label = device.name;
|
||||
}),
|
||||
}),
|
||||
Label({
|
||||
xalign: 0,
|
||||
maxWidthChars: 10,
|
||||
truncate: 'end',
|
||||
label: device.connected ? 'Connected' : (device.paired ? 'Paired' : ''),
|
||||
className: 'txt-subtext',
|
||||
setup: (self) => self.hook(device, (self) => {
|
||||
self.label = device.connected ? 'Connected' : (device.paired ? 'Paired' : '');
|
||||
}),
|
||||
}),
|
||||
]
|
||||
});
|
||||
const deviceConnectButton = ConfigToggle({
|
||||
vpack: 'center',
|
||||
expandWidget: false,
|
||||
desc: 'Toggle connection',
|
||||
initValue: device.connected,
|
||||
onChange: (self, newValue) => {
|
||||
device.setConnection(newValue);
|
||||
},
|
||||
extraSetup: (self) => self.hook(device, (self) => {
|
||||
Utils.timeout(200, () => self.enabled.value = device.connected);
|
||||
}),
|
||||
})
|
||||
const deviceRemoveButton = Button({
|
||||
vpack: 'center',
|
||||
className: 'sidebar-bluetooth-device-remove',
|
||||
child: MaterialIcon('delete', 'norm'),
|
||||
tooltipText: 'Remove device',
|
||||
setup: setupCursorHover,
|
||||
onClicked: () => execAsync(['bluetoothctl', 'remove', device.address]).catch(print),
|
||||
});
|
||||
return Box({
|
||||
className: 'sidebar-bluetooth-device spacing-h-10',
|
||||
children: [
|
||||
deviceIcon,
|
||||
deviceStatus,
|
||||
Box({
|
||||
className: 'spacing-h-5',
|
||||
children: [
|
||||
deviceConnectButton,
|
||||
deviceRemoveButton,
|
||||
]
|
||||
})
|
||||
]
|
||||
})
|
||||
}
|
||||
|
||||
export default (props) => {
|
||||
const emptyContent = Box({
|
||||
homogeneous: true,
|
||||
children: [Box({
|
||||
vertical: true,
|
||||
vpack: 'center',
|
||||
className: 'txt spacing-v-10',
|
||||
children: [
|
||||
Box({
|
||||
vertical: true,
|
||||
className: 'spacing-v-5 txt-subtext',
|
||||
children: [
|
||||
MaterialIcon('bluetooth_disabled', 'gigantic'),
|
||||
Label({ label: 'No Bluetooth devices', className: 'txt-small' }),
|
||||
]
|
||||
}),
|
||||
]
|
||||
})]
|
||||
});
|
||||
const deviceList = Scrollable({
|
||||
vexpand: true,
|
||||
child: Box({
|
||||
attribute: {
|
||||
'updateDevices': (self) => {
|
||||
const devices = Bluetooth.devices;
|
||||
self.children = devices.map(d => BluetoothDevice(d));
|
||||
},
|
||||
},
|
||||
vertical: true,
|
||||
className: 'spacing-v-5',
|
||||
setup: (self) => self
|
||||
.hook(Bluetooth, self.attribute.updateDevices, 'device-added')
|
||||
.hook(Bluetooth, self.attribute.updateDevices, 'device-removed')
|
||||
,
|
||||
})
|
||||
});
|
||||
const mainContent = Stack({
|
||||
children: {
|
||||
'empty': emptyContent,
|
||||
'list': deviceList,
|
||||
},
|
||||
setup: (self) => self.hook(Bluetooth, (self) => {
|
||||
self.shown = (Bluetooth.devices.length > 0 ? 'list' : 'empty')
|
||||
}),
|
||||
})
|
||||
return Box({
|
||||
...props,
|
||||
className: 'spacing-v-5',
|
||||
vertical: true,
|
||||
children: [
|
||||
mainContent,
|
||||
// status,
|
||||
]
|
||||
});
|
||||
}
|
175
.config/ags/modules/sideright/centermodules/notificationlist.js
Normal file
175
.config/ags/modules/sideright/centermodules/notificationlist.js
Normal file
|
@ -0,0 +1,175 @@
|
|||
// This file is for the notification list on the sidebar
|
||||
// For the popup notifications, see onscreendisplay.js
|
||||
// The actual widget for each single notification is in ags/modules/.commonwidgets/notification.js
|
||||
import Widget from 'resource:///com/github/Aylur/ags/widget.js';
|
||||
import Notifications from 'resource:///com/github/Aylur/ags/service/notifications.js';
|
||||
const { Box, Button, Label, Revealer, Scrollable, Stack } = Widget;
|
||||
import { MaterialIcon } from '../../.commonwidgets/materialicon.js';
|
||||
import { setupCursorHover } from '../../.widgetutils/cursorhover.js';
|
||||
import Notification from '../../.commonwidgets/notification.js';
|
||||
import { ConfigToggle } from '../../.commonwidgets/configwidgets.js';
|
||||
|
||||
export default (props) => {
|
||||
const notifEmptyContent = Box({
|
||||
homogeneous: true,
|
||||
children: [Box({
|
||||
vertical: true,
|
||||
vpack: 'center',
|
||||
className: 'txt spacing-v-10',
|
||||
children: [
|
||||
Box({
|
||||
vertical: true,
|
||||
className: 'spacing-v-5 txt-subtext',
|
||||
children: [
|
||||
MaterialIcon('notifications_active', 'gigantic'),
|
||||
Label({ label: 'No notifications', className: 'txt-small' }),
|
||||
]
|
||||
}),
|
||||
]
|
||||
})]
|
||||
});
|
||||
const notificationList = Box({
|
||||
vertical: true,
|
||||
vpack: 'start',
|
||||
className: 'spacing-v-5-revealer',
|
||||
setup: (self) => self
|
||||
.hook(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')
|
||||
.hook(Notifications, (box, id) => {
|
||||
if (!id) return;
|
||||
for (const ch of box.children) {
|
||||
if (ch._id === id) {
|
||||
ch.attribute.destroyWithAnims();
|
||||
}
|
||||
}
|
||||
}, '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;
|
||||
self.toggleClassName('notif-listaction-btn-enabled', Notifications.dnd);
|
||||
});
|
||||
// const silenceToggle = ConfigToggle({
|
||||
// expandWidget: false,
|
||||
// icon: 'do_not_disturb_on',
|
||||
// name: 'Do Not Disturb',
|
||||
// initValue: false,
|
||||
// onChange: (self, newValue) => {
|
||||
// Notifications.dnd = newValue;
|
||||
// },
|
||||
// })
|
||||
const clearButton = Revealer({
|
||||
transition: 'slide_right',
|
||||
transitionDuration: userOptions.animations.durationSmall,
|
||||
setup: (self) => self.hook(Notifications, (self) => {
|
||||
self.revealChild = Notifications.notifications.length > 0;
|
||||
}),
|
||||
child: ListActionButton('clear_all', 'Clear', () => {
|
||||
Notifications.clear();
|
||||
const kids = notificationList.get_children();
|
||||
for (let i = 0; i < kids.length; i++) {
|
||||
const kid = kids[i];
|
||||
Utils.timeout(userOptions.animations.choreographyDelay * i, () => kid.attribute.destroyWithAnims());
|
||||
}
|
||||
})
|
||||
})
|
||||
const notifCount = Label({
|
||||
attribute: {
|
||||
updateCount: (self) => {
|
||||
const count = Notifications.notifications.length;
|
||||
if (count > 0) self.label = `${count} notifications`;
|
||||
else self.label = '';
|
||||
},
|
||||
},
|
||||
hexpand: true,
|
||||
xalign: 0,
|
||||
className: 'txt-small margin-left-10',
|
||||
label: `${Notifications.notifications.length}`,
|
||||
setup: (self) => self
|
||||
.hook(Notifications, (box, id) => self.attribute.updateCount(self), 'notified')
|
||||
.hook(Notifications, (box, id) => self.attribute.updateCount(self), 'dismissed')
|
||||
.hook(Notifications, (box, id) => self.attribute.updateCount(self), 'closed')
|
||||
,
|
||||
});
|
||||
const listTitle = Box({
|
||||
vpack: 'start',
|
||||
className: 'txt spacing-h-5',
|
||||
children: [
|
||||
notifCount,
|
||||
silenceButton,
|
||||
// silenceToggle,
|
||||
// Box({ hexpand: true }),
|
||||
clearButton,
|
||||
]
|
||||
});
|
||||
const notifList = Scrollable({
|
||||
hexpand: true,
|
||||
hscroll: 'never',
|
||||
vscroll: 'automatic',
|
||||
child: Box({
|
||||
vexpand: true,
|
||||
// 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: userOptions.animations.durationLarge,
|
||||
children: {
|
||||
'empty': notifEmptyContent,
|
||||
'list': notifList,
|
||||
},
|
||||
setup: (self) => self.hook(Notifications, (self) => {
|
||||
self.shown = (Notifications.notifications.length > 0 ? 'list' : 'empty')
|
||||
}),
|
||||
});
|
||||
return Box({
|
||||
...props,
|
||||
className: 'spacing-v-5',
|
||||
vertical: true,
|
||||
children: [
|
||||
listContents,
|
||||
listTitle,
|
||||
]
|
||||
});
|
||||
}
|
140
.config/ags/modules/sideright/centermodules/volumemixer.js
Normal file
140
.config/ags/modules/sideright/centermodules/volumemixer.js
Normal file
|
@ -0,0 +1,140 @@
|
|||
// This file is for the notification list on the sidebar
|
||||
// For the popup notifications, see onscreendisplay.js
|
||||
// The actual widget for each single notification is in ags/modules/.commonwidgets/notification.js
|
||||
import Widget from 'resource:///com/github/Aylur/ags/widget.js';
|
||||
import Audio from 'resource:///com/github/Aylur/ags/service/audio.js';
|
||||
const { Box, Button, Icon, Label, Scrollable, Slider, Stack } = Widget;
|
||||
import { MaterialIcon } from '../../.commonwidgets/materialicon.js';
|
||||
import { setupCursorHover } from '../../.widgetutils/cursorhover.js';
|
||||
// import { AnimatedSlider } from '../../.commonwidgets/cairo_slider.js';
|
||||
|
||||
const AppVolume = (stream) => Box({
|
||||
className: 'sidebar-volmixer-stream spacing-h-10',
|
||||
children: [
|
||||
Icon({
|
||||
className: 'sidebar-volmixer-stream-appicon',
|
||||
vpack: 'center',
|
||||
tooltipText: stream.stream.name,
|
||||
setup: (self) => {
|
||||
self.hook(stream, (self) => {
|
||||
self.icon = stream.stream.name.toLowerCase();
|
||||
})
|
||||
},
|
||||
}),
|
||||
Box({
|
||||
hexpand: true,
|
||||
vpack: 'center',
|
||||
vertical: true,
|
||||
className: 'spacing-v-5',
|
||||
children: [
|
||||
Label({
|
||||
xalign: 0,
|
||||
maxWidthChars: 10,
|
||||
truncate: 'end',
|
||||
label: stream.description,
|
||||
className: 'txt-small',
|
||||
setup: (self) => self.hook(stream, (self) => {
|
||||
self.label = `${stream.description}`
|
||||
})
|
||||
}),
|
||||
Slider({
|
||||
drawValue: false,
|
||||
hpack: 'fill',
|
||||
className: 'sidebar-volmixer-stream-slider',
|
||||
value: stream.volume,
|
||||
min: 0, max: 1,
|
||||
onChange: ({ value }) => {
|
||||
stream.volume = value;
|
||||
},
|
||||
setup: (self) => self.hook(stream, (self) => {
|
||||
self.value = stream.volume;
|
||||
})
|
||||
}),
|
||||
// Box({
|
||||
// homogeneous: true,
|
||||
// className: 'test',
|
||||
// children: [AnimatedSlider({
|
||||
// className: 'sidebar-volmixer-stream-slider',
|
||||
// value: stream.volume,
|
||||
// })],
|
||||
// })
|
||||
]
|
||||
})
|
||||
]
|
||||
});
|
||||
|
||||
export default (props) => {
|
||||
const emptyContent = Box({
|
||||
homogeneous: true,
|
||||
children: [Box({
|
||||
vertical: true,
|
||||
vpack: 'center',
|
||||
className: 'txt spacing-v-10',
|
||||
children: [
|
||||
Box({
|
||||
vertical: true,
|
||||
className: 'spacing-v-5 txt-subtext',
|
||||
children: [
|
||||
MaterialIcon('brand_awareness', 'gigantic'),
|
||||
Label({ label: 'No audio source', className: 'txt-small' }),
|
||||
]
|
||||
}),
|
||||
]
|
||||
})]
|
||||
});
|
||||
const appList = Scrollable({
|
||||
vexpand: true,
|
||||
child: Box({
|
||||
attribute: {
|
||||
'updateStreams': (self) => {
|
||||
const streams = Audio.apps;
|
||||
self.children = streams.map(stream => AppVolume(stream));
|
||||
},
|
||||
},
|
||||
vertical: true,
|
||||
className: 'spacing-v-5',
|
||||
setup: (self) => self
|
||||
.hook(Audio, self.attribute.updateStreams, 'stream-added')
|
||||
.hook(Audio, self.attribute.updateStreams, 'stream-removed')
|
||||
,
|
||||
})
|
||||
})
|
||||
const status = Box({
|
||||
className: 'sidebar-volmixer-status spacing-h-5',
|
||||
children: [
|
||||
Label({
|
||||
className: 'txt-small margin-top-5 margin-bottom-8',
|
||||
attribute: { headphones: undefined },
|
||||
setup: (self) => {
|
||||
const updateAudioDevice = (self) => {
|
||||
const usingHeadphones = (Audio.speaker?.stream?.port)?.toLowerCase().includes('headphone');
|
||||
if (self.attribute.headphones === undefined ||
|
||||
self.attribute.headphones !== usingHeadphones) {
|
||||
self.attribute.headphones = usingHeadphones;
|
||||
self.label = `Output: ${usingHeadphones ? 'Headphones' : 'Speakers'}`;
|
||||
}
|
||||
}
|
||||
self.hook(Audio, updateAudioDevice);
|
||||
}
|
||||
})
|
||||
]
|
||||
});
|
||||
const mainContent = Stack({
|
||||
children: {
|
||||
'empty': emptyContent,
|
||||
'list': appList,
|
||||
},
|
||||
setup: (self) => self.hook(Audio, (self) => {
|
||||
self.shown = (Audio.apps.length > 0 ? 'list' : 'empty')
|
||||
}),
|
||||
})
|
||||
return Box({
|
||||
...props,
|
||||
className: 'spacing-v-5',
|
||||
vertical: true,
|
||||
children: [
|
||||
mainContent,
|
||||
status,
|
||||
]
|
||||
});
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue