aboutsummaryrefslogtreecommitdiff
path: root/users/ryan/modules/simple-bar/simple-bar-source/lib/components/aerospace
diff options
context:
space:
mode:
Diffstat (limited to 'users/ryan/modules/simple-bar/simple-bar-source/lib/components/aerospace')
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/aerospace/opened-apps.jsx33
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/aerospace/process.jsx72
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/aerospace/space.jsx84
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/aerospace/spaces.jsx67
-rwxr-xr-xusers/ryan/modules/simple-bar/simple-bar-source/lib/components/aerospace/window.jsx99
5 files changed, 355 insertions, 0 deletions
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/aerospace/opened-apps.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/aerospace/opened-apps.jsx
new file mode 100755
index 0000000..5b56966
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/aerospace/opened-apps.jsx
@@ -0,0 +1,33 @@
1import * as Uebersicht from "uebersicht";
2import * as AppIcons from "../../app-icons.js";
3import { SuspenseIcon } from "../icons/icon.jsx";
4import * as Utils from "../../utils.js";
5
6const { React } = Uebersicht;
7
8/**
9 * OpenedApps component to display icons of opened applications.
10 * @param {Object} props - The component props.
11 * @param {Array} props.apps - The list of opened applications.
12 * @returns {JSX.Element|null} The rendered component or null if no apps are opened.
13 */
14export default function OpenedApps({ apps }) {
15 if (!apps.length) return null;
16
17 return apps.map((app, i) => {
18 const { focused } = app;
19 const appName = Utils.normalizeAppName(app["app-name"]);
20 const Icon = AppIcons.apps[appName] || AppIcons.apps.Default;
21
22 // Generate class names for the app icon
23 const classes = Utils.classNames("space__icon", {
24 "space__icon--focused": focused,
25 });
26
27 return (
28 <SuspenseIcon key={i}>
29 <Icon className={classes} />
30 </SuspenseIcon>
31 );
32 });
33}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/aerospace/process.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/aerospace/process.jsx
new file mode 100755
index 0000000..0c461cc
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/aerospace/process.jsx
@@ -0,0 +1,72 @@
1import * as Uebersicht from "uebersicht";
2import Window from "./window.jsx";
3import * as Utils from "../../utils";
4import { useAerospaceContext } from "../aerospace-context.jsx";
5import { useSimpleBarContext } from "../simple-bar-context.jsx";
6
7export { processStyles as styles } from "../../styles/components/process";
8
9const { React } = Uebersicht;
10
11/**
12 * Process component to display windows in the current space.
13 * @returns {JSX.Element|null} The rendered component or null if not visible.
14 */
15const Component = React.memo(() => {
16 // Get spaces from aerospace context
17 const { spaces } = useAerospaceContext();
18 // Get settings and display index from simple bar context
19 const { settings, displayIndex } = useSimpleBarContext();
20 const { spacesDisplay, process, widgets } = settings;
21 const { exclusionsAsRegex } = spacesDisplay;
22 const { processWidget } = widgets;
23 const { centered, showOnDisplay } = process;
24
25 // Determine if the component should be visible
26 const visible =
27 spaces?.length &&
28 processWidget &&
29 Utils.isVisibleOnDisplay(displayIndex, showOnDisplay);
30
31 if (!visible) return null;
32
33 // Find the focused space on the current display
34 const { windows = [] } =
35 spaces.find((space) => space.focused && space.monitor === displayIndex) ||
36 {};
37
38 if (!windows.length) return null;
39
40 // Get exclusions for filtering windows
41 const exclusions = exclusionsAsRegex
42 ? spacesDisplay.exclusions
43 : spacesDisplay.exclusions.split(", ");
44
45 const titleExclusions = exclusionsAsRegex
46 ? spacesDisplay.titleExclusions
47 : spacesDisplay.titleExclusions.split(", ");
48
49 // Generate class names for the component
50 const classes = Utils.classNames("process", {
51 "process--centered": centered,
52 });
53
54 // Filter windows based on exclusions
55 const filteredWindows = windows.filter((window) =>
56 Utils.filterApps(window, exclusions, titleExclusions, exclusionsAsRegex),
57 );
58
59 return (
60 <div className={classes}>
61 <div className="process__container">
62 {filteredWindows.map((window, i) => (
63 <Window key={i} window={window} />
64 ))}
65 </div>
66 </div>
67 );
68});
69
70Component.displayName = "Process";
71
72export default Component;
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/aerospace/space.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/aerospace/space.jsx
new file mode 100755
index 0000000..ab91bbb
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/aerospace/space.jsx
@@ -0,0 +1,84 @@
1import * as Uebersicht from "uebersicht";
2import OpenedApps from "./opened-apps.jsx";
3import { useSimpleBarContext } from "../simple-bar-context.jsx";
4import * as Utils from "../../utils.js";
5import * as Aerospace from "../../aerospace.js";
6
7const { React } = Uebersicht;
8
9/**
10 * Space component to display a single space.
11 * @param {Object} props - The component props.
12 * @param {Object} props.space - The space object.
13 * @param {boolean} props.lastOfSpace - Indicates if this is the last space of the monitor.
14 * @returns {JSX.Element|null} The rendered component.
15 */
16export default function Space({ space, lastOfSpace }) {
17 const { windows } = space;
18 const { settings } = useSimpleBarContext();
19 const { spacesDisplay } = settings;
20 const {
21 displayAllSpacesOnAllScreens,
22 exclusionsAsRegex,
23 hideDuplicateAppsInSpaces,
24 } = spacesDisplay;
25 const { workspace, focused } = space;
26
27 /**
28 * Handle click event to switch to the clicked space.
29 * @param {Event} e - The click event.
30 */
31 const onClick = (e) => {
32 if (focused) return;
33 Aerospace.goToSpace(workspace);
34 Utils.clickEffect(e);
35 };
36
37 // Determine if the space should be hidden
38 const hidden = !focused && !windows.length && spacesDisplay.hideEmptySpaces;
39
40 if (hidden) return null;
41
42 // Get exclusions and title exclusions based on settings
43 const exclusions = exclusionsAsRegex
44 ? spacesDisplay.exclusions
45 : spacesDisplay.exclusions.split(", ");
46 const titleExclusions = exclusionsAsRegex
47 ? spacesDisplay.titleExclusions
48 : spacesDisplay.titleExclusions.split(", ");
49
50 // Filter windows based on exclusions
51 const filteredWindows = windows.filter((window) =>
52 Utils.filterApps(window, exclusions, titleExclusions, exclusionsAsRegex),
53 );
54
55 // Remove duplicate apps if the setting is enabled
56 const displayedWindows = hideDuplicateAppsInSpaces
57 ? filteredWindows.reduce((acc, window) => {
58 const isDuplicate = acc.find(
59 (w) => w["app-name"] === window["app-name"],
60 );
61 return isDuplicate ? acc : [...acc, window];
62 }, [])
63 : filteredWindows;
64
65 // Determine the CSS classes for the space
66 const classes = Utils.classNames("space", {
67 "space--focused": focused,
68 "space--empty": windows.length,
69 });
70
71 return (
72 <React.Fragment>
73 {displayAllSpacesOnAllScreens && lastOfSpace && (
74 <div className="spaces__separator" />
75 )}
76 <div className={classes}>
77 <button className="space__inner" onClick={onClick}>
78 {workspace}
79 <OpenedApps apps={displayedWindows} />
80 </button>
81 </div>
82 </React.Fragment>
83 );
84}
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/aerospace/spaces.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/aerospace/spaces.jsx
new file mode 100755
index 0000000..d576389
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/aerospace/spaces.jsx
@@ -0,0 +1,67 @@
1import * as Uebersicht from "uebersicht";
2import Space from "./space.jsx";
3import { useAerospaceContext } from "../aerospace-context.jsx";
4import { useSimpleBarContext } from "../simple-bar-context.jsx";
5import * as Utils from "../../utils.js";
6import * as AeroSpace from "../../aerospace.js";
7
8export { spacesStyles as styles } from "../../styles/components/spaces/spaces.js";
9
10const { React } = Uebersicht;
11
12/**
13 * Spaces component to display spaces on the screen.
14 * @returns {JSX.Element|null} The rendered component.
15 */
16const Component = React.memo(() => {
17 // Get spaces from aerospace context
18 const { spaces } = useAerospaceContext();
19 // Get displays, displayIndex, and settings from simple bar context
20 const { displays, displayIndex, settings } = useSimpleBarContext();
21 const { spacesDisplay, process } = settings;
22 const { displayAllSpacesOnAllScreens, showOnDisplay } = spacesDisplay;
23 // Determine if the component should be visible on the current display
24 const visible = Utils.isVisibleOnDisplay(displayIndex, showOnDisplay);
25 const isProcessVisible = Utils.isVisibleOnDisplay(
26 displayIndex,
27 process.showOnDisplay
28 );
29
30 // If not visible, return null
31 if (!visible) return null;
32
33 // If there are no spaces, return an empty div
34 if (!spaces?.length) {
35 return <div className="spaces spaces--empty" />;
36 }
37
38 // Map through displays and render spaces for the current display
39 return displays.map((display) => {
40 const displayId = AeroSpace.getDisplayIndex(display);
41 if (displayId !== displayIndex) return null;
42
43 // Filter spaces based on display settings
44 const filteredSpaces = displayAllSpacesOnAllScreens
45 ? spaces
46 : spaces.filter((space) => space.monitor === displayId);
47
48 return (
49 <div key={displayId} className="spaces">
50 {filteredSpaces.map((space, i) => {
51 const { workspace } = space;
52 const lastOfSpace =
53 i !== 0 && space.monitor !== spaces[i - 1].monitor;
54
55 return (
56 <Space key={workspace} space={space} lastOfSpace={lastOfSpace} />
57 );
58 })}
59 {isProcessVisible && <div className="spaces__end-separator" />}
60 </div>
61 );
62 });
63});
64
65Component.displayName = "Spaces";
66
67export default Component;
diff --git a/users/ryan/modules/simple-bar/simple-bar-source/lib/components/aerospace/window.jsx b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/aerospace/window.jsx
new file mode 100755
index 0000000..04b54d6
--- /dev/null
+++ b/users/ryan/modules/simple-bar/simple-bar-source/lib/components/aerospace/window.jsx
@@ -0,0 +1,99 @@
1import * as Uebersicht from "uebersicht";
2import * as AppIcons from "../../app-icons";
3import { SuspenseIcon } from "../icons/icon.jsx";
4import { useSimpleBarContext } from "../simple-bar-context.jsx";
5import * as Utils from "../../utils";
6import * as Aerospace from "../../aerospace";
7
8const { React } = Uebersicht;
9
10/**
11 * Window component to display a window in the process bar.
12 * @param {Object} props - The component props.
13 * @param {Object} props.window - The window object.
14 * @returns {JSX.Element|null} The rendered component.
15 */
16export default function Window({ window }) {
17 // Get settings from context
18 const { settings } = useSimpleBarContext();
19 // Create a ref for the button element
20 const ref = React.useRef();
21 // Destructure settings
22 const {
23 displayOnlyCurrent,
24 hideWindowTitle,
25 displayOnlyIcon,
26 expandAllProcesses,
27 } = settings.process;
28 // Destructure window properties
29 const {
30 focused,
31 "app-name": appName,
32 "window-title": title,
33 "window-id": id,
34 } = window;
35
36 // If displayOnlyCurrent is true and the window is not focused, return null
37 if (displayOnlyCurrent && !focused) {
38 return null;
39 }
40
41 // Get the icon for the app or use the default icon
42 const Icon = AppIcons.apps[appName] || AppIcons.apps.Default;
43
44 /**
45 * Handle click event on the window button.
46 * @param {Event} e - The click event.
47 */
48 const onClick = (e) => {
49 !displayOnlyCurrent && Utils.clickEffect(e);
50 Aerospace.focusWindow(id);
51 };
52
53 /**
54 * Handle mouse enter event on the window button.
55 */
56 const onMouseEnter = () => {
57 Utils.startSliding(ref.current, ".process__inner", ".process__name");
58 };
59
60 /**
61 * Handle mouse leave event on the window button.
62 */
63 const onMouseLeave = () => {
64 Utils.stopSliding(ref.current, ".process__name");
65 };
66
67 // Generate class names based on settings and window state
68 const classes = Utils.classNames("process__window", {
69 "process__window--expanded": expandAllProcesses,
70 "process__window--focused": !displayOnlyCurrent && focused,
71 "process__window--only-current": displayOnlyCurrent,
72 "process__window--only-icon": displayOnlyIcon,
73 });
74
75 // Clean up the window title
76 const cleanedUpName =
77 appName !== title && title.length ? `${appName} / ${title}` : appName;
78 const processName = hideWindowTitle ? appName : cleanedUpName;
79
80 // Render the window button
81 return (
82 <button
83 ref={ref}
84 className={classes}
85 onClick={onClick}
86 onMouseEnter={displayOnlyIcon ? undefined : onMouseEnter}
87 onMouseLeave={displayOnlyIcon ? undefined : onMouseLeave}
88 >
89 <SuspenseIcon>
90 <Icon className="process__icon" />
91 </SuspenseIcon>
92 {!displayOnlyIcon && (
93 <span className="process__inner">
94 <span className="process__name">{processName}</span>
95 </span>
96 )}
97 </button>
98 );
99}