✨ feat: use gtk icons instead of nerdfonts across the shell
also removed hour count from recording widgets
This commit is contained in:
@@ -47,11 +47,10 @@ export const NotifHistory = () => {
|
||||
className: "clear-all",
|
||||
child: new Widget.Box({
|
||||
children: [
|
||||
new Widget.Label({
|
||||
className: "nf",
|
||||
css: "margin-right: 6px",
|
||||
label: ""
|
||||
} as Widget.LabelProps),
|
||||
new Widget.Icon({
|
||||
css: "margin-right: 6px;",
|
||||
icon: "edit-clear-all-symbolic"
|
||||
} as Widget.IconProps),
|
||||
new Widget.Label({
|
||||
label: tr("clear")
|
||||
} as Widget.LabelProps)
|
||||
|
||||
@@ -7,8 +7,9 @@ import { Wallpaper } from "../../scripts/wallpaper";
|
||||
|
||||
function LockButton(): Widget.Button {
|
||||
return new Widget.Button({
|
||||
className: "nf",
|
||||
label: "",
|
||||
image: new Widget.Icon({
|
||||
icon: "system-lock-screen-symbolic"
|
||||
} as Widget.IconProps),
|
||||
onClick: () => {
|
||||
Windows.close("control-center");
|
||||
AstalHyprland.get_default().dispatch("exec", "hyprlock");
|
||||
@@ -18,8 +19,9 @@ function LockButton(): Widget.Button {
|
||||
|
||||
function ColorPickerButton(): Widget.Button {
|
||||
return new Widget.Button({
|
||||
className: "nf",
|
||||
label: "",
|
||||
image: new Widget.Icon({
|
||||
icon: "color-select-symbolic"
|
||||
} as Widget.IconProps),
|
||||
onClick: () => AstalHyprland.get_default().dispatch(
|
||||
"exec",
|
||||
"sh $HOME/.config/hypr/scripts/color-picker.sh"
|
||||
@@ -29,8 +31,9 @@ function ColorPickerButton(): Widget.Button {
|
||||
|
||||
function ScreenshotButton(): Widget.Button {
|
||||
return new Widget.Button({
|
||||
className: "nf",
|
||||
label: "",
|
||||
image: new Widget.Icon({
|
||||
icon: "applets-screenshooter-symbolic"
|
||||
} as Widget.IconProps),
|
||||
onClick: () => {
|
||||
Windows.close("control-center");
|
||||
execAsync(`sh ${GLib.get_user_config_dir()}/hypr/scripts/screenshot.sh`);
|
||||
@@ -40,8 +43,9 @@ function ScreenshotButton(): Widget.Button {
|
||||
|
||||
function SelectWallpaperButton(): Widget.Button {
|
||||
return new Widget.Button({
|
||||
className: "nf",
|
||||
label: "",
|
||||
image: new Widget.Icon({
|
||||
icon: "preferences-desktop-wallpaper-symbolic"
|
||||
} as Widget.IconProps),
|
||||
onClick: () => {
|
||||
Windows.close("control-center");
|
||||
Wallpaper.getDefault().pickWallpaper();
|
||||
@@ -51,8 +55,9 @@ function SelectWallpaperButton(): Widget.Button {
|
||||
|
||||
function LogoutButton(): Widget.Button {
|
||||
return new Widget.Button({
|
||||
className: "nf",
|
||||
label: "",
|
||||
image: new Widget.Icon({
|
||||
icon: "system-shutdown-symbolic"
|
||||
} as Widget.IconProps),
|
||||
onClick: () => Windows.open("logout-menu")
|
||||
} as Widget.ButtonProps);
|
||||
}
|
||||
@@ -76,13 +81,20 @@ export const QuickActions = () => {
|
||||
tooltipText: "Host name",
|
||||
label: GLib.get_host_name()
|
||||
} as Widget.LabelProps),
|
||||
new Widget.Label({
|
||||
className: "uptime",
|
||||
xalign: 0,
|
||||
tooltipText: "Uptime",
|
||||
onDestroy: () => uptime.drop(),
|
||||
label: uptime().as((uptime: string) => ` ${uptime}`)
|
||||
} as Widget.LabelProps)
|
||||
new Widget.Box({
|
||||
children: [
|
||||
new Widget.Icon({
|
||||
icon: "hourglass-symbolic"
|
||||
} as Widget.IconProps),
|
||||
new Widget.Label({
|
||||
className: "uptime",
|
||||
xalign: 0,
|
||||
tooltipText: "Uptime",
|
||||
onDestroy: () => uptime.drop(),
|
||||
label: uptime()
|
||||
} as Widget.LabelProps)
|
||||
]
|
||||
} as Widget.BoxProps)
|
||||
]
|
||||
} as Widget.BoxProps),
|
||||
new Widget.Box({
|
||||
|
||||
@@ -12,20 +12,18 @@ export function Sliders() {
|
||||
className: "sliders",
|
||||
orientation: Gtk.Orientation.VERTICAL,
|
||||
expand: true,
|
||||
spacing: 10,
|
||||
children: [
|
||||
new Widget.Box({
|
||||
className: "sink speaker",
|
||||
spacing: 3,
|
||||
children: bind(Wireplumber.getWireplumber(), "defaultSpeaker").as((sink) => [
|
||||
new Widget.Button({
|
||||
className: "nf",
|
||||
onClick: () => Wireplumber.getDefault().toggleMuteSink(),
|
||||
children: [
|
||||
new Widget.Icon ({
|
||||
icon: bind(sink, "volumeIcon").as((icon) =>
|
||||
!Wireplumber.getDefault().isMutedSink() && Wireplumber.getDefault().getSinkVolume() > 0 ? icon : "audio-volume-muted-symbolic"),
|
||||
css: "margin-right: 10px;"
|
||||
} as Widget.IconProps),
|
||||
]
|
||||
image: new Widget.Icon ({
|
||||
icon: bind(sink, "volumeIcon").as((icon) =>
|
||||
!Wireplumber.getDefault().isMutedSink() && Wireplumber.getDefault().getSinkVolume() > 0 ? icon : "audio-volume-muted-symbolic"),
|
||||
} as Widget.IconProps),
|
||||
} as Widget.ButtonProps),
|
||||
new Widget.Slider({
|
||||
drawValue: false,
|
||||
@@ -46,17 +44,14 @@ export function Sliders() {
|
||||
} as Widget.BoxProps),
|
||||
new Widget.Box({
|
||||
className: "source microphone",
|
||||
spacing: 3,
|
||||
children: bind(Wireplumber.getWireplumber(), "defaultMicrophone").as((source) => [
|
||||
new Widget.Button({
|
||||
className: "nf",
|
||||
onClick: () => Wireplumber.getDefault().toggleMuteSource(),
|
||||
children: [
|
||||
new Widget.Icon ({
|
||||
icon: bind(source, "volumeIcon").as((icon) =>
|
||||
!Wireplumber.getDefault().isMutedSource() && Wireplumber.getDefault().getSourceVolume() > 0 ? icon : "microphone-sensitivity-muted-symbolic"),
|
||||
css: "margin-right: 10px;"
|
||||
} as Widget.IconProps),
|
||||
]
|
||||
image: new Widget.Icon ({
|
||||
icon: bind(source, "volumeIcon").as((icon) =>
|
||||
!Wireplumber.getDefault().isMutedSource() && Wireplumber.getDefault().getSourceVolume() > 0 ? icon : "microphone-sensitivity-muted-symbolic"),
|
||||
} as Widget.IconProps),
|
||||
} as Widget.ButtonProps),
|
||||
new Widget.Slider({
|
||||
drawValue: false,
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
import { bind, Variable } from "astal";
|
||||
import { bind, Gio, Variable } from "astal";
|
||||
import { Gtk, Widget } from "astal/gtk3";
|
||||
import AstalBluetooth from "gi://AstalBluetooth";
|
||||
import { Page, PageButton } from "./Page";
|
||||
import { tr } from "../../../i18n/intl";
|
||||
import AstalHyprland from "gi://AstalHyprland";
|
||||
import { Windows } from "../../../windows";
|
||||
import { Notifications } from "../../../scripts/notifications";
|
||||
import AstalNotifd from "gi://AstalNotifd";
|
||||
|
||||
export const BluetoothPage: (() => Page) = () => new Page({
|
||||
id: "bluetooth",
|
||||
@@ -13,9 +15,13 @@ export const BluetoothPage: (() => Page) = () => new Page({
|
||||
className: "bluetooth",
|
||||
headerButtons: [
|
||||
new Widget.Button({
|
||||
className: "discover nf",
|
||||
label: bind(AstalBluetooth.get_default().adapter, "discovering").as((discovering) =>
|
||||
!discovering ? '' : ''),
|
||||
className: "discover",
|
||||
image: new Widget.Icon({
|
||||
icon: bind(AstalBluetooth.get_default().adapter, "discovering").as((discovering) =>
|
||||
!discovering ?
|
||||
"arrow-circular-top-right-symbolic"
|
||||
: "media-playback-stop-symbolic")
|
||||
} as Widget.IconProps),
|
||||
tooltipText: bind(AstalBluetooth.get_default().adapter, "discovering").as((discovering) =>
|
||||
!discovering ?
|
||||
tr("control_center.pages.bluetooth.start_discovering")
|
||||
@@ -117,8 +123,11 @@ function DeviceWidget(dev: AstalBluetooth.Device): Gtk.Widget {
|
||||
bind(dev, "trusted")
|
||||
], (connected, paired, trusted) => paired ? [
|
||||
new Widget.Button({
|
||||
className: "nf",
|
||||
label: connected ? '' : "",
|
||||
image: new Widget.Icon({
|
||||
icon: connected ?
|
||||
"list-remove-symbolic"
|
||||
: "user-trash-symbolic"
|
||||
} as Widget.IconProps),
|
||||
tooltipText: tr(connected ? "disconnect" : "control_center.pages.bluetooth.unpair_device"),
|
||||
onClick: () => {
|
||||
if(!connected) {
|
||||
@@ -130,8 +139,11 @@ function DeviceWidget(dev: AstalBluetooth.Device): Gtk.Widget {
|
||||
},
|
||||
} as Widget.ButtonProps),
|
||||
new Widget.Button({
|
||||
className: "nf",
|
||||
label: trusted ? "" : "",
|
||||
image: new Widget.Icon({
|
||||
icon: trusted ?
|
||||
"shield-safe-symbolic"
|
||||
: "shield-danger-symbolic"
|
||||
} as Widget.IconProps),
|
||||
tooltipText: tr(`control_center.pages.bluetooth.${trusted ? "un": ""}trust_device`),
|
||||
onClick: () => dev.set_trusted(!trusted)
|
||||
} as Widget.ButtonProps)
|
||||
@@ -141,15 +153,36 @@ function DeviceWidget(dev: AstalBluetooth.Device): Gtk.Widget {
|
||||
className: bind(dev, "connected").as((connected) => connected ? "connected" : ""),
|
||||
title: bind(dev, "alias").as(alias => alias ?? "Unknown Device"),
|
||||
icon: dev.icon ?? "bluetooth-active-symbolic",
|
||||
description: bind(dev, "connecting").as(connecting =>
|
||||
connecting ? `${tr("connecting")}...` : ""),
|
||||
tooltipText: bind(dev, "connected").as(connected => !connected ?
|
||||
tr("connect")
|
||||
: ""),
|
||||
onDestroy: () => devActions.drop(),
|
||||
onClick: () => {
|
||||
if(dev.connected) return;
|
||||
if(!dev.paired) dev.pair();
|
||||
|
||||
dev.connect_device(null);
|
||||
let skipConnection: boolean = false;
|
||||
if(!dev.paired)
|
||||
(async () => dev.pair())().catch((err: Gio.IOErrorEnum) => {
|
||||
skipConnection = true;
|
||||
Notifications.getDefault().sendNotification({
|
||||
appName: "bluetooth",
|
||||
summary: "Device pairing error",
|
||||
body: `Couldn't connect to ${dev.alias ?? dev.name}, an error occurred: ${err.message || err.stack}`,
|
||||
urgency: AstalNotifd.Urgency.NORMAL
|
||||
})
|
||||
});
|
||||
|
||||
if(!skipConnection)
|
||||
(async () => dev.connect_device(null))().catch((err: Gio.IOErrorEnum) =>
|
||||
Notifications.getDefault().sendNotification({
|
||||
appName: "bluetooth",
|
||||
summary: "Device connection error",
|
||||
body: `Couldn't connect to ${dev.alias ?? dev.name}, an error occurred: ${err.message || err.stack}`,
|
||||
urgency: AstalNotifd.Urgency.NORMAL
|
||||
})
|
||||
);
|
||||
},
|
||||
endWidget: new Widget.Box({
|
||||
visible: bind(dev, "batteryPercentage").as((batt: number) =>
|
||||
@@ -160,12 +193,13 @@ function DeviceWidget(dev: AstalBluetooth.Device): Gtk.Widget {
|
||||
children: [
|
||||
new Widget.Label({
|
||||
halign: Gtk.Align.END,
|
||||
label: bind(dev, "batteryPercentage").as((bat: number) =>
|
||||
`${Math.floor(bat * 100)}%`)
|
||||
label: bind(dev, "batteryPercentage").as((batt: number) =>
|
||||
`${Math.floor(batt * 100)}%`)
|
||||
} as Widget.LabelProps),
|
||||
new Widget.Icon({
|
||||
icon: "battery-symbolic",
|
||||
css: "font-size: 18px; margin-left: 6px;"
|
||||
icon: bind(dev, "batteryPercentage").as(batt =>
|
||||
`battery-level-${Math.floor(batt * 100)}-symbolic`),
|
||||
css: "font-size: 16px; margin-left: 6px;"
|
||||
} as Widget.IconProps)
|
||||
]
|
||||
} as Widget.BoxProps)
|
||||
|
||||
@@ -13,11 +13,12 @@ export const PageNetwork: (() => Page) = () => new Page({
|
||||
className: "network",
|
||||
headerButtons: [
|
||||
new Widget.Button({
|
||||
className: "reload nf",
|
||||
label: "",
|
||||
visible: bind(AstalNetwork.get_default(), "primary").as(
|
||||
(primary: AstalNetwork.Primary) => primary === AstalNetwork.Primary.WIFI
|
||||
),
|
||||
className: "reload",
|
||||
image: new Widget.Icon({
|
||||
icon: "arrow-circular-top-right-symbolic"
|
||||
} as Widget.IconProps),
|
||||
visible: bind(AstalNetwork.get_default(), "primary").as((primary) =>
|
||||
primary === AstalNetwork.Primary.WIFI),
|
||||
tooltipText: "Re-scan connections",
|
||||
onClick: () => AstalNetwork.get_default().wifi.scan()
|
||||
} as Widget.ButtonProps)
|
||||
|
||||
@@ -177,6 +177,7 @@ export function PageButton(props: {
|
||||
icon?: string | Binding<string>;
|
||||
title: string | Binding<string>;
|
||||
endWidget?: Gtk.Widget | Binding<Gtk.Widget>;
|
||||
description?: string | Binding<string>;
|
||||
extraButtons?: Array<Widget.Button> | Binding<Array<Gtk.Widget>>;
|
||||
onDestroy?: (self: Widget.Box) => void;
|
||||
onClick?: (self: Widget.Button) => void;
|
||||
@@ -203,13 +204,28 @@ export function PageButton(props: {
|
||||
visible: props.icon,
|
||||
css: "font-size: 20px; margin-right: 6px;"
|
||||
} as Widget.IconProps),
|
||||
new Widget.Label({
|
||||
className: "title",
|
||||
halign: Gtk.Align.START,
|
||||
hexpand: true,
|
||||
truncate: true,
|
||||
label: props.title
|
||||
} as Widget.LabelProps),
|
||||
new Widget.Box({
|
||||
orientation: Gtk.Orientation.VERTICAL,
|
||||
expand: true,
|
||||
children: [
|
||||
new Widget.Label({
|
||||
className: "title",
|
||||
xalign: 0,
|
||||
truncate: true,
|
||||
label: props.title
|
||||
} as Widget.LabelProps),
|
||||
new Widget.Label({
|
||||
className: "description",
|
||||
xalign: 0,
|
||||
visible: (props.description instanceof Binding) ?
|
||||
props.description.as(Boolean)
|
||||
: Boolean(props.description),
|
||||
label: props.description,
|
||||
truncate: true,
|
||||
tooltipText: props.description
|
||||
} as Widget.LabelProps)
|
||||
]
|
||||
} as Widget.BoxProps),
|
||||
new Widget.Box({
|
||||
visible: (props.endWidget instanceof Binding) ?
|
||||
props.endWidget.as(Boolean)
|
||||
|
||||
@@ -11,7 +11,10 @@ export const TileBluetooth = () => {
|
||||
bind(AstalBluetooth.get_default(), "isConnected")
|
||||
],
|
||||
(powered: boolean, isConnected: boolean) =>
|
||||
powered ? ( isConnected ? "" : "" ) : ""
|
||||
powered ? ( isConnected ?
|
||||
"bluetooth-active-symbolic"
|
||||
: "bluetooth-symbolic"
|
||||
) : "bluetooth-disabled-symbolic"
|
||||
);
|
||||
return Tile({
|
||||
title: "Bluetooth",
|
||||
|
||||
@@ -9,7 +9,7 @@ export const TileDND = Tile({
|
||||
(dnd: boolean) => dnd ? tr("control_center.tiles.enabled") : tr("control_center.tiles.disabled")),
|
||||
onToggledOff: () => Notifications.getDefault().getNotifd().dontDisturb = false,
|
||||
onToggledOn: () => Notifications.getDefault().getNotifd().dontDisturb = true,
|
||||
icon: "",
|
||||
icon: "minus-circle-filled-symbolic",
|
||||
iconSize: 16,
|
||||
toggleState: Notifications.getDefault().getNotifd().dontDisturb
|
||||
});
|
||||
|
||||
@@ -33,8 +33,7 @@ export const TileNetwork = () => new Widget.Box({
|
||||
onToggledOn: () => wifi.set_enabled(true),
|
||||
onToggledOff: () => wifi.set_enabled(false),
|
||||
onClickMore: () => TilesPages?.toggle(PageNetwork()),
|
||||
icon: "",
|
||||
iconSize: 16,
|
||||
icon: "network-wireless-signal-excellent-symbolic",
|
||||
toggleState: bind(wifi, "enabled")
|
||||
} as TileProps)();
|
||||
|
||||
@@ -57,12 +56,12 @@ export const TileNetwork = () => new Widget.Box({
|
||||
icon: bind(wired, "internet").as((internet: AstalNetwork.Internet) => {
|
||||
switch(internet) {
|
||||
case AstalNetwork.Internet.CONNECTED:
|
||||
return '';
|
||||
return "network-wired-symbolic";
|
||||
case AstalNetwork.Internet.DISCONNECTED:
|
||||
return '';
|
||||
return "network-wired-disconnected-symbolic";
|
||||
}
|
||||
|
||||
return "";
|
||||
return "network-wired-no-route-symbolic";
|
||||
}),
|
||||
iconSize: 16,
|
||||
toggleState: bind(wired, "internet").as((internet: AstalNetwork.Internet) =>
|
||||
@@ -78,7 +77,7 @@ export const TileNetwork = () => new Widget.Box({
|
||||
onToggledOn: () => execAsync("nmcli n on"),
|
||||
onToggledOff: () => execAsync("nmcli n off"),
|
||||
onClickMore: () => TilesPages?.toggle(PageNetwork()),
|
||||
icon: "",
|
||||
icon: "network-wired-disconnected-symbolic",
|
||||
iconSize: 16,
|
||||
toggleState: bind(wired, "internet").as((internet: AstalNetwork.Internet) =>
|
||||
internet === AstalNetwork.Internet.CONNECTING || internet === AstalNetwork.Internet.CONNECTED)
|
||||
|
||||
@@ -10,7 +10,7 @@ import { Widget } from "astal/gtk3";
|
||||
export const TileNightLight = () => isInstalled("hyprsunset") ?
|
||||
Tile({
|
||||
title: tr("control_center.tiles.night_light.title"),
|
||||
icon: "",
|
||||
icon: "weather-clear-night-symbolic",
|
||||
description: Variable.derive([
|
||||
bind(NightLight.getDefault(), "temperature"),
|
||||
bind(NightLight.getDefault(), "gamma")
|
||||
|
||||
@@ -18,19 +18,16 @@ export const TileRecording = () => {
|
||||
const startedAtSeconds = dateTime.to_unix() - Recording.getDefault().startedAt!.to_unix();
|
||||
if(startedAtSeconds <= 0) return "00:00";
|
||||
|
||||
const hours = Math.floor(startedAtSeconds / 120);
|
||||
const minutes = Math.floor(startedAtSeconds / 60);
|
||||
const seconds = Math.floor(startedAtSeconds % 60);
|
||||
|
||||
return `${ hours > 0 ? `${hours < 10 ? `0${hours}` : hours }:` : ""
|
||||
}${ minutes < 10 ? `0${minutes}` : minutes
|
||||
}:${ seconds < 10 ? `0${seconds}` : seconds }`;
|
||||
return `${ minutes < 10 ? `0${minutes}` : minutes }:${ seconds < 10 ? `0${seconds}` : seconds }`;
|
||||
});
|
||||
|
||||
return Tile({
|
||||
title: tr("control_center.tiles.recording.title") || "Screen Recording",
|
||||
description: description(),
|
||||
icon: "",
|
||||
icon: "media-record-symbolic",
|
||||
visible: wfRecorderInstalled,
|
||||
onDestroy: () => description.drop(),
|
||||
onToggledOff: () => Recording.getDefault().stopRecording(),
|
||||
|
||||
@@ -65,11 +65,14 @@ export function Tile(props: TileProps): (() => Gtk.Widget) {
|
||||
expand: true,
|
||||
hexpand: true,
|
||||
children: [
|
||||
new Widget.Label({
|
||||
className: "icon nf",
|
||||
label: props.icon || "icon",
|
||||
css: `label { font-size: ${props.iconSize || 12}px; }`
|
||||
} as Widget.LabelProps),
|
||||
new Widget.Icon({
|
||||
className: "icon",
|
||||
icon: props.icon,
|
||||
visible: (props.icon instanceof Binding) ?
|
||||
props.icon.as(Boolean)
|
||||
: Boolean(props.icon),
|
||||
css: `font-size: ${props.iconSize ?? 16}px;`
|
||||
} as Widget.IconProps),
|
||||
new Widget.Box({
|
||||
className: "text",
|
||||
orientation: Gtk.Orientation.VERTICAL,
|
||||
|
||||
Reference in New Issue
Block a user