✨ ags: add center-window and logout-menu windows and more
This commit is contained in:
@@ -26,6 +26,7 @@ App.start({
|
|||||||
|
|
||||||
Wireplumber.getDefault().getDefaultSink().connect("notify::volume", () =>
|
Wireplumber.getDefault().getDefaultSink().connect("notify::volume", () =>
|
||||||
!Windows.isVisible(ControlCenter) && triggerOSD(OSDModes.SINK));
|
!Windows.isVisible(ControlCenter) && triggerOSD(OSDModes.SINK));
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ export function handleArguments(request: string): any {
|
|||||||
return handleVolumeArgs(args);
|
return handleVolumeArgs(args);
|
||||||
|
|
||||||
case "reload":
|
case "reload":
|
||||||
restartInstance({ log: false, instanceName: "astal" });
|
restartInstance();
|
||||||
return "Reloading instance..."
|
return "Reloading instance..."
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -1,20 +1,45 @@
|
|||||||
import AstalNotifd from "gi://AstalNotifd";
|
import AstalNotifd from "gi://AstalNotifd";
|
||||||
import { timeout } from "astal/time";
|
import { timeout } from "astal/time";
|
||||||
|
import { Connectable } from "astal/binding";
|
||||||
|
import { GObject, register, property, signal } from "astal";
|
||||||
|
import { Windows } from "../windows";
|
||||||
|
|
||||||
const notifd: AstalNotifd.Notifd = new AstalNotifd.Notifd({
|
@register()
|
||||||
ignoreTimeout: false,
|
class Notifications extends GObject.Object implements Connectable {
|
||||||
|
|
||||||
|
private static instance: Notifications;
|
||||||
|
private notifd: AstalNotifd.Notifd;
|
||||||
|
|
||||||
|
public notifications: Array<AstalNotifd.Notification> = [];
|
||||||
|
public notificationHistory: Array<AstalNotifd.Notification> = [];
|
||||||
|
|
||||||
|
@signal()
|
||||||
|
declare "notification-added": (notification: AstalNotifd.Notification) => void;
|
||||||
|
|
||||||
|
|
||||||
|
public static getDefault(): Notifications {
|
||||||
|
if(!Notifications.instance) {
|
||||||
|
Notifications.instance = new Notifications();
|
||||||
|
this.instance._init();
|
||||||
|
}
|
||||||
|
|
||||||
|
return Notifications.instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.notifd = new AstalNotifd.Notifd({
|
||||||
|
ignoreTimeout: true,
|
||||||
dontDisturb: false
|
dontDisturb: false
|
||||||
|
} as AstalNotifd.Notifd.ConstructorProps);
|
||||||
|
|
||||||
|
this.getNotifd().connect("notified", (_source: AstalNotifd.Notifd, id: number, _replaced: boolean) => {
|
||||||
|
this.addNotification(this.getNotifd().get_notification(id));
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
export let notifications: Array<AstalNotifd.Notification> = getNotifd().notifications;
|
public addNotification(notification: AstalNotifd.Notification) {
|
||||||
export let notificationHistory: Array<AstalNotifd.Notification> = [];
|
this.prependArray(this.notifications, this.getNotifd().get_notification(notification.id));
|
||||||
|
|
||||||
notifd.connect("notified", (_source: AstalNotifd.Notifd, id: number, _replaced: boolean) => {
|
|
||||||
addNotification(getNotifd().get_notification(id));
|
|
||||||
});
|
|
||||||
|
|
||||||
function addNotification(notification: AstalNotifd.Notification) {
|
|
||||||
prependArray(notifications, getNotifd().get_notification(notification.id));
|
|
||||||
|
|
||||||
// default timeout if undefined
|
// default timeout if undefined
|
||||||
let notificationTimeout = 4000;
|
let notificationTimeout = 4000;
|
||||||
@@ -28,36 +53,45 @@ function addNotification(notification: AstalNotifd.Notification) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
notification.urgency !== AstalNotifd.Urgency.CRITICAL && timeout(notificationTimeout, () => {
|
notification.urgency !== AstalNotifd.Urgency.CRITICAL ?
|
||||||
notificationTimeout--;
|
timeout(notificationTimeout, () => {
|
||||||
if(notificationTimeout === 0) {
|
this.notifications.map((item: AstalNotifd.Notification) =>
|
||||||
removeNotification(notification.id);
|
item.id === notification.id && (() => {
|
||||||
addToNotificationHistory(notification);
|
this.removeNotification(notification.id);
|
||||||
};
|
this.addToNotificationHistory(notification);
|
||||||
});
|
})())
|
||||||
|
})
|
||||||
|
: this.addToNotificationHistory(notification);
|
||||||
|
|
||||||
|
this.emit("notification-added", notification);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function removeNotification(notificationId: number) {
|
public removeNotification(notificationId: number) {
|
||||||
notifications = notifications.filter((notification: AstalNotifd.Notification) =>
|
if(this.notifications.length === 1)
|
||||||
|
Windows.close(Windows.getWindow("floating-notifications")!);
|
||||||
|
|
||||||
|
this.notifications = this.notifications.filter((notification: AstalNotifd.Notification) =>
|
||||||
notification.id !== notificationId);
|
notification.id !== notificationId);
|
||||||
|
|
||||||
|
this.emit("notification-removed", notificationId);
|
||||||
}
|
}
|
||||||
|
|
||||||
function addToNotificationHistory(notification: AstalNotifd.Notification) {
|
public addToNotificationHistory(notification: AstalNotifd.Notification) {
|
||||||
prependArray(notificationHistory, notification);
|
this.prependArray(this.notificationHistory, notification);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function removeFromNotificationHistory(notificationId: number) {
|
public removeFromNotificationHistory(notificationId: number) {
|
||||||
notifications = notifications.filter((curNotification: AstalNotifd.Notification) =>
|
this.notificationHistory = this.notificationHistory.filter((curNotification: AstalNotifd.Notification) =>
|
||||||
curNotification.id !== notificationId);
|
curNotification.id !== notificationId);
|
||||||
}
|
}
|
||||||
|
|
||||||
function prependArray(array: Array<any>, item: any) {
|
private prependArray(array: Array<any>, item: any): Array<any> {
|
||||||
let tmpArray = array;
|
let tmpArray = array.reverse();
|
||||||
tmpArray.reverse();
|
|
||||||
tmpArray.push(item);
|
tmpArray.push(item);
|
||||||
array = tmpArray.reverse();
|
return tmpArray.reverse();
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getNotifd(): AstalNotifd.Notifd {
|
public getNotifd(): AstalNotifd.Notifd {
|
||||||
return notifd;
|
return this.notifd;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,30 +1,18 @@
|
|||||||
import { monitorFile, Process } from "astal";
|
import { monitorFile, Process } from "astal";
|
||||||
import { getUserDirs } from "./user";
|
|
||||||
import { App } from "astal/gtk3";
|
import { App } from "astal/gtk3";
|
||||||
|
|
||||||
const monitoringPaths = [ "./scripts", "./window", "./app.ts", "env.d.ts" ];
|
const monitoringPaths = [ "./scripts", "./window", "./app.ts", "env.d.ts" ];
|
||||||
|
|
||||||
export interface InstanceProps {
|
export function restartInstance(instanceName?: string): void {
|
||||||
instanceName?: string;
|
Process.exec_async(`astal -q ${ instanceName || App.instanceName || "astal" }`, () => {});
|
||||||
log?: boolean;
|
Process.exec_async(`ags run`, () => {});
|
||||||
}
|
|
||||||
|
|
||||||
export function restartInstance(props: InstanceProps = { instanceName: "astal", log: false }): void {
|
|
||||||
Process.exec_async(`astal -q ${props.instanceName}`, () => {});
|
|
||||||
Process.exec_async(`ags run ${ props.log && `--log-file
|
|
||||||
${ getUserDirs().cache}/ags-${ App.instanceName || "astal" }.log` }`.replaceAll('\n', ' ').trim(),
|
|
||||||
() => {}
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function monitorPaths(): void {
|
export function monitorPaths(): void {
|
||||||
monitoringPaths.map((path: string) => {
|
monitoringPaths.map((path: string) => {
|
||||||
monitorFile(
|
monitorFile(
|
||||||
path,
|
path,
|
||||||
() => restartInstance({
|
() => restartInstance()
|
||||||
instanceName: App.instanceName || "astal",
|
|
||||||
log: true
|
|
||||||
})
|
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ export function reloadStyle(): void {
|
|||||||
export function compileStyle(): void {
|
export function compileStyle(): void {
|
||||||
console.log("[LOG] Compiling sass (stylesheet)");
|
console.log("[LOG] Compiling sass (stylesheet)");
|
||||||
Process.exec(`mkdir -p ${stylePath}`);
|
Process.exec(`mkdir -p ${stylePath}`);
|
||||||
Process.exec(`bash -c "sass -I ./style ./style.scss ${stylePath}/style.css"`);
|
Process.exec(`sh -c "sass -I ./style ./style.scss ${stylePath}/style.css"`);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function applyStyle(): void {
|
export function applyStyle(): void {
|
||||||
|
|||||||
+9
-46
@@ -1,55 +1,18 @@
|
|||||||
@use "sass:color";
|
@use "sass:color";
|
||||||
@use "./style/bar";
|
|
||||||
@use "./style/wal";
|
@use "./style/wal";
|
||||||
|
@use "./style/mixins";
|
||||||
|
|
||||||
|
@use "./style/bar";
|
||||||
@use "./style/osd";
|
@use "./style/osd";
|
||||||
@use "./style/control-center";
|
@use "./style/control-center";
|
||||||
|
@use "./style/center-window";
|
||||||
|
|
||||||
|
|
||||||
* {
|
* {
|
||||||
all: unset;
|
@include mixins.reset-props;
|
||||||
transition: 120ms linear;
|
|
||||||
color: color.adjust($color: wal.$foreground, $lightness: 15%);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.button-row {
|
window * {
|
||||||
& > button {
|
@include mixins.default-styles;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
+66
-61
@@ -1,39 +1,31 @@
|
|||||||
@use "sass:color";
|
@use "sass:color";
|
||||||
@use "./wal";
|
|
||||||
@use "./mixins";
|
@use "./mixins";
|
||||||
|
@use "./colors";
|
||||||
|
|
||||||
.bar-container {
|
.bar-container {
|
||||||
|
@include mixins.reset-props;
|
||||||
|
@include mixins.default-styles;
|
||||||
|
|
||||||
padding: 6px;
|
padding: 6px;
|
||||||
padding-bottom: 0px;
|
padding-bottom: 0px;
|
||||||
|
|
||||||
& {
|
|
||||||
button {
|
|
||||||
padding: 6px 8px;
|
|
||||||
border-radius: 12px;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background: wal.$color1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
label {
|
label {
|
||||||
font-size: 12px;
|
@include mixins.reset-props;
|
||||||
font-family: "Cantarell", "Noto Sans";
|
|
||||||
font-weight: 500;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Style widget groups
|
// Style widget groups
|
||||||
& > .bar-centerbox > * {
|
& > .bar-centerbox > * {
|
||||||
background: rgba($color: wal.$background, $alpha: .6);
|
background: colors.$bg-translucent;
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
border-radius: 18px;
|
border-radius: 18px;
|
||||||
|
|
||||||
// Style widgets
|
// Style widgets
|
||||||
& > *,
|
& > button,
|
||||||
& > * > button
|
& > eventbox,
|
||||||
& > * {
|
& > box {
|
||||||
margin: 0 2px;
|
margin: 0 2px;
|
||||||
|
|
||||||
&:first-child {
|
&:first-child {
|
||||||
@@ -43,22 +35,33 @@
|
|||||||
&:last-child {
|
&:last-child {
|
||||||
margin-right: 0;
|
margin-right: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
& > button,
|
||||||
|
& > eventbox > box {
|
||||||
|
padding: 4px 8px;
|
||||||
|
border-radius: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
& > button:hover,
|
||||||
|
& > eventbox:hover > box {
|
||||||
|
background: colors.$bg-primary;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.workspaces {
|
.workspaces {
|
||||||
|
@include mixins.reset-props;
|
||||||
padding: 2px 2px;
|
padding: 2px 2px;
|
||||||
|
|
||||||
& button {
|
& button {
|
||||||
all: unset;
|
|
||||||
border-radius: 16px;
|
border-radius: 16px;
|
||||||
transition: 80ms linear;
|
transition: 80ms linear;
|
||||||
padding: 12px 12px;
|
padding: 12px 12px;
|
||||||
background: wal.$color1;
|
background: colors.$bg-tertiary;
|
||||||
margin: 1px 2px;
|
margin: 1px 2px;
|
||||||
|
|
||||||
&.focus {
|
&.focus {
|
||||||
background: wal.$foreground;
|
background: colors.$fg-primary;
|
||||||
padding: 12px 20px;
|
padding: 12px 20px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -76,58 +79,47 @@
|
|||||||
font-size: 9px;
|
font-size: 9px;
|
||||||
font-family: monospace;
|
font-family: monospace;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
color: color.adjust($color: wal.$foreground, $lightness: -11%);
|
color: colors.$fg-disabled;
|
||||||
margin-top: 1px;
|
margin-top: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
& > .title {
|
& > .title {
|
||||||
font-size: 11.5px;
|
font-size: 12px;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
margin-top: -2px;
|
margin-top: -2px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.logo button {
|
|
||||||
padding: 0 11px;
|
|
||||||
padding-right: 16px;
|
|
||||||
|
|
||||||
& label {
|
|
||||||
font-size: 14px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.media-eventbox {
|
.media-eventbox {
|
||||||
& > .media > box {
|
& > .media {
|
||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
background: wal.$color1;
|
background: colors.$bg-primary;
|
||||||
padding: 0 7px;
|
padding: 0 8px;
|
||||||
|
}
|
||||||
|
|
||||||
& .icon {
|
& .nf {
|
||||||
margin-right: 6px;
|
margin-right: 4px;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
&.reveal {
|
|
||||||
& .media > box {
|
|
||||||
transition: 50ms linear;
|
|
||||||
border-top-right-radius: 0;
|
|
||||||
border-bottom-right-radius: 0;
|
|
||||||
}
|
|
||||||
& .media-controls {
|
& .media-controls {
|
||||||
|
transition: none;
|
||||||
padding-left: 6px;
|
padding-left: 6px;
|
||||||
border-top-right-radius: 12px;
|
border-top-right-radius: 12px;
|
||||||
border-bottom-right-radius: 12px;
|
border-bottom-right-radius: 12px;
|
||||||
transition: unset;
|
background: linear-gradient(to left, colors.$bg-primary 45px, colors.$bg-primary);
|
||||||
background: linear-gradient(to left, color.adjust($color: wal.$color1, $lightness: -15%) 45px, wal.$color1);
|
|
||||||
|
|
||||||
& > button {
|
& > button {
|
||||||
margin: 0px 1px;
|
margin: 4px 1px;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
|
|
||||||
|
label {
|
||||||
|
font-size: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background: wal.$color2;
|
background: colors.$bg-secondary;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:first-child {
|
&:first-child {
|
||||||
@@ -143,6 +135,13 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
&.reveal {
|
||||||
|
& .media > box {
|
||||||
|
border-top-right-radius: 0;
|
||||||
|
border-bottom-right-radius: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -170,26 +169,32 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.audio {
|
.audio {
|
||||||
&:hover > box {
|
@include mixins.reset-props;
|
||||||
background: wal.$color1;
|
|
||||||
}
|
|
||||||
|
|
||||||
& .notification-bell {
|
&:hover > box {
|
||||||
padding-left: 10px;
|
background: colors.$bg-primary;
|
||||||
padding-right: 4px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
& > box {
|
& > box {
|
||||||
padding: 0 9px;
|
padding: 0 8px;
|
||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
|
|
||||||
|
& > * > * {
|
||||||
|
margin: 0 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
& .sink .icon {
|
& .nf {
|
||||||
margin-right: 6px;
|
margin: {
|
||||||
|
right: 3px;
|
||||||
|
left: 2px;
|
||||||
|
};
|
||||||
|
|
||||||
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
& .source .icon {
|
& .bell {
|
||||||
margin-right: 4px;
|
margin: 0 4px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,40 @@
|
|||||||
|
@use "sass:color";
|
||||||
|
@use "./wal";
|
||||||
|
@use "./functions" as funs; // Did you know that you can use the 'as' keyword? I just found out!
|
||||||
|
|
||||||
|
.center-window-container {
|
||||||
|
background: wal.$background;
|
||||||
|
border-radius: 18px;
|
||||||
|
padding: 12px;
|
||||||
|
|
||||||
|
& .left {
|
||||||
|
.top {
|
||||||
|
.time {
|
||||||
|
font-size: 22px;
|
||||||
|
font-weight: 800;
|
||||||
|
}
|
||||||
|
|
||||||
|
.date {
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: funs.toRGB(color.adjust($color: wal.$foreground, $lightness: -15%));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
& .calendar-box {
|
||||||
|
padding: 5px;
|
||||||
|
& calendar {
|
||||||
|
border-radius: 6px;
|
||||||
|
padding: 2px;
|
||||||
|
|
||||||
|
&.view {
|
||||||
|
background: funs.toRGB(color.adjust($color: wal.$color1, $lightness: -35%));
|
||||||
|
|
||||||
|
& header {
|
||||||
|
background: funs.toRGB(color.adjust($color: wal.$background, $lightness: -20%));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
@use "sass:color";
|
||||||
|
@use "./wal";
|
||||||
|
@use "./functions" as funs;
|
||||||
|
|
||||||
|
$bg-primary: funs.toRGB(color.adjust($color: wal.$color1, $lightness: -35%));
|
||||||
|
$bg-secondary: funs.toRGB(color.adjust($color: wal.$color1, $lightness: -16%));
|
||||||
|
$bg-tertiary: funs.toRGB(color.adjust($color: $bg-secondary, $lightness: 10%));
|
||||||
|
$bg-light: wal.$foreground;
|
||||||
|
$bg-translucent: funs.toRGB(color.change($color: $bg-primary, $alpha: 72%));
|
||||||
|
$fg-primary: wal.$foreground;
|
||||||
|
$fg-light: $bg-primary;
|
||||||
|
$fg-disabled: funs.toRGB(color.adjust($color: wal.$foreground, $lightness: -11%));
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
@use "sass:color";
|
@use "sass:color";
|
||||||
@use "./wal";
|
@use "./wal";
|
||||||
|
@use "./functions" as funs;
|
||||||
|
|
||||||
.control-center-container {
|
.control-center-container {
|
||||||
background: rgba(wal.$background, .65);
|
background: rgba(wal.$background, .65);
|
||||||
@@ -29,7 +30,11 @@
|
|||||||
|
|
||||||
& .button-row {
|
& .button-row {
|
||||||
& button {
|
& button {
|
||||||
padding: 4px 6px;
|
padding: 7px;
|
||||||
|
margin: {
|
||||||
|
top: 2px;
|
||||||
|
bottom: 2px;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -49,20 +54,29 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
icon {
|
.icon.nf {
|
||||||
background-size: 48px;
|
margin-right: 8px;
|
||||||
|
font-size: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
trough {
|
trough {
|
||||||
background: color.adjust($color: wal.$color1, $lightness: -20%);
|
background: funs.toRGB(color.adjust($color: wal.$color1, $lightness: -20%));
|
||||||
min-height: .8em;
|
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
trough highlight {
|
trough highlight {
|
||||||
background: wal.$color1;
|
background: wal.$color1;
|
||||||
min-height: inherit;
|
border-top-left-radius: inherit;
|
||||||
border-radius: inherit;
|
border-bottom-left-radius: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
trough slider {
|
||||||
|
min-width: 1.2em;
|
||||||
|
min-height: 1.2em;
|
||||||
|
border-radius: 50%;
|
||||||
|
margin: -3px 0;
|
||||||
|
background: wal.$foreground;
|
||||||
|
margin-left: -1px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
@use "sass:color";
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GTK3 only supports sRGB color space, unfortunatly
|
||||||
|
*/
|
||||||
|
@function toRGB($color) {
|
||||||
|
@return rgba(
|
||||||
|
color.channel($color, "red"),
|
||||||
|
color.channel($color, "green"),
|
||||||
|
color.channel($color, "blue"),
|
||||||
|
color.alpha($color)
|
||||||
|
);
|
||||||
|
}
|
||||||
+74
-1
@@ -1,8 +1,81 @@
|
|||||||
@use "sass:color";
|
@use "sass:color";
|
||||||
@use "./wal";
|
@use "./wal";
|
||||||
|
@use "./colors";
|
||||||
|
@use "./functions" as funs;
|
||||||
|
|
||||||
@mixin reset-props {
|
@mixin reset-props {
|
||||||
all: unset;
|
all: unset;
|
||||||
transition: 120ms linear;
|
transition: 120ms linear;
|
||||||
color: color.adjust($color: wal.$foreground, $lightness: -15%);
|
font-family: "Cantarell", "Noto Sans",
|
||||||
|
"Noto Sans CJK JP", "Noto Sans CJK KR",
|
||||||
|
"Noto Sans CJK HK", "Noto Sans CJK SC",
|
||||||
|
"Noto Sans CJK TC", sans-serif,
|
||||||
|
"Symbols Nerd Font Mono";
|
||||||
|
color: colors.$fg-primary;
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin default-styles {
|
||||||
|
.button-row {
|
||||||
|
& > button {
|
||||||
|
background: colors.$bg-secondary;
|
||||||
|
margin: 0 1px;
|
||||||
|
padding: 0 6px;
|
||||||
|
border-radius: 2px;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: colors.$bg-tertiary;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:first-child {
|
||||||
|
border-top-left-radius: 10px;
|
||||||
|
border-bottom-left-radius: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
border-top-right-radius: 10px;
|
||||||
|
border-bottom-right-radius: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
label.nf,
|
||||||
|
button.nf label {
|
||||||
|
font-size: 12px;
|
||||||
|
font-family: "Symbols Nerd Font Mono", "Noto Sans Nerd Font Mono",
|
||||||
|
"0xProto Nerd Font Mono", "Fira Code Nerd Font Mono",
|
||||||
|
"Symbols Nerd Font", "Noto Sans Nerd Font", "Fira Code Nerd Font",
|
||||||
|
"Font Awesome";
|
||||||
|
}
|
||||||
|
|
||||||
|
& menu {
|
||||||
|
padding: 4px;
|
||||||
|
background: wal.$background;
|
||||||
|
border-radius: 14px;
|
||||||
|
|
||||||
|
& separator {
|
||||||
|
margin: 0 4px;
|
||||||
|
color: wal.$background;
|
||||||
|
}
|
||||||
|
|
||||||
|
& menuitem {
|
||||||
|
padding: 8px 16px;
|
||||||
|
border-radius: 10px;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 600;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: wal.$color1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
& tooltip {
|
||||||
|
padding: 8px;
|
||||||
|
border-radius: 14px;
|
||||||
|
|
||||||
|
& label {
|
||||||
|
font-size: 14px;
|
||||||
|
color: colors.$fg-primary;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-2
@@ -1,8 +1,9 @@
|
|||||||
@use "sass:color";
|
@use "sass:color";
|
||||||
@use "./wal";
|
@use "./wal";
|
||||||
|
@use "./functions" as funs;
|
||||||
|
|
||||||
.osd {
|
.osd {
|
||||||
background: color.change($color: wal.$background, $alpha: 65%);
|
background: funs.toRGB(color.change($color: wal.$background, $alpha: 65%));
|
||||||
padding: 14px 16px;
|
padding: 14px 16px;
|
||||||
border-radius: 20px;
|
border-radius: 20px;
|
||||||
|
|
||||||
@@ -23,7 +24,7 @@
|
|||||||
levelbar {
|
levelbar {
|
||||||
trough block {
|
trough block {
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
background: color.adjust($color: wal.$color1, $lightness: -36%);
|
background: funs.toRGB(color.adjust($color: wal.$color1, $lightness: -36%));
|
||||||
|
|
||||||
&.empty {
|
&.empty {
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
|
|||||||
@@ -21,11 +21,11 @@ export function Audio() {
|
|||||||
child: new Widget.Box({
|
child: new Widget.Box({
|
||||||
children: [
|
children: [
|
||||||
new Widget.Label({
|
new Widget.Label({
|
||||||
className: "icon nf",
|
className: "nf",
|
||||||
label: ""
|
label: ""
|
||||||
} as Widget.LabelProps),
|
} as Widget.LabelProps),
|
||||||
new Widget.Label({
|
new Widget.Label({
|
||||||
className: "icon nf",
|
className: "volume",
|
||||||
label: bind(Wireplumber.getDefault().getDefaultSink(), "volume").as((volume: number) =>
|
label: bind(Wireplumber.getDefault().getDefaultSink(), "volume").as((volume: number) =>
|
||||||
Math.floor(volume * 100) + "%")
|
Math.floor(volume * 100) + "%")
|
||||||
} as Widget.LabelProps)
|
} as Widget.LabelProps)
|
||||||
@@ -42,22 +42,21 @@ export function Audio() {
|
|||||||
child: new Widget.Box({
|
child: new Widget.Box({
|
||||||
children: [
|
children: [
|
||||||
new Widget.Label({
|
new Widget.Label({
|
||||||
className: "icon",
|
className: "nf",
|
||||||
label: ""
|
label: ""
|
||||||
} as Widget.LabelProps),
|
} as Widget.LabelProps),
|
||||||
new Widget.Label({
|
new Widget.Label({
|
||||||
|
className: "volume",
|
||||||
label: bind(Wireplumber.getDefault().getDefaultSource(), "volume").as((volume: number) =>
|
label: bind(Wireplumber.getDefault().getDefaultSource(), "volume").as((volume: number) =>
|
||||||
Math.floor(volume * 100) + "%")
|
Math.floor(volume * 100) + "%")
|
||||||
} as Widget.LabelProps)
|
} as Widget.LabelProps)
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
} as Widget.EventBoxProps),
|
} as Widget.EventBoxProps),
|
||||||
new Widget.Box({
|
new Widget.Label({
|
||||||
className: "notification-bell",
|
className: "bell nf",
|
||||||
child: new Widget.Label({
|
|
||||||
label: ""
|
label: ""
|
||||||
} as Widget.LabelProps)
|
} as Widget.LabelProps)
|
||||||
} as Widget.BoxProps)
|
|
||||||
]
|
]
|
||||||
} as Widget.BoxProps)
|
} as Widget.BoxProps)
|
||||||
} as Widget.EventBoxProps);
|
} as Widget.EventBoxProps);
|
||||||
|
|||||||
@@ -17,13 +17,13 @@ export function FocusedClient() {
|
|||||||
(getAppIcon(client.initialClass) || client.initialClass)
|
(getAppIcon(client.initialClass) || client.initialClass)
|
||||||
:
|
:
|
||||||
"image-missing"
|
"image-missing"
|
||||||
),
|
)
|
||||||
iconSize: Gtk.IconSize.SMALL_TOOLBAR
|
|
||||||
}),
|
}),
|
||||||
new Widget.Box({
|
new Widget.Box({
|
||||||
className: "text-content",
|
className: "text-content",
|
||||||
orientation: Gtk.Orientation.VERTICAL,
|
orientation: Gtk.Orientation.VERTICAL,
|
||||||
homogeneous: false,
|
homogeneous: false,
|
||||||
|
valign: Gtk.Align.CENTER,
|
||||||
children: [
|
children: [
|
||||||
new Widget.Label({
|
new Widget.Label({
|
||||||
className: "class",
|
className: "class",
|
||||||
|
|||||||
@@ -7,7 +7,8 @@ export function Logo() {
|
|||||||
//tooltipText: tr("bar.logo.tooltip"),
|
//tooltipText: tr("bar.logo.tooltip"),
|
||||||
child: new Widget.Button({
|
child: new Widget.Button({
|
||||||
onClick: () => AstalHyprland.get_default().dispatch("exec", "anyrun"),
|
onClick: () => AstalHyprland.get_default().dispatch("exec", "anyrun"),
|
||||||
label: ""
|
className: "nf",
|
||||||
|
label: "",
|
||||||
} as Widget.ButtonProps)
|
} as Widget.ButtonProps)
|
||||||
} as Widget.BoxProps);
|
} as Widget.BoxProps);
|
||||||
}
|
}
|
||||||
|
|||||||
+15
-11
@@ -1,4 +1,4 @@
|
|||||||
import { bind, Process } from "astal";
|
import { bind, GLib, Process } from "astal";
|
||||||
import { Gtk, Widget } from "astal/gtk3";
|
import { Gtk, Widget } from "astal/gtk3";
|
||||||
import AstalMpris from "gi://AstalMpris";
|
import AstalMpris from "gi://AstalMpris";
|
||||||
import { Separator, SeparatorProps } from "../Separator";
|
import { Separator, SeparatorProps } from "../Separator";
|
||||||
@@ -19,25 +19,29 @@ export function Media(): Gtk.Widget {
|
|||||||
transitionDuration: 260,
|
transitionDuration: 260,
|
||||||
revealChild: false,
|
revealChild: false,
|
||||||
child: new Widget.Box({
|
child: new Widget.Box({
|
||||||
className: "media-controls",
|
className: "media-controls button-row",
|
||||||
expand: false,
|
expand: false,
|
||||||
homogeneous: false,
|
homogeneous: false,
|
||||||
children: bind(mpris, "players").as((players: Array<AstalMpris.Player>) =>
|
children: bind(mpris, "players").as((players: Array<AstalMpris.Player>) =>
|
||||||
players[0] ? [
|
players[0] ? [
|
||||||
new Widget.Button({
|
new Widget.Button({
|
||||||
className: "link",
|
className: "link nf",
|
||||||
label: "",
|
label: "",
|
||||||
visible: bind(players[0], "metadata").as(metadata =>
|
tooltipText: "Copy link to Clipboard",
|
||||||
metadata?.["xesam:url"] ? true : false),
|
visible: bind(players[0], "metadata").as((_metadata: GLib.HashTable) =>
|
||||||
onClick: () => Process.exec(`echo ${players[0].metadata.url}"`)
|
players[0].get_meta("xesam:url") === null),
|
||||||
|
onClick: () => Process.exec(`wl-copy ${players[0].get_meta("xesam:url")?.get_string()[0]}`)
|
||||||
} as Widget.ButtonProps),
|
} as Widget.ButtonProps),
|
||||||
new Widget.Button({
|
new Widget.Button({
|
||||||
className: "previous",
|
className: "previous nf",
|
||||||
label: "",
|
label: "",
|
||||||
|
tooltipText: "Previous",
|
||||||
onClick: () => players[0].canGoPrevious && players[0].previous()
|
onClick: () => players[0].canGoPrevious && players[0].previous()
|
||||||
} as Widget.ButtonProps),
|
} as Widget.ButtonProps),
|
||||||
new Widget.Button({
|
new Widget.Button({
|
||||||
className: "pause",
|
className: "pause nf",
|
||||||
|
tooltipText: bind(players[0], "playback_status").as((status: AstalMpris.PlaybackStatus) =>
|
||||||
|
status === AstalMpris.PlaybackStatus.PLAYING ? "Pause" : "Play"),
|
||||||
label: bind(players[0], "playbackStatus").as((status: AstalMpris.PlaybackStatus) =>
|
label: bind(players[0], "playbackStatus").as((status: AstalMpris.PlaybackStatus) =>
|
||||||
status === AstalMpris.PlaybackStatus.PLAYING ? "" : ""),
|
status === AstalMpris.PlaybackStatus.PLAYING ? "" : ""),
|
||||||
onClick: () => {
|
onClick: () => {
|
||||||
@@ -48,7 +52,7 @@ export function Media(): Gtk.Widget {
|
|||||||
}
|
}
|
||||||
} as Widget.ButtonProps),
|
} as Widget.ButtonProps),
|
||||||
new Widget.Button({
|
new Widget.Button({
|
||||||
className: "next",
|
className: "next nf",
|
||||||
label: "",
|
label: "",
|
||||||
onClick: () => players[0].canGoNext && players[0].next()
|
onClick: () => players[0].canGoNext && players[0].next()
|
||||||
} as Widget.ButtonProps)
|
} as Widget.ButtonProps)
|
||||||
@@ -69,7 +73,7 @@ export function Media(): Gtk.Widget {
|
|||||||
children: bind(mpris, "players").as((players: Array<AstalMpris.Player>) =>
|
children: bind(mpris, "players").as((players: Array<AstalMpris.Player>) =>
|
||||||
players[0] ? [
|
players[0] ? [
|
||||||
new Widget.Label({
|
new Widget.Label({
|
||||||
className: "icon",
|
className: "player-icon nf",
|
||||||
label: bind(players[0], "busName").as((busName: string) => {
|
label: bind(players[0], "busName").as((busName: string) => {
|
||||||
const playerName: string = busName.split('.')[busName.split('.').length-1];
|
const playerName: string = busName.split('.')[busName.split('.').length-1];
|
||||||
return playerIcons[playerName as keyof typeof playerIcons] || "";
|
return playerIcons[playerName as keyof typeof playerIcons] || "";
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { bind } from "astal";
|
import { bind, Gio } from "astal";
|
||||||
import { Gtk, Widget } from "astal/gtk3";
|
import { Gtk, Widget } from "astal/gtk3";
|
||||||
import AstalTray from "gi://AstalTray"
|
import AstalTray from "gi://AstalTray"
|
||||||
|
|
||||||
@@ -19,7 +19,7 @@ export function Tray() {
|
|||||||
direction: Gtk.ArrowType.DOWN,
|
direction: Gtk.ArrowType.DOWN,
|
||||||
halign: Gtk.Align.CENTER,
|
halign: Gtk.Align.CENTER,
|
||||||
child: new Widget.Icon({
|
child: new Widget.Icon({
|
||||||
gIcon: bind(item, "gicon"),
|
gicon: bind(item, "gicon"),
|
||||||
iconSize: Gtk.IconSize.SMALL_TOOLBAR
|
iconSize: Gtk.IconSize.SMALL_TOOLBAR
|
||||||
})
|
})
|
||||||
} as Widget.MenuButtonProps)
|
} as Widget.MenuButtonProps)
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
import { Gtk, Widget } from "astal/gtk3";
|
||||||
|
|
||||||
|
export const BigMedia: Gtk.Widget = new Widget.Box({
|
||||||
|
className: "big-media",
|
||||||
|
//TODO
|
||||||
|
} as Widget.BoxProps);
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
import { bind } from "astal";
|
||||||
|
import { Gtk, Widget } from "astal/gtk3";
|
||||||
|
import AstalNotifd from "gi://AstalNotifd";
|
||||||
|
import { Notifications } from "../../scripts/notification-handler";
|
||||||
|
|
||||||
|
export const NotificationHistory: Gtk.Widget = new Widget.Scrollable({
|
||||||
|
hscroll: Gtk.PolicyType.NEVER,
|
||||||
|
vscroll: Gtk.PolicyType.AUTOMATIC,
|
||||||
|
child: new Widget.Box({
|
||||||
|
className: "notifications",
|
||||||
|
children: bind(Notifications, "notificationHistory").as((history: Array<AstalNotifd.Notification>) =>
|
||||||
|
history && history.length > 0 && history.map((notification: AstalNotifd.Notification) =>
|
||||||
|
new Widget.Box({
|
||||||
|
className: "notification",
|
||||||
|
hexpand: true,
|
||||||
|
orientation: Gtk.Orientation.VERTICAL,
|
||||||
|
children: [
|
||||||
|
new Widget.Box({
|
||||||
|
className: "top",
|
||||||
|
expand: true,
|
||||||
|
children: [
|
||||||
|
new Widget.Box({
|
||||||
|
className: "app",
|
||||||
|
children: [
|
||||||
|
new Widget.Icon({
|
||||||
|
icon: notification.appIcon || notification.appName.toLowerCase(),
|
||||||
|
iconSize: Gtk.IconSize.LARGE_TOOLBAR
|
||||||
|
}),
|
||||||
|
new Widget.Label({
|
||||||
|
className: "name",
|
||||||
|
label: notification.appName || "Unknown"
|
||||||
|
} as Widget.LabelProps)
|
||||||
|
]
|
||||||
|
} as Widget.BoxProps),
|
||||||
|
new Widget.Button({
|
||||||
|
className: "remove",
|
||||||
|
label: "",
|
||||||
|
onClick: () => Notifications.removeFromNotificationHistory(notification.id)
|
||||||
|
} as Widget.ButtonProps)
|
||||||
|
]
|
||||||
|
} as Widget.BoxProps),
|
||||||
|
new Widget.Box({
|
||||||
|
className: "content",
|
||||||
|
expand: true,
|
||||||
|
children: [
|
||||||
|
new Widget.Box({
|
||||||
|
className: "image",
|
||||||
|
visible: notification.image !== "",
|
||||||
|
css: `.image { background-image: url('${notification.image}') }`
|
||||||
|
} as Widget.BoxProps),
|
||||||
|
new Widget.Box({
|
||||||
|
orientation: Gtk.Orientation.VERTICAL,
|
||||||
|
children: [
|
||||||
|
new Widget.Label({
|
||||||
|
className: "summary",
|
||||||
|
useMarkup: true,
|
||||||
|
label: notification.summary
|
||||||
|
} as Widget.LabelProps),
|
||||||
|
new Widget.Label({
|
||||||
|
className: "body",
|
||||||
|
useMarkup: true,
|
||||||
|
label: notification.body
|
||||||
|
} as Widget.LabelProps)
|
||||||
|
]
|
||||||
|
} as Widget.BoxProps)
|
||||||
|
]
|
||||||
|
} as Widget.BoxProps)
|
||||||
|
]
|
||||||
|
} as Widget.BoxProps)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
} as Widget.BoxProps)
|
||||||
|
} as Widget.ScrollableProps)
|
||||||
@@ -10,6 +10,7 @@ const uptime = new Variable<string>("Just turned on")
|
|||||||
|
|
||||||
function LockButton(): Widget.Button {
|
function LockButton(): Widget.Button {
|
||||||
return new Widget.Button({
|
return new Widget.Button({
|
||||||
|
className: "nf",
|
||||||
label: "",
|
label: "",
|
||||||
onClick: () => AstalHyprland.get_default().dispatch("exec", "hyprlock")
|
onClick: () => AstalHyprland.get_default().dispatch("exec", "hyprlock")
|
||||||
} as Widget.ButtonProps)
|
} as Widget.ButtonProps)
|
||||||
@@ -17,6 +18,7 @@ function LockButton(): Widget.Button {
|
|||||||
|
|
||||||
function ColorPickerButton(): Widget.Button {
|
function ColorPickerButton(): Widget.Button {
|
||||||
return new Widget.Button({
|
return new Widget.Button({
|
||||||
|
className: "nf",
|
||||||
label: "",
|
label: "",
|
||||||
onClick: () => AstalHyprland.get_default().dispatch(
|
onClick: () => AstalHyprland.get_default().dispatch(
|
||||||
"exec",
|
"exec",
|
||||||
@@ -27,6 +29,7 @@ function ColorPickerButton(): Widget.Button {
|
|||||||
|
|
||||||
function ScreenshotButton(): Widget.Button {
|
function ScreenshotButton(): Widget.Button {
|
||||||
return new Widget.Button({
|
return new Widget.Button({
|
||||||
|
className: "nf",
|
||||||
label: "",
|
label: "",
|
||||||
onClick: () => Process.exec_async(
|
onClick: () => Process.exec_async(
|
||||||
"bash -c 'hyprshot -m region -o $HOME/Screenshots'",
|
"bash -c 'hyprshot -m region -o $HOME/Screenshots'",
|
||||||
@@ -37,6 +40,7 @@ function ScreenshotButton(): Widget.Button {
|
|||||||
|
|
||||||
function SelectWallpaperButton(): Widget.Button {
|
function SelectWallpaperButton(): Widget.Button {
|
||||||
return new Widget.Button({
|
return new Widget.Button({
|
||||||
|
className: "nf",
|
||||||
label: "",
|
label: "",
|
||||||
onClick: () => Process.exec_async(
|
onClick: () => Process.exec_async(
|
||||||
"bash -c 'sh $HOME/.config/hypr/scripts/change-wallpaper.sh'",
|
"bash -c 'sh $HOME/.config/hypr/scripts/change-wallpaper.sh'",
|
||||||
@@ -47,6 +51,7 @@ function SelectWallpaperButton(): Widget.Button {
|
|||||||
|
|
||||||
function LogoutButton(): Widget.Button {
|
function LogoutButton(): Widget.Button {
|
||||||
return new Widget.Button({
|
return new Widget.Button({
|
||||||
|
className: "nf",
|
||||||
label: "",
|
label: "",
|
||||||
onClick: () => Process.exec_async(
|
onClick: () => Process.exec_async(
|
||||||
"bash -c 'wlogout -b 5'",
|
"bash -c 'wlogout -b 5'",
|
||||||
|
|||||||
@@ -10,9 +10,10 @@ export const Sliders: Gtk.Widget = new Widget.Box({
|
|||||||
new Widget.Box({
|
new Widget.Box({
|
||||||
className: "sink speaker",
|
className: "sink speaker",
|
||||||
children: [
|
children: [
|
||||||
new Widget.Icon({
|
new Widget.Label({
|
||||||
icon: "audio-volume-high-symbolic"
|
className: "nf icon",
|
||||||
} as Widget.IconProps),
|
label: ""
|
||||||
|
} as Widget.LabelProps),
|
||||||
new Widget.Slider({
|
new Widget.Slider({
|
||||||
drawValue: false,
|
drawValue: false,
|
||||||
hexpand: true,
|
hexpand: true,
|
||||||
@@ -26,9 +27,10 @@ export const Sliders: Gtk.Widget = new Widget.Box({
|
|||||||
new Widget.Box({
|
new Widget.Box({
|
||||||
className: "source microphone",
|
className: "source microphone",
|
||||||
children: [
|
children: [
|
||||||
new Widget.Icon({
|
new Widget.Label({
|
||||||
icon: "microphone-sensitivity-high-symbolic"
|
className: "nf icon",
|
||||||
} as Widget.IconProps),
|
label: ""
|
||||||
|
} as Widget.LabelProps),
|
||||||
new Widget.Slider({
|
new Widget.Slider({
|
||||||
drawValue: false,
|
drawValue: false,
|
||||||
hexpand: true,
|
hexpand: true,
|
||||||
@@ -42,6 +44,10 @@ export const Sliders: Gtk.Widget = new Widget.Box({
|
|||||||
/*new Widget.Box({
|
/*new Widget.Box({
|
||||||
className: "brightness screen",
|
className: "brightness screen",
|
||||||
children: [
|
children: [
|
||||||
|
new Widget.Label({
|
||||||
|
className: "icon nf",
|
||||||
|
label: ""
|
||||||
|
} as Widget.LabelProps),
|
||||||
new Widget.Slider({
|
new Widget.Slider({
|
||||||
drawValue: false,
|
drawValue: false,
|
||||||
hexpand: true,
|
hexpand: true,
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ export const tileList: Array<Gtk.Widget> = [
|
|||||||
|
|
||||||
export const Tiles: Widget.Box = new Widget.Box({
|
export const Tiles: Widget.Box = new Widget.Box({
|
||||||
child: new Gtk.Grid({
|
child: new Gtk.Grid({
|
||||||
|
visible: true,
|
||||||
orientation: Gtk.Orientation.HORIZONTAL,
|
orientation: Gtk.Orientation.HORIZONTAL,
|
||||||
rowHomogeneous: true
|
rowHomogeneous: true
|
||||||
} as Gtk.Grid.ConstructorProps)
|
} as Gtk.Grid.ConstructorProps)
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ import { GLib } from "astal";
|
|||||||
|
|
||||||
import { getDateTime } from "../scripts/time";
|
import { getDateTime } from "../scripts/time";
|
||||||
|
|
||||||
|
|
||||||
export const CenterWindow: Widget.Window = new Widget.Window({
|
export const CenterWindow: Widget.Window = new Widget.Window({
|
||||||
className: "center-window",
|
className: "center-window",
|
||||||
namespace: "center-window",
|
namespace: "center-window",
|
||||||
@@ -12,7 +11,8 @@ export const CenterWindow: Widget.Window = new Widget.Window({
|
|||||||
layer: Astal.Layer.OVERLAY,
|
layer: Astal.Layer.OVERLAY,
|
||||||
exclusivity: Astal.Exclusivity.NORMAL,
|
exclusivity: Astal.Exclusivity.NORMAL,
|
||||||
visible: false,
|
visible: false,
|
||||||
height_request: 600,
|
height_request: 400,
|
||||||
|
margin_top: 10,
|
||||||
anchor: Astal.WindowAnchor.TOP,
|
anchor: Astal.WindowAnchor.TOP,
|
||||||
child: new Widget.Box({
|
child: new Widget.Box({
|
||||||
className: "center-window-container",
|
className: "center-window-container",
|
||||||
@@ -23,7 +23,7 @@ export const CenterWindow: Widget.Window = new Widget.Window({
|
|||||||
width_request: 300,
|
width_request: 300,
|
||||||
children: [
|
children: [
|
||||||
new Widget.Box({
|
new Widget.Box({
|
||||||
className: "top time date",
|
className: "top",
|
||||||
orientation: Gtk.Orientation.VERTICAL,
|
orientation: Gtk.Orientation.VERTICAL,
|
||||||
children: [
|
children: [
|
||||||
new Widget.Label({
|
new Widget.Label({
|
||||||
@@ -37,7 +37,7 @@ export const CenterWindow: Widget.Window = new Widget.Window({
|
|||||||
dateTime.format("%A, %B %d %Y"))
|
dateTime.format("%A, %B %d %Y"))
|
||||||
} as Widget.LabelProps)
|
} as Widget.LabelProps)
|
||||||
]
|
]
|
||||||
} as Widget.BoxProps)
|
} as Widget.BoxProps),
|
||||||
]
|
]
|
||||||
} as Widget.BoxProps),
|
} as Widget.BoxProps),
|
||||||
new Widget.Box({
|
new Widget.Box({
|
||||||
@@ -46,6 +46,7 @@ export const CenterWindow: Widget.Window = new Widget.Window({
|
|||||||
new Widget.Box({
|
new Widget.Box({
|
||||||
className: "calendar-box",
|
className: "calendar-box",
|
||||||
child: new Gtk.Calendar({
|
child: new Gtk.Calendar({
|
||||||
|
visible: true,
|
||||||
show_heading: true,
|
show_heading: true,
|
||||||
show_day_names: true,
|
show_day_names: true,
|
||||||
show_week_numbers: false
|
show_week_numbers: false
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ export const ControlCenter: Widget.Window = new Widget.Window({
|
|||||||
layer: Astal.Layer.OVERLAY,
|
layer: Astal.Layer.OVERLAY,
|
||||||
margin_top: 10,
|
margin_top: 10,
|
||||||
margin_right: 10,
|
margin_right: 10,
|
||||||
width_request: 450,
|
width_request: 400,
|
||||||
monitor: 0,
|
monitor: 0,
|
||||||
visible: false
|
visible: false
|
||||||
} as Widget.WindowProps, widgetsContainer);
|
} as Widget.WindowProps, widgetsContainer);
|
||||||
|
|||||||
@@ -1,26 +1,29 @@
|
|||||||
import { Astal, Gtk, Widget } from "astal/gtk3";
|
import { Astal, Gtk, Widget } from "astal/gtk3";
|
||||||
import { getNotifd, notifications, removeNotification } from "../scripts/notification-handler";
|
|
||||||
import AstalNotifd from "gi://AstalNotifd";
|
import AstalNotifd from "gi://AstalNotifd";
|
||||||
import { bind } from "astal";
|
import { bind } from "astal";
|
||||||
|
import { Notifications } from "../scripts/notification-handler";
|
||||||
|
|
||||||
export const FloatingNotifications: Widget.Window = new Widget.Window({
|
export const FloatingNotifications: Widget.Window = new Widget.Window({
|
||||||
className: "floating-notifications",
|
|
||||||
namespace: "floating-notifications",
|
namespace: "floating-notifications",
|
||||||
canFocus: false,
|
canFocus: false,
|
||||||
anchor: Astal.WindowAnchor.RIGHT,
|
anchor: Astal.WindowAnchor.RIGHT,
|
||||||
monitor: 0,
|
monitor: 0,
|
||||||
layer: Astal.Layer.OVERLAY,
|
layer: Astal.Layer.OVERLAY,
|
||||||
visible: false,
|
visible: false,
|
||||||
|
width_request: 350,
|
||||||
exclusivity: Astal.Exclusivity.NORMAL,
|
exclusivity: Astal.Exclusivity.NORMAL,
|
||||||
child: new Widget.Box({
|
child: new Widget.Box({
|
||||||
className: "notifications",
|
className: "floating-notifications-container",
|
||||||
orientation: Gtk.Orientation.VERTICAL,
|
orientation: Gtk.Orientation.VERTICAL,
|
||||||
homogeneous: false,
|
homogeneous: false,
|
||||||
children: bind(getNotifd(), "notifications").as(() => {
|
children: bind(Notifications, "notifications").as((notifications: Array<AstalNotifd.Notification>) => {
|
||||||
notifications.length > 0 ? notifications.map((notification: AstalNotifd.Notification) =>
|
console.log("something changed!");
|
||||||
|
return notifications.map((notification: AstalNotifd.Notification) =>
|
||||||
new Widget.Box({
|
new Widget.Box({
|
||||||
className: "notification",
|
className: "notification",
|
||||||
homogeneous: false,
|
homogeneous: false,
|
||||||
|
expand: false,
|
||||||
|
orientation: Gtk.Orientation.VERTICAL,
|
||||||
children: [
|
children: [
|
||||||
new Widget.Box({
|
new Widget.Box({
|
||||||
className: "top",
|
className: "top",
|
||||||
@@ -35,13 +38,40 @@ export const FloatingNotifications: Widget.Window = new Widget.Window({
|
|||||||
} as Widget.LabelProps),
|
} as Widget.LabelProps),
|
||||||
new Widget.Button({
|
new Widget.Button({
|
||||||
className: "close-button",
|
className: "close-button",
|
||||||
onClick: () => removeNotification(notification.id)
|
onClick: () => Notifications.removeNotification(notification.id)
|
||||||
} as Widget.ButtonProps)
|
} as Widget.ButtonProps)
|
||||||
]
|
]
|
||||||
|
} as Widget.BoxProps),
|
||||||
|
new Widget.Box({
|
||||||
|
className: "content",
|
||||||
|
orientation: Gtk.Orientation.HORIZONTAL,
|
||||||
|
children: [
|
||||||
|
new Widget.Box({
|
||||||
|
className: "image",
|
||||||
|
visible: notification.image !== "",
|
||||||
|
css: `.image { background-image: url('${notification.image}'); }`
|
||||||
|
} as Widget.BoxProps),
|
||||||
|
new Widget.Box({
|
||||||
|
className: "text",
|
||||||
|
orientation: Gtk.Orientation.VERTICAL,
|
||||||
|
children: [
|
||||||
|
new Widget.Label({
|
||||||
|
className: "summary",
|
||||||
|
useMarkup: true,
|
||||||
|
label: notification.summary
|
||||||
|
}),
|
||||||
|
new Widget.Label({
|
||||||
|
className: "body",
|
||||||
|
useMarkup: true,
|
||||||
|
label: notification.body
|
||||||
|
} as Widget.LabelProps)
|
||||||
|
]
|
||||||
} as Widget.BoxProps)
|
} as Widget.BoxProps)
|
||||||
]
|
]
|
||||||
} as Widget.BoxProps)
|
} as Widget.BoxProps)
|
||||||
) : new Widget.Box({})
|
]
|
||||||
|
} as Widget.BoxProps)
|
||||||
|
)
|
||||||
})
|
})
|
||||||
} as Widget.BoxProps)
|
} as Widget.BoxProps)
|
||||||
} as Widget.WindowProps);
|
} as Widget.WindowProps);
|
||||||
|
|||||||
@@ -0,0 +1,72 @@
|
|||||||
|
import { Astal, Gdk, Gtk, Widget } from "astal/gtk3";
|
||||||
|
import { getDateTime } from "../scripts/time";
|
||||||
|
import { execAsync, GLib, Process } from "astal";
|
||||||
|
|
||||||
|
|
||||||
|
const { TOP, LEFT, RIGHT, BOTTOM } = Astal.WindowAnchor;
|
||||||
|
|
||||||
|
export const LogoutMenu: Widget.Window = new Widget.Window({
|
||||||
|
namespace: "logout-menu",
|
||||||
|
anchor: TOP | LEFT | RIGHT | BOTTOM,
|
||||||
|
layer: Astal.Layer.OVERLAY,
|
||||||
|
exclusivity: Astal.Exclusivity.IGNORE,
|
||||||
|
monitor: 0,
|
||||||
|
visible: false,
|
||||||
|
widthRequest: Gdk.Screen.get_default()?.get_monitor_geometry(0)?.width,
|
||||||
|
height_request: Gdk.Screen.get_default()?.get_monitor_geometry(0)?.height,
|
||||||
|
child: new Widget.EventBox({
|
||||||
|
className: "logout-menu",
|
||||||
|
onClick: () => Process.exec_async("astal close logout-menu", () => {}),
|
||||||
|
child: new Widget.Box({
|
||||||
|
homogeneous: false,
|
||||||
|
orientation: Gtk.Orientation.VERTICAL,
|
||||||
|
children: [
|
||||||
|
new Widget.Box({
|
||||||
|
className: "top",
|
||||||
|
expand: true,
|
||||||
|
orientation: Gtk.Orientation.VERTICAL,
|
||||||
|
children: [
|
||||||
|
new Widget.Label({
|
||||||
|
className: "time",
|
||||||
|
label: getDateTime().as((dateTime: GLib.DateTime) =>
|
||||||
|
dateTime.format("%H:%M"))
|
||||||
|
} as Widget.LabelProps),
|
||||||
|
new Widget.Label({
|
||||||
|
className: "date",
|
||||||
|
label: getDateTime().as((dateTime: GLib.DateTime) =>
|
||||||
|
dateTime.format("%A, %B %d %Y"))
|
||||||
|
} as Widget.LabelProps)
|
||||||
|
]
|
||||||
|
} as Widget.BoxProps),
|
||||||
|
new Widget.Box({
|
||||||
|
className: "button-row",
|
||||||
|
homogeneous: true,
|
||||||
|
expand: true,
|
||||||
|
valign: Gtk.Align.CENTER,
|
||||||
|
children: [
|
||||||
|
new Widget.Button({
|
||||||
|
className: "poweroff nf",
|
||||||
|
label: "",
|
||||||
|
onClick: "ask user if it's fr!"
|
||||||
|
} as Widget.ButtonProps),
|
||||||
|
new Widget.Button({
|
||||||
|
className: "reboot nf",
|
||||||
|
label: "",
|
||||||
|
onClick: "ask user if it's fr!"
|
||||||
|
} as Widget.ButtonProps),
|
||||||
|
new Widget.Button({
|
||||||
|
className: "suspend nf",
|
||||||
|
label: "",
|
||||||
|
onClick: "ask user if it's fr!"
|
||||||
|
} as Widget.ButtonProps),
|
||||||
|
new Widget.Button({
|
||||||
|
className: "logout nf",
|
||||||
|
label: "",
|
||||||
|
onClick: () => execAsync("astal close logout-menu && bash -c 'loginctl terminate-user $USER'")
|
||||||
|
} as Widget.ButtonProps),
|
||||||
|
]
|
||||||
|
} as Widget.BoxProps)
|
||||||
|
]
|
||||||
|
})
|
||||||
|
} as Widget.EventBoxProps)
|
||||||
|
} as Widget.WindowProps);
|
||||||
+2
-1
@@ -6,6 +6,7 @@ import { ControlCenter } from "./window/ControlCenter";
|
|||||||
import { CenterWindow } from "./window/CenterWindow";
|
import { CenterWindow } from "./window/CenterWindow";
|
||||||
import { FloatingNotifications } from "./window/FloatingNotifications";
|
import { FloatingNotifications } from "./window/FloatingNotifications";
|
||||||
import { GObject } from "astal";
|
import { GObject } from "astal";
|
||||||
|
import { LogoutMenu } from "./window/LogoutMenu";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* get open windows / interact with windows(e.g.: close, open or toggle)
|
* get open windows / interact with windows(e.g.: close, open or toggle)
|
||||||
@@ -20,7 +21,7 @@ export const Windows = GObject.registerClass({
|
|||||||
WindowsClass.windowsMap.set("osd", OSD);
|
WindowsClass.windowsMap.set("osd", OSD);
|
||||||
WindowsClass.windowsMap.set("control-center", ControlCenter);
|
WindowsClass.windowsMap.set("control-center", ControlCenter);
|
||||||
WindowsClass.windowsMap.set("center-window", CenterWindow);
|
WindowsClass.windowsMap.set("center-window", CenterWindow);
|
||||||
WindowsClass.windowsMap.set("floating-notifications", FloatingNotifications);
|
WindowsClass.windowsMap.set("logout-menu", LogoutMenu);
|
||||||
}
|
}
|
||||||
|
|
||||||
public _init(...args: any[]) {
|
public _init(...args: any[]) {
|
||||||
|
|||||||
Reference in New Issue
Block a user