notifications: merge title widget, remove placeholder, restyle

parent 07222731
:root { :root {
--notification-icon-size: 64px; --notification-icon-size: 48px;
--notification-app-icon-size: calc(var(--notification-icon-size) / 3); --notification-app-icon-size: calc(var(--notification-icon-size) / 3);
--notification-group-icon-size: 32px; --notification-group-icon-size: 24px;
--border-radius: 12px;
--hover-tranistion: background 0.15s ease-in-out; --hover-tranistion: background 0.15s ease-in-out;
--group-collapse-tranistion: opacity 400ms ease-in-out; --group-collapse-tranistion: opacity 400ms ease-in-out;
...@@ -24,306 +22,16 @@ notificationwindow, blankwindow { ...@@ -24,306 +22,16 @@ notificationwindow, blankwindow {
background: transparent; background: transparent;
} }
.floating-notifications {
background: transparent;
.notification {
box-shadow: none;
}
}
.close-button {
background: unquote("alpha(var(--window-bg-color), 0.6)");
color: var(--window-fg-color);
text-shadow: none;
padding: 0;
border-radius: 100%;
margin-top: $margin;
margin-right: $margin;
box-shadow: none;
border: none;
min-width: 24px;
min-height: 24px;
&:hover {
box-shadow: none;
background: unquote("alpha(var(--window-bg-color), 0.4)");
transition: var(--hover-tranistion);
border: none;
}
}
.notification-row {
background: none;
outline: none;
&:focus {
background: none;
}
.notification-background {
padding: 5px 0;
.close-button {}
.notification {
border-radius: var(--window-radius);
border: 1px solid var(--border-color);
padding: 0;
transition: var(--hover-tranistion);
background: var(--dialog-bg-color);
box-shadow: 0 0 5px 0 var(--headerbar-shade-color);
&.low {
border-left: 4px solid var(--success-bg-color);
}
&.normal {
border-left: 4px solid var(--blue-3);
}
&.critical {
border-left: 4px solid var(--error-bg-color);
}
.notification-default-action {
padding: 10px;
margin: 0;
box-shadow: none;
background: transparent;
border: none;
color: var(--window-fg-color);
transition: var(--hover-tranistion);
border-radius: var(--window-radius);
&:hover {
-gtk-icon-filter: none;
background: unquote("alpha(var(--window-fg-color), 0.05)");
}
&:not(:only-child) {
border-bottom-left-radius: 0px;
border-bottom-right-radius: 0px;
}
.notification-content {
background: transparent;
border-radius: var(--border-radius);
$margin: 4px;
padding: 0;
.image {
-gtk-icon-filter: none;
-gtk-icon-size: var(--notification-icon-size);
border-radius: var(--window-radius);
margin: 0px 10px 0px 0px;
}
.app-icon {
-gtk-icon-filter: none;
-gtk-icon-size: var(--notification-app-icon-size);
-gtk-icon-shadow: 0 1px 4px black;
margin: 6px;
}
.text-box {
label {
filter: none;
}
.summary {
font-weight: bold;
background: transparent;
color: var(--window-fg-color);
text-shadow: none;
}
.time {
font-weight: bold;
background: transparent;
color: var(--window-fg-color);
text-shadow: none;
margin-right: 20px;
}
.body {
font-weight: normal;
background: transparent;
color: var(--window-fg-color);
text-shadow: none;
}
}
progressbar {
margin-top: $margin;
}
.body-image {
margin-top: $margin;
background-color: white;
-gtk-icon-filter: none;
}
.inline-reply {
margin-top: $margin;
.inline-reply-entry {
background: var(--view-bg-color);
color: var(--window-fg-color);
caret-color: var(--window-fg-color);
border: 1px solid var(--border-color);
border-radius: var(--border-radius);
}
.inline-reply-button {
margin-left: 4px;
background: var(--dialog-bg-color);
border: 1px solid var(--border-color);
border-radius: var(--border-radius);
color: var(--window-fg-color);
&:disabled {
background: initial;
color: unquote("alpha(var(--window-fg-color), 0.5)");
border-color: transparent;
}
&:hover {
background: unquote("alpha(var(--window-fg-color), 0.05)");
}
}
}
}
}
.notification-alt-actions {
background: none;
border-bottom-left-radius: var(--border-radius);
border-bottom-right-radius: var(--border-radius);
padding: $margin / 2;
}
.notification-action {
margin: $margin / 2;
padding: 0;
&>button {
border-radius: var(--window-radius);
color: var(--window-fg-color);
background: unquote("alpha(var(--window-bg-color), 0.4)");
border: 1px solid var(--border-color);
&:hover {
background: unquote("alpha(var(--window-bg-color), 0.2)");
border: 2px solid var(--accent-bg-color);
}
}
}
}
}
}
.notification-group {
transition: opacity 200ms ease-in-out;
&:focus {
background: none;
}
.notification-group-close-button .close-button {
background: unquote("alpha(var(--window-bg-color), 0.4)");
box-shadow: 0 0 5px 0 var(--headerbar-shade-color);
margin: $margin * 1.5 $margin * 2.5;
&:hover {
background: unquote("alpha(var(--window-bg-color), 0.8)");
}
}
%header {
margin: 0 $margin * 2;
color: var(--window-fg-color);
}
.notification-group-headers {
@extend %header;
.notification-group-icon {
color: var(--window-fg-color);
-gtk-icon-size: var(--notification-group-icon-size);
}
.notification-group-header {
color: var(--window-fg-color);
}
}
.notification-group-buttons {
@extend %header;
padding: 5px;
}
&.collapsed {
&.not-expanded {
opacity: 0.4;
}
.notification-row:not(:last-child) {
.notification {
background-color: var(--window-bg-color);
}
}
.notification-row:not(:last-child) {
.notification-action,
.notification-default-action {
opacity: 0;
}
.notification.low {
border-left: 3px solid unquote("alpha(var(--success-bg-color), 0.5)");
}
.notification.normal {
border-left: 3px solid unquote("alpha(var(--blue-3), 0.5)");
}
.notification.critical {
border-left: 3px solid unquote("alpha(var(--error-bg-color), 0.5)");
}
}
&:hover {
.notification-row:not(:only-child) {
.notification {
background-color: var(--dialog-bg-color);
}
}
}
}
}
.control-center { .control-center {
padding: 15px;
background: var(--window-bg-color); background: var(--window-bg-color);
color: var(--window-fg-color); color: var(--window-fg-color);
border-radius: var(--window-radius); border-radius: var(--window-radius);
box-shadow: 0 0 10px 0 var(--headerbar-shade-color); box-shadow: 0 0 10px 0 var(--headerbar-shade-color);
}
.control-center-list-placeholder { scrollbar {
opacity: 0.5; opacity: 0;
}
.control-center-list {
background: transparent;
margin: 0px 15px;
.notification {
.notification-default-action,
.notification-action {
transition: var(--group-collapse-tranistion), var(--hover-tranistion);
}
}
}
} }
/*** Widgets ***/ /*** Widgets ***/
...@@ -331,8 +39,8 @@ notificationwindow, blankwindow { ...@@ -331,8 +39,8 @@ notificationwindow, blankwindow {
padding: 0; padding: 0;
} }
/* Title widget */ /* Notifications widget */
@import "widgets/title"; @import "widgets/notifications";
/* Label widget */ /* Label widget */
@import "widgets/label"; @import "widgets/label";
/* Mpris widget */ /* Mpris widget */
......
.widget-backlight { .widget-backlight {
padding: 0; padding: 0;
margin: 5px 15px; margin: 5px 0px;
border-radius: var(--window-radius); border-radius: var(--window-radius);
&.expanded { &.expanded {
...@@ -8,8 +8,8 @@ ...@@ -8,8 +8,8 @@
box-shadow: 0px 0px 10px var(--headerbar-shade-color); box-shadow: 0px 0px 10px var(--headerbar-shade-color);
border: 1px solid var(--border-color); border: 1px solid var(--border-color);
} }
}
.widget-backlight .image-button { .image-button {
background: transparent; background: transparent;
}
} }
.widget-inhibitors { .widget-inhibitors {
background: transparent; background: transparent;
padding: 0px; padding: 0px;
margin: 10px 15px; margin: 5px 0px;
&>label { & > label {
font-size: 1.5rem; font-size: 1.5rem;
margin-right: $margin; margin-right: $margin;
} }
&>button { & > button {
background: var(--dialog-bg-color); background: var(--dialog-bg-color);
border-radius: 999px; border-radius: 999px;
border: 1px solid var(--border-color); border: 1px solid var(--border-color);
......
.widget-label { .widget-label {
margin: 5px 15px; margin: 5px 0px;
&>label { & > label {
font-size: 1.1rem; font-size: 1.1rem;
} }
} }
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
.widget-mpris { .widget-mpris {
padding: 0; padding: 0;
margin: 5px 15px; margin: 5px 0px;
border-radius: var(--window-radius); border-radius: var(--window-radius);
box-shadow: 0px 0px 10px var(--headerbar-shade-color); box-shadow: 0px 0px 10px var(--headerbar-shade-color);
border: 1px solid var(--border-color); border: 1px solid var(--border-color);
......
/* Floating notifications window */
.floating-notifications {
background: transparent;
.notification {
box-shadow: none;
}
}
/* Close button (shared) */
.close-button {
background: unquote("alpha(var(--window-bg-color), 0.6)");
color: var(--window-fg-color);
text-shadow: none;
padding: 0;
border-radius: 100%;
margin-top: 5px;
margin-right: 5px;
box-shadow: none;
border: 1px solid var(--border-color);
min-width: 24px;
min-height: 24px;
&:hover {
box-shadow: none;
background: unquote("alpha(var(--window-bg-color), 0.4)");
transition: var(--hover-tranistion);
}
}
/* Single notification */
.notification-row {
background: none;
outline: none;
&:focus {
background: none;
}
}
.notification-background {
padding: 5px 0;
}
.notification {
border-radius: var(--window-radius);
border: 1px solid var(--border-color);
padding: 10px;
transition: var(--hover-tranistion);
background: var(--dialog-bg-color);
box-shadow: 0 0 5px 0 var(--headerbar-shade-color);
&.low {
border-left: 4px solid var(--success-bg-color);
}
&.normal {
border-left: 4px solid var(--blue-3);
}
&.critical {
border-left: 4px solid var(--error-bg-color);
}
.notification-default-action {
padding: 0;
margin: 0;
box-shadow: none;
background: transparent;
border: none;
color: var(--window-fg-color);
}
.notification-content {
background: transparent;
border-radius: var(--window-radius);
padding: 0;
.image {
-gtk-icon-filter: none;
-gtk-icon-size: var(--notification-icon-size);
border-radius: var(--window-radius);
margin: 0px 5px 0px 0px;
}
.app-icon {
-gtk-icon-filter: none;
-gtk-icon-size: var(--notification-app-icon-size);
-gtk-icon-shadow: 0 1px 4px black;
margin: 6px;
}
.text-box {
label {
filter: none;
}
.summary {
font-weight: bold;
background: transparent;
color: var(--window-fg-color);
text-shadow: none;
}
.time {
font-weight: bold;
color: var(--window-fg-color);
text-shadow: none;
}
.body {
font-weight: normal;
color: var(--window-fg-color);
}
}
.inline-reply {
.inline-reply-entry {
background: unquote("alpha(var(--window-bg-color), 0.4)");
color: var(--window-fg-color);
caret-color: var(--window-fg-color);
border: 1px solid var(--border-color);
border-radius: var(--window-radius);
}
.inline-reply-button {
margin-left: 5px;
background: unquote("alpha(var(--window-bg-color), 0.4)");
border: 1px solid var(--border-color);
border-radius: var(--window-radius);
color: var(--window-fg-color);
&:disabled {
background: initial;
color: unquote("alpha(var(--window-fg-color), 0.5)");
border-color: transparent;
}
&:hover {
background: unquote("alpha(var(--window-bg-color), 0.2)");
}
}
}
}
.notification-alt-actions .notification-action {
margin-top: 10px;
padding: 0;
background: transparent;
}
.notification-action > button {
border-radius: var(--window-radius);
color: var(--window-fg-color);
background: unquote("alpha(var(--window-bg-color), 0.4)");
border: 1px solid var(--border-color);
&:hover {
background: unquote("alpha(var(--window-bg-color), 0.2)");
border: 2px solid var(--accent-bg-color);
}
}
}
/* Notification group (control center only) */
.notification-group {
transition: opacity 200ms ease-in-out;
&:focus {
background: none;
}
.notification-group-close-button .close-button {
background: unquote("alpha(var(--window-bg-color), 0.4)");
box-shadow: 0 0 5px 0 var(--headerbar-shade-color);
margin-top: 10px;
margin-right: 7px;
&:hover {
background: unquote("alpha(var(--window-bg-color), 0.8)");
}
}
.notification-group-headers,
.notification-group-buttons {
margin: 0;
color: var(--window-fg-color);
}
.notification-group-headers {
.notification-group-icon {
-gtk-icon-size: var(--notification-group-icon-size);
}
.notification-group-header {
font-size: 1.5rem;
}
}
.notification-group-buttons {
padding: 0;
}
&.collapsed {
&.not-expanded {
opacity: 0.4;
}
.notification-row:not(:last-child) {
.notification {
background-color: var(--window-bg-color);
}
.notification-action,
.notification-default-action {
opacity: 0;
}
.notification.low {
border-left: 3px solid
unquote("alpha(var(--success-bg-color), 0.5)");
}
.notification.normal {
border-left: 3px solid
unquote("alpha(var(--blue-3), 0.5)");
}
.notification.critical {
border-left: 3px solid
unquote("alpha(var(--error-bg-color), 0.5)");
}
}
&:hover {
.notification-row:not(:only-child) {
.notification {
background-color: var(--dialog-bg-color);
}
}
}
}
}
/* Notification list in control center */
.control-center .control-center-list {
background: transparent;
margin: 0;
.notification {
&:hover {
background: unquote("alpha(var(--window-fg-color), 0.15)");
}
.notification-default-action,
.notification-action {
transition: var(--group-collapse-tranistion),
var(--hover-tranistion);
}
}
}
/* Notifications header */
.notifications-header {
background: transparent;
margin: 10px 0px;
& > label {
font-size: 1.3rem;
}
& > button {
background: var(--dialog-bg-color);
border-radius: 999px;
font-size: 0.9rem;
border: 1px solid var(--border-color);
&:hover {
background: unquote("alpha(var(--dialog-bg-color), 0.5)");
border: 1px solid var(--accent-bg-color);
}
}
}
.widget-quick-settings { .widget-quick-settings {
padding: 0; padding: 0;
margin: 5px 15px; margin: 5px 0px;
} }
.quick-settings-row { .quick-settings-row {
...@@ -60,7 +60,7 @@ ...@@ -60,7 +60,7 @@
} }
.quick-settings-submenu { .quick-settings-submenu {
border-radius: var(--border-radius); border-radius: var(--window-radius);
margin: 5px 0; margin: 5px 0;
padding: 4px 0; padding: 4px 0;
background: var(--dialog-bg-color); background: var(--dialog-bg-color);
......
.widget-title {
background: transparent;
padding: 0px;
margin: 10px 15px;
&>label {
font-size: 1.5rem;
margin-right: $margin;
}
&>button {
background: var(--dialog-bg-color);
border-radius: 999px;
border: 1px solid var(--border-color);
margin-left: $margin;
&:hover {
background: unquote("alpha(var(--dialog-bg-color), 0.5)");
border: 1px solid var(--accent-bg-color);
}
}
}
.widget-volume { .widget-volume {
padding: 0; padding: 0;
margin: 5px 15px; margin: 5px 0px;
border-radius: var(--window-radius); border-radius: var(--window-radius);
&.expanded { &.expanded {
...@@ -9,27 +9,25 @@ ...@@ -9,27 +9,25 @@
border: 1px solid var(--border-color); border: 1px solid var(--border-color);
} }
&>box { & > box {
padding: 0 10px; padding: 0 10px;
margin: 0 0 0 3px; margin: 0 0 0 3px;
} }
}
.widget-volume .image-button { .image-button {
background: transparent; background: transparent;
}
} }
.widget-volume>box>button {}
.per-app-volume { .per-app-volume {
background: transparent; background: transparent;
padding: 0 10px; padding: 0 10px;
margin: 0; margin: 0;
border-radius: var(--border-radius); border-radius: var(--window-radius);
}
.per-app-volume row { row {
background: transparent; background: transparent;
}
} }
.sink-selector { .sink-selector {
......
...@@ -4,59 +4,54 @@ template $XimperShellNotificationCenterWidgetsNotifications: $XimperShellNotific ...@@ -4,59 +4,54 @@ template $XimperShellNotificationCenterWidgetsNotifications: $XimperShellNotific
orientation: vertical; orientation: vertical;
overflow: hidden; overflow: hidden;
Stack stack { Box header_box {
hhomogeneous: true; visible: false;
vhomogeneous: true;
transition-type: crossfade;
transition-duration: 200;
vexpand: true;
StackPage {
name: "notifications-list";
child: ScrolledWindow scrolled_window {
hscrollbar-policy: never;
has-frame: false;
child: Viewport viewport { styles ["notifications-header"]
vexpand: true;
child: ListBox list_box { Label title_label {
valign: fill; label: _("Notifications");
hexpand: true;
styles [ halign: start;
"control-center-list",
]
};
};
};
} }
StackPage { Button clear_all_button {
name: "notifications-placeholder"; can-focus: false;
valign: center;
clicked => $on_clear_all_clicked();
child: Box { styles ["control-center-clear-all"]
halign: center;
valign: center;
hexpand: true;
vexpand: true;
orientation: vertical;
spacing: 12;
styles [ Box {
"control-center-list-placeholder", orientation: horizontal;
] spacing: 10;
Image { Image {
pixel-size: 96; icon-name: "edit-clear-all-symbolic";
icon-name: "preferences-system-notifications-symbolic";
use-fallback: true;
} }
Label text_empty_label { Label {
label: _("No Notifications"); label: _("Clear All");
} }
}; }
} }
} }
ScrolledWindow scrolled_window {
hscrollbar-policy: never;
has-frame: false;
vexpand: true;
child: Viewport viewport {
vexpand: true;
child: ListBox list_box {
valign: fill;
styles [
"control-center-list",
]
};
};
}
} }
using Gtk 4.0;
template $XimperShellNotificationCenterWidgetsTitle:
$XimperShellNotificationCenterWidgetsBaseWidget {
Label title_widget {
hexpand: true;
halign: start;
}
Button clear_all_button {
can-focus: false;
valign: center;
clicked => $on_clear_all_clicked();
styles ["control-center-clear-all"]
Box {
orientation: horizontal;
spacing: 10;
Image {
icon-name: "edit-clear-all-symbolic";
}
Label {
label: _("Clear All");
}
}
}
}
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
<file preprocess="xml-stripblanks">ui/widgets/mpris_player.ui</file> <file preprocess="xml-stripblanks">ui/widgets/mpris_player.ui</file>
<file preprocess="xml-stripblanks">ui/widgets/notifications.ui</file> <file preprocess="xml-stripblanks">ui/widgets/notifications.ui</file>
<file preprocess="xml-stripblanks">ui/widgets/label.ui</file> <file preprocess="xml-stripblanks">ui/widgets/label.ui</file>
<file preprocess="xml-stripblanks">ui/widgets/title.ui</file>
<file preprocess="xml-stripblanks">ui/widgets/inhibitors.ui</file> <file preprocess="xml-stripblanks">ui/widgets/inhibitors.ui</file>
<file preprocess="xml-stripblanks">ui/widgets/volume.ui</file> <file preprocess="xml-stripblanks">ui/widgets/volume.ui</file>
<file preprocess="xml-stripblanks">ui/widgets/backlight.ui</file> <file preprocess="xml-stripblanks">ui/widgets/backlight.ui</file>
......
...@@ -166,10 +166,6 @@ config file to be able to detect config errors ...@@ -166,10 +166,6 @@ config file to be able to detect config errors
default: true ++ default: true ++
description: Hides the control center when clicking on notification action description: Hides the control center when clicking on notification action
*text-empty* ++
type: string ++
default: "No Notifications" ++
description: Text that appears when there are no notifications to show
*fit-to-screen* ++ *fit-to-screen* ++
type: bool ++ type: bool ++
...@@ -323,12 +319,9 @@ config file to be able to detect config errors ...@@ -323,12 +319,9 @@ config file to be able to detect config errors
*widgets* ++ *widgets* ++
type: array ++ type: array ++
Default values: ["inhibitors", "title", "notifications"] ++ Default values: ["notifications"] ++
Valid array values (see *widget-config* for more information): ++ Valid array values (see *widget-config* for more information): ++
*notifications*++ *notifications*++
required: true ++
optional: false ++
*title*++
optional: true ++ optional: true ++
*label*++ *label*++
optional: true ++ optional: true ++
...@@ -350,14 +343,13 @@ config file to be able to detect config errors ...@@ -350,14 +343,13 @@ config file to be able to detect config errors
will be placed at the bottom. ++ will be placed at the bottom. ++
multiple of same widget: ++ multiple of same widget: ++
Append a # with any value to the end of the widget name. ++ Append a # with any value to the end of the widget name. ++
Example: "title#TheMainTitle" ++ Example: "label#MyLabel" ++
To address this widget specifically in the css file use the css class .TheMainTitle ++ To address this widget specifically in the css file use the css class .MyLabel ++
example: example:
``` ```
{ {
"widgets": [ "widgets": [
"inhibitors", "inhibitors",
"title",
"notifications" "notifications"
] ]
} }
...@@ -368,35 +360,24 @@ config file to be able to detect config errors ...@@ -368,35 +360,24 @@ config file to be able to detect config errors
description: Configure specific widget properties. ++ description: Configure specific widget properties. ++
multiple of same widget: ++ multiple of same widget: ++
Append a # with any value to the end of the widget name. ++ Append a # with any value to the end of the widget name. ++
Example: "title#TheMainTitle" ++ Example: "label#MyLabel" ++
To address this widget specifically in the css file use the css class .TheMainTitle ++ To address this widget specifically in the css file use the css class .MyLabel ++
Widgets to customize: ++ Widgets to customize: ++
*notifications*++ *notifications*++
type: object ++ type: object ++
css class: widget-notifications ++ css class: widget-notifications ++
properties: ++ properties: ++
vexpand: ++ show-title: ++
type: bool ++
optional: true ++
default: true ++
description: Whether or not the notifications widget ++
should vertically expand or not ++
description: The Notifications Widget. ++
*title*++
type: object ++
css class: widget-title ++
properties: ++
text: ++
type: string ++ type: string ++
optional: true ++ optional: true ++
default: "Notifications" ++ default: "auto" ++
description: The title of the widget ++ enum: auto, true, false ++
clear-all-button: ++ description: Title bar visibility. ++
type: bool ++ auto: show when notifications exist. ++
optional: true ++ true: always visible. ++
default: true ++ false: hidden, only clear button ++
description: Whether to display a "Clear All" button ++ shown when notifications exist. ++
description: The notification visibility state. ++ description: The Notifications Widget. ++
*label*++ *label*++
type: object ++ type: object ++
css class: widget-label ++ css class: widget-label ++
...@@ -550,9 +531,8 @@ config file to be able to detect config errors ...@@ -550,9 +531,8 @@ config file to be able to detect config errors
``` ```
{ {
"widget-config": { "widget-config": {
"title": { "notifications": {
"text": "Notifications", "show-title": "auto"
"clear-all-button": true
}, },
"label": { "label": {
"max-lines": 5, "max-lines": 5,
......
src/main.vala src/main.vala
src/notification/notification.vala src/notification/notification.vala
src/controlCenter/widgets/title/title.vala
src/controlCenter/widgets/inhibitors/inhibitors.vala src/controlCenter/widgets/inhibitors/inhibitors.vala
src/controlCenter/widgets/volume/volume.vala src/controlCenter/widgets/volume/volume.vala
src/controlCenter/widgets/backlight/backlight.vala src/controlCenter/widgets/backlight/backlight.vala
...@@ -15,6 +14,5 @@ src/controlCenter/widgets/quickSettings/tiles/wifiTile.vala ...@@ -15,6 +14,5 @@ src/controlCenter/widgets/quickSettings/tiles/wifiTile.vala
src/controlCenter/widgets/quickSettings/tiles/vpnTile.vala src/controlCenter/widgets/quickSettings/tiles/vpnTile.vala
src/controlCenter/widgets/quickSettings/tiles/bluetoothTile.vala src/controlCenter/widgets/quickSettings/tiles/bluetoothTile.vala
data/ui/widgets/notifications.blp data/ui/widgets/notifications.blp
data/ui/widgets/title.blp
data/ui/widgets/inhibitors.blp data/ui/widgets/inhibitors.blp
data/ui/widgets/backlight.blp data/ui/widgets/backlight.blp
...@@ -7,7 +7,7 @@ msgid "" ...@@ -7,7 +7,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: ximper-shell-notification-center 0.1.0\n" "Project-Id-Version: ximper-shell-notification-center 0.1.0\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-03-26 22:05+0300\n" "POT-Creation-Date: 2026-03-27 20:18+0300\n"
"PO-Revision-Date: 2026-03-24 00:00+0300\n" "PO-Revision-Date: 2026-03-24 00:00+0300\n"
"Last-Translator: \n" "Last-Translator: \n"
"Language-Team: Russian\n" "Language-Team: Russian\n"
...@@ -59,10 +59,6 @@ msgstr[0] "%d д. назад" ...@@ -59,10 +59,6 @@ msgstr[0] "%d д. назад"
msgstr[1] "%d д. назад" msgstr[1] "%d д. назад"
msgstr[2] "%d д. назад" msgstr[2] "%d д. назад"
#: src/controlCenter/widgets/title/title.vala:21
msgid "Notifications"
msgstr "Уведомления"
#: src/controlCenter/widgets/inhibitors/inhibitors.vala:21 #: src/controlCenter/widgets/inhibitors/inhibitors.vala:21
msgid "Inhibitors" msgid "Inhibitors"
msgstr "Блокировки" msgstr "Блокировки"
...@@ -158,11 +154,11 @@ msgstr "Отключить" ...@@ -158,11 +154,11 @@ msgstr "Отключить"
msgid "Bluetooth Settings" msgid "Bluetooth Settings"
msgstr "Настройки Bluetooth" msgstr "Настройки Bluetooth"
#: data/ui/widgets/notifications.blp:57 #: data/ui/widgets/notifications.blp:13
msgid "No Notifications" msgid "Notifications"
msgstr "Нет уведомлений" msgstr "Уведомления"
#: data/ui/widgets/title.blp:27 data/ui/widgets/inhibitors.blp:25 #: data/ui/widgets/notifications.blp:34 data/ui/widgets/inhibitors.blp:25
msgid "Clear All" msgid "Clear All"
msgstr "Очистить" msgstr "Очистить"
...@@ -170,5 +166,8 @@ msgstr "Очистить" ...@@ -170,5 +166,8 @@ msgstr "Очистить"
msgid "Brightness" msgid "Brightness"
msgstr "Яркость" msgstr "Яркость"
#~ msgid "No Notifications"
#~ msgstr "Нет уведомлений"
#~ msgid "No active sink input" #~ msgid "No active sink input"
#~ msgstr "Нет активного источника" #~ msgstr "Нет активного источника"
...@@ -8,7 +8,7 @@ msgid "" ...@@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: ximper-shell-notification-center\n" "Project-Id-Version: ximper-shell-notification-center\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-03-26 22:05+0300\n" "POT-Creation-Date: 2026-03-27 20:18+0300\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
...@@ -56,10 +56,6 @@ msgid_plural "%d days ago" ...@@ -56,10 +56,6 @@ msgid_plural "%d days ago"
msgstr[0] "" msgstr[0] ""
msgstr[1] "" msgstr[1] ""
#: src/controlCenter/widgets/title/title.vala:21
msgid "Notifications"
msgstr ""
#: src/controlCenter/widgets/inhibitors/inhibitors.vala:21 #: src/controlCenter/widgets/inhibitors/inhibitors.vala:21
msgid "Inhibitors" msgid "Inhibitors"
msgstr "" msgstr ""
...@@ -155,11 +151,11 @@ msgstr "" ...@@ -155,11 +151,11 @@ msgstr ""
msgid "Bluetooth Settings" msgid "Bluetooth Settings"
msgstr "" msgstr ""
#: data/ui/widgets/notifications.blp:57 #: data/ui/widgets/notifications.blp:13
msgid "No Notifications" msgid "Notifications"
msgstr "" msgstr ""
#: data/ui/widgets/title.blp:27 data/ui/widgets/inhibitors.blp:25 #: data/ui/widgets/notifications.blp:34 data/ui/widgets/inhibitors.blp:25
msgid "Clear All" msgid "Clear All"
msgstr "" msgstr ""
......
...@@ -32,7 +32,6 @@ ...@@ -32,7 +32,6 @@
"quick-settings", "quick-settings",
"inhibitors", "inhibitors",
"mpris", "mpris",
"title",
"notifications" "notifications"
], ],
"widget-config": { "widget-config": {
......
...@@ -556,8 +556,6 @@ namespace XimperShellNotificationCenter { ...@@ -556,8 +556,6 @@ namespace XimperShellNotificationCenter {
/** Hides the control center when clicking on notification action */ /** Hides the control center when clicking on notification action */
public bool hide_on_action { get; set; default = true; } public bool hide_on_action { get; set; default = true; }
/** Text that appears when there are no notifications to show */
public string text_empty { get; set; default = "No Notifications"; }
/** The controlcenters horizontal alignment. Supersedes `positionX` if not `NONE` */ /** The controlcenters horizontal alignment. Supersedes `positionX` if not `NONE` */
public PositionX control_center_positionX { // vala-lint=naming-convention public PositionX control_center_positionX { // vala-lint=naming-convention
......
...@@ -203,11 +203,6 @@ ...@@ -203,11 +203,6 @@
"description": "Hides the control center when clicking on notification action", "description": "Hides the control center when clicking on notification action",
"default": true "default": true
}, },
"text-empty": {
"type": "string",
"description": "Text that appears when there are no notifications to show",
"default": "No Notifications"
},
"notification-action-filter": { "notification-action-filter": {
"type": "object", "type": "object",
"description": "Hides matching action(s) of matching notifications. If the notification doesn't include one of the properties, that property will be ignored. If all properties match the given notification, the matching actions will be hidden.", "description": "Hides matching action(s) of matching notifications. If the notification doesn't include one of the properties, that property will be ignored. If all properties match the given notification, the matching actions will be hidden.",
...@@ -325,10 +320,6 @@ ...@@ -325,10 +320,6 @@
"$comment": "References the widget structure from \"widgets\" below", "$comment": "References the widget structure from \"widgets\" below",
"$ref": "#/widgets/notifications" "$ref": "#/widgets/notifications"
}, },
"^title(#[a-zA-Z0-9_-]{1,}){0,1}?$": {
"$comment": "References the widget structure from \"widgets\" below",
"$ref": "#/widgets/title"
},
"^label(#[a-zA-Z0-9_-]{1,}){0,1}?$": { "^label(#[a-zA-Z0-9_-]{1,}){0,1}?$": {
"$ref": "#/widgets/label" "$ref": "#/widgets/label"
}, },
...@@ -355,30 +346,14 @@ ...@@ -355,30 +346,14 @@
"$comment": "New widgets go here", "$comment": "New widgets go here",
"notifications": { "notifications": {
"type": "object", "type": "object",
"description": "Control Center Title Widget", "description": "Notifications widget with title and clear button",
"additionalProperties": false, "additionalProperties": false,
"properties": { "properties": {
"vexpand": { "show-title": {
"type": "boolean",
"description": "Whether or not the notifications widget should vertically expand or not",
"default": true
}
}
},
"title": {
"type": "object",
"description": "Control Center Title Widget",
"additionalProperties": false,
"properties": {
"text": {
"type": "string", "type": "string",
"description": "The title of the widget", "description": "Title bar visibility: auto (show when notifications exist), true (always visible), false (hidden, only clear button shown when notifications exist)",
"default": "Notifications" "default": "auto",
}, "enum": ["auto", "true", "false"]
"clear-all-button": {
"type": "boolean",
"description": "Whether to display a \"Clear All\" button",
"default": true
} }
} }
}, },
......
...@@ -14,7 +14,7 @@ namespace XimperShellNotificationCenter { ...@@ -14,7 +14,7 @@ namespace XimperShellNotificationCenter {
/** Unsorted list of copies of all notifications */ /** Unsorted list of copies of all notifications */
private List<unowned Widgets.BaseWidget> widgets; private List<unowned Widgets.BaseWidget> widgets;
private const string[] DEFAULT_WIDGETS = { "title", "dnd", "notifications" }; private const string[] DEFAULT_WIDGETS = { "notifications" };
private string ?monitor_name = null; private string ?monitor_name = null;
......
...@@ -16,9 +16,6 @@ namespace XimperShellNotificationCenter.Widgets { ...@@ -16,9 +16,6 @@ namespace XimperShellNotificationCenter.Widgets {
is_notifications = true; is_notifications = true;
message ("Loading widget: widget-notifications"); message ("Loading widget: widget-notifications");
return null; return null;
case "title":
widget = new Title (suffix);
break;
case "label": case "label":
widget = new Label (suffix); widget = new Label (suffix);
break; break;
......
...@@ -10,13 +10,13 @@ namespace XimperShellNotificationCenter.Widgets { ...@@ -10,13 +10,13 @@ namespace XimperShellNotificationCenter.Widgets {
public uint n_notifications { get; private set; default = 0; } public uint n_notifications { get; private set; default = 0; }
public uint n_groups { get; private set; default = 0; } public uint n_groups { get; private set; default = 0; }
const string STACK_NOTIFICATIONS_PAGE = "notifications-list";
const string STACK_PLACEHOLDER_PAGE = "notifications-placeholder";
[GtkChild] [GtkChild]
unowned Gtk.Label text_empty_label; unowned Gtk.Box header_box;
[GtkChild] [GtkChild]
unowned Gtk.Stack stack; unowned Gtk.Label title_label;
[GtkChild]
unowned Gtk.Button clear_all_button;
[GtkChild] [GtkChild]
unowned Gtk.ScrolledWindow scrolled_window; unowned Gtk.ScrolledWindow scrolled_window;
[GtkChild] [GtkChild]
...@@ -31,16 +31,19 @@ namespace XimperShellNotificationCenter.Widgets { ...@@ -31,16 +31,19 @@ namespace XimperShellNotificationCenter.Widgets {
} }
private uint scroll_timer_id = 0; private uint scroll_timer_id = 0;
private Gee.HashMap<uint32, unowned NotificationGroup> noti_groups_id = private Gee.HashMap<uint32, unowned NotificationGroup>
new Gee.HashMap<uint32, unowned NotificationGroup> (); noti_groups_id =
/** NOTE: Only includes groups with ids with length of > 0 */ new Gee.HashMap<uint32,
private Gee.HashMap<string, unowned NotificationGroup> noti_groups_name = unowned NotificationGroup> ();
new Gee.HashMap<string, unowned NotificationGroup> (); /** Only includes groups with ids with length > 0 */
private Gee.HashMap<string, unowned NotificationGroup>
noti_groups_name =
new Gee.HashMap<string,
unowned NotificationGroup> ();
private bool list_reverse = false; private bool list_reverse = false;
// Default config values string show_title = "auto";
bool vertical_expand = true;
public Notifications () { public Notifications () {
base (""); base ("");
...@@ -49,14 +52,6 @@ namespace XimperShellNotificationCenter.Widgets { ...@@ -49,14 +52,6 @@ namespace XimperShellNotificationCenter.Widgets {
notify["expanded-group"].connect (expanded_changed); notify["expanded-group"].connect (expanded_changed);
// TODO: Move this into notifications config!
string empty_text = ConfigModel.instance.text_empty;
text_empty_label.set_text (
empty_text == "No Notifications"
? _("No Notifications") : empty_text);
stack.set_visible_child_name (STACK_PLACEHOLDER_PAGE);
list_box.set_valign (Gtk.Align.START); list_box.set_valign (Gtk.Align.START);
reload_config (); reload_config ();
...@@ -94,17 +89,47 @@ namespace XimperShellNotificationCenter.Widgets { ...@@ -94,17 +89,47 @@ namespace XimperShellNotificationCenter.Widgets {
public void reload_config () { public void reload_config () {
Json.Object ?config = get_config (this); Json.Object ?config = get_config (this);
if (config != null) { if (config != null) {
// Get vexpand string ?st = get_prop<string> (
bool found_vexpand; config, "show-title");
bool ?vexpand = get_prop<bool> (config, "vexpand", out found_vexpand); if (st != null) {
if (found_vexpand) { this.show_title = st;
this.vertical_expand = vexpand;
} }
} }
set_vexpand (this.vertical_expand); bool dynamic =
scrolled_window.set_propagate_natural_height (!this.vertical_expand); ConfigModel.instance
stack.set_vhomogeneous (this.vertical_expand); .control_center_dynamic_height;
set_vexpand (!dynamic);
scrolled_window.set_propagate_natural_height (
dynamic);
update_header_visibility ();
}
private void update_header_visibility () {
bool has_notis = !is_empty ();
scrolled_window.set_visible (has_notis);
switch (show_title) {
case "true":
header_box.set_visible (true);
title_label.set_visible (true);
clear_all_button.set_sensitive (has_notis);
break;
case "false":
header_box.set_visible (has_notis);
title_label.set_visible (false);
break;
default: // auto
header_box.set_visible (has_notis);
title_label.set_visible (true);
break;
}
}
[GtkCallback]
private void on_clear_all_clicked () {
noti_daemon
.request_dismiss_all_notifications (
ClosedReasons.DISMISSED);
} }
public inline bool is_empty () { public inline bool is_empty () {
...@@ -144,7 +169,7 @@ namespace XimperShellNotificationCenter.Widgets { ...@@ -144,7 +169,7 @@ namespace XimperShellNotificationCenter.Widgets {
if (list_box_controller.length < 1) { if (list_box_controller.length < 1) {
n_notifications = 0; n_notifications = 0;
n_groups = 0; n_groups = 0;
stack.set_visible_child_name (STACK_PLACEHOLDER_PAGE); update_header_visibility ();
} }
} }
...@@ -262,8 +287,6 @@ namespace XimperShellNotificationCenter.Widgets { ...@@ -262,8 +287,6 @@ namespace XimperShellNotificationCenter.Widgets {
noti_groups_name.set (param.name_id, group); noti_groups_name.set (param.name_id, group);
} }
stack.set_visible_child_name (STACK_NOTIFICATIONS_PAGE);
list_box_controller.append (group); list_box_controller.append (group);
n_groups++; n_groups++;
} }
...@@ -279,6 +302,7 @@ namespace XimperShellNotificationCenter.Widgets { ...@@ -279,6 +302,7 @@ namespace XimperShellNotificationCenter.Widgets {
n_notifications++; n_notifications++;
list_box.invalidate_sort (); list_box.invalidate_sort ();
update_header_visibility ();
scroll_to_start (); scroll_to_start ();
} }
......
namespace XimperShellNotificationCenter.Widgets {
[GtkTemplate (ui = "/ru/ximperlinux/shell/NotificationCenter/ui/widgets/title.ui")]
public class Title : BaseWidget {
public override string widget_name {
get {
return "title";
}
}
[GtkChild]
unowned Gtk.Label title_widget;
[GtkChild]
unowned Gtk.Button clear_all_button;
// Default config values
string title;
bool has_clear_all_button = true;
public Title (string suffix) {
base (suffix);
title = _("Notifications");
Json.Object ?config = get_config (this);
if (config != null) {
// Get title
string ?title = get_prop<string> (config, "text");
if (title != null) {
this.title = title;
}
// Get has clear-all-button
bool found_clear_all;
bool ?has_clear_all_button = get_prop<bool> (
config, "clear-all-button", out found_clear_all);
if (found_clear_all) {
this.has_clear_all_button = has_clear_all_button;
}
}
title_widget.set_text (title);
clear_all_button.set_visible (
has_clear_all_button
&& notifications_widget != null);
if (notifications_widget != null) {
clear_all_button.set_sensitive (
!notifications_widget.is_empty ());
ximper_shell_notification_center_daemon
.subscribe_v2.connect ((count) => {
clear_all_button.set_sensitive (count > 0);
});
}
}
[GtkCallback]
private void on_clear_all_clicked () {
noti_daemon.request_dismiss_all_notifications (ClosedReasons.DISMISSED);
}
}
}
...@@ -30,8 +30,6 @@ widget_sources = [ ...@@ -30,8 +30,6 @@ widget_sources = [
'controlCenter/widgets/factory.vala', 'controlCenter/widgets/factory.vala',
# Widget: Notifications # Widget: Notifications
'controlCenter/widgets/notifications/notifications.vala', 'controlCenter/widgets/notifications/notifications.vala',
# Widget: Title
'controlCenter/widgets/title/title.vala',
# Widget: Label # Widget: Label
'controlCenter/widgets/label/label.vala', 'controlCenter/widgets/label/label.vala',
# Widget: MPRIS # Widget: MPRIS
......
...@@ -139,6 +139,23 @@ namespace XimperShellNotificationCenter { ...@@ -139,6 +139,23 @@ namespace XimperShellNotificationCenter {
break; break;
} }
GtkLayerShell.set_margin (this,
GtkLayerShell.Edge.TOP,
ConfigModel.instance
.control_center_margin_top);
GtkLayerShell.set_margin (this,
GtkLayerShell.Edge.BOTTOM,
ConfigModel.instance
.control_center_margin_bottom);
GtkLayerShell.set_margin (this,
GtkLayerShell.Edge.LEFT,
ConfigModel.instance
.control_center_margin_left);
GtkLayerShell.set_margin (this,
GtkLayerShell.Edge.RIGHT,
ConfigModel.instance
.control_center_margin_right);
// Set the preferred monitor // Set the preferred monitor
string ?monitor_name = ConfigModel.instance.notification_window_preferred_output; string ?monitor_name = ConfigModel.instance.notification_window_preferred_output;
if (NotificationWindow.monitor_name != null) { if (NotificationWindow.monitor_name != null) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment