updates
This commit is contained in:
1 parent
6b14451fe6
commit
1d69e6c2ce
17 files changed
+440
-189
No files matched your search
@@ -0,0 +1,78 @@
|
||||
const apps_script = `python -OOO ${App.configDir}/scripts/apps.py`;
|
||||
import { MaterialIcon } from "icons";
|
||||
|
||||
const Row = (app: string, title: string, icon: string) => Widget.EventBox({
|
||||
class_name: "row",
|
||||
on_primary_click: self => {
|
||||
self.child.children[1]!.activate()
|
||||
},
|
||||
child: Widget.Box({
|
||||
class_name: "row",
|
||||
vpack: "start",
|
||||
children: [
|
||||
MaterialIcon(icon),
|
||||
Widget.Box({
|
||||
vertical: true,
|
||||
hexpand: true,
|
||||
vpack: "center",
|
||||
children: [
|
||||
Widget.Label({
|
||||
hpack: "start",
|
||||
class_name: "title",
|
||||
label: title
|
||||
})
|
||||
]
|
||||
}),
|
||||
Widget.Entry({
|
||||
hpack: "end",
|
||||
css: "border: 2px solid; border-color: transparent;",
|
||||
attribute: {
|
||||
"get": (self) => {
|
||||
Utils.execAsync(`${apps_script} --get ${app}`)
|
||||
.then((out) => {
|
||||
self.text = out;
|
||||
})
|
||||
.catch(print)
|
||||
}
|
||||
},
|
||||
on_accept: self => {
|
||||
Utils.execAsync(`${apps_script} --${app} ${self.text}`)
|
||||
.then(() => {
|
||||
self.css = "border: 2px solid; border-color: #66BB6A;"
|
||||
Utils.timeout(1000, () => {
|
||||
self.css = "border: 2px solid; border-color: transparent"
|
||||
})
|
||||
})
|
||||
.catch(() => {
|
||||
self.css = "border: 2px solid; border-color: @error;"
|
||||
Utils.timeout(1000, () => {
|
||||
self.css = "border: 2px solid; border-color: transparent"
|
||||
})
|
||||
self.attribute.get(self)
|
||||
})
|
||||
},
|
||||
setup: (self) => {
|
||||
self.attribute.get(self)
|
||||
}
|
||||
})
|
||||
]
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
export function Apps() {
|
||||
const box = Widget.Box({
|
||||
vertical: true,
|
||||
children: [
|
||||
Row("browser", "Browser", "web"),
|
||||
Row("editor", "Editor", "edit"),
|
||||
Row("filemanager", "File manager", "folder"),
|
||||
Row("terminal", "Terminal", "terminal")
|
||||
],
|
||||
})
|
||||
return Widget.Scrollable({
|
||||
hscroll: "never",
|
||||
child: box,
|
||||
vexpand: true
|
||||
})
|
||||
}
|
||||
@@ -3,7 +3,8 @@ import { Network } from "./network";
|
||||
import { Bluetooth } from "./bluetooth";
|
||||
import { Wallpapers } from "./wallpapers";
|
||||
import { Info } from "./info";
|
||||
import { Widget as WidgetType } from "types/widgets/widget";
|
||||
import { Apps } from "./apps";
|
||||
import { MaterialIcon } from "icons";
|
||||
const hyprland = await Service.import("hyprland")
|
||||
import Gtk from "gi://Gtk?version=3.0"
|
||||
|
||||
@@ -42,14 +43,15 @@ function Settings(cur_tab: string) {
|
||||
"network": Page(Network(), "Network"),
|
||||
"bluetooth": Page(Bluetooth(), "Bluetooth"),
|
||||
"wallpaper": Page(Wallpapers(), "Wallpapers"),
|
||||
"info": Page(Info(), "Info")
|
||||
"info": Page(Info(), "Info"),
|
||||
"apps": Page(Apps(), "Apps")
|
||||
}
|
||||
})
|
||||
const Row = (name: string, label: string, icon: string = "image-missing") => Widget.Button({
|
||||
on_clicked: () => { current_tab.setValue(name) },
|
||||
child: Widget.Box({
|
||||
children: [
|
||||
Widget.Icon(icon),
|
||||
MaterialIcon(icon),
|
||||
Widget.Label(label)
|
||||
]
|
||||
}),
|
||||
@@ -61,12 +63,14 @@ function Settings(cur_tab: string) {
|
||||
class_name: "sidebar",
|
||||
spacing: 2,
|
||||
children: [
|
||||
Row("network", "Network", "network-wireless-signal-excellent-symbolic"),
|
||||
Row("bluetooth", "Bluetooth", "bluetooth-active-symbolic"),
|
||||
Row("network", "Network", "signal_wifi_4_bar"),
|
||||
Row("bluetooth", "Bluetooth", "bluetooth"),
|
||||
Widget.Separator(),
|
||||
Row("wallpaper", "Wallpapers", "folder-pictures-symbolic"),
|
||||
Row("wallpaper", "Wallpapers", "image"),
|
||||
Widget.Separator(),
|
||||
Row("info", "Info", "dialog-information-symbolic"),
|
||||
Row("apps", "Apps", "grid_view"),
|
||||
Widget.Separator(),
|
||||
Row("info", "Info", "info")
|
||||
]
|
||||
})
|
||||
return Widget.Box({
|
||||
|
||||
@@ -1,8 +1,17 @@
|
||||
import Gtk from "gi://Gtk?version=3.0"
|
||||
import { timeout } from "resource:///com/github/Aylur/ags/utils.js";
|
||||
import { Variable as VariableType } from "types/variable";
|
||||
import { MaterialIcon } from "icons";
|
||||
const systemtray = await Service.import("systemtray")
|
||||
|
||||
const MATERIAL_SYMBOL_SIGNAL_STRENGTH = {
|
||||
'network-wireless-signal-excellent-symbolic': "signal_wifi_4_bar",
|
||||
'network-wireless-signal-good-symbolic': "network_wifi_3_bar",
|
||||
'network-wireless-signal-ok-symbolic': "network_wifi_2_bar",
|
||||
'network-wireless-signal-weak-symbolic': "network_wifi_1_bar",
|
||||
'network-wireless-signal-none-symbolic': "signal_wifi_0_bar",
|
||||
}
|
||||
|
||||
type AccessPoint = {
|
||||
bssid: string | null;
|
||||
address: string | null;
|
||||
@@ -70,10 +79,10 @@ const WifiNetwork = (access_point: AccessPoint) => {
|
||||
child: Widget.Box({
|
||||
class_name: "wifi_network_box",
|
||||
children: [
|
||||
Widget.Icon({
|
||||
icon: access_point.iconName,
|
||||
size: 20
|
||||
}),
|
||||
MaterialIcon(
|
||||
MATERIAL_SYMBOL_SIGNAL_STRENGTH[access_point.iconName!],
|
||||
"20px"
|
||||
),
|
||||
// @ts-ignore
|
||||
Widget.Box({
|
||||
vertical: true,
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"browser": "firefox",
|
||||
"editor": "nvim",
|
||||
"filemanager": "thunar",
|
||||
"terminal": "kitty"
|
||||
}
|
||||
File renamed without changes.
@@ -0,0 +1,12 @@
|
||||
import { LabelProps } from "types/widgets/label"
|
||||
|
||||
const _icons_folder = `${App.configDir}/assets/icons`
|
||||
|
||||
export const MaterialIcon = (icon: string, size: string = "24px", props?: LabelProps) => Widget.Label({
|
||||
label: icon,
|
||||
class_name: "icon material_icon",
|
||||
css: `font-size: ${size};`,
|
||||
hpack: "center",
|
||||
vpack: "center",
|
||||
...props
|
||||
})
|
||||
+33
-34
@@ -17,6 +17,7 @@ const mpris = await Service.import("mpris")
|
||||
const bluetooth = await Service.import("bluetooth")
|
||||
const { Box, Button, EventBox } = Widget;
|
||||
import Gtk from "gi://Gtk?version=3.0"
|
||||
import { MaterialIcon } from "icons.js"
|
||||
|
||||
|
||||
function checkKeymap() {
|
||||
@@ -32,6 +33,14 @@ hyprland.connect("keyboard-layout", (hyprland, keyboardname, layoutname) => {
|
||||
keyboard_layout.setValue(layoutname.trim().toLowerCase().substr(0, 2))
|
||||
})
|
||||
|
||||
const MATERIAL_SYMBOL_SIGNAL_STRENGTH = {
|
||||
'network-wireless-signal-excellent-symbolic': "signal_wifi_4_bar",
|
||||
'network-wireless-signal-good-symbolic': "network_wifi_3_bar",
|
||||
'network-wireless-signal-ok-symbolic': "network_wifi_2_bar",
|
||||
'network-wireless-signal-weak-symbolic': "network_wifi_1_bar",
|
||||
'network-wireless-signal-none-symbolic': "signal_wifi_0_bar",
|
||||
}
|
||||
|
||||
const time = Variable("", {
|
||||
poll: [1000, 'date "+%I:%M %p"'],
|
||||
})
|
||||
@@ -246,9 +255,7 @@ function AppLauncher() {
|
||||
on_clicked: () => {
|
||||
App.toggleWindow("applauncher")
|
||||
},
|
||||
child: Widget.Label(
|
||||
"\uf002"
|
||||
)
|
||||
child: MaterialIcon("search")
|
||||
})
|
||||
|
||||
return button
|
||||
@@ -256,9 +263,11 @@ function AppLauncher() {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
function Wifi() {
|
||||
return Widget.Button({
|
||||
class_name: "bar_wifi icon",
|
||||
class_name: "bar_wifi",
|
||||
on_primary_click: () => {
|
||||
OpenSettings("network")
|
||||
},
|
||||
@@ -270,25 +279,24 @@ function Wifi() {
|
||||
Utils.execAsync("nm-connection-editor").catch(print)
|
||||
}
|
||||
},
|
||||
child: Widget.Icon({
|
||||
icon: "network-wireless-offline-symbolic"
|
||||
}),
|
||||
child: MaterialIcon("signal_wifi_off", "16px"),
|
||||
tooltip_text: 'Disabled'
|
||||
}).hook(network, self => {
|
||||
if (network.wifi.enabled) {
|
||||
self.tooltip_text = network.wifi.ssid || 'Unknown';
|
||||
self.child.icon = network.wifi.icon_name;
|
||||
self.child.label = MATERIAL_SYMBOL_SIGNAL_STRENGTH[network.wifi.icon_name] || "signal_wifi_off";
|
||||
} else {
|
||||
self.tooltip_text = 'Disabled'
|
||||
self.child.icon = "network-wireless-offline-symbolic";
|
||||
self.child.label = "signal_wifi_off";
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
|
||||
function Bluetooth() {
|
||||
return Widget.Button({
|
||||
class_name: "bar_bluetooth icon",
|
||||
class_name: "bar_bluetooth",
|
||||
on_primary_click: () => {
|
||||
OpenSettings("bluetooth")
|
||||
},
|
||||
@@ -300,14 +308,12 @@ function Bluetooth() {
|
||||
Utils.execAsync("blueman-manager").catch(print)
|
||||
}
|
||||
},
|
||||
child: Widget.Icon({
|
||||
icon: "bluetooth-disabled-symbolic"
|
||||
}),
|
||||
child: MaterialIcon("bluetooth_disabled", "18px"),
|
||||
}).hook(bluetooth, self => {
|
||||
if (bluetooth.enabled) {
|
||||
self.child.icon = "bluetooth-active-symbolic";
|
||||
self.child.icon = "bluetooth";
|
||||
} else {
|
||||
self.child.icon = "bluetooth-disabled-symbolic";
|
||||
self.child.icon = "bluetooth_disabled";
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -328,14 +334,11 @@ function MediaPlayer() {
|
||||
class_name: "filled_tonal_button awesome_icon",
|
||||
on_primary_click: () => {
|
||||
App.toggleWindow("media")
|
||||
// Utils.execAsync(["ags", "-t", "media"])
|
||||
},
|
||||
on_secondary_click: () => {
|
||||
Utils.execAsync(["playerctl", "play-pause"]).catch(print)
|
||||
},
|
||||
child: Widget.Label(
|
||||
""
|
||||
),
|
||||
child: MaterialIcon("play_circle"),
|
||||
visible: false,
|
||||
tooltip_text: "Unknown"
|
||||
}).hook(mpris, self => {
|
||||
@@ -375,7 +378,7 @@ function OpenSideBar() {
|
||||
on_secondary_click: () => {
|
||||
OpenSettings()
|
||||
},
|
||||
label: ""
|
||||
child: MaterialIcon("dock_to_left")
|
||||
})
|
||||
|
||||
return button
|
||||
@@ -432,31 +435,27 @@ if (globalWidgets.length === 0) {
|
||||
|
||||
function volumeIndicator() {
|
||||
return Widget.EventBox({
|
||||
onScrollUp: () => {
|
||||
audio.speaker.volume = Math.min(audio.speaker.volume + 0.05, 1);
|
||||
},
|
||||
onScrollDown: () => {
|
||||
audio.speaker.volume = Math.max(audio.speaker.volume - 0.05, 0);
|
||||
},
|
||||
onScrollUp: () => audio.speaker.volume += 0.01,
|
||||
onScrollDown: () => audio.speaker.volume -= 0.01,
|
||||
class_name: "filled_tonal_button volume_box",
|
||||
child: Widget.Button({
|
||||
on_primary_click: () => Utils.execAsync("pavucontrol").catch(print),
|
||||
on_secondary_click: () => audio.speaker.is_muted = !audio.speaker.is_muted,
|
||||
child: Widget.Box({
|
||||
children: [
|
||||
Widget.Icon().hook(audio.speaker, self => {
|
||||
MaterialIcon("volume_off", "20px").hook(audio.speaker, self => {
|
||||
const vol = audio.speaker.volume * 100;
|
||||
const icon = [
|
||||
[101, 'overamplified'],
|
||||
[67, 'high'],
|
||||
[34, 'medium'],
|
||||
[1, 'low'],
|
||||
[0, 'muted'],
|
||||
[101, 'sound_detection_loud_sound'],
|
||||
[67, 'volume_up'],
|
||||
[34, 'volume_down'],
|
||||
[1, 'volume_mute'],
|
||||
[0, 'volume_off'],
|
||||
].find(([threshold]) => Number(threshold) <= vol)?.[1];
|
||||
if (audio.speaker.is_muted)
|
||||
self.icon = `audio-volume-muted-symbolic`;
|
||||
self.label = "volume_off";
|
||||
else
|
||||
self.icon = `audio-volume-${icon}-symbolic`;
|
||||
self.label = String(icon!);
|
||||
self.tooltip_text = `Volume ${Math.floor(vol)}%`;
|
||||
}),
|
||||
Widget.Label({
|
||||
|
||||
@@ -140,7 +140,7 @@ function Emoji({ width = 500, height = 500, spacing = 12 }) {
|
||||
setup: self => self.hook(App, (_, windowName, visible) => {
|
||||
if (windowName !== WINDOW_NAME) return;
|
||||
if (visible && emojisCache.length === 0) {
|
||||
loadEmojis(`${App.configDir}/emojis.json`)
|
||||
loadEmojis(`${App.configDir}/assets/emojis.json`)
|
||||
.then(emojis => {
|
||||
emojisCache = emojis;
|
||||
list.children = emojis.map(entry => EmojiItem(entry));
|
||||
|
||||
+12
-11
@@ -1,14 +1,15 @@
|
||||
import { MprisPlayer } from 'types/service/mpris.js';
|
||||
import popupwindow from './misc/popupwindow.ts';
|
||||
import Label from 'types/widgets/label.js';
|
||||
import { MaterialIcon } from 'icons.ts';
|
||||
const mpris = await Service.import("mpris")
|
||||
const players = mpris.bind("players")
|
||||
|
||||
const FALLBACK_ICON = "audio-x-generic-symbolic"
|
||||
const PLAY_ICON = "media-playback-start-symbolic"
|
||||
const PAUSE_ICON = "media-playback-pause-symbolic"
|
||||
const PREV_ICON = "media-skip-backward-symbolic"
|
||||
const NEXT_ICON = "media-skip-forward-symbolic"
|
||||
const PLAY_ICON = "play_arrow"
|
||||
const PAUSE_ICON = "pause"
|
||||
const PREV_ICON = "skip_previous"
|
||||
const NEXT_ICON = "skip_next"
|
||||
const WINDOW_NAME = "media"
|
||||
|
||||
function lengthStr(length: number): string {
|
||||
@@ -96,27 +97,28 @@ function Player(player: MprisPlayer) {
|
||||
class_name: "play-pause",
|
||||
on_clicked: () => player.playPause(),
|
||||
visible: player.bind("can_play"),
|
||||
child: Widget.Icon({
|
||||
icon: player.bind("play_back_status").transform(s => {
|
||||
child: MaterialIcon(
|
||||
// @ts-ignore
|
||||
player.bind("play_back_status").transform(s => {
|
||||
switch (s) {
|
||||
case "Playing": return PAUSE_ICON
|
||||
case "Paused":
|
||||
case "Stopped": return PLAY_ICON
|
||||
}
|
||||
}),
|
||||
}),
|
||||
}
|
||||
), "18px"),
|
||||
})
|
||||
|
||||
const prev = Widget.Button({
|
||||
on_clicked: () => player.previous(),
|
||||
visible: player.bind("can_go_prev"),
|
||||
child: Widget.Icon(PREV_ICON),
|
||||
child: MaterialIcon(PREV_ICON, "18px"),
|
||||
})
|
||||
|
||||
const next = Widget.Button({
|
||||
on_clicked: () => player.next(),
|
||||
visible: player.bind("can_go_next"),
|
||||
child: Widget.Icon(NEXT_ICON),
|
||||
child: MaterialIcon(NEXT_ICON, "18px"),
|
||||
})
|
||||
|
||||
return Widget.Box(
|
||||
@@ -169,6 +171,5 @@ export const media = popupwindow({
|
||||
visible: false,
|
||||
keymode: "exclusive",
|
||||
child: Media(),
|
||||
//anchor: ["left", "top"],
|
||||
anchor: ["left", "bottom"],
|
||||
})
|
||||
@@ -5,6 +5,7 @@ import { timeout } from "resource:///com/github/Aylur/ags/utils.js";
|
||||
import GLib from "gi://GLib";
|
||||
import Pango from "gi://Pango";
|
||||
import Label from "types/widgets/label";
|
||||
import { MaterialIcon } from "icons";
|
||||
|
||||
const notifications = await Service.import("notifications")
|
||||
import Gtk from "gi://Gtk?version=3.0"
|
||||
@@ -73,11 +74,11 @@ export const Notification = (notification: NotificationType, dismiss = true) =>
|
||||
}),
|
||||
Widget.Label({
|
||||
class_name: "notification-time",
|
||||
label: GLib.DateTime.new_from_unix_local(notification.time).format("%I:%M %p"),
|
||||
label: GLib.DateTime.new_from_unix_local(notification.time).format("%H:%M"),
|
||||
}),
|
||||
Widget.Button({
|
||||
class_name: "standard_icon_button",
|
||||
child: Widget.Icon("window-close-symbolic"),
|
||||
class_name: "standard_icon_button notification-close",
|
||||
child: MaterialIcon("close"),
|
||||
on_clicked: () => {
|
||||
if (dismiss) {
|
||||
notification.dismiss();
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
import { MaterialIcon } from "icons";
|
||||
|
||||
const { GLib } = imports.gi;
|
||||
|
||||
const lock_command = `hyprlock`;
|
||||
const logout_command = `loginctl kill-session $XDG_SESSION_ID`;
|
||||
const shutdown_command = `systemctl poweroff`;
|
||||
@@ -9,10 +12,7 @@ function LockButton({ icon, ...props }) {
|
||||
let clickCount = 0;
|
||||
let button = Widget.Button({
|
||||
tooltip_text: "Lock",
|
||||
child: Widget.Label({
|
||||
label: icon,
|
||||
class_name: "awesome_icon"
|
||||
}),
|
||||
child: MaterialIcon(icon, "20px"),
|
||||
class_name: "outline_button",
|
||||
...props,
|
||||
})
|
||||
@@ -37,10 +37,7 @@ function SuspendButton({ icon, ...props }) {
|
||||
let clickCount = 0;
|
||||
let button = Widget.Button({
|
||||
tooltip_text: "Suspend",
|
||||
child: Widget.Label({
|
||||
label: icon,
|
||||
class_name: "awesome_icon"
|
||||
}),
|
||||
child: MaterialIcon(icon, "20px"),
|
||||
class_name: "outline_button",
|
||||
...props,
|
||||
})
|
||||
@@ -67,10 +64,7 @@ function LogoutButton({ icon, ...props }) {
|
||||
let clickCount = 0;
|
||||
let button = Widget.Button({
|
||||
tooltip_text: "Logout",
|
||||
child: Widget.Label({
|
||||
label: icon,
|
||||
class_name: "awesome_icon"
|
||||
}),
|
||||
child: MaterialIcon(icon, "20px"),
|
||||
class_name: "outline_button",
|
||||
...props,
|
||||
})
|
||||
@@ -95,10 +89,7 @@ function RebootButton({ icon, ...props }) {
|
||||
let clickCount = 0;
|
||||
let button = Widget.Button({
|
||||
tooltip_text: "Reboot",
|
||||
child: Widget.Label({
|
||||
label: icon,
|
||||
class_name: "awesome_icon"
|
||||
}),
|
||||
child: MaterialIcon(icon, "20px"),
|
||||
class_name: "outline_button",
|
||||
...props,
|
||||
})
|
||||
@@ -123,10 +114,7 @@ function ShutdownButton({ icon, ...props }) {
|
||||
let clickCount = 0;
|
||||
let button = Widget.Button({
|
||||
tooltip_text: "Shutdown",
|
||||
child: Widget.Label({
|
||||
label: icon,
|
||||
class_name: "awesome_icon"
|
||||
}),
|
||||
child: MaterialIcon(icon, "20px"),
|
||||
class_name: "outline_button",
|
||||
...props,
|
||||
})
|
||||
@@ -154,23 +142,23 @@ export function Buttons() {
|
||||
spacing: 5,
|
||||
children: [
|
||||
LockButton({
|
||||
icon: "",
|
||||
icon: "lock",
|
||||
hexpand: true,
|
||||
}),
|
||||
SuspendButton({
|
||||
icon: "",
|
||||
icon: "clear_night",
|
||||
hexpand: true,
|
||||
}),
|
||||
LogoutButton({
|
||||
icon: "",
|
||||
icon: "logout",
|
||||
hexpand: true,
|
||||
}),
|
||||
RebootButton({
|
||||
icon: "",
|
||||
icon: "restart_alt",
|
||||
hexpand: true,
|
||||
}),
|
||||
ShutdownButton({
|
||||
icon: "",
|
||||
icon: "power_settings_new",
|
||||
hexpand: true,
|
||||
})
|
||||
]
|
||||
|
||||
@@ -5,6 +5,7 @@ const powerProfiles = await Service.import('powerprofiles')
|
||||
import { OpenSettings } from "apps/settings/main.ts";
|
||||
import { WINDOW_NAME } from "./main.ts"
|
||||
import { bluetooth_enabled, idle_inhibitor, night_light, screen_recorder } from "variables.ts";
|
||||
import { MaterialIcon } from "icons.ts";
|
||||
|
||||
import Gtk from "gi://Gtk?version=3.0"
|
||||
|
||||
@@ -16,11 +17,7 @@ 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;`,
|
||||
}),
|
||||
MaterialIcon("signal_wifi_4_bar", "20px"),
|
||||
Widget.Box({
|
||||
visible: network.wifi.bind('enabled'),
|
||||
orientation: Gtk.Orientation.VERTICAL,
|
||||
@@ -47,10 +44,8 @@ function WifiIndicator() {
|
||||
Widget.Box({
|
||||
hpack: "end",
|
||||
hexpand: true,
|
||||
child: Widget.Label({
|
||||
label: "",
|
||||
class_name: "awesome_icon",
|
||||
css: `font-weight: normal; font-size: 15px;`,
|
||||
child: MaterialIcon("chevron_right", "20px", {
|
||||
class_name: "material_icon icon arrow"
|
||||
})
|
||||
})
|
||||
],
|
||||
@@ -60,9 +55,7 @@ function WifiIndicator() {
|
||||
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'),
|
||||
}),
|
||||
MaterialIcon("settings_ethernet", "20px"),
|
||||
Widget.Label({
|
||||
label: "Internet",
|
||||
}),
|
||||
@@ -83,11 +76,7 @@ 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};`,
|
||||
}),
|
||||
MaterialIcon(icon, "20px"),
|
||||
Widget.Label({
|
||||
label: label,
|
||||
justification: "center",
|
||||
@@ -98,10 +87,8 @@ function IconAndName({ label, icon, padding = "0.3em", arrow = false }) {
|
||||
const arrow = Widget.Box({
|
||||
hpack: "end",
|
||||
hexpand: true,
|
||||
child: Widget.Label({
|
||||
label: "",
|
||||
class_name: "awesome_icon",
|
||||
css: `font-weight: normal; font-size: 15px;`,
|
||||
child: MaterialIcon("chevron_right", "20px", {
|
||||
class_name: "material_icon icon arrow"
|
||||
})
|
||||
})
|
||||
// @ts-ignore
|
||||
@@ -133,7 +120,10 @@ function startRecordingTimer(button) {
|
||||
recordingStartTime = Date.now();
|
||||
recordingInterval = setInterval(() => {
|
||||
let elapsedTime = Date.now() - recordingStartTime;
|
||||
button.label = formatTime(elapsedTime);
|
||||
button.child = IconAndName({
|
||||
label: formatTime(elapsedTime),
|
||||
icon: "stop_circle"
|
||||
});
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
@@ -141,7 +131,11 @@ function stopRecordingTimer(button) {
|
||||
clearInterval(recordingInterval);
|
||||
recordingStartTime = null;
|
||||
recordingInterval = null;
|
||||
button.label = ' Screen Recorder';
|
||||
button.label = 'Screen Recorder';
|
||||
button.child = IconAndName({
|
||||
label: "Screen Recorder",
|
||||
icon: "screen_record"
|
||||
});
|
||||
}
|
||||
|
||||
// Widget
|
||||
@@ -177,7 +171,7 @@ function Page1() {
|
||||
),
|
||||
child: IconAndName({
|
||||
label: "Bluetooth",
|
||||
icon: "",
|
||||
icon: "bluetooth",
|
||||
arrow: true,
|
||||
}),
|
||||
on_primary_click: () => {
|
||||
@@ -202,7 +196,7 @@ function Page1() {
|
||||
.as(bool => bool ? "management_button active" : "management_button"),
|
||||
child: IconAndName({
|
||||
label: "Idle inhibitor",
|
||||
icon: ""
|
||||
icon: "schedule"
|
||||
}),
|
||||
onClicked: () => {
|
||||
idle_inhibitor.setValue(!idle_inhibitor.value)
|
||||
@@ -223,7 +217,8 @@ function Page1() {
|
||||
},
|
||||
child: IconAndName({
|
||||
label: "Do Not Disturb",
|
||||
icon: ""
|
||||
icon: notifications.bind("dnd")
|
||||
.as((bool) => bool ? "do_not_disturb_on" : "do_not_disturb_off")
|
||||
})
|
||||
})
|
||||
]
|
||||
@@ -234,37 +229,42 @@ function Page1() {
|
||||
hexpand: true,
|
||||
children: [
|
||||
Widget.Button({
|
||||
hexpand: true,
|
||||
class_name: screen_recorder.bind()
|
||||
.as(bool => bool ? "management_button active" : "management_button"),
|
||||
on_clicked: (self) => {
|
||||
hexpand: true,
|
||||
class_name: screen_recorder.bind()
|
||||
.as(bool => bool ? "management_button active" : "management_button"),
|
||||
child: IconAndName({
|
||||
label: "Screen Recorder",
|
||||
icon: "screen_record"
|
||||
}),
|
||||
onClicked: (self) => {
|
||||
isScreenRecordingOn().then(isRecording => {
|
||||
if (isRecording) {
|
||||
stopRecordingTimer(self);
|
||||
} else {
|
||||
startRecordingTimer(self);
|
||||
}
|
||||
self.toggleClassName("active-button", !isRecording);
|
||||
self.toggleClassName("recording", !isRecording);
|
||||
|
||||
Utils.execAsync(['bash', '-c', 'mkdir -p ~/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)
|
||||
.then(() => {
|
||||
isScreenRecordingOn().then(newIsRecording => {
|
||||
if (!newIsRecording) {
|
||||
stopRecordingTimer(self);
|
||||
}
|
||||
})
|
||||
});
|
||||
} else {
|
||||
startRecordingTimer(self);
|
||||
}
|
||||
self.toggleClassName("active-button", !isRecording);
|
||||
self.toggleClassName("recording", !isRecording);
|
||||
Utils.execAsync(['bash', '-c', 'mkdir -p ~/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)
|
||||
.then(() => {
|
||||
isScreenRecordingOn().then(newIsRecording => {
|
||||
if (!newIsRecording) {
|
||||
stopRecordingTimer(self);
|
||||
}
|
||||
});
|
||||
},
|
||||
child: IconAndName({
|
||||
label: "Screen Recorder",
|
||||
icon: "",
|
||||
setup: self => {
|
||||
self.label = ' Screen Recorder';
|
||||
}
|
||||
})
|
||||
});
|
||||
});
|
||||
},
|
||||
setup: (self) => {
|
||||
isScreenRecordingOn().then(isRecording => {
|
||||
if (isRecording) {
|
||||
startRecordingTimer(self);
|
||||
self.addClassName("active-button");
|
||||
self.addClassName("recording");
|
||||
}
|
||||
});
|
||||
}
|
||||
}),
|
||||
Widget.Button({
|
||||
hexpand: true,
|
||||
@@ -272,7 +272,7 @@ function Page1() {
|
||||
.as(mode => mode ? "management_button active" : "management_button"),
|
||||
child: IconAndName({
|
||||
label: "Night Light",
|
||||
icon: ""
|
||||
icon: "nightlight"
|
||||
}),
|
||||
onClicked: () => {
|
||||
night_light.setValue(!night_light.value)
|
||||
@@ -317,7 +317,7 @@ function Page2() {
|
||||
class_name: "management_button",
|
||||
child: IconAndName({
|
||||
label: "Color picker",
|
||||
icon: "",
|
||||
icon: "colorize",
|
||||
arrow: true,
|
||||
}),
|
||||
on_primary_click: () => {
|
||||
@@ -338,11 +338,11 @@ function Page2() {
|
||||
icon: powerProfiles.bind('active_profile').as(profile => {
|
||||
switch (profile) {
|
||||
case 'balanced':
|
||||
return '';
|
||||
return 'balance';
|
||||
case 'performance':
|
||||
return '';
|
||||
return 'bolt';
|
||||
default:
|
||||
return '';
|
||||
return 'eco';
|
||||
}
|
||||
})
|
||||
}),
|
||||
@@ -377,7 +377,7 @@ function Page2() {
|
||||
class_name: "management_button",
|
||||
child: IconAndName({
|
||||
label: "Settings",
|
||||
icon: "",
|
||||
icon: "settings",
|
||||
arrow: true,
|
||||
}),
|
||||
on_primary_click: () => {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
|
||||
import { NotificationsBox } from "./notifications.ts"
|
||||
import { SystemBox } from "./system.ts"
|
||||
let shown = Variable("Messages");
|
||||
import Gtk from "gi://Gtk?version=3.0"
|
||||
import { MaterialIcon } from "icons.ts";
|
||||
|
||||
|
||||
type ButtonType = {
|
||||
@@ -22,13 +22,9 @@ function Button({ page, label, icon }: ButtonType) {
|
||||
children: [
|
||||
Widget.Box({
|
||||
orientation: Gtk.Orientation.VERTICAL,
|
||||
hpack: "end",
|
||||
hpack: "center",
|
||||
class_name: "container",
|
||||
child: Widget.Label({
|
||||
hpack: "center",
|
||||
label: icon,
|
||||
class_name: "awesome_icon icon"
|
||||
}),
|
||||
child: MaterialIcon(icon, "20px"),
|
||||
}),
|
||||
Widget.Label({
|
||||
label: label,
|
||||
@@ -63,17 +59,17 @@ export function Navigation() {
|
||||
Button({
|
||||
page: "Messages",
|
||||
label: "Messages",
|
||||
icon: ""
|
||||
icon: "chat"
|
||||
}),
|
||||
Button({
|
||||
page: "Notifications",
|
||||
label: "Notifs",
|
||||
icon: ""
|
||||
icon: "notifications"
|
||||
}),
|
||||
Button({
|
||||
page: "System",
|
||||
label: "System",
|
||||
icon: ""
|
||||
icon: "info"
|
||||
})
|
||||
]
|
||||
})
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
import argparse
|
||||
import re
|
||||
import os
|
||||
import json
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
group = parser.add_mutually_exclusive_group(required=True)
|
||||
group.add_argument('--browser', type=str, help="Change default browser")
|
||||
group.add_argument('--filemanager', type=str, help="Change file manager")
|
||||
group.add_argument('--editor', type=str, help="Change default editor")
|
||||
group.add_argument('--terminal', type=str, help="Change default terminal")
|
||||
group.add_argument('--get', type=str, help="Get default app", choices=["browser", "editor", "terminal", "filemanager"])
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
config_file = os.path.expanduser("~/dotfiles/hypr/UserConfigs/Apps.conf")
|
||||
json_config_file = os.path.expanduser("~/dotfiles/ags/assets/apps.json")
|
||||
|
||||
def read_apps_conf():
|
||||
with open(config_file) as f:
|
||||
return f.read().strip()
|
||||
|
||||
def write_apps_conf(content):
|
||||
with open(config_file, 'w') as f:
|
||||
f.write(content + '\n')
|
||||
|
||||
def read_json_config():
|
||||
with open(json_config_file) as json_file:
|
||||
return json.load(json_file)
|
||||
|
||||
def write_json_config(config):
|
||||
with open(json_config_file, 'w') as json_file:
|
||||
json.dump(config, json_file, indent=4)
|
||||
|
||||
def which(program: str):
|
||||
def is_executable(fpath):
|
||||
return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
|
||||
|
||||
fpath, fname = os.path.split(program)
|
||||
if fpath:
|
||||
if is_executable(program):
|
||||
return program
|
||||
else:
|
||||
for path in os.environ["PATH"].split(os.pathsep):
|
||||
path = path.strip('"')
|
||||
exe_file = os.path.join(path, program)
|
||||
if is_executable(exe_file):
|
||||
return exe_file
|
||||
raise ProgramNotFound(value)
|
||||
|
||||
def extract_associations(env_str):
|
||||
pattern = re.compile(r'^\s*env\s*=\s*(\w+)\s*,\s*(.*?)\s*#\s*!\s*-\s*@(\w+)\s*$', re.MULTILINE) # noqa
|
||||
associations = {}
|
||||
matches = pattern.findall(env_str)
|
||||
for key, _, association in matches:
|
||||
if association not in associations:
|
||||
associations[association] = []
|
||||
if key not in associations[association]:
|
||||
associations[association].append(key)
|
||||
return associations
|
||||
|
||||
def replace_value(env_str, key, new_value):
|
||||
pattern = re.compile(
|
||||
r'^(\s*env\s*=\s*' +
|
||||
re.escape(key) +
|
||||
r'\s*,\s*)(.*?)\s*(#.*)?$', re.MULTILINE
|
||||
)
|
||||
return re.sub(pattern, r'\1' + new_value + r' \3', env_str)
|
||||
|
||||
class AssociationNotFound(Exception):
|
||||
def __init__(self, name: str, *args: object) -> None:
|
||||
error = f"{name} association not found"
|
||||
super().__init__(error, *args)
|
||||
|
||||
class ProgramNotFound(Exception):
|
||||
def __init__(self, name: str, *args: object) -> None:
|
||||
error = f"{name} not found"
|
||||
super().__init__(error, *args)
|
||||
|
||||
def change_association(key: str, value: str):
|
||||
env_str = read_apps_conf()
|
||||
which(value)
|
||||
associations = extract_associations(env_str)
|
||||
if key not in associations:
|
||||
raise AssociationNotFound(key)
|
||||
|
||||
for key in associations[key]:
|
||||
env_str = replace_value(env_str, key, value)
|
||||
|
||||
write_apps_conf(env_str)
|
||||
|
||||
def update_json_config(key: str, value: str):
|
||||
config = read_json_config()
|
||||
config[key] = value
|
||||
write_json_config(config)
|
||||
|
||||
if args.get:
|
||||
json_config = read_json_config()
|
||||
print(json_config[args.get])
|
||||
elif args.browser:
|
||||
change_association("browser", args.browser)
|
||||
update_json_config("browser", args.browser)
|
||||
elif args.filemanager:
|
||||
change_association("filemanager", args.filemanager)
|
||||
update_json_config("filemanager", args.filemanager)
|
||||
elif args.editor:
|
||||
change_association("editor", args.editor)
|
||||
update_json_config("editor", args.editor)
|
||||
elif args.terminal:
|
||||
change_association("terminal", args.terminal)
|
||||
update_json_config("terminal", args.terminal)
|
||||
@@ -67,7 +67,7 @@
|
||||
color: @onSecondaryContainer;
|
||||
}
|
||||
|
||||
.settings .sidebar .row image {
|
||||
.settings .sidebar .row .icon {
|
||||
margin-right: 12px;
|
||||
color: @onSurfaceVariant;
|
||||
}
|
||||
@@ -111,6 +111,10 @@
|
||||
background-color: mix(@onSurface, @surface, 0.92)
|
||||
}
|
||||
|
||||
.settings .row:active {
|
||||
background-color: mix(@onSurface, @surface, 0.8)
|
||||
}
|
||||
|
||||
.settings .row.focused {
|
||||
background-color: mix(@onSurface, @surface, 0.8)
|
||||
}
|
||||
@@ -127,6 +131,11 @@
|
||||
color: @onSurfaceVariant
|
||||
}
|
||||
|
||||
.settings .row .icon {
|
||||
color: @onSurfaceVariant;
|
||||
margin-right: 16px;
|
||||
}
|
||||
|
||||
.settings .bottom_bar {
|
||||
background-color: @surface;
|
||||
font-weight: normal;
|
||||
@@ -142,7 +151,7 @@
|
||||
min-width: 30px;
|
||||
min-height: 32px;
|
||||
border-radius: 4px;
|
||||
background-color: @surfaceContainerHighest;
|
||||
background-color: @surfaceContainerHigh;
|
||||
}
|
||||
|
||||
.settings entry label, .settings combobox label {
|
||||
@@ -152,12 +161,12 @@
|
||||
|
||||
/* Wifi */
|
||||
|
||||
.settings .wifi_list .row image {
|
||||
.settings .wifi_list .row .icon {
|
||||
color: @onSurfaceVariant;
|
||||
margin-right: 16px;
|
||||
}
|
||||
|
||||
.settings .wifi_list .row.active image {
|
||||
.settings .wifi_list .row.active .icon {
|
||||
color: @primary;
|
||||
}
|
||||
|
||||
|
||||
+63
-31
@@ -271,6 +271,10 @@ window.notification-popups box.notifications {
|
||||
color: @primary;
|
||||
}
|
||||
|
||||
.notification-close .icon {
|
||||
font-weight: 300;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* Applications
|
||||
* ----------------------------------------------------- */
|
||||
@@ -342,25 +346,6 @@ window.notification-popups box.notifications {
|
||||
* Clipboard history
|
||||
* ----------------------------------------------------- */
|
||||
|
||||
.emoji_box {
|
||||
border-radius: 24px;
|
||||
background-color: @background;
|
||||
border: 2px solid;
|
||||
border-color: @outlineVariant;
|
||||
padding: 11px;
|
||||
}
|
||||
|
||||
.emoji_entry {
|
||||
background-color: @surfaceContainerHigh;
|
||||
color: @onSurface;
|
||||
border: none;
|
||||
outline: none;
|
||||
border-radius: 100px;
|
||||
margin-bottom: 16px;
|
||||
padding: 5px;
|
||||
padding-left: 25px;
|
||||
}
|
||||
|
||||
.cliphistory_box {
|
||||
border-radius: 24px;
|
||||
background-color: @background;
|
||||
@@ -416,6 +401,28 @@ window.notification-popups box.notifications {
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* Emoji
|
||||
* -----------------------------------------------------*/
|
||||
|
||||
.emoji_box {
|
||||
border-radius: 24px;
|
||||
background-color: @background;
|
||||
border: 2px solid;
|
||||
border-color: @outlineVariant;
|
||||
padding: 11px;
|
||||
}
|
||||
|
||||
.emoji_entry {
|
||||
background-color: @surfaceContainerHigh;
|
||||
color: @onSurface;
|
||||
border: none;
|
||||
outline: none;
|
||||
border-radius: 100px;
|
||||
margin-bottom: 16px;
|
||||
padding: 5px;
|
||||
padding-left: 25px;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* Media player
|
||||
@@ -486,10 +493,12 @@ window.notification-popups box.notifications {
|
||||
min-height: 1em;
|
||||
min-width: 1em;
|
||||
padding: .3em;
|
||||
padding-top: 0px;
|
||||
padding-bottom: 0px;
|
||||
color: @onSecondary;
|
||||
}
|
||||
|
||||
.player button image {
|
||||
.player button .icon {
|
||||
color: @onSecondary;
|
||||
}
|
||||
|
||||
@@ -515,7 +524,12 @@ window.notification-popups box.notifications {
|
||||
border-radius: 100px;
|
||||
}
|
||||
|
||||
.volume_box image {
|
||||
.volume_box button {
|
||||
padding-top: 0px;
|
||||
padding-bottom: 0px;
|
||||
}
|
||||
|
||||
.volume_box .icon {
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
@@ -523,6 +537,10 @@ window.notification-popups box.notifications {
|
||||
font-family: "Font Awesome 6 Free";
|
||||
}
|
||||
|
||||
.material_icon {
|
||||
font-family: "Material Symbols Outlined", "Material Symbols Sharp";
|
||||
}
|
||||
|
||||
.battery {
|
||||
background-color: @surfaceContainer;
|
||||
border-radius: 100px;
|
||||
@@ -544,7 +562,7 @@ window.notification-popups box.notifications {
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
.bar_applets image {
|
||||
.bar_applets .icon {
|
||||
color: @onSurface;
|
||||
}
|
||||
|
||||
@@ -595,7 +613,12 @@ window.notification-popups box.notifications {
|
||||
}
|
||||
|
||||
.management_button .icon {
|
||||
color: @onSurface
|
||||
color: @onSurface;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.management_button .arrow {
|
||||
margin-right: 0px;
|
||||
}
|
||||
|
||||
.management_button:hover {
|
||||
@@ -606,8 +629,9 @@ window.notification-popups box.notifications {
|
||||
color: @onPrimary
|
||||
}
|
||||
|
||||
.management_button.active .icon {
|
||||
color: @onPrimary
|
||||
.management_button.active .icon{
|
||||
color: @onPrimary;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.management_button.active {
|
||||
@@ -682,7 +706,7 @@ window.notification-popups box.notifications {
|
||||
}
|
||||
|
||||
.system_scale.backlight {
|
||||
margin-bottom: 25px;
|
||||
margin-bottom: 28px;
|
||||
}
|
||||
|
||||
.system_scale.brightness slider {
|
||||
@@ -799,6 +823,7 @@ window.notification-popups box.notifications {
|
||||
.outline_button label, .outline_button .icon,
|
||||
.outline_button .awesome_icon, .outline_button image {
|
||||
color: @primary;
|
||||
font-weight: 300;
|
||||
}
|
||||
|
||||
.outline_button:hover {
|
||||
@@ -815,11 +840,16 @@ window.notification-popups box.notifications {
|
||||
background-color: @secondaryContainer;
|
||||
color: @onSecondaryContainer;
|
||||
border-radius: 100px;
|
||||
padding: 0px;
|
||||
padding-left: 6px;
|
||||
padding-right: 6px;
|
||||
}
|
||||
|
||||
.filled_tonal_button label, .filled_tonal_button .icon,
|
||||
.filled_tonal_button .awesome_icon, .filled_tonal_button image {
|
||||
color: @onSecondaryContainer;
|
||||
font-weight: 400;
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
.filled_tonal_button:hover {
|
||||
@@ -940,19 +970,19 @@ filled_button.disabled .awesome_icon, .filled_button.disabled image {
|
||||
|
||||
.navigation_button .container {
|
||||
border-radius: 16px;
|
||||
padding: 5px;
|
||||
padding-left: 5px;
|
||||
padding-right: 5px;
|
||||
min-height: 15px;
|
||||
min-width: 0px;
|
||||
transition-property: min-width, color, background-color, border-color;
|
||||
}
|
||||
|
||||
.navigation_button .icon {
|
||||
font-weight: normal;
|
||||
font-weight: 400;
|
||||
color: @onSurface;
|
||||
}
|
||||
|
||||
.navigation_button.active .icon {
|
||||
font-weight: bold;
|
||||
color: @onSecondaryContainer;
|
||||
}
|
||||
|
||||
@@ -1048,6 +1078,7 @@ switch:checked:hover slider, switch:checked:active slider {
|
||||
background-color: @primaryContainer;
|
||||
}
|
||||
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* Cheatsheet
|
||||
* ----------------------------------------------------- */
|
||||
@@ -1069,8 +1100,9 @@ switch:checked:hover slider, switch:checked:active slider {
|
||||
}
|
||||
|
||||
.cheatsheet .category separator {
|
||||
margin-top: 2px;
|
||||
margin-bottom: 2px;
|
||||
margin-top: 4px;
|
||||
margin-bottom: 4px;
|
||||
color: @outline;
|
||||
}
|
||||
|
||||
.cheatsheet .category .row {
|
||||
|
||||
Reference in new issue
Block a user