ags: finish center-window widget with big-media and calendar
This commit is contained in:
@@ -1,29 +1,30 @@
|
|||||||
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 { Subscribable } from "astal/binding";
|
||||||
import { GObject, register, signal } from "astal";
|
import { GObject, property, register, Variable } from "astal";
|
||||||
import { Windows } from "../windows";
|
import { Windows } from "../windows";
|
||||||
|
import { FloatingNotifications } from "../window/FloatingNotifications";
|
||||||
|
|
||||||
@register({ GTypeName: "Notifications" })
|
@register({ GTypeName: "Notifications" })
|
||||||
class NotificationsClass extends GObject.Object implements Connectable {
|
class NotificationsClass extends GObject.Object implements Subscribable {
|
||||||
|
|
||||||
private static instance: NotificationsClass;
|
private static instance: NotificationsClass;
|
||||||
|
|
||||||
|
@property(AstalNotifd.Notifd)
|
||||||
private notifd: AstalNotifd.Notifd;
|
private notifd: AstalNotifd.Notifd;
|
||||||
|
|
||||||
public notifications: Array<AstalNotifd.Notification> = [];
|
@property(Boolean)
|
||||||
|
private doNotDisturb: boolean = false;
|
||||||
|
|
||||||
|
@property()
|
||||||
public notificationHistory: Array<AstalNotifd.Notification> = [];
|
public notificationHistory: Array<AstalNotifd.Notification> = [];
|
||||||
|
|
||||||
@signal(AstalNotifd.Notification)
|
@property()
|
||||||
declare notificationAdded: (added: AstalNotifd.Notification) => void;
|
public notifications: Variable<Array<AstalNotifd.Notification>> = new Variable<Array<AstalNotifd.Notification>>([]);
|
||||||
|
|
||||||
@signal(Number)
|
|
||||||
declare notificationRemoved: (id: number) => void;
|
|
||||||
|
|
||||||
|
|
||||||
public static getDefault(): NotificationsClass {
|
public static getDefault(): NotificationsClass {
|
||||||
if(!NotificationsClass.instance) {
|
if(!NotificationsClass.instance) {
|
||||||
NotificationsClass.instance = new NotificationsClass();
|
NotificationsClass.instance = new NotificationsClass();
|
||||||
this.instance._init();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return NotificationsClass.instance;
|
return NotificationsClass.instance;
|
||||||
@@ -36,13 +37,28 @@ class NotificationsClass extends GObject.Object implements Connectable {
|
|||||||
dontDisturb: false
|
dontDisturb: false
|
||||||
} as AstalNotifd.Notifd.ConstructorProps);
|
} as AstalNotifd.Notifd.ConstructorProps);
|
||||||
|
|
||||||
this.getNotifd().connect("notified", (_source: AstalNotifd.Notifd, id: number, _replaced: boolean) => {
|
this.getNotifd().connect("notified", (daemon: AstalNotifd.Notifd, id: number) => {
|
||||||
this.addNotification(this.getNotifd().get_notification(id));
|
const notification: (AstalNotifd.Notification|null) = daemon.get_notification(id);
|
||||||
|
if(!notification) {
|
||||||
|
console.log("[LOG] Notification is null, ignoring");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!this.doNotDisturb) {
|
||||||
|
this.handleNotification(notification);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.addHistory(notification);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public addNotification(notification: AstalNotifd.Notification) {
|
public handleNotification(notification: AstalNotifd.Notification): void {
|
||||||
this.prependArray(this.notifications, this.getNotifd().get_notification(notification.id));
|
Windows.open(FloatingNotifications);
|
||||||
|
|
||||||
|
let tmpArray = this.notifications.get().reverse();
|
||||||
|
tmpArray.push(notification);
|
||||||
|
this.notifications.set(tmpArray.reverse());
|
||||||
|
|
||||||
// default timeout if undefined
|
// default timeout if undefined
|
||||||
let notificationTimeout = 4000;
|
let notificationTimeout = 4000;
|
||||||
@@ -56,47 +72,38 @@ class NotificationsClass extends GObject.Object implements Connectable {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
notification.urgency !== AstalNotifd.Urgency.CRITICAL ?
|
notification.urgency !== AstalNotifd.Urgency.CRITICAL &&
|
||||||
timeout(notificationTimeout, () => {
|
timeout(notificationTimeout, () => {
|
||||||
this.notifications.map((item: AstalNotifd.Notification) =>
|
notification.dismiss();
|
||||||
item.id === notification.id && (() => {
|
this.notifications.set(this.notifications.get().filter((item) => item.id !== notification.id));
|
||||||
this.removeNotification(notification.id);
|
this.addHistory(notification);
|
||||||
this.addToNotificationHistory(notification);
|
});
|
||||||
})())
|
|
||||||
})
|
|
||||||
: this.addToNotificationHistory(notification);
|
|
||||||
|
|
||||||
this.emit("notification-added", notification);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public removeNotification(notificationId: number) {
|
public addHistory(notification: AstalNotifd.Notification): void {
|
||||||
if(this.notifications.length === 1)
|
let tmpArray: Array<AstalNotifd.Notification> = this.notificationHistory.reverse()
|
||||||
Windows.close(Windows.getWindow("floating-notifications")!);
|
.filter((item: AstalNotifd.Notification) => item.id !== notification.id);
|
||||||
|
tmpArray.push(notification);
|
||||||
this.notifications = this.notifications.filter((notification: AstalNotifd.Notification) =>
|
this.notificationHistory = tmpArray.reverse();
|
||||||
notification.id !== notificationId);
|
|
||||||
|
|
||||||
this.emit("notification-removed", notificationId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public addToNotificationHistory(notification: AstalNotifd.Notification) {
|
public removeHistory(notification: AstalNotifd.Notification) {
|
||||||
this.prependArray(this.notificationHistory, notification);
|
|
||||||
}
|
|
||||||
|
|
||||||
public removeFromNotificationHistory(notificationId: number) {
|
|
||||||
this.notificationHistory = this.notificationHistory.filter((curNotification: AstalNotifd.Notification) =>
|
this.notificationHistory = this.notificationHistory.filter((curNotification: AstalNotifd.Notification) =>
|
||||||
curNotification.id !== notificationId);
|
curNotification.id !== notification.id);
|
||||||
}
|
|
||||||
|
|
||||||
private prependArray(array: Array<any>, item: any): Array<any> {
|
|
||||||
let tmpArray = array.reverse();
|
|
||||||
tmpArray.push(item);
|
|
||||||
return tmpArray.reverse();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public getNotifd(): AstalNotifd.Notifd {
|
public getNotifd(): AstalNotifd.Notifd {
|
||||||
return this.notifd;
|
return this.notifd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get() {
|
||||||
|
return this.notifications.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
subscribe(callback: (list: Array<AstalNotifd.Notification>) => void) {
|
||||||
|
return this.notifications.subscribe(callback);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Notifications = new NotificationsClass();
|
export const Notifications = new NotificationsClass();
|
||||||
|
|||||||
@@ -2,11 +2,13 @@
|
|||||||
|
|
||||||
@use "./style/wal";
|
@use "./style/wal";
|
||||||
@use "./style/mixins";
|
@use "./style/mixins";
|
||||||
|
@use "./style/colors";
|
||||||
|
|
||||||
@use "./style/bar";
|
@use "./style/bar";
|
||||||
@use "./style/osd";
|
@use "./style/osd";
|
||||||
@use "./style/control-center";
|
@use "./style/control-center";
|
||||||
@use "./style/center-window";
|
@use "./style/center-window";
|
||||||
|
@use "./style/float-notifications";
|
||||||
|
|
||||||
|
|
||||||
* {
|
* {
|
||||||
@@ -16,3 +18,17 @@
|
|||||||
window * {
|
window * {
|
||||||
@include mixins.default-styles;
|
@include mixins.default-styles;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tooltip {
|
||||||
|
padding: 16px;
|
||||||
|
|
||||||
|
& > box {
|
||||||
|
padding: 7px 8px;
|
||||||
|
border-radius: 10px;
|
||||||
|
background: rgba(colors.$bg-primary, .98);
|
||||||
|
font-size: 13.1px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: colors.$fg-primary;
|
||||||
|
box-shadow: 0 1px 4px 1px rgba(colors.$bg-primary, .6);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
+17
-3
@@ -91,6 +91,10 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.clock.open > button {
|
||||||
|
background-color: colors.$bg-primary;
|
||||||
|
}
|
||||||
|
|
||||||
.media-eventbox {
|
.media-eventbox {
|
||||||
& > .media {
|
& > .media {
|
||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
@@ -98,6 +102,10 @@
|
|||||||
padding: 0 8px;
|
padding: 0 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&:hover > .media {
|
||||||
|
box-shadow: inset 0 0 0 300px rgba(colors.$fg-primary, .2);
|
||||||
|
}
|
||||||
|
|
||||||
& .nf {
|
& .nf {
|
||||||
margin-right: 4px;
|
margin-right: 4px;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
@@ -105,10 +113,9 @@
|
|||||||
|
|
||||||
& .media-controls {
|
& .media-controls {
|
||||||
transition: none;
|
transition: none;
|
||||||
padding-left: 6px;
|
padding: 0 6px;
|
||||||
border-top-right-radius: 12px;
|
border-top-right-radius: 12px;
|
||||||
border-bottom-right-radius: 12px;
|
border-bottom-right-radius: 12px;
|
||||||
background: linear-gradient(to left, colors.$bg-primary 45px, colors.$bg-primary);
|
|
||||||
|
|
||||||
& > button {
|
& > button {
|
||||||
margin: 4px 1px;
|
margin: 4px 1px;
|
||||||
@@ -124,6 +131,12 @@
|
|||||||
& .media > box {
|
& .media > box {
|
||||||
border-top-right-radius: 0;
|
border-top-right-radius: 0;
|
||||||
border-bottom-right-radius: 0;
|
border-bottom-right-radius: 0;
|
||||||
|
padding: 0 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
& .media {
|
||||||
|
padding-left: 0;
|
||||||
|
padding-right: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -154,7 +167,8 @@
|
|||||||
.audio {
|
.audio {
|
||||||
@include mixins.reset-props;
|
@include mixins.reset-props;
|
||||||
|
|
||||||
&:hover > box {
|
&:hover > box,
|
||||||
|
&.open > box {
|
||||||
background: colors.$bg-primary;
|
background: colors.$bg-primary;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,24 +8,8 @@
|
|||||||
border-radius: 18px;
|
border-radius: 18px;
|
||||||
padding: 12px;
|
padding: 12px;
|
||||||
|
|
||||||
& .left {
|
|
||||||
& > .top {
|
|
||||||
padding-bottom: 10px;
|
|
||||||
|
|
||||||
& .time {
|
|
||||||
font-size: 28px;
|
|
||||||
font-weight: 800;
|
|
||||||
}
|
|
||||||
|
|
||||||
& .date {
|
|
||||||
font-size: 14px;
|
|
||||||
font-weight: 500;
|
|
||||||
color: colors.$fg-disabled;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
& .big-media {
|
& .big-media {
|
||||||
padding: 6px 16px;
|
padding: 6px;
|
||||||
|
|
||||||
& > box > .image {
|
& > box > .image {
|
||||||
background-size: cover;
|
background-size: cover;
|
||||||
@@ -51,26 +35,90 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
& > .controls {
|
& slider {
|
||||||
padding: 8px 0;
|
background: transparent;
|
||||||
|
min-height: .6em;
|
||||||
|
}
|
||||||
|
|
||||||
|
& trough {
|
||||||
|
border-radius: 4px;
|
||||||
|
min-height: .6em;
|
||||||
|
}
|
||||||
|
|
||||||
|
& trough highlight {
|
||||||
|
border-radius: 4px;
|
||||||
|
min-height: .6em;
|
||||||
|
}
|
||||||
|
|
||||||
|
& .bottom {
|
||||||
|
& .controls {
|
||||||
|
margin-top: 5px;
|
||||||
|
& button {
|
||||||
|
padding: 7px;
|
||||||
|
& label {
|
||||||
|
font-size: 10px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
& .right {
|
& .elapsed,
|
||||||
|
& .length {
|
||||||
|
font-size: 12px;
|
||||||
|
color: colors.$fg-disabled;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
& .left .top {
|
||||||
|
padding-bottom: 10px;
|
||||||
|
|
||||||
|
& .time {
|
||||||
|
font-size: 28px;
|
||||||
|
font-weight: 800;
|
||||||
|
}
|
||||||
|
|
||||||
|
& .date {
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: colors.$fg-disabled;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
& .calendar-box {
|
& .calendar-box {
|
||||||
padding: 5px;
|
|
||||||
& calendar {
|
& calendar {
|
||||||
border-radius: 6px;
|
$border-radius: 10px;
|
||||||
padding: 2px;
|
font-weight: 600;
|
||||||
|
padding-bottom: 2px;
|
||||||
|
|
||||||
&.view {
|
&.view {
|
||||||
background: funs.toRGB(color.adjust($color: wal.$color1, $lightness: -35%));
|
background: colors.$bg-primary;
|
||||||
|
border-radius: $border-radius;
|
||||||
|
}
|
||||||
|
|
||||||
& header {
|
&.header {
|
||||||
background: funs.toRGB(color.adjust($color: wal.$background, $lightness: -20%));
|
background: colors.$bg-secondary;
|
||||||
|
border-top-left-radius: $border-radius;
|
||||||
|
border-top-right-radius: $border-radius;
|
||||||
|
padding: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.button {
|
||||||
|
transition: 80ms linear;
|
||||||
|
border-radius: 6px;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: colors.$bg-tertiary;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&:selected {
|
||||||
|
background: colors.$bg-secondary;
|
||||||
|
border-radius: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.highlight {
|
||||||
|
background: transparent;
|
||||||
|
box-shadow: 0 2px 0 -1px rgba(colors.$bg-secondary, .5);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,41 @@
|
|||||||
|
@use "./colors";
|
||||||
|
|
||||||
|
.floating-notifications-container {
|
||||||
|
padding: {
|
||||||
|
right: 6px;
|
||||||
|
top: 6px;
|
||||||
|
};
|
||||||
|
|
||||||
|
& > .notification {
|
||||||
|
background: colors.$bg-primary;
|
||||||
|
border-radius: 16px;
|
||||||
|
padding: 12px;
|
||||||
|
margin: 6px 0;
|
||||||
|
|
||||||
|
& > .top {
|
||||||
|
& .app-name {
|
||||||
|
font-size: 12px;
|
||||||
|
color: colors.$fg-disabled;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
& .content {
|
||||||
|
& .image {
|
||||||
|
$size: 78px;
|
||||||
|
min-width: $size;
|
||||||
|
min-height: $size;
|
||||||
|
background-size: cover;
|
||||||
|
background-position: center 0;
|
||||||
|
margin: 6px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:first-child {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -69,16 +69,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
& tooltip {
|
|
||||||
padding: 8px;
|
|
||||||
border-radius: 14px;
|
|
||||||
|
|
||||||
& label {
|
|
||||||
font-size: 14px;
|
|
||||||
color: colors.$fg-primary;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
& trough {
|
& trough {
|
||||||
background: funs.toRGB(color.adjust($color: wal.$color1, $lightness: -20%));
|
background: funs.toRGB(color.adjust($color: wal.$color1, $lightness: -20%));
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
|
|||||||
+20
-20
@@ -1,26 +1,26 @@
|
|||||||
// SCSS Variables
|
// SCSS Variables
|
||||||
// Generated by 'wal'
|
// Generated by 'wal'
|
||||||
$wallpaper: "/home/joaov/wallpapers/Miku, Rin and Luka Chibi.jpg";
|
$wallpaper: "/home/joaov/wallpapers/Miku Bush.jpg";
|
||||||
|
|
||||||
// Special
|
// Special
|
||||||
$background: #3d2217;
|
$background: #0f1b06;
|
||||||
$foreground: #cec7c5;
|
$foreground: #c3c6c0;
|
||||||
$cursor: #cec7c5;
|
$cursor: #c3c6c0;
|
||||||
|
|
||||||
// Colors
|
// Colors
|
||||||
$color0: #3d2217;
|
$color0: #0f1b06;
|
||||||
$color1: #b38678;
|
$color1: #4e7278;
|
||||||
$color2: #a4998a;
|
$color2: #5b7b94;
|
||||||
$color3: #b39e8a;
|
$color3: #71807c;
|
||||||
$color4: #a5a09b;
|
$color4: #7b9882;
|
||||||
$color5: #aea299;
|
$color5: #a3a881;
|
||||||
$color6: #b4aea2;
|
$color6: #778591;
|
||||||
$color7: #a39c99;
|
$color7: #93988d;
|
||||||
$color8: #7f6f68;
|
$color8: #626d59;
|
||||||
$color9: #EFB3A1;
|
$color9: #6898A1;
|
||||||
$color10: #DBCCB9;
|
$color10: #7AA5C6;
|
||||||
$color11: #EFD3B9;
|
$color11: #97ABA6;
|
||||||
$color12: #DDD6CF;
|
$color12: #A5CBAE;
|
||||||
$color13: #E8D8CD;
|
$color13: #DAE0AC;
|
||||||
$color14: #F1E8D9;
|
$color14: #9FB2C2;
|
||||||
$color15: #cec7c5;
|
$color15: #c3c6c0;
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
//TODO
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { Binding } from "astal";
|
||||||
import { Gtk, Widget } from "astal/gtk3";
|
import { Gtk, Widget } from "astal/gtk3";
|
||||||
|
|
||||||
export interface SeparatorProps {
|
export interface SeparatorProps {
|
||||||
@@ -6,21 +7,23 @@ export interface SeparatorProps {
|
|||||||
cssColor?: string;
|
cssColor?: string;
|
||||||
orientation?: Gtk.Orientation;
|
orientation?: Gtk.Orientation;
|
||||||
size?: number;
|
size?: number;
|
||||||
|
visible?: boolean | Binding<boolean | undefined>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Separator(props: SeparatorProps) {
|
export function Separator(props: SeparatorProps) {
|
||||||
return new Widget.Box({
|
return new Widget.Box({
|
||||||
className: `separator separator-${ props.orientation == Gtk.Orientation.VERTICAL ? "vertical" : "horizontal" } ${ props.class && props.class }`,
|
className: `separator separator-${ props.orientation == Gtk.Orientation.VERTICAL ? "vertical" : "horizontal" } ${ props.class && props.class }`,
|
||||||
|
visible: props.visible,
|
||||||
css: `.separator {
|
css: `.separator {
|
||||||
background: ${ props.cssColor || "lightgray" };
|
background: ${ props.cssColor || "lightgray" };
|
||||||
opacity: ${ props.alpha || 1 };
|
opacity: ${ props.alpha || 1 };
|
||||||
}
|
}
|
||||||
.separator-horizontal {
|
.separator-horizontal {
|
||||||
padding-right: ${props.size || 1 }px;
|
padding-bottom: ${props.size || 1 }px;
|
||||||
margin: 7px 4px;
|
margin: 7px 4px;
|
||||||
}
|
}
|
||||||
.separator-vertical {
|
.separator-vertical {
|
||||||
padding-bottom: ${props.size || 1 }px;
|
padding-right: ${props.size || 1 }px;
|
||||||
margin: 4px 7px;
|
margin: 4px 7px;
|
||||||
}`,
|
}`,
|
||||||
} as Widget.BoxProps);
|
} as Widget.BoxProps);
|
||||||
|
|||||||
@@ -2,12 +2,14 @@ import { bind, Process } from "astal";
|
|||||||
import { Widget } from "astal/gtk3";
|
import { Widget } from "astal/gtk3";
|
||||||
import AstalWp from "gi://AstalWp";
|
import AstalWp from "gi://AstalWp";
|
||||||
import { Wireplumber } from "../../scripts/volume";
|
import { Wireplumber } from "../../scripts/volume";
|
||||||
|
import { ControlCenter } from "../../window/ControlCenter";
|
||||||
|
|
||||||
const wp = AstalWp.get_default();
|
const wp = AstalWp.get_default();
|
||||||
|
|
||||||
export function Audio() {
|
export function Audio() {
|
||||||
return wp && new Widget.EventBox({
|
return wp && new Widget.EventBox({
|
||||||
className: "audio",
|
className: bind(ControlCenter, "visible").as((visible: boolean) =>
|
||||||
|
visible ? "audio open" : "audio"),
|
||||||
onClick: () => Process.exec_async("astal toggle control-center", () => {}),
|
onClick: () => Process.exec_async("astal toggle control-center", () => {}),
|
||||||
child: new Widget.Box({
|
child: new Widget.Box({
|
||||||
children: [
|
children: [
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
import { Widget } from "astal/gtk3";
|
import { Widget } from "astal/gtk3";
|
||||||
import { getDateTime } from "../../scripts/time";
|
import { getDateTime } from "../../scripts/time";
|
||||||
import { GLib } from "astal";
|
import { bind, GLib } from "astal";
|
||||||
import { Windows } from "../../windows";
|
import { Windows } from "../../windows";
|
||||||
import { CenterWindow } from "../../window/CenterWindow";
|
import { CenterWindow } from "../../window/CenterWindow";
|
||||||
|
|
||||||
export function Clock(): JSX.Element {
|
export function Clock(): JSX.Element {
|
||||||
return new Widget.Box({
|
return new Widget.Box({
|
||||||
className: "clock",
|
className: bind(CenterWindow, "visible").as((visible: boolean) =>
|
||||||
|
visible ? "clock open" : "clock"),
|
||||||
child: new Widget.Button({
|
child: new Widget.Button({
|
||||||
onClick: () => Windows.toggle(CenterWindow),
|
onClick: () => Windows.toggle(CenterWindow),
|
||||||
label: getDateTime().as((dateTime: GLib.DateTime) => {
|
label: getDateTime().as((dateTime: GLib.DateTime) => {
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ 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";
|
||||||
|
import { CenterWindow } from "../../window/CenterWindow";
|
||||||
|
import { Windows } from "../../windows";
|
||||||
|
|
||||||
const mpris: AstalMpris.Mpris = AstalMpris.get_default();
|
const mpris: AstalMpris.Mpris = AstalMpris.get_default();
|
||||||
|
|
||||||
@@ -66,7 +68,10 @@ export function Media(): Gtk.Widget {
|
|||||||
|
|
||||||
const mediaWidget = new Widget.EventBox({
|
const mediaWidget = new Widget.EventBox({
|
||||||
className: "media-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>) => {
|
||||||
|
return players[0] && players[0].get_available() || CenterWindow.is_visible();
|
||||||
|
}),
|
||||||
|
onClick: () => Windows.toggle(CenterWindow),
|
||||||
child: new Widget.Box({
|
child: new Widget.Box({
|
||||||
className: "media",
|
className: "media",
|
||||||
children: [
|
children: [
|
||||||
@@ -85,6 +90,7 @@ export function Media(): Gtk.Widget {
|
|||||||
label: bind(players[0], "title").as((title: string) => title || "No Title")
|
label: bind(players[0], "title").as((title: string) => title || "No Title")
|
||||||
} as Widget.LabelProps),
|
} as Widget.LabelProps),
|
||||||
Separator({
|
Separator({
|
||||||
|
orientation: Gtk.Orientation.VERTICAL,
|
||||||
size: 2,
|
size: 2,
|
||||||
cssColor: `rgb(180, 180, 180)`,
|
cssColor: `rgb(180, 180, 180)`,
|
||||||
alpha: 1
|
alpha: 1
|
||||||
|
|||||||
@@ -8,8 +8,11 @@ export const BigMedia: Gtk.Widget = new Widget.Box({
|
|||||||
className: "big-media",
|
className: "big-media",
|
||||||
orientation: Gtk.Orientation.VERTICAL,
|
orientation: Gtk.Orientation.VERTICAL,
|
||||||
homogeneous: false,
|
homogeneous: false,
|
||||||
|
width_request: 250,
|
||||||
|
visible: bind(AstalMpris.get_default(), "players").as((players: Array<AstalMpris.Player>) =>
|
||||||
|
players[0] ? true : false),
|
||||||
children: bind(AstalMpris.get_default(), "players").as((players: Array<AstalMpris.Player>) =>
|
children: bind(AstalMpris.get_default(), "players").as((players: Array<AstalMpris.Player>) =>
|
||||||
players[0] ? [
|
players[0] && [
|
||||||
new Widget.Box({
|
new Widget.Box({
|
||||||
halign: Gtk.Align.CENTER,
|
halign: Gtk.Align.CENTER,
|
||||||
child: new Widget.Box({
|
child: new Widget.Box({
|
||||||
@@ -72,16 +75,29 @@ export const BigMedia: Gtk.Widget = new Widget.Box({
|
|||||||
})
|
})
|
||||||
]
|
]
|
||||||
}),
|
}),
|
||||||
new Widget.Box({
|
new Widget.CenterBox({
|
||||||
className: "controls button-row",
|
className: "bottom",
|
||||||
|
homogeneous: false,
|
||||||
hexpand: true,
|
hexpand: true,
|
||||||
halign: Gtk.Align.CENTER,
|
startWidget: new Widget.Label({
|
||||||
|
className: "elapsed",
|
||||||
|
valign: Gtk.Align.START,
|
||||||
|
halign: Gtk.Align.START,
|
||||||
|
label: bind(players[0], "position").as((pos: number) => {
|
||||||
|
const sec: number = Math.floor(pos % 60);
|
||||||
|
return pos > 0 && players[0].length > 0 ?
|
||||||
|
`${Math.floor(pos / 60)}:${sec < 10 ? "0" : ""}${sec}`
|
||||||
|
: `0:00`;
|
||||||
|
})
|
||||||
|
} as Widget.LabelProps),
|
||||||
|
centerWidget: new Widget.Box({
|
||||||
|
className: "controls button-row",
|
||||||
children: [
|
children: [
|
||||||
new Widget.Button({
|
new Widget.Button({
|
||||||
className: "link nf",
|
className: "link nf",
|
||||||
label: "",
|
label: "",
|
||||||
tooltipText: "Copy link to Clipboard",
|
tooltipText: "Copy link to Clipboard",
|
||||||
visible: bind(players[0], "metadata").as((_metadata: GLib.HashTable) =>
|
visible: bind(players[0], "metadata").as((_meta: GLib.HashTable) =>
|
||||||
players[0].get_meta("xesam:url") === null),
|
players[0].get_meta("xesam:url") === null),
|
||||||
onClick: () => Process.exec(`wl-copy ${players[0].get_meta("xesam:url")?.get_string()[0]}`)
|
onClick: () => Process.exec(`wl-copy ${players[0].get_meta("xesam:url")?.get_string()[0]}`)
|
||||||
} as Widget.ButtonProps),
|
} as Widget.ButtonProps),
|
||||||
@@ -111,6 +127,18 @@ export const BigMedia: Gtk.Widget = new Widget.Box({
|
|||||||
onClick: () => players[0].canGoNext && players[0].next()
|
onClick: () => players[0].canGoNext && players[0].next()
|
||||||
} as Widget.ButtonProps)
|
} as Widget.ButtonProps)
|
||||||
]
|
]
|
||||||
|
} as Widget.BoxProps),
|
||||||
|
endWidget: new Widget.Label({
|
||||||
|
className: "length",
|
||||||
|
valign: Gtk.Align.START,
|
||||||
|
halign: Gtk.Align.END,
|
||||||
|
label: bind(players[0], "length").as((len/* bananananananana */: number) => {
|
||||||
|
const sec: number = Math.floor(len % 60);
|
||||||
|
return len > 0 ?
|
||||||
|
`${Math.floor(len / 60)}:${sec < 10 ? "0" : ""}${sec}`
|
||||||
|
: "0:00";
|
||||||
})
|
})
|
||||||
] : new Widget.Box({ className: "empty no-media" }))
|
} as Widget.LabelProps)
|
||||||
|
})
|
||||||
|
])
|
||||||
} as Widget.BoxProps);
|
} as Widget.BoxProps);
|
||||||
|
|||||||
+20
-10
@@ -1,8 +1,9 @@
|
|||||||
import { Astal, Gtk, Widget } from "astal/gtk3";
|
import { Astal, Gtk, Widget } from "astal/gtk3";
|
||||||
import { GLib } from "astal";
|
import { bind, GLib } from "astal";
|
||||||
|
|
||||||
import { getDateTime } from "../scripts/time";
|
import { getDateTime } from "../scripts/time";
|
||||||
import { BigMedia } from "../widget/center-window/BigMedia";
|
import { BigMedia } from "../widget/center-window/BigMedia";
|
||||||
|
import { Separator, SeparatorProps } from "../widget/Separator";
|
||||||
|
|
||||||
export const CenterWindow: Widget.Window = new Widget.Window({
|
export const CenterWindow: Widget.Window = new Widget.Window({
|
||||||
className: "center-window",
|
className: "center-window",
|
||||||
@@ -12,7 +13,6 @@ 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: 400,
|
|
||||||
margin_top: 10,
|
margin_top: 10,
|
||||||
anchor: Astal.WindowAnchor.TOP,
|
anchor: Astal.WindowAnchor.TOP,
|
||||||
child: new Widget.Box({
|
child: new Widget.Box({
|
||||||
@@ -21,7 +21,6 @@ export const CenterWindow: Widget.Window = new Widget.Window({
|
|||||||
new Widget.Box({
|
new Widget.Box({
|
||||||
className: "vertical left",
|
className: "vertical left",
|
||||||
orientation: Gtk.Orientation.VERTICAL,
|
orientation: Gtk.Orientation.VERTICAL,
|
||||||
width_request: 300,
|
|
||||||
children: [
|
children: [
|
||||||
new Widget.Box({
|
new Widget.Box({
|
||||||
className: "top",
|
className: "top",
|
||||||
@@ -36,18 +35,15 @@ export const CenterWindow: Widget.Window = new Widget.Window({
|
|||||||
new Widget.Label({
|
new Widget.Label({
|
||||||
className: "date",
|
className: "date",
|
||||||
label: getDateTime().as((dateTime: GLib.DateTime) =>
|
label: getDateTime().as((dateTime: GLib.DateTime) =>
|
||||||
dateTime.format("%A, %B %d %Y"))
|
dateTime.format("%A, %B %d"))
|
||||||
} as Widget.LabelProps)
|
} as Widget.LabelProps)
|
||||||
]
|
]
|
||||||
} as Widget.BoxProps),
|
} as Widget.BoxProps),
|
||||||
BigMedia
|
|
||||||
]
|
|
||||||
} as Widget.BoxProps),
|
|
||||||
new Widget.Box({
|
|
||||||
className: "vertical right",
|
|
||||||
children: [
|
|
||||||
new Widget.Box({
|
new Widget.Box({
|
||||||
className: "calendar-box",
|
className: "calendar-box",
|
||||||
|
vexpand: false,
|
||||||
|
hexpand: true,
|
||||||
|
valign: Gtk.Align.START,
|
||||||
child: new Gtk.Calendar({
|
child: new Gtk.Calendar({
|
||||||
visible: true,
|
visible: true,
|
||||||
show_heading: true,
|
show_heading: true,
|
||||||
@@ -56,6 +52,20 @@ export const CenterWindow: Widget.Window = new Widget.Window({
|
|||||||
} as Gtk.Calendar.ConstructorProps)
|
} as Gtk.Calendar.ConstructorProps)
|
||||||
} as Widget.BoxProps)
|
} as Widget.BoxProps)
|
||||||
]
|
]
|
||||||
|
} as Widget.BoxProps),
|
||||||
|
Separator({
|
||||||
|
visible: bind(BigMedia, "visible"),
|
||||||
|
orientation: Gtk.Orientation.VERTICAL,
|
||||||
|
alpha: .5,
|
||||||
|
cssColor: "gray",
|
||||||
|
size: 1
|
||||||
|
} as SeparatorProps),
|
||||||
|
new Widget.Box({
|
||||||
|
className: "vertical right",
|
||||||
|
orientation: Gtk.Orientation.VERTICAL,
|
||||||
|
children: [
|
||||||
|
BigMedia
|
||||||
|
]
|
||||||
} as Widget.BoxProps)
|
} as Widget.BoxProps)
|
||||||
]
|
]
|
||||||
} as Widget.BoxProps)
|
} as Widget.BoxProps)
|
||||||
|
|||||||
@@ -16,14 +16,22 @@ function NotificationWidget(notification: AstalNotifd.Notification): Gtk.Widget
|
|||||||
hexpand: true,
|
hexpand: true,
|
||||||
vexpand: false,
|
vexpand: false,
|
||||||
children: [
|
children: [
|
||||||
|
new Widget.Icon({
|
||||||
|
className: "icon",
|
||||||
|
visible: notification.appIcon !== "",
|
||||||
|
icon: notification.appIcon || "image-missing",
|
||||||
|
iconSize: Gtk.IconSize.DND,
|
||||||
|
css: ".icon { font-size: 24px; }"
|
||||||
|
}),
|
||||||
new Widget.Label({
|
new Widget.Label({
|
||||||
className: "app-name",
|
className: "app-name",
|
||||||
halign: Gtk.Align.START,
|
halign: Gtk.Align.START,
|
||||||
label: notification.appName || "Unknown Application"
|
label: notification.appName || "Unknown Application"
|
||||||
} as Widget.LabelProps),
|
} as Widget.LabelProps),
|
||||||
new Widget.Button({
|
new Widget.Button({
|
||||||
className: "close-button",
|
className: "close nf",
|
||||||
onClick: () => Notifications.removeNotification(notification.id)
|
onClick: () => notification.dismiss(),
|
||||||
|
label: ""
|
||||||
} as Widget.ButtonProps)
|
} as Widget.ButtonProps)
|
||||||
]
|
]
|
||||||
} as Widget.BoxProps),
|
} as Widget.BoxProps),
|
||||||
@@ -71,8 +79,8 @@ export const FloatingNotifications: Widget.Window = new Widget.Window({
|
|||||||
className: "floating-notifications-container",
|
className: "floating-notifications-container",
|
||||||
orientation: Gtk.Orientation.VERTICAL,
|
orientation: Gtk.Orientation.VERTICAL,
|
||||||
homogeneous: false,
|
homogeneous: false,
|
||||||
children: bind(Notifications, "notifications").as((notifications: Array<AstalNotifd.Notification>) =>
|
children: Notifications.notifications().as((notifications: Array<AstalNotifd.Notification>) =>
|
||||||
notifications.map((notification: AstalNotifd.Notification) =>
|
notifications.map((item: AstalNotifd.Notification) =>
|
||||||
NotificationWidget(notification)))
|
NotificationWidget(item)))
|
||||||
} as Widget.BoxProps)
|
} as Widget.BoxProps)
|
||||||
} as Widget.WindowProps);
|
} as Widget.WindowProps);
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
import { Variable } from "astal";
|
||||||
|
import { Astal, Gtk, Widget } from "astal/gtk3";
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
|
||||||
|
export interface RunnerProps {
|
||||||
|
anchor?: Astal.WindowAnchor;
|
||||||
|
width?: number;
|
||||||
|
height?: number;
|
||||||
|
entryPlaceHolder?: string;
|
||||||
|
resultsPlaceholder?: Array<Gtk.Widget>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function Runner(props?: RunnerProps) {
|
||||||
|
|
||||||
|
const entryText: Variable<string> = new Variable<string>("");
|
||||||
|
|
||||||
|
const resultsBox: Widget.Box = new Widget.Box({
|
||||||
|
className: "results",
|
||||||
|
|
||||||
|
} as Widget.BoxProps);
|
||||||
|
|
||||||
|
return new Widget.Window({
|
||||||
|
namespace: "runner",
|
||||||
|
widthRequest: props?.width || 600,
|
||||||
|
heightRequest: props?.height || 500,
|
||||||
|
child: new Widget.Box({
|
||||||
|
className: "main",
|
||||||
|
children: [
|
||||||
|
new Widget.Entry({
|
||||||
|
className: "search",
|
||||||
|
onChanged: (entry) => entryText.set(entry.text),
|
||||||
|
} as Widget.EntryProps),
|
||||||
|
]
|
||||||
|
} as Widget.BoxProps)
|
||||||
|
} as Widget.WindowProps);
|
||||||
|
}
|
||||||
+2
-1
@@ -1,4 +1,4 @@
|
|||||||
import { Gtk, Widget } from "astal/gtk3";
|
import { Gtk } from "astal/gtk3";
|
||||||
|
|
||||||
import { Bar } from "./window/Bar";
|
import { Bar } from "./window/Bar";
|
||||||
import { OSD } from "./window/OSD";
|
import { OSD } from "./window/OSD";
|
||||||
@@ -22,6 +22,7 @@ export const Windows = GObject.registerClass({
|
|||||||
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("logout-menu", LogoutMenu);
|
WindowsClass.windowsMap.set("logout-menu", LogoutMenu);
|
||||||
|
WindowsClass.windowsMap.set("floating-notifications", FloatingNotifications);
|
||||||
}
|
}
|
||||||
|
|
||||||
public _init(...args: any[]) {
|
public _init(...args: any[]) {
|
||||||
|
|||||||
Reference in New Issue
Block a user