💥 fix(ags): bar/media widget, new appearance to control center

This commit is contained in:
retrozinndev
2025-02-05 16:31:23 -03:00
parent 8bd3245dab
commit 0bd0b53589
16 changed files with 278 additions and 282 deletions
+8 -8
View File
@@ -2,16 +2,16 @@
import { GLib } from "astal";
export const i18nKeys = {
"en_US": () => import("./lang/en_US"),
"pt_BR": () => import("./lang/pt_BR")
const i18nKeys = {
"en_US": (() => import("./lang/en_US")!)(),
"pt_BR": (() => import("./lang/pt_BR")!)()
}
export const languages: Array<string> = (() =>
const languages: Array<string> = (() =>
Object.keys(i18nKeys))()
const defaultLanguage: string = languages[0];
let language: string = defaultLanguage;
let language: string = getSystemLanguage();
export function getSystemLanguage(): string {
const sysLanguage: (string|null|undefined) = GLib.getenv("LANG") || GLib.getenv("LANGUAGE");
@@ -40,14 +40,14 @@ export function setLanguage(lang: keyof typeof i18nKeys): (string|Error) {
}
export function tr(key: string): (string|undefined) {
let langKeys: Object = i18nKeys[language as keyof typeof i18nKeys];
let result = i18nKeys[language as keyof typeof i18nKeys],
defResult = i18nKeys[defaultLanguage as keyof typeof i18nKeys];
key.split('.').map((keyString: string) => {
for(const keyString in key.split('.')) {
console.log(result);
result = result[keyString as keyof typeof result];
defResult = defResult[keyString as keyof typeof defResult];
});
}
return (result as never) || (defResult as never) || undefined;
}
+5
View File
@@ -1,3 +1,8 @@
export default {
"language": "English (United States)",
"bar": {
"logo": {
"tooltip": "Applications"
}
}
}
+6 -1
View File
@@ -1,3 +1,8 @@
export default {
"language": "Português (Brasil)"
"language": "Português (Brasil)",
"bar": {
"logo": {
"tooltip": "Aplicativos"
}
}
}
+4
View File
@@ -27,4 +27,8 @@ export class Windows {
public close(window: Widget.Window): void {
window.hide();
}
public toggle(window: Widget.Window): void {
window.is_visible() ? this.close(window) : this.open(window);
}
}
+51 -1
View File
@@ -1,4 +1,54 @@
@use "sass:color";
@use "./style/bar";
@use "./style/wal";
@use "./style/osd";
@use "./style/control-center"
@use "./style/control-center";
* {
all: unset;
transition: 120ms linear;
}
.button-row {
& > button {
background: color.scale($color: wal.$foreground, $lightness: -30%, $alpha: 70%);
margin: 0 1px;
border-radius: 2px;
&:hover {
background: color.scale($color: wal.$foreground, $lightness: -30%, $alpha: 100%);
}
&:first-child {
border-top-left-radius: 10px;
border-bottom-left-radius: 10px;
}
&:last-child {
border-top-right-radius: 10px;
border-bottom-right-radius: 10px;
}
}
}
menu {
padding: 4px;
background: wal.$background;
border-radius: 14px;
& > separator {
margin: 0 4px;
color: wal.$background;
}
& > menuitem {
padding: 8px 0px;
border-radius: 10px;
font-size: 12px;
font-weight: 600;
&:hover {
background: wal.$color1;
}
}
}
+11 -35
View File
@@ -6,31 +6,6 @@
padding-bottom: 0px;
& * {
all: unset;
transition: 120ms linear;
menu {
padding: 4px;
background: wal.$background;
border-radius: 14px;
& > separator {
margin: 0 4px;
color: wal.$background;
}
& > menuitem {
padding: 8px 0px;
border-radius: 10px;
font-size: 12px;
font-weight: 600;
&:hover {
background: wal.$color1;
}
}
}
button {
padding: 6px 8px;
border-radius: 12px;
@@ -39,6 +14,13 @@
background: wal.$color1;
}
}
label {
font-size: 12px;
font-family: "Cantarell", "Noto Sans";
font-weight: 500;
}
}
// Style widget groups
@@ -62,13 +44,6 @@
}
}
}
}
.bar-container label {
font-size: 12px;
font-family: "Cantarell", "Noto Sans";
font-weight: 500;
}
.workspaces {
padding: 2px 2px;
@@ -88,7 +63,7 @@
}
}
.focused-window {
.focused-client {
padding: 0 6px;
& > .icon {
@@ -124,7 +99,7 @@
.media-eventbox {
& > .media > box {
border-radius: 12px;
background: wal.$color2;
background: wal.$color1;
padding: 0 6px;
& .icon {
@@ -142,7 +117,7 @@
padding-left: 3px;
border-top-right-radius: 12px;
border-bottom-right-radius: 12px;
background: scale-color($color: wal.$color3, $lightness: -12%);
background: scale-color($color: wal.$color1, $lightness: -20%);
& > button {
margin: 0px 1px;
@@ -211,3 +186,4 @@
padding-left: $padding-inline;
padding-right: calc($padding-inline + 2px);
}
}
+10 -37
View File
@@ -1,52 +1,25 @@
@use "sass:color";
@use "./wal";
.control-center-container {
all: unset;
background: rgba(wal.$background, .6);
border-top-left-radius: 16px;
border-bottom-left-radius: 16px;
& * {
all: unset;
transition: 120ms linear;
}
background: rgba(wal.$background, .65);
border-radius: 24px;
padding: 24px 22px;
& {
& button {
padding: 4px 6px;
background: scale-color($color: wal.$color1, $lightness: -20%);
border-radius: 12px;
}
& .quickactions {
padding: 10px 16px;
& .button-row {
& > button {
margin: 5px 2px;
border-radius: 2px;
padding: 0 8px;
background: rgba($color: scale-color($color: wal.$color1, $lightness: -20%), $alpha: .7);
& label {
font-size: 16px;
background: wal.$color1;
& .hostname {
font-size: 15px;
font-weight: 600;
}
&:hover {
background: rgba($color: scale-color($color: wal.$color1, $lightness: -20%), $alpha: 1);
}
&:first-child {
margin-left: 0;
border-top-left-radius: 8px;
border-bottom-left-radius: 8px;
}
&:last-child {
margin-right: 0;
border-top-right-radius: 8px;
border-bottom-right-radius: 8px;
}
}
& .uptime {
font-size: 12px;
}
}
}
+3 -2
View File
@@ -1,5 +1,5 @@
import { bind } from "astal";
import { Astal, Widget } from "astal/gtk3";
import { bind, Process } from "astal";
import { Widget } from "astal/gtk3";
import AstalWp from "gi://AstalWp?version=0.1";
import { Wireplumber } from "../../scripts/volume";
@@ -8,6 +8,7 @@ const wp = AstalWp.get_default();
export function Audio() {
return wp && new Widget.EventBox({
className: "audio",
onClick: () => Process.exec_async("astal toggle control-center", () => {}),
child: new Widget.Box({
children: [
new Widget.EventBox({
-11
View File
@@ -1,11 +0,0 @@
import {Process} from "astal";
import { Box, Button } from "astal/gtk3/widget";
export function CCToggle() {
return (
<Box className={"cc-toggle"}>
<Button onClick={() => Process.exec("eww open --toggle control-center")}
label={"󰂚"}/>
</Box>
)
}
@@ -5,9 +5,9 @@ import { getAppIcon } from "../../scripts/apps";
const hyprland = AstalHyprland.get_default();
export function FocusedWindow() {
export function FocusedClient() {
return new Widget.Box({
className: "focused-window",
className: "focused-client",
visible: bind(hyprland, "focusedClient").as(Boolean),
children: [
new Widget.Icon({
+7 -4
View File
@@ -1,10 +1,13 @@
import { Widget } from "astal/gtk3";
import { Box, Button } from "astal/gtk3/widget";
import AstalHyprland from "gi://AstalHyprland";
import { tr } from "../../i18n/intl";
export function Logo() {
return (
<Box className={"logo"}>
return new Widget.Box({
className: "logo",
//tooltipText: tr("bar.logo.tooltip"),
child:
<Button onClick={ () => AstalHyprland.get_default().dispatch("exec", "anyrun") } label={""} />
</Box>
)
} as Widget.BoxProps);
}
+27 -31
View File
@@ -4,7 +4,6 @@ import AstalMpris from "gi://AstalMpris";
import { Separator, SeparatorProps } from "../Separator";
const mpris: AstalMpris.Mpris = AstalMpris.get_default();
let defaultPlayer: (AstalMpris.Player|undefined) = mpris.get_players()?.[0];
const playerIcons = {
spotify: '󰓇',
@@ -15,69 +14,63 @@ const playerIcons = {
}
export function Media(): JSX.Element {
bind(mpris, "players")?.as((players: Array<AstalMpris.Player>) => {
defaultPlayer = players?.[0] as AstalMpris.Player;
});
const mediaControlsRevealer: Widget.Revealer = new Widget.Revealer({
transitionType: Gtk.RevealerTransitionType.SLIDE_RIGHT,
transitionDuration: 260,
revealChild: false,
child: new Widget.Box({
className: "media-controls",
expand: false,
homogeneous: false,
children: [
children: bind(mpris, "players").as((players: Array<AstalMpris.Player>) =>
players[0] ? [
new Widget.Button({
className: "previous",
label: "󰒮",
onClick: () => {
if(bind(defaultPlayer!, "canGoPrevious").as(Boolean))
defaultPlayer?.previous();
}
onClick: () => players[0].canGoPrevious && players[0].previous()
} as Widget.ButtonProps),
new Widget.Button({
className: "pause",
label: bind(defaultPlayer!, "playback_status").as((status: AstalMpris.PlaybackStatus) => {
return status === AstalMpris.PlaybackStatus.PLAYING ? "󰏤" : "󰐊"
}),
label: bind(players[0], "playbackStatus").as((status: AstalMpris.PlaybackStatus) =>
status === AstalMpris.PlaybackStatus.PLAYING ? "󰏤" : "󰐊"),
onClick: () => {
if(bind(defaultPlayer!, "canPlay").as(Boolean)
|| bind(defaultPlayer!, "canPause").as(Boolean))
defaultPlayer?.play_pause();
players[0].playbackStatus === AstalMpris.PlaybackStatus.PAUSED ?
players[0].play()
:
players[0].pause()
}
} as Widget.ButtonProps),
new Widget.Button({
className: "next",
label: "󰒭",
onClick: () => {
if(bind(defaultPlayer!, "canGoNext").as(Boolean))
defaultPlayer?.next();
}
onClick: () => players[0].canGoNext && players[0].next()
} as Widget.ButtonProps)
]
] : new Widget.Label({
label: "Don't Stop The Music!"
} as Widget.LabelProps)
)
} as Widget.BoxProps)
} as Widget.RevealerProps);
const mediaWidget = new Widget.EventBox({
className: "media-eventbox",
visible: bind(mpris, "players").as((players: Array<AstalMpris.Player>) => players?.[0]).as(Boolean),
visible: bind(mpris, "players").as((players: Array<AstalMpris.Player>) => players[0]).as(Boolean),
child: new Widget.Box({
className: "media",
children: [
new Widget.Box({
children: [
children: bind(mpris, "players").as((players: Array<AstalMpris.Player>) =>
players[0] ? [
new Widget.Label({
className: "icon",
label: defaultPlayer && bind(defaultPlayer, "busName")?.as((name: string) => {
const banana: Array<string> = name.split('.');
const playerName: string = banana[banana.length-1];
return playerIcons[playerName as keyof typeof playerIcons] || '󰎇';
label: bind(players[0], "busName").as((busName: string) => {
const playerName: string = busName.split('.')[busName.split('.').length-1];
return playerIcons[playerName as keyof typeof playerIcons] || "󰎇";
})
} as Widget.LabelProps),
new Widget.Label({
className: "title",
label: defaultPlayer && bind(defaultPlayer, "title")?.as((title: string) => title)
label: bind(players[0], "title").as((title: string) => title || "No Title")
} as Widget.LabelProps),
Separator({
size: 2,
@@ -86,9 +79,12 @@ export function Media(): JSX.Element {
} as SeparatorProps),
new Widget.Label({
className: "artist",
label: defaultPlayer && bind(defaultPlayer, "artist")?.as((artist: string) => artist)
label: bind(players[0], "artist").as((artist: string) => artist || "No Artist")
} as Widget.LabelProps)
]
] : new Widget.Label({
label: "Crazy to think this widget didn't disappear yet!"
} as Widget.LabelProps)
)
} as Widget.BoxProps),
mediaControlsRevealer
]
+1 -1
View File
@@ -49,7 +49,7 @@ function LogoutButton(): Widget.Button {
return new Widget.Button({
label: "󰗽",
onClick: () => Process.exec_async(
"bash -c 'loginctl terminate-user $USER'",
"bash -c 'wlogout -b 5'",
() => {}
)
} as Widget.ButtonProps);
@@ -1,4 +1,4 @@
import { Binding } from "astal";
import { Binding, Variable } from "astal";
import { Gtk, Widget } from "astal/gtk3";
export interface NormalTileProps {
@@ -14,9 +14,6 @@ export interface NormalTileProps {
export function MoreTile(props: NormalTileProps): Gtk.Widget {
let toggleState: boolean = props?.toggleState !== undefined ?
props.toggleState : false;
const mainEventBox = new Widget.EventBox({
onClick: () => toggleState ? props.onToggledOff() : props.onToggledOn(),
expand: true,
+5 -7
View File
@@ -2,12 +2,11 @@ import { Gdk, Astal, Gtk, Widget } from "astal/gtk3";
import { Clock } from "../widget/bar/Clock";
import { Logo } from "../widget/bar/Logo";
import { CCToggle } from "../widget/bar/CCToggle";
import { Tray } from "../widget/bar/Tray";
import { Workspaces } from "../widget/bar/Workspaces";
import { Audio } from "../widget/bar/Audio";
import { FocusedWindow } from "../widget/bar/FocusedWindow";
//import { Media } from "../widget/bar/Media";
import { FocusedClient } from "../widget/bar/FocusedClient";
import { Media } from "../widget/bar/Media";
export const Bar: Widget.Window = new Widget.Window({
className: "bar",
@@ -34,7 +33,7 @@ export const Bar: Widget.Window = new Widget.Window({
children: [
Logo(),
Workspaces(),
FocusedWindow()
FocusedClient()
]
} as Widget.BoxProps),
centerWidget: new Widget.Box({
@@ -43,7 +42,7 @@ export const Bar: Widget.Window = new Widget.Window({
halign: Gtk.Align.CENTER,
children: [
Clock(),
/*<Media />*/
Media()
]
} as Widget.BoxProps),
endWidget: new Widget.Box({
@@ -52,8 +51,7 @@ export const Bar: Widget.Window = new Widget.Window({
halign: Gtk.Align.END,
children: [
Tray(),
Audio(),
CCToggle()
Audio()
]
} as Widget.BoxProps)
} as Widget.CenterBoxProps)
+4 -5
View File
@@ -1,10 +1,7 @@
import { Astal, Gdk, Gtk, Widget } from "astal/gtk3";
import { QuickActions } from "../widget/control-center/QuickActions";
import { Bar } from "./Bar";
import { Tiles } from "../widget/control-center/Tiles";
const monitorHeight: number = Gdk.Screen.get_default()?.get_monitor_geometry(0)?.height!;
const widgetsContainer: Widget.Box = new Widget.Box({
className: "control-center-container",
orientation: Gtk.Orientation.VERTICAL,
@@ -17,9 +14,11 @@ export const ControlCenter: Widget.Window = new Widget.Window({
namespace: "control-center",
canFocus: true,
exclusivity: Astal.Exclusivity.NORMAL,
anchor: Astal.WindowAnchor.RIGHT,
anchor: Astal.WindowAnchor.TOP | Astal.WindowAnchor.RIGHT,
margin_top: 10,
margin_right: 10,
width_request: 450,
height_request: Bar.is_visible() ? monitorHeight - Bar.get_size()[1] - 18 : 700,
height_request: 400,
monitor: 0,
visible: false
} as Widget.WindowProps, widgetsContainer);