Implemented battery, power profile and brightness all in one menu
This commit is contained in:
@@ -1,9 +1,9 @@
|
|||||||
const battery = await Service.import("battery");
|
const battery = await Service.import("battery");
|
||||||
|
import { closeAllMenus } from "../bar.js";
|
||||||
|
|
||||||
const BatteryLabel = () => {
|
const BatteryLabel = () => {
|
||||||
const isVis = Variable(battery.available);
|
const isVis = Variable(battery.available);
|
||||||
|
|
||||||
const value = battery.bind("percent").as((p) => (p > 0 ? p / 100 : 0));
|
|
||||||
const icon = battery
|
const icon = battery
|
||||||
.bind("percent")
|
.bind("percent")
|
||||||
.as((p) => `battery-level-${Math.floor(p / 10) * 10}-symbolic`);
|
.as((p) => `battery-level-${Math.floor(p / 10) * 10}-symbolic`);
|
||||||
@@ -12,23 +12,58 @@ const BatteryLabel = () => {
|
|||||||
isVis.value = available;
|
isVis.value = available;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const formatTime = (seconds) => {
|
||||||
|
const hours = Math.floor(seconds / 3600);
|
||||||
|
const minutes = Math.floor((seconds % 3600) / 60);
|
||||||
|
return { hours, minutes };
|
||||||
|
};
|
||||||
|
|
||||||
|
const generateTooltip = (timeSeconds, isCharging, isCharged) => {
|
||||||
|
if (isCharged) {
|
||||||
|
return "Fully Charged!!!";
|
||||||
|
}
|
||||||
|
|
||||||
|
const { hours, minutes } = formatTime(timeSeconds);
|
||||||
|
if (isCharging) {
|
||||||
|
return `${hours} hours ${minutes} minutes until full`;
|
||||||
|
} else {
|
||||||
|
return `${hours} hours ${minutes} minutes left`;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
component: Widget.Box({
|
component: Widget.Box({
|
||||||
class_name: "battery",
|
class_name: "battery",
|
||||||
visible: battery.bind("available"),
|
visible: battery.bind("available"),
|
||||||
|
tooltip_text: battery.bind("time_remaining").as((t) => t.toString()),
|
||||||
children: [
|
children: [
|
||||||
Widget.Icon({ icon }),
|
Widget.Icon({ icon }),
|
||||||
Widget.Label({
|
Widget.Label({
|
||||||
label: battery.bind("percent").as((p) => (`${p}%`)),
|
label: battery.bind("percent").as((p) => ` ${p}%`),
|
||||||
})
|
}),
|
||||||
// Widget.LevelBar({
|
|
||||||
// widthRequest: 20,
|
|
||||||
// vpack: "center",
|
|
||||||
// value,
|
|
||||||
// }),
|
|
||||||
],
|
],
|
||||||
|
setup: (self) => {
|
||||||
|
self.hook(battery, () => {
|
||||||
|
self.tooltip_text = generateTooltip(
|
||||||
|
battery.time_remaining,
|
||||||
|
battery.charging,
|
||||||
|
battery.charged,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
},
|
||||||
}),
|
}),
|
||||||
isVis,
|
isVis,
|
||||||
|
props: {
|
||||||
|
on_primary_click: (_, event) => {
|
||||||
|
const clickPos = event.get_root_coords();
|
||||||
|
const coords = [clickPos[1], clickPos[2]];
|
||||||
|
|
||||||
|
globalMousePos.value = coords;
|
||||||
|
|
||||||
|
closeAllMenus();
|
||||||
|
App.toggleWindow("energymenu");
|
||||||
|
},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ const Media = () => {
|
|||||||
|
|
||||||
const songIcon = Variable("");
|
const songIcon = Variable("");
|
||||||
|
|
||||||
const label = Utils.watch(" No media playing ", mpris, "changed", () => {
|
const label = Utils.watch(" Media ", mpris, "changed", () => {
|
||||||
if (activePlayer.value) {
|
if (activePlayer.value) {
|
||||||
const { track_title, identity } = activePlayer.value;
|
const { track_title, identity } = activePlayer.value;
|
||||||
songIcon.value = getIconForPlayer(identity);
|
songIcon.value = getIconForPlayer(identity);
|
||||||
@@ -59,7 +59,7 @@ const Media = () => {
|
|||||||
: ` ${track_title}`;
|
: ` ${track_title}`;
|
||||||
} else {
|
} else {
|
||||||
songIcon.value = "";
|
songIcon.value = "";
|
||||||
return " No media playing ";
|
return " Media ";
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ const Network = () => {
|
|||||||
Widget.Label({
|
Widget.Label({
|
||||||
label: network.wifi
|
label: network.wifi
|
||||||
.bind("ssid")
|
.bind("ssid")
|
||||||
.as((ssid) => (ssid ? ` ${ssid}` : " Unknown")),
|
.as((ssid) => (ssid ? ` ${ssid}` : " --").substring(0, 7)),
|
||||||
}),
|
}),
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
53
modules/menus/energy/brightness/index.js
Normal file
53
modules/menus/energy/brightness/index.js
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
import brightness from "../../../../services/Brightness.js";
|
||||||
|
import icons from "../../../icons/index.js";
|
||||||
|
|
||||||
|
const Brightness = () => {
|
||||||
|
return Widget.Box({
|
||||||
|
class_name: "menu-section-container brightness",
|
||||||
|
vertical: true,
|
||||||
|
children: [
|
||||||
|
Widget.Box({
|
||||||
|
class_name: "menu-label-container",
|
||||||
|
hpack: "fill",
|
||||||
|
child: Widget.Label({
|
||||||
|
class_name: "menu-label",
|
||||||
|
hexpand: true,
|
||||||
|
hpack: "start",
|
||||||
|
label: "Brightness",
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
Widget.Box({
|
||||||
|
class_name: "menu-items-section",
|
||||||
|
vpack: "fill",
|
||||||
|
vexpand: true,
|
||||||
|
vertical: true,
|
||||||
|
child: Widget.Box({
|
||||||
|
class_name: "brightness-container",
|
||||||
|
children: [
|
||||||
|
Widget.Icon({
|
||||||
|
class_name: "brightness-slider-icon",
|
||||||
|
icon: icons.brightness.screen,
|
||||||
|
}),
|
||||||
|
Widget.Slider({
|
||||||
|
value: brightness.bind("screen_value"),
|
||||||
|
class_name: "menu-active-slider menu-slider brightness",
|
||||||
|
draw_value: false,
|
||||||
|
hexpand: true,
|
||||||
|
min: 0,
|
||||||
|
max: 1,
|
||||||
|
onChange: ({ value }) => (brightness.screen_value = value),
|
||||||
|
}),
|
||||||
|
Widget.Label({
|
||||||
|
class_name: "brightness-slider-label",
|
||||||
|
label: brightness
|
||||||
|
.bind("screen_value")
|
||||||
|
.as((b) => `${Math.floor(b * 100)}%`),
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export { Brightness };
|
||||||
25
modules/menus/energy/index.js
Normal file
25
modules/menus/energy/index.js
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
import DropdownMenu from "../DropdownMenu.js";
|
||||||
|
import { EnergyProfiles } from "./profiles/index.js";
|
||||||
|
import { Brightness } from "./brightness/index.js";
|
||||||
|
|
||||||
|
export default () => {
|
||||||
|
return DropdownMenu({
|
||||||
|
name: "energymenu",
|
||||||
|
transition: "crossfade",
|
||||||
|
child: Widget.Box({
|
||||||
|
class_name: "menu-items",
|
||||||
|
hpack: "fill",
|
||||||
|
hexpand: true,
|
||||||
|
child: Widget.Box({
|
||||||
|
vertical: true,
|
||||||
|
hpack: "fill",
|
||||||
|
hexpand: true,
|
||||||
|
class_name: "menu-items-container energy",
|
||||||
|
children: [
|
||||||
|
Brightness(),
|
||||||
|
EnergyProfiles(),
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
};
|
||||||
58
modules/menus/energy/profiles/index.js
Normal file
58
modules/menus/energy/profiles/index.js
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
const powerProfiles = await Service.import("powerprofiles");
|
||||||
|
import icons from "../../../icons/index.js";
|
||||||
|
|
||||||
|
const EnergyProfiles = () => {
|
||||||
|
return Widget.Box({
|
||||||
|
class_name: "menu-section-container",
|
||||||
|
vertical: true,
|
||||||
|
children: [
|
||||||
|
Widget.Box({
|
||||||
|
class_name: "menu-label-container",
|
||||||
|
hpack: "fill",
|
||||||
|
child: Widget.Label({
|
||||||
|
class_name: "menu-label",
|
||||||
|
hexpand: true,
|
||||||
|
hpack: "start",
|
||||||
|
label: "Power Profile",
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
Widget.Box({
|
||||||
|
class_name: "menu-items-section",
|
||||||
|
vpack: "fill",
|
||||||
|
vexpand: true,
|
||||||
|
vertical: true,
|
||||||
|
children: powerProfiles.bind("profiles").as((profiles) => {
|
||||||
|
return profiles.map((prof) => {
|
||||||
|
const ProfileLabels = {
|
||||||
|
"power-saver": "Power Saver",
|
||||||
|
balanced: "Balanced",
|
||||||
|
performance: "Performance",
|
||||||
|
};
|
||||||
|
return Widget.Button({
|
||||||
|
on_primary_click: () => {
|
||||||
|
powerProfiles.active_profile = prof.Profile;
|
||||||
|
},
|
||||||
|
class_name: powerProfiles.bind("active_profile").as((active) => {
|
||||||
|
return `power-profile-item ${active === prof.Profile ? "active" : ""}`;
|
||||||
|
}),
|
||||||
|
child: Widget.Box({
|
||||||
|
children: [
|
||||||
|
Widget.Icon({
|
||||||
|
class_name: "power-profile-icon",
|
||||||
|
icon: icons.powerprofile[prof.Profile],
|
||||||
|
}),
|
||||||
|
Widget.Label({
|
||||||
|
class_name: "power-profile-label",
|
||||||
|
label: ProfileLabels[prof.Profile],
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export { EnergyProfiles };
|
||||||
@@ -6,5 +6,15 @@ import BluetoothMenu from "./bluetooth/index.js";
|
|||||||
import MediaMenu from "./media/index.js";
|
import MediaMenu from "./media/index.js";
|
||||||
import NotificationsMenu from "./notifications/index.js";
|
import NotificationsMenu from "./notifications/index.js";
|
||||||
import CalendarMenu from "./calendar/index.js";
|
import CalendarMenu from "./calendar/index.js";
|
||||||
|
import EnergyMenu from "./energy/index.js";
|
||||||
export default [PowerMenu(), Verification(), AudioMenu(), NetworkMenu(), BluetoothMenu(), MediaMenu(), NotificationsMenu(), CalendarMenu()];
|
export default [
|
||||||
|
PowerMenu(),
|
||||||
|
Verification(),
|
||||||
|
AudioMenu(),
|
||||||
|
NetworkMenu(),
|
||||||
|
BluetoothMenu(),
|
||||||
|
MediaMenu(),
|
||||||
|
NotificationsMenu(),
|
||||||
|
CalendarMenu(),
|
||||||
|
EnergyMenu(),
|
||||||
|
];
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ const Ethernet = () => {
|
|||||||
hpack: "start",
|
hpack: "start",
|
||||||
truncate: "end",
|
truncate: "end",
|
||||||
wrap: true,
|
wrap: true,
|
||||||
label: `Ethernet Connection ${typeof wired.speed === "number" ? `(${wired.speed / 1000} Gbps)` : ""}`,
|
label: `Ethernet Connection ${wired.state !== "unknown" && typeof wired?.speed === "number" ? `(${wired?.speed / 1000} Gbps)` : ""}`,
|
||||||
}),
|
}),
|
||||||
Widget.Label({
|
Widget.Label({
|
||||||
hpack: "start",
|
hpack: "start",
|
||||||
|
|||||||
12
scss/bar/battery.scss
Normal file
12
scss/bar/battery.scss
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
@import '../colors';
|
||||||
|
|
||||||
|
.bar {
|
||||||
|
.battery {
|
||||||
|
label {
|
||||||
|
color: $yellow;
|
||||||
|
}
|
||||||
|
image {
|
||||||
|
color: $yellow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -24,6 +24,7 @@
|
|||||||
@import "bar/notifications";
|
@import "bar/notifications";
|
||||||
@import "bar/power";
|
@import "bar/power";
|
||||||
@import "bar/bar";
|
@import "bar/bar";
|
||||||
|
@import "bar/battery";
|
||||||
|
|
||||||
//modules - menus
|
//modules - menus
|
||||||
@import "menus/menu";
|
@import "menus/menu";
|
||||||
@@ -34,6 +35,7 @@
|
|||||||
@import "menus/media";
|
@import "menus/media";
|
||||||
@import "menus/notifications";
|
@import "menus/notifications";
|
||||||
@import "menus/calendar";
|
@import "menus/calendar";
|
||||||
|
@import "menus/energy";
|
||||||
|
|
||||||
//notifications
|
//notifications
|
||||||
@import "notifications/popups";
|
@import "notifications/popups";
|
||||||
|
|||||||
47
scss/menus/energy.scss
Normal file
47
scss/menus/energy.scss
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
@import "../colors";
|
||||||
|
|
||||||
|
.menu-items-container.energy {
|
||||||
|
.menu-label {
|
||||||
|
color: $yellow;
|
||||||
|
}
|
||||||
|
|
||||||
|
.power-profile-item {
|
||||||
|
margin-bottom: 0.5em;
|
||||||
|
|
||||||
|
label {
|
||||||
|
margin-left: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
image {
|
||||||
|
font-size: 1.3em;
|
||||||
|
min-width: 1em;
|
||||||
|
min-height: 1em;
|
||||||
|
|
||||||
|
color: $overlay1;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
label {
|
||||||
|
color: $yellow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
image {
|
||||||
|
color: $yellow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.menu-active-slider.brightness {
|
||||||
|
trough {
|
||||||
|
highlight,
|
||||||
|
progress {
|
||||||
|
background: $yellow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.brightness-container {
|
||||||
|
padding-bottom: 1em;
|
||||||
|
}
|
||||||
|
}
|
||||||
50
style.css
50
style.css
@@ -1,7 +1,7 @@
|
|||||||
* {
|
* {
|
||||||
all: unset;
|
all: unset;
|
||||||
font-family: "Ubuntu Nerd Font";
|
font-family: "Ubuntu Nerd Font";
|
||||||
font-size: 1.175rem;
|
font-size: 1.1rem;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -428,6 +428,13 @@ spinner:checked {
|
|||||||
margin-right: 1.9rem;
|
margin-right: 1.9rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.bar .battery label {
|
||||||
|
color: #f9e2af;
|
||||||
|
}
|
||||||
|
.bar .battery image {
|
||||||
|
color: #f9e2af;
|
||||||
|
}
|
||||||
|
|
||||||
.menu-slider trough {
|
.menu-slider trough {
|
||||||
border-radius: 0.3rem;
|
border-radius: 0.3rem;
|
||||||
background: #313244;
|
background: #313244;
|
||||||
@@ -498,13 +505,13 @@ tooltip label {
|
|||||||
background: #11111b;
|
background: #11111b;
|
||||||
border: 0.13em solid #313244;
|
border: 0.13em solid #313244;
|
||||||
border-radius: 0.7rem;
|
border-radius: 0.7rem;
|
||||||
min-width: 400px;
|
min-width: 250px;
|
||||||
color: #cdd6f4;
|
color: #cdd6f4;
|
||||||
}
|
}
|
||||||
|
|
||||||
.menu-items-container {
|
.menu-items-container {
|
||||||
border-radius: 0.4em;
|
border-radius: 0.4em;
|
||||||
min-width: 400px;
|
min-width: 250px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.menu-section-container {
|
.menu-section-container {
|
||||||
@@ -1071,14 +1078,13 @@ window#powermenu .powermenu.box {
|
|||||||
|
|
||||||
.menu-content-container.notifications {
|
.menu-content-container.notifications {
|
||||||
margin: 1.35em;
|
margin: 1.35em;
|
||||||
margin-bottom: 0em;
|
|
||||||
min-height: 4em;
|
min-height: 4em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.notification-menu-controls {
|
.notification-menu-controls {
|
||||||
background: #1e1e2e;
|
background: #1e1e2e;
|
||||||
margin: 1em 1.3em;
|
margin: 1em 1.3em;
|
||||||
margin-bottom: 0.5em;
|
margin-bottom: 0em;
|
||||||
border-radius: 0.4em;
|
border-radius: 0.4em;
|
||||||
padding: 0.4em 0.75em;
|
padding: 0.4em 0.75em;
|
||||||
}
|
}
|
||||||
@@ -1090,7 +1096,10 @@ window#powermenu .powermenu.box {
|
|||||||
margin: 0em;
|
margin: 0em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.notification-card-content-container {
|
.notification-card-content-container:first-child {
|
||||||
|
margin-top: 0.5em;
|
||||||
|
}
|
||||||
|
.notification-card-content-container:not(:last-child) {
|
||||||
margin-bottom: 1em;
|
margin-bottom: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1270,6 +1279,35 @@ window#powermenu .powermenu.box {
|
|||||||
color: #f5c2e7;
|
color: #f5c2e7;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.menu-items-container.energy .menu-label {
|
||||||
|
color: #f9e2af;
|
||||||
|
}
|
||||||
|
.menu-items-container.energy .power-profile-item {
|
||||||
|
margin-bottom: 0.5em;
|
||||||
|
}
|
||||||
|
.menu-items-container.energy .power-profile-item label {
|
||||||
|
margin-left: 1em;
|
||||||
|
}
|
||||||
|
.menu-items-container.energy .power-profile-item image {
|
||||||
|
font-size: 1.3em;
|
||||||
|
min-width: 1em;
|
||||||
|
min-height: 1em;
|
||||||
|
color: #7f849c;
|
||||||
|
}
|
||||||
|
.menu-items-container.energy .power-profile-item:hover label {
|
||||||
|
color: #f9e2af;
|
||||||
|
}
|
||||||
|
.menu-items-container.energy .power-profile-item.active image {
|
||||||
|
color: #f9e2af;
|
||||||
|
}
|
||||||
|
.menu-items-container.energy .menu-active-slider.brightness trough highlight,
|
||||||
|
.menu-items-container.energy .menu-active-slider.brightness trough progress {
|
||||||
|
background: #f9e2af;
|
||||||
|
}
|
||||||
|
.menu-items-container.energy .brightness-container {
|
||||||
|
padding-bottom: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
.notification-card-container {
|
.notification-card-container {
|
||||||
margin-top: 3.5rem;
|
margin-top: 3.5rem;
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user