update ags
This commit is contained in:
1 parent
88822cb8e8
commit
a9c19bd2e1
134 files changed
+4732
-5813
No files matched your search
@@ -0,0 +1,178 @@
|
||||
const { Gtk, GLib } = imports.gi;
|
||||
const lock_command = `hyprlock`;
|
||||
const logout_command = `loginctl kill-session $XDG_SESSION_ID`;
|
||||
const shutdown_command = `systemctl poweroff`;
|
||||
const reboot_command = `systemctl reboot`;
|
||||
const suspend_command = `systemctl suspend`;
|
||||
|
||||
function LockButton({ icon, ...props }) {
|
||||
let clickCount = 0;
|
||||
let button = Widget.Button({
|
||||
tooltip_text: "Lock",
|
||||
child: Widget.Label({
|
||||
label: icon,
|
||||
class_name: "awesome_icon"
|
||||
}),
|
||||
class_name: "outline_button",
|
||||
...props,
|
||||
})
|
||||
|
||||
button.connect('clicked', () => {
|
||||
clickCount++;
|
||||
if (clickCount === 2) {
|
||||
Utils.execAsync(lock_command).catch(print);
|
||||
clickCount = 0;
|
||||
}
|
||||
});
|
||||
|
||||
button.connect('focus-out-event', () => {
|
||||
clickCount = 0;
|
||||
});
|
||||
|
||||
return button
|
||||
}
|
||||
|
||||
|
||||
function SuspendButton({ icon, ...props }) {
|
||||
let clickCount = 0;
|
||||
let button = Widget.Button({
|
||||
tooltip_text: "Suspend",
|
||||
child: Widget.Label({
|
||||
label: icon,
|
||||
class_name: "awesome_icon"
|
||||
}),
|
||||
class_name: "outline_button",
|
||||
...props,
|
||||
})
|
||||
|
||||
button.connect('clicked', () => {
|
||||
clickCount++;
|
||||
if (clickCount === 2) {
|
||||
Utils.execAsync(`mpc -q pause`).catch();
|
||||
Utils.execAsync(`playerctl pause`).catch();
|
||||
Utils.execAsync(suspend_command).catch();
|
||||
clickCount = 0;
|
||||
}
|
||||
});
|
||||
|
||||
button.connect('focus-out-event', () => {
|
||||
clickCount = 0;
|
||||
});
|
||||
|
||||
return button
|
||||
}
|
||||
|
||||
|
||||
function LogoutButton({ icon, ...props }) {
|
||||
let clickCount = 0;
|
||||
let button = Widget.Button({
|
||||
tooltip_text: "Logout",
|
||||
child: Widget.Label({
|
||||
label: icon,
|
||||
class_name: "awesome_icon"
|
||||
}),
|
||||
class_name: "outline_button",
|
||||
...props,
|
||||
})
|
||||
|
||||
button.connect('clicked', () => {
|
||||
clickCount++;
|
||||
if (clickCount === 2) {
|
||||
Utils.execAsync(logout_command).catch();
|
||||
clickCount = 0;
|
||||
}
|
||||
});
|
||||
|
||||
button.connect('focus-out-event', () => {
|
||||
clickCount = 0;
|
||||
});
|
||||
|
||||
return button
|
||||
}
|
||||
|
||||
|
||||
function RebootButton({ icon, ...props }) {
|
||||
let clickCount = 0;
|
||||
let button = Widget.Button({
|
||||
tooltip_text: "Reboot",
|
||||
child: Widget.Label({
|
||||
label: icon,
|
||||
class_name: "awesome_icon"
|
||||
}),
|
||||
class_name: "outline_button",
|
||||
...props,
|
||||
})
|
||||
|
||||
button.connect('clicked', () => {
|
||||
clickCount++;
|
||||
if (clickCount === 2) {
|
||||
Utils.execAsync(reboot_command).catch();
|
||||
clickCount = 0;
|
||||
}
|
||||
});
|
||||
|
||||
button.connect('focus-out-event', () => {
|
||||
clickCount = 0;
|
||||
});
|
||||
|
||||
return button
|
||||
}
|
||||
|
||||
|
||||
function ShutdownButton({ icon, ...props }) {
|
||||
let clickCount = 0;
|
||||
let button = Widget.Button({
|
||||
tooltip_text: "Shutdown",
|
||||
child: Widget.Label({
|
||||
label: icon,
|
||||
class_name: "awesome_icon"
|
||||
}),
|
||||
class_name: "outline_button",
|
||||
...props,
|
||||
})
|
||||
|
||||
button.connect('clicked', () => {
|
||||
clickCount++;
|
||||
if (clickCount === 2) {
|
||||
Utils.execAsync(shutdown_command).catch();
|
||||
clickCount = 0;
|
||||
}
|
||||
});
|
||||
|
||||
button.connect('focus-out-event', () => {
|
||||
clickCount = 0;
|
||||
});
|
||||
|
||||
return button
|
||||
}
|
||||
|
||||
|
||||
export function Buttons() {
|
||||
return Widget.Box({
|
||||
class_name: "sidebar_buttons",
|
||||
hexpand: true,
|
||||
spacing: 5,
|
||||
children: [
|
||||
LockButton({
|
||||
icon: "",
|
||||
hexpand: true,
|
||||
}),
|
||||
SuspendButton({
|
||||
icon: "",
|
||||
hexpand: true,
|
||||
}),
|
||||
LogoutButton({
|
||||
icon: "",
|
||||
hexpand: true,
|
||||
}),
|
||||
RebootButton({
|
||||
icon: "",
|
||||
hexpand: true,
|
||||
}),
|
||||
ShutdownButton({
|
||||
icon: "",
|
||||
hexpand: true,
|
||||
})
|
||||
]
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
import popupwindow from '../misc/popupwindow.js';
|
||||
import { SideBar } from './sidebar.ts'
|
||||
|
||||
export const WINDOW_NAME = "sidebar"
|
||||
|
||||
|
||||
export const sidebar = popupwindow({
|
||||
name: WINDOW_NAME,
|
||||
|
||||
class_name: "sidebar",
|
||||
visible: false,
|
||||
keymode: "exclusive",
|
||||
child: SideBar(),
|
||||
anchor: ["top", "right", "bottom"],
|
||||
css: "min-width: 443px;"
|
||||
})
|
||||
@@ -0,0 +1,387 @@
|
||||
|
||||
const notifications = await Service.import("notifications")
|
||||
const network = await Service.import('network')
|
||||
import { OpenSettings } from "apps/settings/main.ts";
|
||||
import { WINDOW_NAME } from "./main.ts"
|
||||
|
||||
const { Gtk } = imports.gi;
|
||||
const GLib = imports.gi.GLib;
|
||||
const Gio = imports.gi.Gio;
|
||||
|
||||
const idle_inhibitor = Variable(false);
|
||||
const night_light = Variable(false);
|
||||
const screen_recorder = Variable(false);
|
||||
const currentPage = Variable(0);
|
||||
export const bluetooth_enabled = Variable('off', {
|
||||
poll: [1000, `${App.configDir}/scripts/bluetooth.sh --get`]
|
||||
})
|
||||
|
||||
const powerProfiles = await Service.import('powerprofiles');
|
||||
const icons = {
|
||||
'performance': ' ',
|
||||
'balanced': ' ',
|
||||
'power-saver': ' '
|
||||
};
|
||||
|
||||
function WifiIndicator() {
|
||||
return Widget.Box({
|
||||
css: "padding-left: 15px; padding-right: 15px; padding-top: 5px; padding-bottom: 5px;",
|
||||
children: [
|
||||
Widget.Label({
|
||||
label: "\udb82\udd28",
|
||||
class_name: "awesome_icon",
|
||||
css: `font-weight: bold; font-size: 20px; margin-right: 0.60em;`,
|
||||
}),
|
||||
Widget.Box({
|
||||
visible: network.wifi.bind('enabled'),
|
||||
orientation: Gtk.Orientation.VERTICAL,
|
||||
children: [
|
||||
Widget.Box([
|
||||
Widget.Label({
|
||||
label: "Internet",
|
||||
}),
|
||||
]),
|
||||
Widget.Label({
|
||||
label: network.wifi.bind('ssid')
|
||||
.as(ssid => ssid || 'Unknown'),
|
||||
class_name: "ssid",
|
||||
xalign: 0,
|
||||
vpack: "center",
|
||||
truncate: "end",
|
||||
}),
|
||||
]
|
||||
}),
|
||||
Widget.Label({
|
||||
visible: network.wifi.bind('enabled').as(enabled => !enabled),
|
||||
label: "Internet",
|
||||
}),
|
||||
Widget.Box({
|
||||
halign: Gtk.Align.END,
|
||||
hexpand: true,
|
||||
child: Widget.Label({
|
||||
label: "",
|
||||
class_name: "awesome_icon",
|
||||
css: `font-weight: normal; font-size: 15px;`,
|
||||
})
|
||||
})
|
||||
],
|
||||
})
|
||||
}
|
||||
|
||||
const WiredIndicator = () => Widget.Box({
|
||||
css: "padding-left: 15px; padding-right: 15px; padding-top: 5px; padding-bottom: 5px;",
|
||||
children: [
|
||||
Widget.Icon({
|
||||
icon: network.wired.bind('icon_name'),
|
||||
}),
|
||||
Widget.Label({
|
||||
label: "Internet",
|
||||
}),
|
||||
]
|
||||
})
|
||||
|
||||
|
||||
const NetworkIndicator = () => Widget.Stack({
|
||||
children: {
|
||||
wifi: WifiIndicator(),
|
||||
wired: WiredIndicator(),
|
||||
},
|
||||
shown: network.bind('primary').as(p => p || 'wifi'),
|
||||
})
|
||||
|
||||
|
||||
function IconAndName({ label, icon, padding = "0.3em", arrow = false }) {
|
||||
let box = Widget.Box({
|
||||
css: "padding-left: 15px; padding-right: 15px; padding-top: 5px; padding-bottom: 5px;",
|
||||
children: [
|
||||
Widget.Label({
|
||||
label: icon,
|
||||
class_name: "awesome_icon",
|
||||
css: `font-weight: bold; font-size: 20px; margin-right: ${padding};`,
|
||||
}),
|
||||
Widget.Label({
|
||||
label: label,
|
||||
justification: "center",
|
||||
}),
|
||||
]
|
||||
})
|
||||
if (arrow) {
|
||||
const arrow = Widget.Box({
|
||||
halign: Gtk.Align.END,
|
||||
hexpand: true,
|
||||
child: Widget.Label({
|
||||
label: "",
|
||||
class_name: "awesome_icon",
|
||||
css: `font-weight: normal; font-size: 15px;`,
|
||||
})
|
||||
})
|
||||
// @ts-ignore
|
||||
box.children = [...box.children, arrow]
|
||||
}
|
||||
return box
|
||||
}
|
||||
|
||||
function isScreenRecordingOn() {
|
||||
// Check if wf-recorder is running
|
||||
// Bash command outputs 0 if yes or 1 if no
|
||||
let state = Utils.execAsync('bash -c "pidof wf-recorder > /dev/null; echo $?"')
|
||||
if (state == "0"){
|
||||
return true
|
||||
}
|
||||
else{
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
function Page1() {
|
||||
return Widget.Box({
|
||||
orientation: Gtk.Orientation.VERTICAL,
|
||||
spacing: 5,
|
||||
hexpand: true,
|
||||
class_name: "management_box",
|
||||
children: [
|
||||
Widget.Box({
|
||||
orientation: Gtk.Orientation.HORIZONTAL,
|
||||
hexpand: true,
|
||||
spacing: 2.5,
|
||||
children: [
|
||||
Widget.Button({
|
||||
hexpand: true,
|
||||
class_name: network.wifi.bind("enabled")
|
||||
.as(enabled => enabled ? "management_button active" : "management_button"),
|
||||
child: NetworkIndicator(),
|
||||
on_primary_click: () => {
|
||||
network.toggleWifi();
|
||||
},
|
||||
on_secondary_click: () => {
|
||||
App.closeWindow(WINDOW_NAME);
|
||||
App.openWindow("network");
|
||||
}
|
||||
}),
|
||||
Widget.Button({
|
||||
hexpand: true,
|
||||
class_name: bluetooth_enabled.bind()
|
||||
.as(state => state.trim() == "yes" ? "management_button active" : "management_button"
|
||||
),
|
||||
child: IconAndName({
|
||||
label: "Bluetooth",
|
||||
icon: "",
|
||||
arrow: true,
|
||||
}),
|
||||
on_primary_click: () => {
|
||||
Utils.execAsync(`${App.configDir}/scripts/bluetooth.sh --toggle`)
|
||||
.then(out => { bluetooth_enabled.setValue(out) })
|
||||
},
|
||||
on_secondary_click: () => {
|
||||
Utils.execAsync("blueman-manager")
|
||||
App.closeWindow(WINDOW_NAME)
|
||||
}
|
||||
})
|
||||
]
|
||||
}),
|
||||
Widget.Box({
|
||||
orientation: Gtk.Orientation.HORIZONTAL,
|
||||
spacing: 2.5,
|
||||
hexpand: true,
|
||||
children: [
|
||||
Widget.Button({
|
||||
hexpand: true,
|
||||
class_name: idle_inhibitor.bind()
|
||||
.as(bool => bool ? "management_button active" : "management_button"),
|
||||
child: IconAndName({
|
||||
label: "Idle inhibitor",
|
||||
icon: ""
|
||||
}),
|
||||
onClicked: () => {
|
||||
idle_inhibitor.setValue(!idle_inhibitor.value)
|
||||
if (idle_inhibitor.value) Utils.execAsync(['bash', '-c', `pidof wayland-idle-inhibitor.py || ${App.configDir}/scripts/wayland-idle-inhibitor.py`]).catch(print)
|
||||
else Utils.execAsync('pkill -f wayland-idle-inhibitor.py').catch(print);
|
||||
},
|
||||
setup: () => {
|
||||
idle_inhibitor.setValue(!!Utils.exec('pidof wayland-idle-inhibitor.py'));
|
||||
},
|
||||
}),
|
||||
Widget.Button({
|
||||
hexpand: true,
|
||||
class_name: notifications.bind("dnd").as((bool) => {
|
||||
return bool ? "management_button active" : "management_button";
|
||||
}),
|
||||
on_clicked: () => {
|
||||
notifications.dnd = notifications.dnd ? false : true
|
||||
},
|
||||
child: IconAndName({
|
||||
label: "Do Not Disturb",
|
||||
icon: ""
|
||||
})
|
||||
})
|
||||
]
|
||||
}),
|
||||
Widget.Box({
|
||||
orientation: Gtk.Orientation.HORIZONTAL,
|
||||
spacing: 2.5,
|
||||
hexpand: true,
|
||||
children: [
|
||||
Widget.Button({
|
||||
hexpand: true,
|
||||
class_name: screen_recorder.bind()
|
||||
.as(bool => bool ? "management_button active" : "management_button"),
|
||||
on_clicked: (self) => {
|
||||
screen_recorder.setValue(!screen_recorder.value)
|
||||
// Adjust indicator
|
||||
let isRecording = isScreenRecordingOn()
|
||||
self.toggleClassName("active-button", !isRecording) // Toggles active indicator
|
||||
self.toggleClassName("recording", !isRecording) // Toggles active indicator
|
||||
|
||||
// Starts screen recorder if not running
|
||||
// Stops screen recorder if running
|
||||
Utils.execAsync(['bash', '-c', 'mkdir ~/Videos/Screenrecordings; pkill wf-recorder; if [ $? -ne 0 ]; then wf-recorder -f ~/Videos/Screenrecordings/recording_"$(date +\'%b-%d-%Y-%I:%M:%S-%P\')".mp4 -g "$(slurp)" --pixel-format yuv420p; fi']).catch(logError);
|
||||
},
|
||||
child: IconAndName({
|
||||
label: "Screen Recorder",
|
||||
icon: "",
|
||||
setup: self=>{}
|
||||
})
|
||||
}),
|
||||
|
||||
Widget.Button({
|
||||
hexpand: true,
|
||||
class_name: night_light.bind()
|
||||
.as(mode => mode ? "management_button active" : "management_button"),
|
||||
child: IconAndName({
|
||||
label: "Night Light",
|
||||
icon: ""
|
||||
}),
|
||||
onClicked: () => {
|
||||
night_light.setValue(!night_light.value)
|
||||
Utils.execAsync(`${App.configDir}/scripts/night-light.sh --toggle`)
|
||||
.then(out => {
|
||||
if (out.trim() == "enabled") night_light.setValue(true)
|
||||
else if (out.trim() == "disabled") night_light.setValue(false)
|
||||
})
|
||||
.catch(err => {
|
||||
night_light.setValue(!night_light.value);
|
||||
});
|
||||
},
|
||||
setup: () => {
|
||||
Utils.execAsync(`${App.configDir}/scripts/night-light.sh --get`)
|
||||
.then(out => {
|
||||
if (out.trim() == "enabled") night_light.setValue(true)
|
||||
else if (out.trim() == "disabled") night_light.setValue(false)
|
||||
})
|
||||
.catch(print);
|
||||
}
|
||||
})
|
||||
]
|
||||
})
|
||||
]
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
function Page2() {
|
||||
return Widget.Box({
|
||||
orientation: Gtk.Orientation.VERTICAL,
|
||||
spacing: 5,
|
||||
hexpand: true,
|
||||
class_name: "management_box",
|
||||
children: [
|
||||
Widget.Box({
|
||||
orientation: Gtk.Orientation.HORIZONTAL,
|
||||
spacing: 2.5,
|
||||
children: [
|
||||
Widget.Button({
|
||||
hexpand: true,
|
||||
class_name: "management_button",
|
||||
child: IconAndName({
|
||||
label: "Color picker",
|
||||
icon: "",
|
||||
arrow: true,
|
||||
}),
|
||||
on_primary_click: () => {
|
||||
App.closeWindow(WINDOW_NAME);
|
||||
Utils.execAsync("sleep 0.5")
|
||||
.then(() =>
|
||||
Utils.execAsync("hyprpicker -a").catch(print)
|
||||
)
|
||||
.catch(print);
|
||||
}
|
||||
}),
|
||||
Widget.Button({
|
||||
hexpand: true,
|
||||
class_name: "management_button",
|
||||
child: Widget.Box({
|
||||
children: [
|
||||
Widget.Label({
|
||||
label: powerProfiles.bind('active_profile').as(x => icons[x])
|
||||
}),
|
||||
Widget.Label({
|
||||
label: powerProfiles.bind('active_profile').as(x => x.toUpperCase())
|
||||
})
|
||||
]
|
||||
}),
|
||||
on_clicked: () => {
|
||||
switch (powerProfiles.active_profile) {
|
||||
case 'balanced':
|
||||
powerProfiles.active_profile = 'performance';
|
||||
break;
|
||||
case 'power-saver':
|
||||
powerProfiles.active_profile = 'balanced';
|
||||
break;
|
||||
default:
|
||||
powerProfiles.active_profile = 'power-saver';
|
||||
break;
|
||||
};
|
||||
},
|
||||
}),
|
||||
]
|
||||
})
|
||||
]
|
||||
})
|
||||
}
|
||||
|
||||
const createDotButton = (index: number) => Widget.Button({
|
||||
label: '',
|
||||
onClicked: () => currentPage.setValue(index),
|
||||
class_name: currentPage.bind().as(v => v == index ? "dotbutton active" : "dotbutton"),
|
||||
hexpand: false,
|
||||
});
|
||||
|
||||
|
||||
export function Management() {
|
||||
let pages = {
|
||||
"page1": Page1(),
|
||||
"page2": Page2()
|
||||
}
|
||||
const numberOfPages = Object.keys(pages).length;
|
||||
const pageNames = Array.from({ length: numberOfPages }, (_, i) => `page${i + 1}`);
|
||||
|
||||
const stack = Widget.Stack({
|
||||
children: pages,
|
||||
// @ts-ignore
|
||||
shown: currentPage.bind().as(v => `page${v + 1}`),
|
||||
transition: "slide_left_right",
|
||||
transitionDuration: 200,
|
||||
})
|
||||
const dotButtons = pageNames.map((_, index) => createDotButton(index));
|
||||
return Widget.EventBox({
|
||||
onScrollUp: () => currentPage.setValue((currentPage.value + 1) % numberOfPages),
|
||||
onScrollDown: () => {
|
||||
if (currentPage.value - 1) {
|
||||
currentPage.setValue(numberOfPages - 1)
|
||||
return
|
||||
}
|
||||
currentPage.setValue(currentPage.value - 1);
|
||||
},
|
||||
child: Widget.Box({
|
||||
orientation: Gtk.Orientation.VERTICAL,
|
||||
children: [
|
||||
stack,
|
||||
Widget.Box({
|
||||
children: dotButtons,
|
||||
class_name: "dotbuttons_box",
|
||||
halign: Gtk.Align.CENTER,
|
||||
})
|
||||
]
|
||||
})
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
const { Gtk } = imports.gi;
|
||||
import { NotificationsBox } from "./notifications.ts"
|
||||
import { SystemBox } from "./system.ts"
|
||||
let shown = Variable("Messages");
|
||||
|
||||
|
||||
type ButtonType = {
|
||||
page: string,
|
||||
label: string,
|
||||
icon: string
|
||||
}
|
||||
|
||||
|
||||
function Button({ page, label, icon }: ButtonType) {
|
||||
return Widget.Button({
|
||||
class_name: shown.bind().as(_page => _page == page ? "navigation_button active" : "navigation_button"),
|
||||
hexpand: true,
|
||||
child: Widget.Box({
|
||||
orientation: Gtk.Orientation.VERTICAL,
|
||||
class_name: "container_outer",
|
||||
children: [
|
||||
Widget.Box({
|
||||
orientation: Gtk.Orientation.VERTICAL,
|
||||
halign: Gtk.Align.CENTER,
|
||||
class_name: "container",
|
||||
child: Widget.Label({
|
||||
hpack: "center",
|
||||
label: icon,
|
||||
class_name: "awesome_icon icon"
|
||||
}),
|
||||
}),
|
||||
Widget.Label({
|
||||
label: label,
|
||||
class_name: "label",
|
||||
})
|
||||
]
|
||||
}),
|
||||
on_clicked: () => {
|
||||
shown.setValue(page)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
export function Navigation() {
|
||||
const messages_apps = ["discord", "materialgram", "Telegram Desktop"]
|
||||
let stack = Widget.Stack({
|
||||
children: {
|
||||
"Messages": NotificationsBox({ include: messages_apps }),
|
||||
"Notifications": NotificationsBox({ exclude: messages_apps }),
|
||||
"System": SystemBox()
|
||||
},
|
||||
transition: "crossfade",
|
||||
transitionDuration: 200,
|
||||
// @ts-ignore
|
||||
shown: shown.bind()
|
||||
})
|
||||
const buttons = Widget.Box({
|
||||
class_name: "navigation",
|
||||
hexpand: true,
|
||||
children: [
|
||||
Button({
|
||||
page: "Messages",
|
||||
label: "Messages",
|
||||
icon: ""
|
||||
}),
|
||||
Button({
|
||||
page: "Notifications",
|
||||
label: "Notifs",
|
||||
icon: ""
|
||||
}),
|
||||
Button({
|
||||
page: "System",
|
||||
label: "System",
|
||||
icon: ""
|
||||
})
|
||||
]
|
||||
})
|
||||
return Widget.Box({
|
||||
vexpand: true,
|
||||
orientation: Gtk.Orientation.VERTICAL,
|
||||
class_name: "sidebar_bottom",
|
||||
children: [
|
||||
stack,
|
||||
buttons
|
||||
]
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,183 @@
|
||||
import { Notification as NotificationType } from "types/service/notifications";
|
||||
|
||||
const notifications = await Service.import("notifications")
|
||||
const { Gtk, Gdk } = imports.gi;
|
||||
|
||||
function NotificationIcon({ app_entry, app_icon, image }: NotificationType) {
|
||||
if (image) {
|
||||
return Widget.Box({
|
||||
css: `background-image: url("${image}");`
|
||||
+ "background-size: contain;"
|
||||
+ "background-repeat: no-repeat;"
|
||||
+ "background-position: center;",
|
||||
})
|
||||
}
|
||||
|
||||
let icon = "dialog-information-symbolic"
|
||||
if (Utils.lookUpIcon(app_icon))
|
||||
icon = app_icon
|
||||
|
||||
if (app_entry && Utils.lookUpIcon(app_entry))
|
||||
icon = app_entry
|
||||
|
||||
return Widget.Box({
|
||||
child: Widget.Icon(icon),
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
function Notification(n: NotificationType) {
|
||||
const icon = Widget.Box({
|
||||
vpack: "start",
|
||||
class_name: "notification_sidebar_icon",
|
||||
child: NotificationIcon(n),
|
||||
})
|
||||
|
||||
const title = Widget.Label({
|
||||
class_name: "notification_sidebar_title",
|
||||
wrap: true,
|
||||
label: n.summary,
|
||||
use_markup: true,
|
||||
hpack: "start",
|
||||
xalign: 0
|
||||
})
|
||||
|
||||
const body = Widget.Label({
|
||||
class_name: "notification_sidebar_body",
|
||||
label: n.body,
|
||||
wrap: true,
|
||||
use_markup: true,
|
||||
hpack: "start",
|
||||
xalign: 0
|
||||
})
|
||||
|
||||
const actions = Widget.Box({
|
||||
halign: Gtk.Align.END,
|
||||
class_name: "notification_sidebar_actions",
|
||||
children: n.actions.map(({ id, label }) => Widget.Button({
|
||||
class_name: "notification_sidebar_button",
|
||||
on_clicked: () => {
|
||||
n.invoke(id)
|
||||
},
|
||||
hexpand: false,
|
||||
child: Widget.Label(label),
|
||||
})),
|
||||
})
|
||||
|
||||
let Box = Widget.EventBox(
|
||||
{
|
||||
attribute: { id: n.id },
|
||||
on_secondary_click: () => n.close(),
|
||||
},
|
||||
Widget.Box(
|
||||
{
|
||||
class_name: `notification_sidebar ${n.urgency}`,
|
||||
vertical: true,
|
||||
},
|
||||
Widget.Box([
|
||||
icon,
|
||||
Widget.Box(
|
||||
{
|
||||
vertical: true,
|
||||
hexpand: true,
|
||||
},
|
||||
title,
|
||||
body,
|
||||
),
|
||||
]),
|
||||
actions,
|
||||
),
|
||||
)
|
||||
return Box
|
||||
}
|
||||
|
||||
type NotificationsBoxType = {
|
||||
exclude?: string[],
|
||||
include?: string[]
|
||||
}
|
||||
|
||||
export function NotificationsBox({ exclude = [], include = [] }: NotificationsBoxType) {
|
||||
let isEmpty = Variable(false)
|
||||
const list = Widget.Box({
|
||||
vertical: true,
|
||||
children: notifications.popups.map(Notification)
|
||||
})
|
||||
|
||||
const _list = Widget.Box({
|
||||
vertical: true,
|
||||
children: [
|
||||
list,
|
||||
Widget.Label({
|
||||
label: "Empty",
|
||||
visible: isEmpty.bind(),
|
||||
class_name: "empty"
|
||||
})
|
||||
],
|
||||
class_name: "notifications_list_sidebar"
|
||||
})
|
||||
|
||||
function setIsEmpty() {
|
||||
if (list.children.length > 0) isEmpty.setValue(false)
|
||||
else isEmpty.setValue(true)
|
||||
}
|
||||
|
||||
function onNotified(_: any, id: number) {
|
||||
const n = notifications.getNotification(id)
|
||||
if (n) {
|
||||
if (exclude.includes(n.app_name.trim()))
|
||||
return
|
||||
if (include.length == 0 || include.includes(n.app_name.trim())) {
|
||||
const notificationWidget = Notification(n)
|
||||
list.children = [notificationWidget, ...list.children]
|
||||
setIsEmpty()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function onClosed(_: any, id: number) {
|
||||
list.children.find(n => n.attribute.id === id)?.destroy()
|
||||
setIsEmpty()
|
||||
}
|
||||
list.hook(notifications, onNotified, "notified")
|
||||
.hook(notifications, onClosed, "closed")
|
||||
|
||||
const menu = Widget.Menu({
|
||||
class_name: "notifications_menu",
|
||||
children: [
|
||||
Widget.MenuItem({
|
||||
child: Widget.Label('Close all'),
|
||||
class_name: "notifications_menu_item",
|
||||
on_activate: () => {
|
||||
for (let x of list.children) {
|
||||
const n = notifications.getNotification(x.attribute.id)
|
||||
if (n) {
|
||||
n.dismiss()
|
||||
n.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
}),
|
||||
],
|
||||
})
|
||||
|
||||
return Widget.EventBox({
|
||||
vexpand: true,
|
||||
hexpand: true,
|
||||
on_secondary_click: (_, event) => {
|
||||
menu.popup_at_pointer(event)
|
||||
},
|
||||
child: Widget.Scrollable({
|
||||
class_name: "notifications_sidebar_scrollable",
|
||||
hscroll: "never",
|
||||
child: _list,
|
||||
hexpand: true
|
||||
|
||||
/** this is a simple one liner that could be used instead of
|
||||
hooking into the 'notified' and 'dismissed' signals.
|
||||
but its not very optimized becuase it will recreate
|
||||
the whole list everytime a notification is added or dismissed */
|
||||
// children: notifications.bind('popups')
|
||||
// .as(popups => popups.map(Notification))
|
||||
}),
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
import { Notification as NotificationType } from "types/service/notifications";
|
||||
import { NotificationPopups, Notification } from "modules/notificationPopups";
|
||||
import Box from "types/widgets/box";
|
||||
|
||||
const notifications = await Service.import("notifications")
|
||||
const { Gtk, Gdk } = imports.gi;
|
||||
|
||||
type NotificationsBoxType = {
|
||||
exclude?: string[],
|
||||
include?: string[]
|
||||
}
|
||||
|
||||
const NotificationNoReveal = (notification: NotificationType, visible = false, dismiss = true) => {
|
||||
type BoxAttrs = {
|
||||
destroyWithAnims: any,
|
||||
count: number,
|
||||
id: number,
|
||||
}
|
||||
|
||||
const _notification = Notification(notification, dismiss);
|
||||
|
||||
let box: Box<any, BoxAttrs>;
|
||||
|
||||
const destroyWithAnims = () => {
|
||||
box.destroy();
|
||||
};
|
||||
box = Widget.Box({
|
||||
hexpand: true,
|
||||
attribute: {
|
||||
"destroyWithAnims": destroyWithAnims,
|
||||
count: 0,
|
||||
id: notification.id,
|
||||
},
|
||||
children: [_notification],
|
||||
});
|
||||
return box;
|
||||
};
|
||||
|
||||
export function NotificationsBox({ exclude = [], include = [] }: NotificationsBoxType) {
|
||||
const popups = NotificationPopups(
|
||||
false, { exclude: exclude, include: include },
|
||||
false, NotificationNoReveal
|
||||
);
|
||||
|
||||
const menu = Widget.Menu({
|
||||
class_name: "notifications_menu",
|
||||
children: [
|
||||
Widget.MenuItem({
|
||||
child: Widget.Label('Close all'),
|
||||
class_name: "notifications_menu_item",
|
||||
on_activate: () => {
|
||||
for (let n of notifications.notifications) {
|
||||
if (n) {
|
||||
n.dismiss()
|
||||
n.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
}),
|
||||
],
|
||||
})
|
||||
|
||||
return Widget.EventBox({
|
||||
vexpand: true,
|
||||
hexpand: true,
|
||||
on_secondary_click: (_, event) => {
|
||||
menu.popup_at_pointer(event)
|
||||
},
|
||||
child: Widget.Scrollable({
|
||||
class_name: "notifications_sidebar_scrollable",
|
||||
hscroll: "never",
|
||||
child: popups,
|
||||
hexpand: true
|
||||
}),
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
import { Management } from "./management.ts"
|
||||
import { Buttons } from "./buttons.ts";
|
||||
import { Navigation } from "./navigation.ts";
|
||||
const { Gtk } = imports.gi;
|
||||
|
||||
export function SideBar() {
|
||||
return Widget.Box({
|
||||
orientation: Gtk.Orientation.VERTICAL,
|
||||
class_name: "sidebar_main_box",
|
||||
hexpand: true,
|
||||
children: [
|
||||
Management(),
|
||||
Buttons(),
|
||||
Navigation()
|
||||
// NotificationsBox()
|
||||
]
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,210 @@
|
||||
import { Variable as VariableType } from "types/variable";
|
||||
|
||||
const { Gtk } = imports.gi;
|
||||
|
||||
const cpu_name = await Utils.execAsync(`${App.configDir}/scripts/system.sh --cpu-name`);
|
||||
const cpu_cores = await Utils.execAsync(`${App.configDir}/scripts/system.sh --cpu-cores`);
|
||||
const amount_of_ram = await Utils.execAsync(`${App.configDir}/scripts/system.sh --ram`);
|
||||
const kernel_name = await Utils.execAsync(`${App.configDir}/scripts/system.sh --kernel`);
|
||||
|
||||
type InfoType = {
|
||||
cpu: string,
|
||||
ram: string,
|
||||
swap: string,
|
||||
cpu_temp: string
|
||||
}
|
||||
|
||||
async function SystemInfo(): Promise<InfoType> {
|
||||
const cpu_usage = await Utils.execAsync(`${App.configDir}/scripts/system.sh --cpu-usage`)
|
||||
.then(str => String(str))
|
||||
.catch(err => {
|
||||
print(err)
|
||||
return "0"
|
||||
});
|
||||
const ram_usage = await Utils.execAsync(`${App.configDir}/scripts/system.sh --ram-usage`)
|
||||
.then(str => String(str))
|
||||
.catch(err => {
|
||||
print(err)
|
||||
return "0"
|
||||
});
|
||||
const swap_usage = await Utils.execAsync(`${App.configDir}/scripts/system.sh --swap-usage`)
|
||||
.then(str => String(str))
|
||||
.catch(err => {
|
||||
print(err)
|
||||
return "0"
|
||||
});
|
||||
const cpu_temp = await Utils.execAsync(`${App.configDir}/scripts/system.sh --cpu-temp`)
|
||||
.then(str => String(str))
|
||||
.catch(err => {
|
||||
print(err)
|
||||
return "0"
|
||||
});
|
||||
return {
|
||||
cpu: cpu_usage,
|
||||
ram: ram_usage,
|
||||
swap: swap_usage,
|
||||
cpu_temp: cpu_temp
|
||||
}
|
||||
}
|
||||
|
||||
const usage = Variable({
|
||||
cpu: "0",
|
||||
ram: "0",
|
||||
swap: "0",
|
||||
cpu_temp: "0"
|
||||
} as unknown as Promise<InfoType>, {
|
||||
poll: [1000, async () => {
|
||||
const result = await SystemInfo()
|
||||
.then(result => result)
|
||||
return result
|
||||
}]
|
||||
})
|
||||
|
||||
function checkBacklight() {
|
||||
const get = Utils.execAsync(`${App.configDir}/scripts/backlight.sh --get`)
|
||||
.then(out => Number(out.trim()))
|
||||
.catch(print);
|
||||
return get
|
||||
}
|
||||
|
||||
function checkBrightness() {
|
||||
const get = Utils.execAsync(`${App.configDir}/scripts/brightness.sh --get`)
|
||||
.then(out => Number(out.trim()))
|
||||
.catch(print);
|
||||
return get
|
||||
}
|
||||
|
||||
const current_backlight = Variable(100, {
|
||||
poll: [500, checkBacklight]
|
||||
})
|
||||
|
||||
const current_brightness = Variable(100, {
|
||||
poll: [500, checkBrightness]
|
||||
})
|
||||
|
||||
const Usage = (
|
||||
name: string, var_name: keyof InfoType,
|
||||
class_name: string | undefined
|
||||
) => {
|
||||
const usage_progress_bar = Widget.ProgressBar({
|
||||
class_name: "usage_bar",
|
||||
value: usage.bind().as(usage => Number(usage[var_name]) / 100),
|
||||
})
|
||||
const usage_overlay = Widget.Overlay({
|
||||
child: usage_progress_bar,
|
||||
overlay: Widget.Box({
|
||||
halign: Gtk.Align.END,
|
||||
valign: Gtk.Align.CENTER,
|
||||
class_name: "usage_bar_point"
|
||||
})
|
||||
})
|
||||
const _usage = Widget.Box({
|
||||
class_name: `${class_name} usage_box`,
|
||||
orientation: Gtk.Orientation.VERTICAL,
|
||||
children: [
|
||||
Widget.Label({
|
||||
label: usage.bind().as(usage => `${name}: ${usage[var_name]}%`),
|
||||
hpack: "start",
|
||||
vpack: "center"
|
||||
}),
|
||||
usage_overlay
|
||||
]
|
||||
})
|
||||
|
||||
return _usage
|
||||
}
|
||||
|
||||
const InfoLabel = (name: string, var_name: keyof InfoType, end: string) => {
|
||||
return Widget.Label({
|
||||
class_name: "info_label",
|
||||
truncate: "end",
|
||||
hpack: "start",
|
||||
label: usage.bind().as(usage => `${name}: ${usage[var_name]}${end}`)
|
||||
})
|
||||
}
|
||||
|
||||
const InfoLabelString = (name: string, value: string, end: string) => {
|
||||
return Widget.Label({
|
||||
class_name: "info_label",
|
||||
truncate: "end",
|
||||
hpack: "start",
|
||||
label: `${name}: ${value}${end}`
|
||||
})
|
||||
}
|
||||
|
||||
export function SystemBox() {
|
||||
const backlight = Widget.Slider({
|
||||
min: 0,
|
||||
max: 100,
|
||||
draw_value: false,
|
||||
class_name: "system_scale backlight",
|
||||
// @ts-ignore
|
||||
value: current_backlight.bind(),
|
||||
on_change: self => {
|
||||
current_backlight.setValue(Number(self.value));
|
||||
Utils.execAsync(`${App.configDir}/scripts/backlight.sh --smooth ${self.value}`)
|
||||
.catch(print);
|
||||
},
|
||||
tooltip_markup: "Backlight"
|
||||
})
|
||||
const brightness = Widget.Slider({
|
||||
min: 0,
|
||||
max: 1,
|
||||
draw_value: false,
|
||||
class_name: "system_scale brightness",
|
||||
// @ts-ignore
|
||||
value: current_brightness.bind(),
|
||||
on_change: self => {
|
||||
current_brightness.setValue(Number(self.value));
|
||||
Utils.execAsync(`${App.configDir}/scripts/brightness.sh --set ${self.value}`)
|
||||
.catch(print);
|
||||
},
|
||||
tooltip_markup: "Brightness"
|
||||
})
|
||||
const slider_box = Widget.Box({
|
||||
orientation: Gtk.Orientation.VERTICAL,
|
||||
class_name: "slider_box",
|
||||
children: [
|
||||
backlight,
|
||||
brightness
|
||||
]
|
||||
})
|
||||
|
||||
const usage_box = Widget.Box({
|
||||
orientation: Gtk.Orientation.VERTICAL,
|
||||
class_name: "usage_box",
|
||||
spacing: 0,
|
||||
children: [
|
||||
Usage("CPU", "cpu", "cpu_usage"),
|
||||
Usage("RAM", "ram", "ram_usage"),
|
||||
Usage("SWAP", "swap", "swap_usage")
|
||||
]
|
||||
})
|
||||
|
||||
const info_box = Widget.Box({
|
||||
orientation: Gtk.Orientation.VERTICAL,
|
||||
class_name: "info_box",
|
||||
spacing: 0,
|
||||
children: [
|
||||
InfoLabel("CPU temp", "cpu_temp", "°C"),
|
||||
InfoLabelString("CPU name", cpu_name, ""),
|
||||
InfoLabelString("CPU cores", cpu_cores, ""),
|
||||
InfoLabelString("RAM amount", amount_of_ram, ""),
|
||||
InfoLabelString("Kernel", kernel_name, "")
|
||||
],
|
||||
vexpand: true
|
||||
})
|
||||
|
||||
return Widget.Scrollable({
|
||||
child: Widget.Box({
|
||||
orientation: Gtk.Orientation.VERTICAL,
|
||||
class_name: "system_box",
|
||||
spacing: 10,
|
||||
children: [
|
||||
slider_box,
|
||||
usage_box,
|
||||
info_box
|
||||
]
|
||||
})
|
||||
})
|
||||
}
|
||||
Reference in new issue
Block a user