forked from Shinonome/dots-hyprland
should add multimonitor support
This commit is contained in:
+28
-20
@@ -1,13 +1,14 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
// Import
|
// Import
|
||||||
|
import Gdk from 'gi://Gdk';
|
||||||
import App from 'resource:///com/github/Aylur/ags/app.js'
|
import App from 'resource:///com/github/Aylur/ags/app.js'
|
||||||
import * as Utils from 'resource:///com/github/Aylur/ags/utils.js'
|
import * as Utils from 'resource:///com/github/Aylur/ags/utils.js'
|
||||||
// Widgets
|
// Widgets
|
||||||
import Bar from './widgets/bar/main.js';
|
import { Bar, BarCornerTopleft, BarCornerTopright } from './widgets/bar/main.js';
|
||||||
import Cheatsheet from './widgets/cheatsheet/main.js';
|
import Cheatsheet from './widgets/cheatsheet/main.js';
|
||||||
import DesktopBackground from './widgets/desktopbackground/main.js';
|
import DesktopBackground from './widgets/desktopbackground/main.js';
|
||||||
// import Dock from './widgets/dock/main.js';
|
// import Dock from './widgets/dock/main.js';
|
||||||
import { CornerTopleft, CornerTopright, CornerBottomleft, CornerBottomright } from './widgets/screencorners/main.js';
|
import Corner from './widgets/screencorners/main.js';
|
||||||
import Indicator from './widgets/indicators/main.js';
|
import Indicator from './widgets/indicators/main.js';
|
||||||
import Osk from './widgets/onscreenkeyboard/main.js';
|
import Osk from './widgets/onscreenkeyboard/main.js';
|
||||||
import Overview from './widgets/overview/main.js';
|
import Overview from './widgets/overview/main.js';
|
||||||
@@ -15,7 +16,11 @@ import Session from './widgets/session/main.js';
|
|||||||
import SideLeft from './widgets/sideleft/main.js';
|
import SideLeft from './widgets/sideleft/main.js';
|
||||||
import SideRight from './widgets/sideright/main.js';
|
import SideRight from './widgets/sideright/main.js';
|
||||||
|
|
||||||
const CLOSE_ANIM_TIME = 210; // Longer than actual anim time (see styles) to make sure widgets animate fully
|
const range = (length, start = 1) => Array.from({ length }, (_, i) => i + start);
|
||||||
|
function forMonitors(widget) {
|
||||||
|
const n = Gdk.Display.get_default()?.get_n_monitors() || 1;
|
||||||
|
return range(n, 0).map(widget).flat(1);
|
||||||
|
}
|
||||||
|
|
||||||
// SCSS compilation
|
// SCSS compilation
|
||||||
Utils.exec(`bash -c 'echo "" > ${App.configDir}/scss/_musicwal.scss'`); // reset music styles
|
Utils.exec(`bash -c 'echo "" > ${App.configDir}/scss/_musicwal.scss'`); // reset music styles
|
||||||
@@ -28,7 +33,25 @@ function applyStyle() {
|
|||||||
}
|
}
|
||||||
applyStyle();
|
applyStyle();
|
||||||
|
|
||||||
// Config object
|
const Windows = () => [
|
||||||
|
DesktopBackground(),
|
||||||
|
// Dock(),
|
||||||
|
Overview(),
|
||||||
|
forMonitors(Indicator),
|
||||||
|
Cheatsheet(),
|
||||||
|
SideLeft(),
|
||||||
|
SideRight(),
|
||||||
|
Osk(),
|
||||||
|
Session(),
|
||||||
|
Bar(),
|
||||||
|
BarCornerTopleft(),
|
||||||
|
BarCornerTopright(),
|
||||||
|
forMonitors((id) => Corner(id, 'top left')),
|
||||||
|
forMonitors((id) => Corner(id, 'top right')),
|
||||||
|
forMonitors((id) => Corner(id, 'bottom left')),
|
||||||
|
forMonitors((id) => Corner(id, 'bottom right')),
|
||||||
|
];
|
||||||
|
const CLOSE_ANIM_TIME = 210; // Longer than actual anim time to make sure widgets animate fully
|
||||||
export default {
|
export default {
|
||||||
css: `${App.configDir}/style.css`,
|
css: `${App.configDir}/style.css`,
|
||||||
stackTraceOnError: true,
|
stackTraceOnError: true,
|
||||||
@@ -37,20 +60,5 @@ export default {
|
|||||||
'sideleft': CLOSE_ANIM_TIME,
|
'sideleft': CLOSE_ANIM_TIME,
|
||||||
'osk': CLOSE_ANIM_TIME,
|
'osk': CLOSE_ANIM_TIME,
|
||||||
},
|
},
|
||||||
windows: [
|
windows: Windows().flat(1),
|
||||||
CornerTopleft(),
|
|
||||||
CornerTopright(),
|
|
||||||
CornerBottomleft(),
|
|
||||||
CornerBottomright(),
|
|
||||||
DesktopBackground(), // If you're going to uncomment these,
|
|
||||||
// Dock(), // Buggy // uncomment the import statement too.
|
|
||||||
Overview(),
|
|
||||||
Indicator(),
|
|
||||||
Cheatsheet(),
|
|
||||||
SideLeft(),
|
|
||||||
SideRight(),
|
|
||||||
Osk(), // On-screen keyboard
|
|
||||||
Session(), // Power menu, if that's what you like to call it
|
|
||||||
Bar(),
|
|
||||||
],
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -3,20 +3,19 @@ const require = async file => (await import(resource(file))).default;
|
|||||||
const service = async file => (await require(`service/${file}`));
|
const service = async file => (await require(`service/${file}`));
|
||||||
|
|
||||||
export const App = await require('app');
|
export const App = await require('app');
|
||||||
export const Widget = await require('widget');
|
// export const Widget = await require('widget');
|
||||||
export const Service = await require('service');
|
// export const Service = await require('service');
|
||||||
export const Variable = await require('variable');
|
// export const Variable = await require('variable');
|
||||||
export const Utils = await import(resource('utils'));
|
export const Utils = await import(resource('utils'));
|
||||||
|
// export const Applications = await service('applications');
|
||||||
export const Applications = await service('applications');
|
// export const Audio = await service('audio');
|
||||||
export const Audio = await service('audio');
|
// export const Battery = await service('battery');
|
||||||
export const Battery = await service('battery');
|
// export const Bluetooth = await service('bluetooth');
|
||||||
export const Bluetooth = await service('bluetooth');
|
|
||||||
// export const Hyprland = await service('hyprland');
|
// export const Hyprland = await service('hyprland');
|
||||||
export const Mpris = await service('mpris');
|
export const Mpris = await service('mpris');
|
||||||
export const Network = await service('network');
|
export const Network = await service('network');
|
||||||
export const Notifications = await service('notifications');
|
export const Notifications = await service('notifications');
|
||||||
export const SystemTray = await service('systemtray');
|
// export const SystemTray = await service('systemtray');
|
||||||
|
|
||||||
globalThis['App'] = App; //////////////////////////////
|
globalThis['App'] = App; //////////////////////////////
|
||||||
// globalThis['Widget'] = Widget;
|
// globalThis['Widget'] = Widget;
|
||||||
|
|||||||
@@ -40,7 +40,6 @@ export const MarginRevealer = ({
|
|||||||
child.css = `margin-top: -${child.get_allocated_height()}px;`;
|
child.css = `margin-top: -${child.get_allocated_height()}px;`;
|
||||||
},
|
},
|
||||||
'toggle': () => {
|
'toggle': () => {
|
||||||
console.log('toggle');
|
|
||||||
if (widget.attribute.revealChild) widget.attribute.hide();
|
if (widget.attribute.revealChild) widget.attribute.hide();
|
||||||
else widget.attribute.show();
|
else widget.attribute.show();
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
import Widget from 'resource:///com/github/Aylur/ags/widget.js';
|
import Widget from 'resource:///com/github/Aylur/ags/widget.js';
|
||||||
const { Gtk } = imports.gi;
|
const { Gtk } = imports.gi;
|
||||||
const Lang = imports.lang;
|
const Lang = imports.lang;
|
||||||
|
import Cairo from 'gi://cairo?version=1.0';
|
||||||
|
|
||||||
|
export const dummyRegion = new Cairo.Region();
|
||||||
|
export const enableClickthrough = (self) => self.input_shape_combine_region(dummyRegion);
|
||||||
|
|
||||||
export const RoundedCorner = (place, props) => Widget.DrawingArea({
|
export const RoundedCorner = (place, props) => Widget.DrawingArea({
|
||||||
...props,
|
...props,
|
||||||
|
|||||||
@@ -331,6 +331,11 @@ $bar_subgroup_bg: $surfaceVariant;
|
|||||||
background-color: $onSurfaceVariant;
|
background-color: $onSurfaceVariant;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.bar-corner-spacing {
|
||||||
|
min-width: $rounding_large;
|
||||||
|
min-height: $rounding_large;
|
||||||
|
}
|
||||||
|
|
||||||
.corner {
|
.corner {
|
||||||
background-color: $t_background;
|
background-color: $t_background;
|
||||||
@include large-rounding;
|
@include large-rounding;
|
||||||
|
|||||||
@@ -823,6 +823,10 @@ tooltip {
|
|||||||
min-height: 0.409rem;
|
min-height: 0.409rem;
|
||||||
background-color: #bfc8ca; }
|
background-color: #bfc8ca; }
|
||||||
|
|
||||||
|
.bar-corner-spacing {
|
||||||
|
min-width: 1.705rem;
|
||||||
|
min-height: 1.705rem; }
|
||||||
|
|
||||||
.corner {
|
.corner {
|
||||||
background-color: #0b0f10;
|
background-color: #0b0f10;
|
||||||
border-radius: 1.705rem;
|
border-radius: 1.705rem;
|
||||||
@@ -2276,6 +2280,20 @@ tooltip {
|
|||||||
.notif-action-critical:active {
|
.notif-action-critical:active {
|
||||||
background-color: #566e73; }
|
background-color: #566e73; }
|
||||||
|
|
||||||
|
@keyframes flyin-top {
|
||||||
|
from {
|
||||||
|
margin-top: -2.795rem; }
|
||||||
|
to {
|
||||||
|
margin-top: 0rem; } }
|
||||||
|
|
||||||
|
@keyframes flyin-bottom {
|
||||||
|
from {
|
||||||
|
margin-top: 4.841rem;
|
||||||
|
margin-bottom: -4.841rem; }
|
||||||
|
to {
|
||||||
|
margin-bottom: 0rem;
|
||||||
|
margin-top: 0rem; } }
|
||||||
|
|
||||||
.osd-music {
|
.osd-music {
|
||||||
transition: 300ms cubic-bezier(0.1, 1, 0, 1);
|
transition: 300ms cubic-bezier(0.1, 1, 0, 1);
|
||||||
box-shadow: 0px 2px 3px rgba(0, 0, 0, 0.45);
|
box-shadow: 0px 2px 3px rgba(0, 0, 0, 0.45);
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
const { Gtk } = imports.gi;
|
const { Gtk } = imports.gi;
|
||||||
import Widget from 'resource:///com/github/Aylur/ags/widget.js';
|
import Widget from 'resource:///com/github/Aylur/ags/widget.js';
|
||||||
|
|
||||||
import { ModuleLeftSpace } from "./leftspace.js";
|
import ModuleSpaceLeft from "./spaceleft.js";
|
||||||
import { ModuleRightSpace } from "./rightspace.js";
|
import ModuleSpaceRight from "./spaceright.js";
|
||||||
import { ModuleMusic } from "./music.js";
|
import { ModuleMusic } from "./music.js";
|
||||||
import { ModuleSystem } from "./system.js";
|
import { ModuleSystem } from "./system.js";
|
||||||
|
import { RoundedCorner, dummyRegion, enableClickthrough } from "../../lib/roundedcorner.js";
|
||||||
const OptionalWorkspaces = async () => {
|
const OptionalWorkspaces = async () => {
|
||||||
try {
|
try {
|
||||||
return (await import('./workspaces_hyprland.js')).default();
|
return (await import('./workspaces_hyprland.js')).default();
|
||||||
@@ -13,42 +14,64 @@ const OptionalWorkspaces = async () => {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
const optionalWorkspacesInstance = await OptionalWorkspaces();
|
||||||
|
|
||||||
const left = Widget.Box({
|
export const Bar = (monitor = 0) => {
|
||||||
className: 'bar-sidemodule',
|
const left = Widget.Box({
|
||||||
children: [ ModuleMusic()],
|
className: 'bar-sidemodule',
|
||||||
});
|
children: [ModuleMusic()],
|
||||||
|
});
|
||||||
|
|
||||||
const center = Widget.Box({
|
const center = Widget.Box({
|
||||||
children: [await OptionalWorkspaces()],
|
children: [optionalWorkspacesInstance],
|
||||||
});
|
});
|
||||||
|
|
||||||
const right = Widget.Box({
|
const right = Widget.Box({
|
||||||
className: 'bar-sidemodule',
|
className: 'bar-sidemodule',
|
||||||
children: [ModuleSystem()],
|
children: [ModuleSystem()],
|
||||||
});
|
});
|
||||||
|
return Widget.Window({
|
||||||
export default () => Widget.Window({
|
monitor,
|
||||||
name: 'bar',
|
name: `bar${monitor}`,
|
||||||
anchor: ['top', 'left', 'right'],
|
anchor: ['top', 'left', 'right'],
|
||||||
exclusivity: 'exclusive',
|
exclusivity: 'exclusive',
|
||||||
visible: true,
|
visible: true,
|
||||||
child: Widget.CenterBox({
|
child: Widget.CenterBox({
|
||||||
className: 'bar-bg',
|
className: 'bar-bg',
|
||||||
startWidget: ModuleLeftSpace(),
|
startWidget: ModuleSpaceLeft(),
|
||||||
centerWidget: Widget.Box({
|
endWidget: ModuleSpaceRight(),
|
||||||
className: 'spacing-h-4',
|
centerWidget: Widget.Box({
|
||||||
children: [
|
className: 'spacing-h-4',
|
||||||
left,
|
children: [
|
||||||
center,
|
left,
|
||||||
right,
|
center,
|
||||||
]
|
right,
|
||||||
|
]
|
||||||
|
}),
|
||||||
|
setup: (self) => {
|
||||||
|
const styleContext = self.get_style_context();
|
||||||
|
const minHeight = styleContext.get_property('min-height', Gtk.StateFlags.NORMAL);
|
||||||
|
// execAsync(['bash', '-c', `hyprctl keyword monitor ,addreserved,${minHeight},0,0,0`]).catch(print);
|
||||||
|
}
|
||||||
}),
|
}),
|
||||||
endWidget: ModuleRightSpace(),
|
});
|
||||||
setup: (self) => {
|
}
|
||||||
const styleContext = self.get_style_context();
|
|
||||||
const minHeight = styleContext.get_property('min-height', Gtk.StateFlags.NORMAL);
|
export const BarCornerTopleft = (id = '') => Widget.Window({
|
||||||
// execAsync(['bash', '-c', `hyprctl keyword monitor ,addreserved,${minHeight},0,0,0`]).catch(print);
|
name: `barcornertl${id}`,
|
||||||
}
|
layer: 'top',
|
||||||
}),
|
anchor: ['top', 'left'],
|
||||||
|
exclusivity: 'normal',
|
||||||
|
visible: true,
|
||||||
|
child: RoundedCorner('topleft', { className: 'corner', }),
|
||||||
|
setup: enableClickthrough,
|
||||||
|
});
|
||||||
|
export const BarCornerTopright = (id = '') => Widget.Window({
|
||||||
|
name: `barcornertr${id}`,
|
||||||
|
layer: 'top',
|
||||||
|
anchor: ['top', 'right'],
|
||||||
|
exclusivity: 'normal',
|
||||||
|
visible: true,
|
||||||
|
child: RoundedCorner('topright', { className: 'corner', }),
|
||||||
|
setup: enableClickthrough,
|
||||||
});
|
});
|
||||||
@@ -6,10 +6,12 @@ import { AnimatedCircProg } from "../../lib/animatedcircularprogress.js";
|
|||||||
import { showMusicControls } from '../../variables.js';
|
import { showMusicControls } from '../../variables.js';
|
||||||
|
|
||||||
function trimTrackTitle(title) {
|
function trimTrackTitle(title) {
|
||||||
var cleanedTitle = title;
|
cleanRegexes = [
|
||||||
cleanedTitle = cleanedTitle.replace(/【[^】]*】/, ''); // Remove stuff like【C93】 at beginning
|
/【[^】]*】/, // Touhou n weeb stuff
|
||||||
cleanedTitle = cleanedTitle.replace(/\[FREE DOWNLOAD\]/g, ''); // Remove F-777's [FREE DOWNLOAD]
|
/\[FREE DOWNLOAD\]/, // F-777
|
||||||
return cleanedTitle.trim();
|
];
|
||||||
|
cleanRegexes.forEach((expr) => cleanedTitle.replace(expr, ''));
|
||||||
|
return title;
|
||||||
}
|
}
|
||||||
|
|
||||||
const TrackProgress = () => {
|
const TrackProgress = () => {
|
||||||
@@ -38,61 +40,66 @@ const moveToRelativeWorkspace = async (self, num) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ModuleMusic = () => Widget.EventBox({ // TODO: use cairo to make button bounce smaller on click
|
export const ModuleMusic = () => {
|
||||||
onScrollUp: (self) => moveToRelativeWorkspace(self, -1),
|
// TODO: use cairo to make button bounce smaller on click, if that's possible
|
||||||
onScrollDown: (self) => moveToRelativeWorkspace(self, +1),
|
const playingState = Widget.Box({ // Wrap a box cuz overlay can't have margins itself
|
||||||
onPrimaryClickRelease: () => showMusicControls.setValue(!showMusicControls.value),
|
homogeneous: true,
|
||||||
onSecondaryClickRelease: () => execAsync(['bash', '-c', 'playerctl next || playerctl position `bc <<< "100 * $(playerctl metadata mpris:length) / 1000000 / 100"` &']),
|
children: [Widget.Overlay({
|
||||||
onMiddleClickRelease: () => execAsync('playerctl play-pause').catch(print),
|
child: Widget.Box({
|
||||||
child: Widget.Box({
|
vpack: 'center',
|
||||||
className: 'bar-group-margin bar-sides',
|
className: 'bar-music-playstate',
|
||||||
children: [
|
homogeneous: true,
|
||||||
Widget.Box({
|
children: [Widget.Label({
|
||||||
className: 'bar-group bar-group-standalone bar-group-pad-music spacing-h-10',
|
vpack: 'center',
|
||||||
children: [
|
className: 'bar-music-playstate-txt',
|
||||||
Widget.Box({ // Wrap a box cuz overlay can't have margins itself
|
justification: 'center',
|
||||||
homogeneous: true,
|
setup: (self) => self.hook(Mpris, label => {
|
||||||
children: [Widget.Overlay({
|
const mpris = Mpris.getPlayer('');
|
||||||
child: Widget.Box({
|
label.label = `${mpris !== null && mpris.playBackStatus == 'Playing' ? 'pause' : 'play_arrow'}`;
|
||||||
vpack: 'center',
|
|
||||||
className: 'bar-music-playstate',
|
|
||||||
homogeneous: true,
|
|
||||||
children: [Widget.Label({
|
|
||||||
vpack: 'center',
|
|
||||||
className: 'bar-music-playstate-txt',
|
|
||||||
justification: 'center',
|
|
||||||
setup: (self) => self.hook(Mpris, label => {
|
|
||||||
const mpris = Mpris.getPlayer('');
|
|
||||||
label.label = `${mpris !== null && mpris.playBackStatus == 'Playing' ? 'pause' : 'play_arrow'}`;
|
|
||||||
}),
|
|
||||||
})],
|
|
||||||
setup: (self) => self.hook(Mpris, label => {
|
|
||||||
const mpris = Mpris.getPlayer('');
|
|
||||||
if (!mpris) return;
|
|
||||||
label.toggleClassName('bar-music-playstate-playing', mpris !== null && mpris.playBackStatus == 'Playing');
|
|
||||||
label.toggleClassName('bar-music-playstate', mpris !== null || mpris.playBackStatus == 'Paused');
|
|
||||||
}),
|
|
||||||
}),
|
|
||||||
overlays: [
|
|
||||||
TrackProgress(),
|
|
||||||
]
|
|
||||||
})]
|
|
||||||
}),
|
}),
|
||||||
Widget.Scrollable({
|
})],
|
||||||
hexpand: true,
|
setup: (self) => self.hook(Mpris, label => {
|
||||||
child: Widget.Label({
|
const mpris = Mpris.getPlayer('');
|
||||||
className: 'txt-smallie txt-onSurfaceVariant',
|
if (!mpris) return;
|
||||||
setup: (self) => self.hook(Mpris, label => {
|
label.toggleClassName('bar-music-playstate-playing', mpris !== null && mpris.playBackStatus == 'Playing');
|
||||||
const mpris = Mpris.getPlayer('');
|
label.toggleClassName('bar-music-playstate', mpris !== null || mpris.playBackStatus == 'Paused');
|
||||||
if (mpris)
|
}),
|
||||||
label.label = `${trimTrackTitle(mpris.trackTitle)} • ${mpris.trackArtists.join(', ')}`;
|
}),
|
||||||
else
|
overlays: [
|
||||||
label.label = 'No media';
|
TrackProgress(),
|
||||||
}),
|
]
|
||||||
})
|
})]
|
||||||
})
|
});
|
||||||
]
|
const trackTitle = Widget.Scrollable({
|
||||||
})
|
hexpand: true,
|
||||||
]
|
child: Widget.Label({
|
||||||
|
className: 'txt-smallie txt-onSurfaceVariant',
|
||||||
|
setup: (self) => self.hook(Mpris, label => {
|
||||||
|
const mpris = Mpris.getPlayer('');
|
||||||
|
if (mpris)
|
||||||
|
label.label = `${trimTrackTitle(mpris.trackTitle)} • ${mpris.trackArtists.join(', ')}`;
|
||||||
|
else
|
||||||
|
label.label = 'No media';
|
||||||
|
}),
|
||||||
|
})
|
||||||
})
|
})
|
||||||
});
|
return Widget.EventBox({
|
||||||
|
onScrollUp: (self) => moveToRelativeWorkspace(self, -1),
|
||||||
|
onScrollDown: (self) => moveToRelativeWorkspace(self, +1),
|
||||||
|
onPrimaryClickRelease: () => showMusicControls.setValue(!showMusicControls.value),
|
||||||
|
onSecondaryClickRelease: () => execAsync(['bash', '-c', 'playerctl next || playerctl position `bc <<< "100 * $(playerctl metadata mpris:length) / 1000000 / 100"` &']),
|
||||||
|
onMiddleClickRelease: () => execAsync('playerctl play-pause').catch(print),
|
||||||
|
child: Widget.Box({
|
||||||
|
className: 'bar-group-margin bar-sides',
|
||||||
|
children: [
|
||||||
|
Widget.Box({
|
||||||
|
className: 'bar-group bar-group-standalone bar-group-pad-music spacing-h-10',
|
||||||
|
children: [
|
||||||
|
playingState,
|
||||||
|
trackTitle,
|
||||||
|
]
|
||||||
|
})
|
||||||
|
]
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -1,81 +0,0 @@
|
|||||||
import App from 'resource:///com/github/Aylur/ags/app.js';
|
|
||||||
import Widget from 'resource:///com/github/Aylur/ags/widget.js';
|
|
||||||
import * as Utils from 'resource:///com/github/Aylur/ags/utils.js';
|
|
||||||
|
|
||||||
import Audio from 'resource:///com/github/Aylur/ags/service/audio.js';
|
|
||||||
import SystemTray from 'resource:///com/github/Aylur/ags/service/systemtray.js';
|
|
||||||
const { execAsync } = Utils;
|
|
||||||
import Indicator from '../../services/indicator.js';
|
|
||||||
import { StatusIcons } from "../../lib/statusicons.js";
|
|
||||||
import { RoundedCorner } from "../../lib/roundedcorner.js";
|
|
||||||
import { Tray } from "./tray.js";
|
|
||||||
|
|
||||||
export const ModuleRightSpace = () => {
|
|
||||||
const barTray = Tray();
|
|
||||||
const barStatusIcons = StatusIcons({
|
|
||||||
className: 'bar-statusicons',
|
|
||||||
setup: (self) => self.hook(App, (self, currentName, visible) => {
|
|
||||||
if (currentName === 'sideright') {
|
|
||||||
self.toggleClassName('bar-statusicons-active', visible);
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
|
|
||||||
return Widget.EventBox({
|
|
||||||
onScrollUp: () => {
|
|
||||||
if (!Audio.speaker) return;
|
|
||||||
Audio.speaker.volume += 0.03;
|
|
||||||
Indicator.popup(1);
|
|
||||||
},
|
|
||||||
onScrollDown: () => {
|
|
||||||
if (!Audio.speaker) return;
|
|
||||||
Audio.speaker.volume -= 0.03;
|
|
||||||
Indicator.popup(1);
|
|
||||||
},
|
|
||||||
onHover: () => { barStatusIcons.toggleClassName('bar-statusicons-hover', true) },
|
|
||||||
onHoverLost: () => { barStatusIcons.toggleClassName('bar-statusicons-hover', false) },
|
|
||||||
onPrimaryClick: () => App.toggleWindow('sideright'),
|
|
||||||
onSecondaryClickRelease: () => execAsync(['bash', '-c', 'playerctl next || playerctl position `bc <<< "100 * $(playerctl metadata mpris:length) / 1000000 / 100"` &']).catch(print),
|
|
||||||
onMiddleClickRelease: () => execAsync('playerctl play-pause').catch(print),
|
|
||||||
child: Widget.Box({
|
|
||||||
homogeneous: false,
|
|
||||||
children: [
|
|
||||||
Widget.Box({
|
|
||||||
hexpand: true,
|
|
||||||
className: 'spacing-h-5 txt',
|
|
||||||
children: [
|
|
||||||
Widget.Box({
|
|
||||||
hexpand: true,
|
|
||||||
className: 'spacing-h-5 txt',
|
|
||||||
children: [
|
|
||||||
Widget.Box({ hexpand: true, }),
|
|
||||||
barTray,
|
|
||||||
Widget.Revealer({
|
|
||||||
transition: 'slide_left',
|
|
||||||
revealChild: false,
|
|
||||||
attribute: {
|
|
||||||
'count': 0,
|
|
||||||
'update': (self, diff) => {
|
|
||||||
self.attribute.count += diff;
|
|
||||||
self.revealChild = (self.attribute.count > 0);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
child: Widget.Box({
|
|
||||||
vpack: 'center',
|
|
||||||
className: 'separator-circle',
|
|
||||||
}),
|
|
||||||
setup: (self) => self
|
|
||||||
.hook(SystemTray, (self) => self.attribute.update(self, 1), 'added')
|
|
||||||
.hook(SystemTray, (self) => self.attribute.update(self, -1), 'removed')
|
|
||||||
,
|
|
||||||
}),
|
|
||||||
barStatusIcons,
|
|
||||||
],
|
|
||||||
}),
|
|
||||||
]
|
|
||||||
}),
|
|
||||||
RoundedCorner('topright', { className: 'corner-black' })
|
|
||||||
]
|
|
||||||
})
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
import App from 'resource:///com/github/Aylur/ags/app.js';
|
import App from 'resource:///com/github/Aylur/ags/app.js';
|
||||||
import Widget from 'resource:///com/github/Aylur/ags/widget.js';
|
import Widget from 'resource:///com/github/Aylur/ags/widget.js';
|
||||||
import { RoundedCorner } from "../../lib/roundedcorner.js";
|
|
||||||
import Brightness from '../../services/brightness.js';
|
import Brightness from '../../services/brightness.js';
|
||||||
import Indicator from '../../services/indicator.js';
|
import Indicator from '../../services/indicator.js';
|
||||||
|
|
||||||
@@ -37,7 +36,7 @@ const WindowTitle = async () => {
|
|||||||
|
|
||||||
const OptionalWindowTitleInstance = await WindowTitle();
|
const OptionalWindowTitleInstance = await WindowTitle();
|
||||||
|
|
||||||
export const ModuleLeftSpace = () => Widget.EventBox({
|
export default () => Widget.EventBox({
|
||||||
onScrollUp: () => {
|
onScrollUp: () => {
|
||||||
Indicator.popup(1); // Since the brightness and speaker are both on the same window
|
Indicator.popup(1); // Since the brightness and speaker are both on the same window
|
||||||
Brightness.screen_value += 0.05;
|
Brightness.screen_value += 0.05;
|
||||||
@@ -52,7 +51,7 @@ export const ModuleLeftSpace = () => Widget.EventBox({
|
|||||||
child: Widget.Box({
|
child: Widget.Box({
|
||||||
homogeneous: false,
|
homogeneous: false,
|
||||||
children: [
|
children: [
|
||||||
RoundedCorner('topleft', { className: 'corner-black' }),
|
Widget.Box({ className: 'bar-corner-spacing' }),
|
||||||
Widget.Overlay({
|
Widget.Overlay({
|
||||||
overlays: [
|
overlays: [
|
||||||
Widget.Box({ hexpand: true }),
|
Widget.Box({ hexpand: true }),
|
||||||
@@ -0,0 +1,82 @@
|
|||||||
|
import App from 'resource:///com/github/Aylur/ags/app.js';
|
||||||
|
import Widget from 'resource:///com/github/Aylur/ags/widget.js';
|
||||||
|
import * as Utils from 'resource:///com/github/Aylur/ags/utils.js';
|
||||||
|
|
||||||
|
import Audio from 'resource:///com/github/Aylur/ags/service/audio.js';
|
||||||
|
import SystemTray from 'resource:///com/github/Aylur/ags/service/systemtray.js';
|
||||||
|
const { execAsync } = Utils;
|
||||||
|
import Indicator from '../../services/indicator.js';
|
||||||
|
import { StatusIcons } from "../../lib/statusicons.js";
|
||||||
|
import { Tray } from "./tray.js";
|
||||||
|
|
||||||
|
export default () => {
|
||||||
|
const barTray = Tray();
|
||||||
|
const notifCounter = Widget.Revealer({
|
||||||
|
transition: 'slide_left',
|
||||||
|
revealChild: false,
|
||||||
|
attribute: {
|
||||||
|
'count': 0,
|
||||||
|
'update': (self, diff) => {
|
||||||
|
self.attribute.count += diff;
|
||||||
|
self.revealChild = (self.attribute.count > 0);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: Widget.Box({
|
||||||
|
vpack: 'center',
|
||||||
|
className: 'separator-circle',
|
||||||
|
}),
|
||||||
|
setup: (self) => self
|
||||||
|
.hook(SystemTray, (self) => self.attribute.update(self, 1), 'added')
|
||||||
|
.hook(SystemTray, (self) => self.attribute.update(self, -1), 'removed')
|
||||||
|
,
|
||||||
|
});
|
||||||
|
const barStatusIcons = StatusIcons({
|
||||||
|
className: 'bar-statusicons',
|
||||||
|
setup: (self) => self.hook(App, (self, currentName, visible) => {
|
||||||
|
if (currentName === 'sideright') {
|
||||||
|
self.toggleClassName('bar-statusicons-active', visible);
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
const actualContent = Widget.Box({
|
||||||
|
hexpand: true,
|
||||||
|
className: 'spacing-h-5 txt',
|
||||||
|
children: [
|
||||||
|
Widget.Box({
|
||||||
|
hexpand: true,
|
||||||
|
className: 'spacing-h-5 txt',
|
||||||
|
children: [
|
||||||
|
Widget.Box({ hexpand: true, }),
|
||||||
|
barTray,
|
||||||
|
notifCounter,
|
||||||
|
barStatusIcons,
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
return Widget.EventBox({
|
||||||
|
onScrollUp: () => {
|
||||||
|
if (!Audio.speaker) return;
|
||||||
|
Audio.speaker.volume += 0.03;
|
||||||
|
Indicator.popup(1);
|
||||||
|
},
|
||||||
|
onScrollDown: () => {
|
||||||
|
if (!Audio.speaker) return;
|
||||||
|
Audio.speaker.volume -= 0.03;
|
||||||
|
Indicator.popup(1);
|
||||||
|
},
|
||||||
|
onHover: () => { barStatusIcons.toggleClassName('bar-statusicons-hover', true) },
|
||||||
|
onHoverLost: () => { barStatusIcons.toggleClassName('bar-statusicons-hover', false) },
|
||||||
|
onPrimaryClick: () => App.toggleWindow('sideright'),
|
||||||
|
onSecondaryClickRelease: () => execAsync(['bash', '-c', 'playerctl next || playerctl position `bc <<< "100 * $(playerctl metadata mpris:length) / 1000000 / 100"` &']).catch(print),
|
||||||
|
onMiddleClickRelease: () => execAsync('playerctl play-pause').catch(print),
|
||||||
|
child: Widget.Box({
|
||||||
|
homogeneous: false,
|
||||||
|
children: [
|
||||||
|
actualContent,
|
||||||
|
Widget.Box({ className: 'bar-corner-spacing' }),
|
||||||
|
]
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -1,83 +0,0 @@
|
|||||||
const { Gdk, Gtk } = imports.gi;
|
|
||||||
const Lang = imports.lang;
|
|
||||||
import { App, Service, Utils, Widget, SCREEN_HEIGHT, SCREEN_WIDTH } from '../../imports.js';
|
|
||||||
const { execAsync, exec } = Utils;
|
|
||||||
const { Box, Label } = Widget;
|
|
||||||
|
|
||||||
const NUM_OF_VERTICES = 30;
|
|
||||||
const NUM_OF_EDGES = 29;
|
|
||||||
// Vertices
|
|
||||||
var vertices = [];
|
|
||||||
for (var i = 0; i < NUM_OF_VERTICES; i++) {
|
|
||||||
vertices.push([
|
|
||||||
Math.floor(Math.random() * SCREEN_WIDTH),
|
|
||||||
Math.floor(Math.random() * SCREEN_HEIGHT)
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
// Edges
|
|
||||||
function generateRandomEdges(numVertices, numEdges) { // TODO: make sure whole graph is connected
|
|
||||||
var edges = new Set();
|
|
||||||
var vertices = [];
|
|
||||||
|
|
||||||
// Generate vertices
|
|
||||||
for (var i = 0; i < numVertices; i++) {
|
|
||||||
vertices.push(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate random distinct edges
|
|
||||||
while (edges.size < numEdges) {
|
|
||||||
var randomVertex1 = vertices[Math.floor(Math.random() * numVertices)];
|
|
||||||
var randomVertex2 = vertices[Math.floor(Math.random() * numVertices)];
|
|
||||||
|
|
||||||
// Ensure the two vertices are distinct and the edge doesn't already exist
|
|
||||||
if (randomVertex1 !== randomVertex2) {
|
|
||||||
var edge = [randomVertex1, randomVertex2].sort();
|
|
||||||
edges.add(edge.join(','));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return Array.from(edges).map(edge => edge.split(',').map(Number));
|
|
||||||
}
|
|
||||||
|
|
||||||
var edges = generateRandomEdges(NUM_OF_VERTICES, NUM_OF_EDGES);
|
|
||||||
|
|
||||||
export default () => Box({
|
|
||||||
hpack: 'fill',
|
|
||||||
vpack: 'fill',
|
|
||||||
homogeneous: true,
|
|
||||||
children: [
|
|
||||||
Widget.DrawingArea({
|
|
||||||
className: 'bg-graph',
|
|
||||||
setup: (area) => {
|
|
||||||
area.connect('draw', Lang.bind(area, (area, cr) => {
|
|
||||||
// area.set_size_request(SCREEN_WIDTH, SCREEN_HEIGHT);
|
|
||||||
// console.log('allocated width/height:', area.get_allocated_width(), '/', area.get_allocated_height())
|
|
||||||
const styleContext = area.get_style_context();
|
|
||||||
const color = styleContext.get_property('color', Gtk.StateFlags.NORMAL);
|
|
||||||
const backgroundColor = styleContext.get_property('background-color', Gtk.StateFlags.NORMAL);
|
|
||||||
const radius = area.get_style_context().get_property('border-radius', Gtk.StateFlags.NORMAL);
|
|
||||||
const borderWidth = area.get_style_context().get_border(Gtk.StateFlags.NORMAL).left; // ur going to write border-width: something anyway
|
|
||||||
|
|
||||||
cr.setSourceRGBA(backgroundColor.red, backgroundColor.green, backgroundColor.blue, backgroundColor.alpha);
|
|
||||||
cr.rectangle(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT)
|
|
||||||
cr.fill();
|
|
||||||
cr.setSourceRGBA(color.red, color.green, color.blue, color.alpha);
|
|
||||||
// Draw edges
|
|
||||||
cr.setLineWidth(borderWidth);
|
|
||||||
console.log("line width:", borderWidth);
|
|
||||||
for (var i = 0; i < NUM_OF_EDGES; i++) {
|
|
||||||
console.log(vertices[edges[i][0]][0], vertices[edges[i][0]][1], '->', vertices[edges[i][1]][0], vertices[edges[i][1]][1])
|
|
||||||
cr.moveTo(vertices[edges[i][0]][0], vertices[edges[i][0]][1]);
|
|
||||||
cr.lineTo(vertices[edges[i][1]][0], vertices[edges[i][1]][1]);
|
|
||||||
cr.stroke();
|
|
||||||
}
|
|
||||||
// Draw vertices
|
|
||||||
for (var i = 0; i < NUM_OF_VERTICES; i++) {
|
|
||||||
cr.arc(vertices[i][0], vertices[i][1], radius, 0, 2 * Math.PI)
|
|
||||||
cr.fill()
|
|
||||||
}
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
]
|
|
||||||
})
|
|
||||||
@@ -1,11 +1,7 @@
|
|||||||
const { Gdk, Gtk } = imports.gi;
|
|
||||||
import Widget from 'resource:///com/github/Aylur/ags/widget.js';
|
import Widget from 'resource:///com/github/Aylur/ags/widget.js';
|
||||||
import * as Utils from 'resource:///com/github/Aylur/ags/utils.js';
|
|
||||||
const { execAsync, exec } = Utils;
|
|
||||||
|
|
||||||
import TimeAndLaunchesWidget from './timeandlaunches.js'
|
import TimeAndLaunchesWidget from './timeandlaunches.js'
|
||||||
import SystemWidget from './system.js'
|
import SystemWidget from './system.js'
|
||||||
import GraphWidget from './graph.js'
|
|
||||||
|
|
||||||
export default () => Widget.Window({
|
export default () => Widget.Window({
|
||||||
name: 'desktopbackground',
|
name: 'desktopbackground',
|
||||||
@@ -19,7 +15,6 @@ export default () => Widget.Window({
|
|||||||
vexpand: true,
|
vexpand: true,
|
||||||
}),
|
}),
|
||||||
overlays: [
|
overlays: [
|
||||||
// GraphWidget(),
|
|
||||||
TimeAndLaunchesWidget(),
|
TimeAndLaunchesWidget(),
|
||||||
SystemWidget(),
|
SystemWidget(),
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// This file is for brightness/volume indicators
|
// This file is for brightness/volume indicators
|
||||||
import Widget from 'resource:///com/github/Aylur/ags/widget.js';
|
import Widget from 'resource:///com/github/Aylur/ags/widget.js';
|
||||||
import Audio from 'resource:///com/github/Aylur/ags/service/audio.js';
|
import Audio from 'resource:///com/github/Aylur/ags/service/audio.js';
|
||||||
const { Box, Label, ProgressBar, Revealer } = Widget;
|
const { Box, Label, ProgressBar } = Widget;
|
||||||
import { MarginRevealer } from '../../lib/advancedwidgets.js';
|
import { MarginRevealer } from '../../lib/advancedwidgets.js';
|
||||||
import Brightness from '../../services/brightness.js';
|
import Brightness from '../../services/brightness.js';
|
||||||
import Indicator from '../../services/indicator.js';
|
import Indicator from '../../services/indicator.js';
|
||||||
@@ -12,7 +12,7 @@ const OsdValue = (name, labelSetup, progressSetup, props = {}) => {
|
|||||||
className: 'osd-label',
|
className: 'osd-label',
|
||||||
label: `${name}`,
|
label: `${name}`,
|
||||||
});
|
});
|
||||||
const valueNumber =Label({
|
const valueNumber = Label({
|
||||||
hexpand: false, className: 'osd-value-txt',
|
hexpand: false, className: 'osd-value-txt',
|
||||||
setup: labelSetup,
|
setup: labelSetup,
|
||||||
});
|
});
|
||||||
@@ -44,51 +44,44 @@ const OsdValue = (name, labelSetup, progressSetup, props = {}) => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const brightnessIndicator = OsdValue('Brightness',
|
export default () => {
|
||||||
(self) => self
|
const brightnessIndicator = OsdValue('Brightness',
|
||||||
.hook(Brightness, self => {
|
(self) => self.hook(Brightness, self => {
|
||||||
self.label = `${Math.round(Brightness.screen_value * 100)}`;
|
self.label = `${Math.round(Brightness.screen_value * 100)}`;
|
||||||
}, 'notify::screen-value')
|
}, 'notify::screen-value'),
|
||||||
,
|
(self) => self.hook(Brightness, (progress) => {
|
||||||
(self) => self
|
|
||||||
.hook(Brightness, (progress) => {
|
|
||||||
const updateValue = Brightness.screen_value;
|
const updateValue = Brightness.screen_value;
|
||||||
progress.value = updateValue;
|
progress.value = updateValue;
|
||||||
}, 'notify::screen-value')
|
}, 'notify::screen-value'),
|
||||||
,
|
)
|
||||||
)
|
|
||||||
|
|
||||||
const volumeIndicator = OsdValue('Volume',
|
const volumeIndicator = OsdValue('Volume',
|
||||||
(self) => self
|
(self) => self.hook(Audio, (label) => {
|
||||||
.hook(Audio, (label) => {
|
|
||||||
label.label = `${Math.round(Audio.speaker?.volume * 100)}`;
|
label.label = `${Math.round(Audio.speaker?.volume * 100)}`;
|
||||||
})
|
}),
|
||||||
,
|
(self) => self.hook(Audio, (progress) => {
|
||||||
(self) => self
|
|
||||||
.hook(Audio, (progress) => {
|
|
||||||
const updateValue = Audio.speaker?.volume;
|
const updateValue = Audio.speaker?.volume;
|
||||||
if (!isNaN(updateValue)) progress.value = updateValue;
|
if (!isNaN(updateValue)) progress.value = updateValue;
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
return MarginRevealer({
|
||||||
|
transition: 'slide_down',
|
||||||
|
showClass: 'osd-show',
|
||||||
|
hideClass: 'osd-hide',
|
||||||
|
extraSetup: (self) => self
|
||||||
|
.hook(Indicator, (revealer, value) => {
|
||||||
|
if (value > -1) revealer.attribute.show();
|
||||||
|
else revealer.attribute.hide();
|
||||||
|
}, 'popup')
|
||||||
|
,
|
||||||
|
child: Box({
|
||||||
|
hpack: 'center',
|
||||||
|
vertical: false,
|
||||||
|
className: 'spacing-h--10',
|
||||||
|
children: [
|
||||||
|
brightnessIndicator,
|
||||||
|
volumeIndicator,
|
||||||
|
]
|
||||||
})
|
})
|
||||||
,
|
});
|
||||||
);
|
}
|
||||||
|
|
||||||
export default () => MarginRevealer({
|
|
||||||
transition: 'slide_down',
|
|
||||||
showClass: 'osd-show',
|
|
||||||
hideClass: 'osd-hide',
|
|
||||||
extraSetup: (self) => self
|
|
||||||
.hook(Indicator, (revealer, value) => {
|
|
||||||
if (value > -1) revealer.attribute.show();
|
|
||||||
else revealer.attribute.hide();
|
|
||||||
}, 'popup')
|
|
||||||
,
|
|
||||||
child: Box({
|
|
||||||
hpack: 'center',
|
|
||||||
vertical: false,
|
|
||||||
className: 'spacing-h--10',
|
|
||||||
children: [
|
|
||||||
brightnessIndicator,
|
|
||||||
volumeIndicator,
|
|
||||||
]
|
|
||||||
})
|
|
||||||
});
|
|
||||||
@@ -5,7 +5,7 @@ import MusicControls from './musiccontrols.js';
|
|||||||
import ColorScheme from './colorscheme.js';
|
import ColorScheme from './colorscheme.js';
|
||||||
import NotificationPopups from './notificationpopups.js';
|
import NotificationPopups from './notificationpopups.js';
|
||||||
|
|
||||||
export default (monitor) => Widget.Window({
|
export default (monitor = 0) => Widget.Window({
|
||||||
name: `indicator${monitor}`,
|
name: `indicator${monitor}`,
|
||||||
monitor,
|
monitor,
|
||||||
className: 'indicator',
|
className: 'indicator',
|
||||||
|
|||||||
@@ -32,17 +32,13 @@ function isRealPlayer(player) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getPlayer = (name = PREFERRED_PLAYER) => {
|
export const getPlayer = (name = PREFERRED_PLAYER) => Mpris.getPlayer(name) || Mpris.players[0] || null;
|
||||||
return Mpris.getPlayer(name) || Mpris.players[0] || null;
|
|
||||||
}
|
|
||||||
|
|
||||||
function lengthStr(length) {
|
function lengthStr(length) {
|
||||||
const min = Math.floor(length / 60);
|
const min = Math.floor(length / 60);
|
||||||
const sec = Math.floor(length % 60);
|
const sec = Math.floor(length % 60);
|
||||||
const sec0 = sec < 10 ? '0' : '';
|
const sec0 = sec < 10 ? '0' : '';
|
||||||
return `${min}:${sec0}${sec}`;
|
return `${min}:${sec0}${sec}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function fileExists(filePath) {
|
function fileExists(filePath) {
|
||||||
let file = Gio.File.new_for_path(filePath);
|
let file = Gio.File.new_for_path(filePath);
|
||||||
return file.query_exists(null);
|
return file.query_exists(null);
|
||||||
@@ -54,17 +50,11 @@ function detectMediaSource(link) {
|
|||||||
return ' Firefox'
|
return ' Firefox'
|
||||||
return " File";
|
return " File";
|
||||||
}
|
}
|
||||||
// Remove protocol if present
|
|
||||||
let url = link.replace(/(^\w+:|^)\/\//, '');
|
let url = link.replace(/(^\w+:|^)\/\//, '');
|
||||||
// Extract the domain name
|
|
||||||
let domain = url.match(/(?:[a-z]+\.)?([a-z]+\.[a-z]+)/i)[1];
|
let domain = url.match(/(?:[a-z]+\.)?([a-z]+\.[a-z]+)/i)[1];
|
||||||
|
if (domain == 'ytimg.com') return ' Youtube';
|
||||||
if (domain == 'ytimg.com')
|
if (domain == 'discordapp.net') return ' Discord';
|
||||||
return ' Youtube';
|
if (domain == 'sndcdn.com') return ' SoundCloud';
|
||||||
if (domain == 'discordapp.net')
|
|
||||||
return ' Discord';
|
|
||||||
if (domain == 'sndcdn.com')
|
|
||||||
return ' SoundCloud';
|
|
||||||
return domain;
|
return domain;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,15 +62,19 @@ const DEFAULT_MUSIC_FONT = 'Gabarito, sans-serif';
|
|||||||
function getTrackfont(player) {
|
function getTrackfont(player) {
|
||||||
const title = player.trackTitle;
|
const title = player.trackTitle;
|
||||||
const artists = player.trackArtists.join(' ');
|
const artists = player.trackArtists.join(' ');
|
||||||
if (artists.includes('TANO*C') || artists.includes('USAO') || artists.includes('Kobaryo')) return 'Chakra Petch'; // Rigid square replacement
|
if (artists.includes('TANO*C') || artists.includes('USAO') || artists.includes('Kobaryo'))
|
||||||
if (title.includes('東方')) return 'Crimson Text, serif'; // Serif for Touhou stuff
|
return 'Chakra Petch'; // Rigid square replacement
|
||||||
|
if (title.includes('東方'))
|
||||||
|
return 'Crimson Text, serif'; // Serif for Touhou stuff
|
||||||
return DEFAULT_MUSIC_FONT;
|
return DEFAULT_MUSIC_FONT;
|
||||||
}
|
}
|
||||||
function trimTrackTitle(title) {
|
function trimTrackTitle(title) {
|
||||||
var cleanedTitle = title;
|
cleanRegexes = [
|
||||||
cleanedTitle = cleanedTitle.replace(/【[^】]*】/, ''); // Remove stuff like【C93】 at beginning
|
/【[^】]*】/, // Touhou n weeb stuff
|
||||||
cleanedTitle = cleanedTitle.replace(/\[FREE DOWNLOAD\]/g, ''); // Remove F-777's [FREE DOWNLOAD]
|
/\[FREE DOWNLOAD\]/, // F-777
|
||||||
return cleanedTitle.trim();
|
];
|
||||||
|
cleanRegexes.forEach((expr) => cleanedTitle.replace(expr, ''));
|
||||||
|
return title;
|
||||||
}
|
}
|
||||||
|
|
||||||
const TrackProgress = ({ player, ...rest }) => {
|
const TrackProgress = ({ player, ...rest }) => {
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ execAsync(`ydotoold`).catch(print); // Start ydotool daemon
|
|||||||
function releaseAllKeys() {
|
function releaseAllKeys() {
|
||||||
const keycodes = Array.from(Array(249).keys());
|
const keycodes = Array.from(Array(249).keys());
|
||||||
execAsync([`ydotool`, `key`, ...keycodes.map(keycode => `${keycode}:0`)])
|
execAsync([`ydotool`, `key`, ...keycodes.map(keycode => `${keycode}:0`)])
|
||||||
.then(console.log('Released all keys'))
|
.then(console.log('[OSK] Released all keys'))
|
||||||
.catch(print);
|
.catch(print);
|
||||||
}
|
}
|
||||||
var modsPressed = false;
|
var modsPressed = false;
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ function moveClientToWorkspace(address, workspace) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function dumpToWorkspace(from, to) {
|
export function dumpToWorkspace(from, to) {
|
||||||
console.log('dump', from, to);
|
|
||||||
if (from == to) return;
|
if (from == to) return;
|
||||||
Hyprland.clients.forEach(client => {
|
Hyprland.clients.forEach(client => {
|
||||||
if (client.workspace.id == from) {
|
if (client.workspace.id == from) {
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ export function launchCustomCommand(command) {
|
|||||||
execAsync([`bash`, `-c`, `systemctl suspend`]).catch(print);
|
execAsync([`bash`, `-c`, `systemctl suspend`]).catch(print);
|
||||||
}
|
}
|
||||||
else if (args[0] == '>logout') { // Log out
|
else if (args[0] == '>logout') { // Log out
|
||||||
execAsync([`bash`, `-c`, `killall Hyprland`]).catch(print);
|
execAsync([`bash`, `-c`, `loginctl terminate-user $USER`]).catch(print);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -166,7 +166,7 @@ export const SearchAndWindows = () => {
|
|||||||
_appSearchResults = Applications.query(text);
|
_appSearchResults = Applications.query(text);
|
||||||
|
|
||||||
// Calculate
|
// Calculate
|
||||||
if (startsWithNumber(text)) { // Eval on typing is dangerous, this is a small workaround.
|
if (startsWithNumber(text)) { // Eval on typing is dangerous; this is a small workaround.
|
||||||
try {
|
try {
|
||||||
const fullResult = eval(text);
|
const fullResult = eval(text);
|
||||||
resultsBox.add(CalculationResultButton({ result: fullResult, text: text }));
|
resultsBox.add(CalculationResultButton({ result: fullResult, text: text }));
|
||||||
|
|||||||
@@ -1,43 +1,16 @@
|
|||||||
import Cairo from 'gi://cairo?version=1.0';
|
|
||||||
import Widget from 'resource:///com/github/Aylur/ags/widget.js';
|
import Widget from 'resource:///com/github/Aylur/ags/widget.js';
|
||||||
import { RoundedCorner } from "../../lib/roundedcorner.js";
|
import { RoundedCorner, dummyRegion, enableClickthrough } from "../../lib/roundedcorner.js";
|
||||||
|
|
||||||
const dummyRegion = new Cairo.Region();
|
export default (monitor = 0, where = 'bottom left') => {
|
||||||
const enableClickthrough = (self) => self.input_shape_combine_region(dummyRegion);
|
const positionString = where.replace(/\s/, ""); // remove space
|
||||||
|
return Widget.Window({
|
||||||
export const CornerTopleft = () => Widget.Window({
|
monitor,
|
||||||
name: 'cornertl',
|
name: `corner${positionString}${monitor}`,
|
||||||
layer: 'top',
|
layer: 'overlay',
|
||||||
anchor: ['top', 'left'],
|
anchor: where.split(' '),
|
||||||
exclusivity: 'normal',
|
exclusivity: 'ignore',
|
||||||
visible: true,
|
visible: true,
|
||||||
child: RoundedCorner('topleft', { className: 'corner', }),
|
child: RoundedCorner(positionString, { className: 'corner-black', }),
|
||||||
setup: enableClickthrough,
|
setup: enableClickthrough,
|
||||||
});
|
});
|
||||||
export const CornerTopright = () => Widget.Window({
|
}
|
||||||
name: 'cornertr',
|
|
||||||
layer: 'top',
|
|
||||||
anchor: ['top', 'right'],
|
|
||||||
exclusivity: 'normal',
|
|
||||||
visible: true,
|
|
||||||
child: RoundedCorner('topright', { className: 'corner', }),
|
|
||||||
setup: enableClickthrough,
|
|
||||||
});
|
|
||||||
export const CornerBottomleft = () => Widget.Window({
|
|
||||||
name: 'cornerbl',
|
|
||||||
layer: 'top',
|
|
||||||
anchor: ['bottom', 'left'],
|
|
||||||
exclusivity: 'ignore',
|
|
||||||
visible: true,
|
|
||||||
child: RoundedCorner('bottomleft', { className: 'corner-black', }),
|
|
||||||
setup: enableClickthrough,
|
|
||||||
});
|
|
||||||
export const CornerBottomright = () => Widget.Window({
|
|
||||||
name: 'cornerbr',
|
|
||||||
layer: 'top',
|
|
||||||
anchor: ['bottom', 'right'],
|
|
||||||
exclusivity: 'ignore',
|
|
||||||
visible: true,
|
|
||||||
child: RoundedCorner('bottomright', { className: 'corner-black', }),
|
|
||||||
setup: enableClickthrough,
|
|
||||||
});
|
|
||||||
@@ -63,7 +63,7 @@ export default () => {
|
|||||||
// lock, logout, sleep
|
// lock, logout, sleep
|
||||||
// const lockButton = SessionButton('Lock', 'lock', () => { App.closeWindow('session'); execAsync('gtklock') });
|
// const lockButton = SessionButton('Lock', 'lock', () => { App.closeWindow('session'); execAsync('gtklock') });
|
||||||
const lockButton = SessionButton('Lock', 'lock', () => { App.closeWindow('session'); execAsync('swaylock') });
|
const lockButton = SessionButton('Lock', 'lock', () => { App.closeWindow('session'); execAsync('swaylock') });
|
||||||
const logoutButton = SessionButton('Logout', 'logout', () => { App.closeWindow('session'); execAsync(['bash', '-c', 'killall Hyprland']) });
|
const logoutButton = SessionButton('Logout', 'logout', () => { App.closeWindow('session'); execAsync(['bash', '-c', 'loginctl terminate-user $USER']) });
|
||||||
const sleepButton = SessionButton('Sleep', 'sleep', () => { App.closeWindow('session'); execAsync('systemctl suspend') });
|
const sleepButton = SessionButton('Sleep', 'sleep', () => { App.closeWindow('session'); execAsync('systemctl suspend') });
|
||||||
// hibernate, shutdown, reboot
|
// hibernate, shutdown, reboot
|
||||||
const hibernateButton = SessionButton('Hibernate', 'downloading', () => { App.closeWindow('session'); execAsync('systemctl hibernate') });
|
const hibernateButton = SessionButton('Hibernate', 'downloading', () => { App.closeWindow('session'); execAsync('systemctl hibernate') });
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ import { MaterialIcon } from '../../lib/materialicon.js';
|
|||||||
|
|
||||||
function expandTilde(path) {
|
function expandTilde(path) {
|
||||||
if (path.startsWith('~')) {
|
if (path.startsWith('~')) {
|
||||||
console.log(GLib.get_home_dir() + path.slice(1));
|
|
||||||
return GLib.get_home_dir() + path.slice(1);
|
return GLib.get_home_dir() + path.slice(1);
|
||||||
} else {
|
} else {
|
||||||
return path;
|
return path;
|
||||||
@@ -120,8 +119,6 @@ export const ModuleInvertColors = async (props = {}) => {
|
|||||||
Hyprland.sendMessage('j/getoption decoration:screen_shader')
|
Hyprland.sendMessage('j/getoption decoration:screen_shader')
|
||||||
.then((output) => {
|
.then((output) => {
|
||||||
const shaderPath = JSON.parse(output)["str"].trim();
|
const shaderPath = JSON.parse(output)["str"].trim();
|
||||||
console.log(output)
|
|
||||||
console.log(shaderPath)
|
|
||||||
if (shaderPath != "[[EMPTY]]" && shaderPath != "") {
|
if (shaderPath != "[[EMPTY]]" && shaderPath != "") {
|
||||||
execAsync(['bash', '-c', `hyprctl keyword decoration:screen_shader '[[EMPTY]]'`]).catch(print);
|
execAsync(['bash', '-c', `hyprctl keyword decoration:screen_shader '[[EMPTY]]'`]).catch(print);
|
||||||
button.toggleClassName('sidebar-button-active', false);
|
button.toggleClassName('sidebar-button-active', false);
|
||||||
|
|||||||
Reference in New Issue
Block a user