✨ chore: make workspaces fit in a single widget, add keyboard support for the logout menu
This commit is contained in:
+10
-2
@@ -69,9 +69,13 @@ entry {
|
|||||||
right: 4px;
|
right: 4px;
|
||||||
};
|
};
|
||||||
|
|
||||||
&:hover, &:focus {
|
&:hover {
|
||||||
background: colors.$bg-secondary;
|
background: colors.$bg-secondary;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
box-shadow: inset 0 0 0 2px colors.$fg-primary;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -114,9 +118,13 @@ entry {
|
|||||||
padding: 2px;
|
padding: 2px;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
|
|
||||||
&:hover, &:focus {
|
&:hover {
|
||||||
background: colors.$bg-secondary;
|
background: colors.$bg-secondary;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
box-shadow: inset 0 0 0 1px colors.$fg-primary;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
& icon.close {
|
& icon.close {
|
||||||
|
|||||||
+6
-11
@@ -5,8 +5,6 @@
|
|||||||
@use "./functions";
|
@use "./functions";
|
||||||
|
|
||||||
.bar-container {
|
.bar-container {
|
||||||
@include mixins.reset-props;
|
|
||||||
|
|
||||||
padding: 6px;
|
padding: 6px;
|
||||||
padding-bottom: 0px;
|
padding-bottom: 0px;
|
||||||
|
|
||||||
@@ -29,7 +27,7 @@
|
|||||||
|
|
||||||
& > eventbox {
|
& > eventbox {
|
||||||
&:hover {
|
&:hover {
|
||||||
& > box:not(.workspaces):not(.special-workspaces) {
|
& > box {
|
||||||
background: $color-hover;
|
background: $color-hover;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -38,7 +36,7 @@
|
|||||||
margin: $padding 0;
|
margin: $padding 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
& > box:not(.workspaces):not(.special-workspaces) {
|
& > box {
|
||||||
padding: 0 8px;
|
padding: 0 8px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -55,16 +53,15 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.workspaces, .special-workspaces {
|
.workspaces-row {
|
||||||
@include mixins.reset-props;
|
padding: 4px;
|
||||||
padding: 0 4px;
|
|
||||||
|
|
||||||
& > eventbox {
|
& eventbox > box > eventbox {
|
||||||
& > box {
|
& > box {
|
||||||
margin: 3px 0;
|
margin: 3px 0;
|
||||||
border-radius: 16px;
|
border-radius: 16px;
|
||||||
transition: 80ms linear;
|
transition: 80ms linear;
|
||||||
min-width: 15px;
|
min-width: 16px;
|
||||||
padding: 0 6px;
|
padding: 0 6px;
|
||||||
background: colors.$bg-tertiary;
|
background: colors.$bg-tertiary;
|
||||||
|
|
||||||
@@ -182,8 +179,6 @@
|
|||||||
padding: 0 6px;
|
padding: 0 6px;
|
||||||
|
|
||||||
& .item {
|
& .item {
|
||||||
all: unset;
|
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background: none;
|
background: none;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,6 +23,10 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*& eventbox:focus, & button:focus {
|
||||||
|
box-shadow: inset 0 0 0 1px colors.$fg-primary;
|
||||||
|
}*/
|
||||||
|
|
||||||
& .quickactions {
|
& .quickactions {
|
||||||
margin-bottom: .8em;
|
margin-bottom: .8em;
|
||||||
|
|
||||||
@@ -188,6 +192,10 @@ box.history {
|
|||||||
& button {
|
& button {
|
||||||
padding: 6px;
|
padding: 6px;
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
box-shadow: inset 0 0 0 1px colors.$fg-primary;
|
||||||
|
}
|
||||||
|
|
||||||
& icon {
|
& icon {
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,6 +24,10 @@
|
|||||||
font-size: 128px;
|
font-size: 128px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
box-shadow: inset 0 0 0 5px colors.$fg-primary;
|
||||||
|
}
|
||||||
|
|
||||||
margin: {
|
margin: {
|
||||||
left: 4px;
|
left: 4px;
|
||||||
right: 4px;
|
right: 4px;
|
||||||
|
|||||||
+20
-20
@@ -1,26 +1,26 @@
|
|||||||
// SCSS Variables
|
// SCSS Variables
|
||||||
// Generated by 'wal'
|
// Generated by 'wal'
|
||||||
$wallpaper: "/home/joaov/wallpapers/Gumi Forest Sunlight.jpg";
|
$wallpaper: "/home/joaov/wallpapers/Frieren Ring.jpeg";
|
||||||
|
|
||||||
// Special
|
// Special
|
||||||
$background: #2a2825;
|
$background: #523c42;
|
||||||
$foreground: #c9c9c8;
|
$foreground: #d3cecf;
|
||||||
$cursor: #c9c9c8;
|
$cursor: #d3cecf;
|
||||||
|
|
||||||
// Colors
|
// Colors
|
||||||
$color0: #2a2825;
|
$color0: #523c42;
|
||||||
$color1: #6a6a3b;
|
$color1: #6c839d;
|
||||||
$color2: #7b7b48;
|
$color2: #7a84a4;
|
||||||
$color3: #908a45;
|
$color3: #9f8a9d;
|
||||||
$color4: #7e876d;
|
$color4: #84a2b5;
|
||||||
$color5: #8a9680;
|
$color5: #9f9cab;
|
||||||
$color6: #a5a679;
|
$color6: #b7a1b2;
|
||||||
$color7: #a29f98;
|
$color7: #b0a7a9;
|
||||||
$color8: #7d7667;
|
$color8: #937b81;
|
||||||
$color9: #8E8E4F;
|
$color9: #90AFD2;
|
||||||
$color10: #A5A560;
|
$color10: #A3B0DB;
|
||||||
$color11: #C0B85C;
|
$color11: #D4B9D2;
|
||||||
$color12: #A9B592;
|
$color12: #B0D9F2;
|
||||||
$color13: #B9C8AB;
|
$color13: #D5D0E5;
|
||||||
$color14: #DDDEA2;
|
$color14: #F5D7EE;
|
||||||
$color15: #c9c9c8;
|
$color15: #d3cecf;
|
||||||
|
|||||||
@@ -1,44 +0,0 @@
|
|||||||
import { bind, Variable } from "astal";
|
|
||||||
import { Gtk, Widget } from "astal/gtk3"
|
|
||||||
import AstalHyprland from "gi://AstalHyprland";
|
|
||||||
import { getAppIcon, getSymbolicIcon } from "../../scripts/apps";
|
|
||||||
|
|
||||||
export const SpecialWorkspaces: (() => Gtk.Widget) = () => new Widget.EventBox({
|
|
||||||
className: "special-ws-eventbox",
|
|
||||||
visible: bind(AstalHyprland.get_default(), "workspaces").as((workspaces) =>
|
|
||||||
workspaces.filter(ws => ws.id < 0).sort((a, b) => a.id - b.id).length > 0),
|
|
||||||
child: new Widget.Box({
|
|
||||||
className: "special-workspaces",
|
|
||||||
spacing: 4,
|
|
||||||
children: bind(AstalHyprland.get_default(), "workspaces").as((workspaces) =>
|
|
||||||
workspaces.filter(ws => ws.id < 0).sort((a, b) => a.id - b.id).map((workspace) =>
|
|
||||||
new Widget.EventBox({
|
|
||||||
className: bind(AstalHyprland.get_default(), "focusedWorkspace").as(focusWs =>
|
|
||||||
`${focusWs.id === workspace.id ? "focus" : ""}`),
|
|
||||||
tooltipText: bind(workspace, "name").as((name) => {
|
|
||||||
name = name.replace(/^special\:/, "");
|
|
||||||
return name.charAt(0).toUpperCase().concat(name.substring(1, name.length));
|
|
||||||
}),
|
|
||||||
child: new Widget.Box({
|
|
||||||
child: bind(workspace, "lastClient").as(lastClient =>
|
|
||||||
new Widget.Icon({
|
|
||||||
className: "last-app-icon",
|
|
||||||
visible: Variable.derive([
|
|
||||||
bind(workspace, "lastClient"),
|
|
||||||
bind(AstalHyprland.get_default(), "focusedWorkspace")
|
|
||||||
], (lastClient, focusedWorkspace) => focusedWorkspace?.id === workspace.id ?
|
|
||||||
false : Boolean(lastClient))(),
|
|
||||||
icon: bind(lastClient, "initialClass").as((initialClass) =>
|
|
||||||
getSymbolicIcon(initialClass) ?? getAppIcon(initialClass) ??
|
|
||||||
"application-x-executable-symbolic")
|
|
||||||
} as Widget.IconProps)
|
|
||||||
)
|
|
||||||
} as Widget.BoxProps),
|
|
||||||
onClickRelease: () => AstalHyprland.get_default().dispatch(
|
|
||||||
"togglespecialworkspace", workspace.name.replace(/^special\:/, "")
|
|
||||||
)
|
|
||||||
} as Widget.EventBoxProps)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
} as Widget.BoxProps)
|
|
||||||
} as Widget.EventBoxProps);
|
|
||||||
+158
-92
@@ -4,6 +4,7 @@ import AstalHyprland from "gi://AstalHyprland";
|
|||||||
import { getAppIcon, getSymbolicIcon } from "../../scripts/apps";
|
import { getAppIcon, getSymbolicIcon } from "../../scripts/apps";
|
||||||
import { Windows } from "../../windows";
|
import { Windows } from "../../windows";
|
||||||
import { Config } from "../../scripts/config";
|
import { Config } from "../../scripts/config";
|
||||||
|
import { Separator, SeparatorProps } from "../Separator";
|
||||||
|
|
||||||
let showWsNum: (Variable<boolean>|undefined);
|
let showWsNum: (Variable<boolean>|undefined);
|
||||||
export const showWorkspaceNumber = (show: boolean) =>
|
export const showWorkspaceNumber = (show: boolean) =>
|
||||||
@@ -13,103 +14,168 @@ export const showWorkspaceNumber = (show: boolean) =>
|
|||||||
export function Workspaces(): Gtk.Widget {
|
export function Workspaces(): Gtk.Widget {
|
||||||
showWsNum ??= new Variable<boolean>(false);
|
showWsNum ??= new Variable<boolean>(false);
|
||||||
|
|
||||||
return new Widget.EventBox({
|
return new Widget.Box({
|
||||||
onScroll: (_, event) =>
|
className: "workspaces-row",
|
||||||
event.delta_y > 0 ?
|
orientation: Gtk.Orientation.HORIZONTAL,
|
||||||
AstalHyprland.get_default().dispatch("workspace", "e-1")
|
children: [
|
||||||
: AstalHyprland.get_default().dispatch("workspace", "e+1"),
|
new Widget.EventBox({
|
||||||
onHover: () => showWorkspaceNumber(true),
|
className: "special",
|
||||||
onHoverLost: () => showWorkspaceNumber(false),
|
visible: bind(AstalHyprland.get_default(), "workspaces").as((workspaces) =>
|
||||||
onDestroy: () => {
|
workspaces.filter(ws => ws.id < 0).sort((a, b) => a.id - b.id).length > 0),
|
||||||
// check if the current widgets is from the only bar
|
child: new Widget.Box({
|
||||||
if((Windows.openWindows["bar"] as (Array<Widget.Window>|undefined))?.length === 1) {
|
className: "special-workspaces",
|
||||||
showWsNum?.drop();
|
spacing: 4,
|
||||||
showWsNum = undefined;
|
children: bind(AstalHyprland.get_default(), "workspaces").as((workspaces) =>
|
||||||
}
|
workspaces.filter(ws => ws.id < 0).sort((a, b) => a.id - b.id).map((workspace) =>
|
||||||
},
|
new Widget.EventBox({
|
||||||
child: new Widget.Box({
|
className: bind(AstalHyprland.get_default(), "focusedWorkspace").as(focusWs =>
|
||||||
className: "workspaces",
|
`${focusWs.id === workspace.id ? "focus" : ""}`),
|
||||||
spacing: 4,
|
tooltipText: bind(workspace, "name").as((name) => {
|
||||||
children: bind(AstalHyprland.get_default(), "workspaces").as((workspaces) =>
|
name = name.replace(/^special\:/, "");
|
||||||
workspaces.filter((ws) => ws.id > 0).sort((a, b) => a.id - b.id).map((workspace, wsIndex, workspaces) => {
|
return name.charAt(0).toUpperCase().concat(name.substring(1, name.length));
|
||||||
|
}),
|
||||||
|
child: new Widget.Box({
|
||||||
|
hexpand: true,
|
||||||
|
child: bind(workspace, "lastClient").as(lastClient =>
|
||||||
|
new Widget.Icon({
|
||||||
|
className: "last-app-icon",
|
||||||
|
halign: Gtk.Align.CENTER,
|
||||||
|
visible: Variable.derive([
|
||||||
|
bind(workspace, "lastClient"),
|
||||||
|
bind(AstalHyprland.get_default(), "focusedWorkspace")
|
||||||
|
], (lastClient, focusedWorkspace) => focusedWorkspace?.id === workspace.id ?
|
||||||
|
false : Boolean(lastClient))(),
|
||||||
|
icon: bind(lastClient, "initialClass").as((initialClass) =>
|
||||||
|
getSymbolicIcon(initialClass) ?? getAppIcon(initialClass) ??
|
||||||
|
"application-x-executable-symbolic")
|
||||||
|
} as Widget.IconProps)
|
||||||
|
)
|
||||||
|
} as Widget.BoxProps),
|
||||||
|
onClickRelease: () => AstalHyprland.get_default().dispatch(
|
||||||
|
"togglespecialworkspace", workspace.name.replace(/^special\:/, "")
|
||||||
|
)
|
||||||
|
} as Widget.EventBoxProps)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
} as Widget.BoxProps)
|
||||||
|
} as Widget.EventBoxProps),
|
||||||
|
Separator({
|
||||||
|
alpha: .2,
|
||||||
|
orientation: Gtk.Orientation.HORIZONTAL,
|
||||||
|
margin: 12,
|
||||||
|
spacing: 8,
|
||||||
|
visible: bind(AstalHyprland.get_default(), "workspaces").as(wss =>
|
||||||
|
wss.filter(ws => ws.id < 0).length > 0)
|
||||||
|
} as SeparatorProps),
|
||||||
|
new Widget.EventBox({
|
||||||
|
onScroll: (_, event) =>
|
||||||
|
event.delta_y > 0 ?
|
||||||
|
AstalHyprland.get_default().dispatch("workspace", "e-1")
|
||||||
|
: AstalHyprland.get_default().dispatch("workspace", "e+1"),
|
||||||
|
onHover: () => showWorkspaceNumber(true),
|
||||||
|
onHoverLost: () => showWorkspaceNumber(false),
|
||||||
|
onDestroy: () => {
|
||||||
|
// check if the current widgets is from the only bar
|
||||||
|
if((Windows.openWindows["bar"] as (Array<Widget.Window>|undefined))?.length === 1) {
|
||||||
|
showWsNum?.drop();
|
||||||
|
showWsNum = undefined;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: new Widget.Box({
|
||||||
|
className: "workspaces",
|
||||||
|
spacing: 4,
|
||||||
|
children: bind(AstalHyprland.get_default(), "workspaces").as((workspaces) =>
|
||||||
|
workspaces.filter((ws) => ws.id > 0).sort((a, b) => a.id - b.id).map((workspace, wsIndex, workspaces) => {
|
||||||
|
|
||||||
const showIds: Variable<boolean> = Variable.derive([
|
const showIds: Variable<boolean> = Variable.derive([
|
||||||
Config.getDefault().bindProperty("workspaces.always_show_id", "boolean").as(Boolean),
|
Config.getDefault().bindProperty("workspaces.always_show_id", "boolean").as(Boolean),
|
||||||
Config.getDefault().bindProperty("workspaces.enable_helper", "boolean").as(Boolean),
|
Config.getDefault().bindProperty("workspaces.enable_helper", "boolean").as(Boolean),
|
||||||
showWsNum!()
|
showWsNum!()
|
||||||
], (alwaysShowIds, enableHelper, showIds) => {
|
], (alwaysShowIds, enableHelper, showIds) => {
|
||||||
if(enableHelper && !alwaysShowIds) {
|
if(enableHelper && !alwaysShowIds) {
|
||||||
const previousWorkspace = workspaces[wsIndex-1];
|
const previousWorkspace = workspaces[wsIndex-1];
|
||||||
const nextWorkspace = workspaces[wsIndex+1];
|
const nextWorkspace = workspaces[wsIndex+1];
|
||||||
|
|
||||||
if((workspaces.filter((_, i) => i < wsIndex).length > 0 &&
|
if((workspaces.filter((_, i) => i < wsIndex).length > 0 &&
|
||||||
previousWorkspace?.id < (workspace.id-1)) ||
|
previousWorkspace?.id < (workspace.id-1)) ||
|
||||||
(workspaces.filter((_, i) => i > wsIndex).length > 0 &&
|
(workspaces.filter((_, i) => i > wsIndex).length > 0 &&
|
||||||
nextWorkspace?.id > (workspace.id+1))) {
|
nextWorkspace?.id > (workspace.id+1))) {
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return alwaysShowIds || showIds;
|
return alwaysShowIds || showIds;
|
||||||
});
|
});
|
||||||
|
|
||||||
const className = Variable.derive([
|
const className = Variable.derive([
|
||||||
bind(AstalHyprland.get_default(), "focusedWorkspace"),
|
bind(AstalHyprland.get_default(), "focusedWorkspace"),
|
||||||
showIds!()
|
showIds!()
|
||||||
], (focusedWs, showWsNumbers) =>
|
], (focusedWs, showWsNumbers) =>
|
||||||
`${focusedWs.id === workspace.id ? "focus" : ""} ${
|
`${focusedWs.id === workspace.id ? "focus" : ""} ${
|
||||||
showWsNumbers ? "show" : ""}`
|
showWsNumbers ? "show" : ""}`
|
||||||
);
|
);
|
||||||
|
|
||||||
const tooltipText = Variable.derive([
|
const tooltipText = Variable.derive([
|
||||||
bind(workspace, "lastClient"),
|
bind(workspace, "lastClient"),
|
||||||
bind(AstalHyprland.get_default(), "focusedWorkspace")
|
bind(AstalHyprland.get_default(), "focusedWorkspace")
|
||||||
], (lastClient, focusWs) => focusWs.id === workspace.id ? "" :
|
], (lastClient, focusWs) => focusWs.id === workspace.id ? "" :
|
||||||
`Workspace ${workspace.id}${ lastClient ? ` - ${
|
`Workspace ${workspace.id}${ lastClient ? ` - ${
|
||||||
!lastClient.title.toLowerCase().includes(lastClient.class) ?
|
!lastClient.title.toLowerCase().includes(lastClient.class) ?
|
||||||
`${lastClient.get_class()}: `
|
`${lastClient.get_class()}: `
|
||||||
: ""
|
: ""
|
||||||
} ${lastClient.title}` : "" }`
|
} ${lastClient.title}` : "" }`
|
||||||
);
|
);
|
||||||
|
|
||||||
return new Widget.EventBox({
|
return new Widget.EventBox({
|
||||||
className: className(),
|
className: className(),
|
||||||
onClickRelease: () => workspace.focus(),
|
onClickRelease: () => workspace.focus(),
|
||||||
tooltipText: tooltipText(),
|
tooltipText: tooltipText(),
|
||||||
onDestroy: () => {
|
onDestroy: () => {
|
||||||
showIds.drop();
|
showIds.drop();
|
||||||
className.drop();
|
className.drop();
|
||||||
tooltipText.drop();
|
tooltipText.drop();
|
||||||
},
|
},
|
||||||
child: new Widget.Box({
|
child: new Widget.Box({
|
||||||
children: bind(workspace, "lastClient").as((lastClient) => [
|
hexpand: true,
|
||||||
new Widget.Revealer({
|
children: bind(workspace, "lastClient").as((lastClient) => {
|
||||||
transitionDuration: 200,
|
const widgets: Array<Gtk.Widget> = [
|
||||||
transitionType: Gtk.RevealerTransitionType.SLIDE_LEFT,
|
new Widget.Revealer({
|
||||||
revealChild: showIds!(),
|
transitionDuration: 200,
|
||||||
child: new Widget.Label({
|
transitionType: Gtk.RevealerTransitionType.SLIDE_LEFT,
|
||||||
label: bind(workspace, "id").as(String),
|
revealChild: showIds!(),
|
||||||
className: "id",
|
hexpand: true,
|
||||||
hexpand: true
|
child: new Widget.Label({
|
||||||
} as Widget.LabelProps)
|
label: bind(workspace, "id").as(String),
|
||||||
} as Widget.RevealerProps),
|
className: "id",
|
||||||
new Widget.Icon({
|
} as Widget.LabelProps)
|
||||||
className: "last-app-icon",
|
} as Widget.RevealerProps),
|
||||||
visible: bind(AstalHyprland.get_default(), "focusedWorkspace").as(focusedWorkspace =>
|
];
|
||||||
workspace.id === focusedWorkspace.id ?
|
|
||||||
false
|
if(lastClient) {
|
||||||
: Boolean(lastClient)),
|
widgets.push(new Widget.Icon({
|
||||||
icon: lastClient ?
|
className: "last-app-icon",
|
||||||
bind(lastClient, "class").as((clss) =>
|
halign: Gtk.Align.CENTER,
|
||||||
getSymbolicIcon(clss) ?? getAppIcon(clss) ?? "application-x-executable-symbolic")
|
expand: true,
|
||||||
: undefined
|
visible: bind(AstalHyprland.get_default(), "focusedWorkspace").as(focusedWorkspace =>
|
||||||
} as Widget.IconProps)
|
workspace.id === focusedWorkspace.id ?
|
||||||
])
|
false
|
||||||
} as Widget.BoxProps)
|
: Boolean(lastClient)),
|
||||||
} as Widget.EventBoxProps);
|
icon: lastClient ?
|
||||||
})
|
bind(lastClient, "initialClass").as((clss) =>
|
||||||
)
|
getSymbolicIcon(clss) ?? getAppIcon(clss) ?? "application-x-executable-symbolic")
|
||||||
} as Widget.BoxProps)
|
: undefined
|
||||||
} as Widget.EventBoxProps);
|
} as Widget.IconProps));
|
||||||
|
}
|
||||||
|
|
||||||
|
return widgets;
|
||||||
|
})
|
||||||
|
} as Widget.BoxProps)
|
||||||
|
} as Widget.EventBoxProps);
|
||||||
|
})
|
||||||
|
)
|
||||||
|
} as Widget.BoxProps)
|
||||||
|
} as Widget.EventBoxProps)
|
||||||
|
]
|
||||||
|
} as Widget.BoxProps);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,10 +7,6 @@ import { Media } from "../widget/bar/Media";
|
|||||||
import { Apps } from "../widget/bar/Apps";
|
import { Apps } from "../widget/bar/Apps";
|
||||||
import { Clock } from "../widget/bar/Clock";
|
import { Clock } from "../widget/bar/Clock";
|
||||||
import { Status } from "../widget/bar/Status";
|
import { Status } from "../widget/bar/Status";
|
||||||
import { SpecialWorkspaces } from "../widget/bar/SpecialWorkspaces";
|
|
||||||
import { Separator, SeparatorProps } from "../widget/Separator";
|
|
||||||
import AstalHyprland from "gi://AstalHyprland?version=0.1";
|
|
||||||
import { bind } from "astal";
|
|
||||||
|
|
||||||
export const Bar = (mon: number) => {
|
export const Bar = (mon: number) => {
|
||||||
const widgetSpacing = 4;
|
const widgetSpacing = 4;
|
||||||
@@ -36,14 +32,6 @@ export const Bar = (mon: number) => {
|
|||||||
spacing: widgetSpacing,
|
spacing: widgetSpacing,
|
||||||
children: [
|
children: [
|
||||||
Apps(),
|
Apps(),
|
||||||
SpecialWorkspaces(),
|
|
||||||
Separator({
|
|
||||||
alpha: .2,
|
|
||||||
orientation: Gtk.Orientation.HORIZONTAL,
|
|
||||||
margin: 14,
|
|
||||||
visible: bind(AstalHyprland.get_default(), "workspaces").as(wss =>
|
|
||||||
wss.filter(ws => ws.id < 0).length > 0)
|
|
||||||
} as SeparatorProps),
|
|
||||||
Workspaces(),
|
Workspaces(),
|
||||||
FocusedClient()
|
FocusedClient()
|
||||||
]
|
]
|
||||||
|
|||||||
+69
-57
@@ -1,7 +1,7 @@
|
|||||||
import { Astal, Gdk, Gtk, Widget } from "astal/gtk3";
|
import { Astal, Gdk, Gtk, Widget } from "astal/gtk3";
|
||||||
import { getDateTime } from "../scripts/time";
|
import { getDateTime } from "../scripts/time";
|
||||||
import { execAsync, Gio, GLib } from "astal";
|
import { execAsync, Gio, GLib } from "astal";
|
||||||
import { AskPopup } from "../widget/AskPopup";
|
import { AskPopup, AskPopupProps } from "../widget/AskPopup";
|
||||||
import { Windows } from "../windows";
|
import { Windows } from "../windows";
|
||||||
import { Notifications } from "../scripts/notifications";
|
import { Notifications } from "../scripts/notifications";
|
||||||
import AstalNotifd from "gi://AstalNotifd";
|
import AstalNotifd from "gi://AstalNotifd";
|
||||||
@@ -60,80 +60,32 @@ export const LogoutMenu = (mon: number) => new Widget.Window({
|
|||||||
image: new Widget.Icon({
|
image: new Widget.Icon({
|
||||||
icon: "system-shutdown-symbolic"
|
icon: "system-shutdown-symbolic"
|
||||||
} as Widget.IconProps),
|
} as Widget.IconProps),
|
||||||
onClick: () => AskPopup({
|
onClick: () => AskPopup(poweroffAsk),
|
||||||
title: "Power Off",
|
onActivate: () => AskPopup(poweroffAsk)
|
||||||
text: "Are you sure you want to power off? Unsaved work will be lost.",
|
|
||||||
onAccept: () => {
|
|
||||||
Config.getDefault().getProperty("night_light.save_on_shutdown", "boolean") &&
|
|
||||||
NightLight.getDefault().saveData();
|
|
||||||
|
|
||||||
execAsync("systemctl poweroff");
|
|
||||||
}
|
|
||||||
})
|
|
||||||
} as Widget.ButtonProps),
|
} as Widget.ButtonProps),
|
||||||
new Widget.Button({
|
new Widget.Button({
|
||||||
className: "reboot",
|
className: "reboot",
|
||||||
image: new Widget.Icon({
|
image: new Widget.Icon({
|
||||||
icon: "arrow-circular-top-right-symbolic"
|
icon: "arrow-circular-top-right-symbolic"
|
||||||
} as Widget.IconProps),
|
} as Widget.IconProps),
|
||||||
onClick: () => AskPopup({
|
onClick: () => AskPopup(rebootAsk),
|
||||||
title: "Reboot",
|
onActivate: () => AskPopup(rebootAsk)
|
||||||
text: "Are you sure you want to Reboot? Unsaved work will be lost.",
|
|
||||||
onAccept: () => {
|
|
||||||
Config.getDefault().getProperty("night_light.save_on_shutdown", "boolean") &&
|
|
||||||
NightLight.getDefault().saveData();
|
|
||||||
|
|
||||||
execAsync("systemctl reboot");
|
|
||||||
}
|
|
||||||
})
|
|
||||||
} as Widget.ButtonProps),
|
} as Widget.ButtonProps),
|
||||||
new Widget.Button({
|
new Widget.Button({
|
||||||
className: "suspend",
|
className: "suspend",
|
||||||
image: new Widget.Icon({
|
image: new Widget.Icon({
|
||||||
icon: "weather-clear-night-symbolic"
|
icon: "weather-clear-night-symbolic"
|
||||||
} as Widget.IconProps),
|
} as Widget.IconProps),
|
||||||
onClick: () => AskPopup({
|
onClick: () => AskPopup(suspendAsk),
|
||||||
title: "Suspend",
|
onActivate: () => AskPopup(suspendAsk)
|
||||||
text: "Are you sure you want to Suspend?",
|
|
||||||
onAccept: () => execAsync("systemctl suspend")
|
|
||||||
})
|
|
||||||
} as Widget.ButtonProps),
|
} as Widget.ButtonProps),
|
||||||
new Widget.Button({
|
new Widget.Button({
|
||||||
className: "logout",
|
className: "logout",
|
||||||
image: new Widget.Icon({
|
image: new Widget.Icon({
|
||||||
icon: "system-log-out-symbolic"
|
icon: "system-log-out-symbolic"
|
||||||
} as Widget.IconProps),
|
} as Widget.IconProps),
|
||||||
onClick: () => AskPopup({
|
onClick: () => AskPopup(logoutAsk),
|
||||||
title: "Log out",
|
onActivate: () => AskPopup(logoutAsk)
|
||||||
text: "Are you sure you want to log out? Your session will be ended.",
|
|
||||||
onAccept: () => {
|
|
||||||
Config.getDefault().getProperty("night_light.save_on_shutdown", "boolean") &&
|
|
||||||
NightLight.getDefault().saveData();
|
|
||||||
|
|
||||||
execAsync(`hyprctl dispatch exit`).catch((err: Gio.IOErrorEnum) =>
|
|
||||||
Notifications.getDefault().sendNotification({
|
|
||||||
appName: "colorshell",
|
|
||||||
summary: "Couldn't exit Hyprland",
|
|
||||||
body: `An error occurred and colorshell couldn't exit Hyprland. Stderr: \n${
|
|
||||||
err.message ? `${err.message}\n` : ""}${err.stack}`,
|
|
||||||
urgency: AstalNotifd.Urgency.NORMAL,
|
|
||||||
actions: [{
|
|
||||||
text: "Report Issue on colorshell",
|
|
||||||
onAction: () => execAsync(
|
|
||||||
`xdg-open https://github.com/retrozinndev/colorshell/issues/new`
|
|
||||||
).catch((err: Gio.IOErrorEnum) =>
|
|
||||||
Notifications.getDefault().sendNotification({
|
|
||||||
appName: "colorshell",
|
|
||||||
summary: "Couldn't open link",
|
|
||||||
body: `Do you have \`xdg-utils\` installed? Stderr: \n${
|
|
||||||
err.message ? `${err.message}\n` : ""}${err.stack}`
|
|
||||||
})
|
|
||||||
)
|
|
||||||
}]
|
|
||||||
})
|
|
||||||
)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
} as Widget.ButtonProps),
|
} as Widget.ButtonProps),
|
||||||
]
|
]
|
||||||
} as Widget.BoxProps)
|
} as Widget.BoxProps)
|
||||||
@@ -141,3 +93,63 @@ export const LogoutMenu = (mon: number) => new Widget.Window({
|
|||||||
})
|
})
|
||||||
} as Widget.EventBoxProps)
|
} as Widget.EventBoxProps)
|
||||||
} as Widget.WindowProps);
|
} as Widget.WindowProps);
|
||||||
|
|
||||||
|
const logoutAsk: AskPopupProps = {
|
||||||
|
title: "Log out",
|
||||||
|
text: "Are you sure you want to log out? Your session will be ended.",
|
||||||
|
onAccept: () => {
|
||||||
|
Config.getDefault().getProperty("night_light.save_on_shutdown", "boolean") &&
|
||||||
|
NightLight.getDefault().saveData();
|
||||||
|
|
||||||
|
execAsync(`hyprctl dispatch exit`).catch((err: Gio.IOErrorEnum) =>
|
||||||
|
Notifications.getDefault().sendNotification({
|
||||||
|
appName: "colorshell",
|
||||||
|
summary: "Couldn't exit Hyprland",
|
||||||
|
body: `An error occurred and colorshell couldn't exit Hyprland. Stderr: \n${
|
||||||
|
err.message ? `${err.message}\n` : ""}${err.stack}`,
|
||||||
|
urgency: AstalNotifd.Urgency.NORMAL,
|
||||||
|
actions: [{
|
||||||
|
text: "Report Issue on colorshell",
|
||||||
|
onAction: () => execAsync(
|
||||||
|
`xdg-open https://github.com/retrozinndev/colorshell/issues/new`
|
||||||
|
).catch((err: Gio.IOErrorEnum) =>
|
||||||
|
Notifications.getDefault().sendNotification({
|
||||||
|
appName: "colorshell",
|
||||||
|
summary: "Couldn't open link",
|
||||||
|
body: `Do you have \`xdg-utils\` installed? Stderr: \n${
|
||||||
|
err.message ? `${err.message}\n` : ""}${err.stack}`
|
||||||
|
})
|
||||||
|
)
|
||||||
|
}]
|
||||||
|
})
|
||||||
|
)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const suspendAsk: AskPopupProps = {
|
||||||
|
title: "Suspend",
|
||||||
|
text: "Are you sure you want to Suspend?",
|
||||||
|
onAccept: () => execAsync("systemctl suspend")
|
||||||
|
};
|
||||||
|
|
||||||
|
const rebootAsk: AskPopupProps = {
|
||||||
|
title: "Reboot",
|
||||||
|
text: "Are you sure you want to Reboot? Unsaved work will be lost.",
|
||||||
|
onAccept: () => {
|
||||||
|
Config.getDefault().getProperty("night_light.save_on_shutdown", "boolean") &&
|
||||||
|
NightLight.getDefault().saveData();
|
||||||
|
|
||||||
|
execAsync("systemctl reboot");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const poweroffAsk: AskPopupProps = {
|
||||||
|
title: "Power Off",
|
||||||
|
text: "Are you sure you want to power off? Unsaved work will be lost.",
|
||||||
|
onAccept: () => {
|
||||||
|
Config.getDefault().getProperty("night_light.save_on_shutdown", "boolean") &&
|
||||||
|
NightLight.getDefault().saveData();
|
||||||
|
|
||||||
|
execAsync("systemctl poweroff");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user