import * as Uebersicht from "uebersicht";
import * as DataWidget from "./data-widget.jsx";
import * as DataWidgetLoader from "./data-widget-loader.jsx";
import useWidgetRefresh from "../../hooks/use-widget-refresh";
import useServerSocket from "../../hooks/use-server-socket";
import { useSimpleBarContext } from "../simple-bar-context.jsx";
import * as Icons from "../icons/icons.jsx";
import * as Utils from "../../utils";
export { spotifyStyles as styles } from "../../styles/components/data/spotify";
const { React } = Uebersicht;
const DEFAULT_REFRESH_FREQUENCY = 10000;
/**
* Spotify widget component.
* @returns {JSX.Element|null} The Spotify widget.
*/
export const Widget = React.memo(() => {
const { displayIndex, settings } = useSimpleBarContext();
const { widgets, spotifyWidgetOptions } = settings;
const { spotifyWidget } = widgets;
const {
refreshFrequency,
showSpecter,
showOnDisplay,
showIcon,
showSpotifyMetadata,
} = spotifyWidgetOptions;
// Determine the refresh frequency for the widget
const refresh = React.useMemo(
() =>
Utils.getRefreshFrequency(refreshFrequency, DEFAULT_REFRESH_FREQUENCY),
[refreshFrequency],
);
// Determine if the widget should be visible
const visible =
Utils.isVisibleOnDisplay(displayIndex, showOnDisplay) && spotifyWidget;
const [state, setState] = React.useState();
const [loading, setLoading] = React.useState(visible);
const [isSpotifyActive, setIsSpotifyActive] = React.useState(false);
/**
* Resets the widget state.
*/
const resetWidget = () => {
setState(undefined);
setLoading(false);
setIsSpotifyActive(false);
};
/**
* Fetches the current Spotify state.
*/
const getSpotify = React.useCallback(async () => {
if (!visible) return;
const isRunning = await Utils.cachedRun(
`pgrep -fq '[S]potify Helper' && echo "true" || echo "false"`,
refresh,
);
if (Utils.cleanupOutput(isRunning) === "false") {
setLoading(false);
setIsSpotifyActive(false);
setState({
playerState: "",
trackName: "",
artistName: "",
});
return;
}
// if showSpotifyMetadata is enabled, retrieves all information
if (showSpotifyMetadata) {
const output = await Utils.cachedRun(
`osascript -e 'tell application "Spotify"' -e 'set output to (player state as string) & "|" & (name of current track as string) & "|" & (artist of current track as string)' -e 'end tell' 2>/dev/null || echo "stopped||"`,
refresh,
);
const [playerState, trackName, artistName] =
Utils.cleanupOutput(output).split("|");
setState({
playerState,
trackName,
artistName,
});
// else, only playerState
} else {
const playerState = await Utils.cachedRun(
`osascript -e 'tell application "Spotify" to player state as string' 2>/dev/null || echo "stopped"`,
refresh,
);
setState({
playerState: Utils.cleanupOutput(playerState),
trackName: "",
artistName: "",
});
}
setIsSpotifyActive(true);
setLoading(false);
}, [visible, showSpotifyMetadata, refresh]);
// Set up server socket and widget refresh hooks
useServerSocket("spotify", visible, getSpotify, resetWidget, setLoading);
useWidgetRefresh(visible, getSpotify, refresh);
if (loading) return ;
if (!state || !isSpotifyActive) return null;
const { playerState, trackName, artistName } = state;
if (!trackName.length && showSpotifyMetadata) return null;
const label = artistName.length ? `${trackName} - ${artistName}` : trackName;
const isPlaying = playerState === "playing";
const Icon = getIcon(playerState);
/**
* Handles click event to toggle play/pause.
* @param {React.MouseEvent} e - The click event.
*/
const onClick = (e) => {
Utils.clickEffect(e);
togglePlay(!isPlaying);
getSpotify();
};
/**
* Handles right-click event to skip to the next track.
* @param {React.MouseEvent} e - The right-click event.
*/
const onRightClick = (e) => {
Utils.clickEffect(e);
Uebersicht.run(`osascript -e 'tell application "Spotify" to Next Track'`);
getSpotify();
};
/**
* Handles middle-click event to open Spotify.
* @param {React.MouseEvent} e - The middle-click event.
*/
const onMiddleClick = (e) => {
Utils.clickEffect(e);
Uebersicht.run(`open -a 'Spotify'`);
getSpotify();
};
const classes = Utils.classNames("spotify", {
"spotify--hidden-metadata": !showSpotifyMetadata,
"spotify--playing": isPlaying,
});
return (
{showSpotifyMetadata && label}
);
});
Widget.displayName = "Spotify";
/**
* Toggles play/pause state of Spotify.
* @param {boolean} isPaused - Whether the player is paused.
*/
function togglePlay(isPaused) {
const state = isPaused ? "play" : "pause";
Uebersicht.run(`osascript -e 'tell application "Spotify" to ${state}'`);
}
/**
* Gets the appropriate icon based on the player state.
* @param {string} playerState - The current state of the player.
* @returns {JSX.Element} The icon component.
*/
function getIcon(playerState) {
if (playerState === "stopped") return Icons.Stopped;
if (playerState === "playing") return Icons.Playing;
return Icons.Paused;
}