feat: make music label more dynamically configurable (#389)
* feat: make music lable more dynamically configurable * fix: move seekbar above controls * fix: add menu for media * fix: add menu for media * fix: add menu for media * Organize media player code * fix: revert back controls position * Delete pnpm-lock.yaml * Update options.ts * Update widget/settings/pages/config/bar/index.ts * fix: merge changes broken --------- Co-authored-by: Jas Singh <jaskiratpal.singh@outlook.com>
This commit is contained in:
71
modules/bar/media/helpers.ts
Normal file
71
modules/bar/media/helpers.ts
Normal file
@@ -0,0 +1,71 @@
|
||||
import { MediaTags } from 'lib/types/audio.js';
|
||||
import { Opt } from 'lib/option';
|
||||
import { Variable } from 'types/variable';
|
||||
import { MprisPlayer } from 'types/service/mpris';
|
||||
|
||||
const getIconForPlayer = (playerName: string): string => {
|
||||
const windowTitleMap = [
|
||||
['Firefox', ''],
|
||||
['Microsoft Edge', ''],
|
||||
['Discord', ''],
|
||||
['Plex', ''],
|
||||
['Spotify', ''],
|
||||
['(.*)', ''],
|
||||
];
|
||||
|
||||
const foundMatch = windowTitleMap.find((wt) => RegExp(wt[0], 'i').test(playerName));
|
||||
|
||||
return foundMatch ? foundMatch[1] : '';
|
||||
};
|
||||
|
||||
const isValidMediaTag = (tag: unknown): tag is keyof MediaTags => {
|
||||
if (typeof tag !== 'string') {
|
||||
return false;
|
||||
}
|
||||
|
||||
const mediaTagKeys = ['title', 'artists', 'artist', 'album', 'name', 'identity'] as const;
|
||||
return (mediaTagKeys as readonly string[]).includes(tag);
|
||||
};
|
||||
|
||||
export const generateMediaLabel = (
|
||||
truncation_size: Opt<number>,
|
||||
show_label: Opt<boolean>,
|
||||
format: Opt<string>,
|
||||
songIcon: Variable<string>,
|
||||
activePlayer: Variable<MprisPlayer>,
|
||||
): string => {
|
||||
if (activePlayer.value && show_label.value) {
|
||||
const { track_title, identity, track_artists, track_album, name } = activePlayer.value;
|
||||
songIcon.value = getIconForPlayer(identity);
|
||||
|
||||
const mediaTags: MediaTags = {
|
||||
title: track_title,
|
||||
artists: track_artists.join(', '),
|
||||
artist: track_artists[0] || '',
|
||||
album: track_album,
|
||||
name: name,
|
||||
identity: identity,
|
||||
};
|
||||
|
||||
const mediaFormat = format.getValue();
|
||||
|
||||
const truncatedLabel = mediaFormat.replace(
|
||||
/{(title|artists|artist|album|name|identity)(:[^}]*)?}/g,
|
||||
(_, p1: string | undefined, p2: string | undefined) => {
|
||||
if (!isValidMediaTag(p1)) {
|
||||
return '';
|
||||
}
|
||||
const value = p1 !== undefined ? mediaTags[p1] : '';
|
||||
const suffix = p2?.length ? p2.slice(1) : '';
|
||||
return value ? value + suffix : '';
|
||||
},
|
||||
);
|
||||
|
||||
const mediaLabel =
|
||||
truncation_size.value > 0 ? truncatedLabel.substring(0, truncation_size.value) : truncatedLabel;
|
||||
return mediaLabel;
|
||||
} else {
|
||||
songIcon.value = getIconForPlayer(activePlayer.value?.identity || '');
|
||||
return `Media`;
|
||||
}
|
||||
};
|
||||
@@ -7,8 +7,9 @@ import { BarBoxChild } from 'lib/types/bar.js';
|
||||
import Button from 'types/widgets/button.js';
|
||||
import { Attribute, Child } from 'lib/types/widget.js';
|
||||
import { runAsyncCommand } from 'customModules/utils.js';
|
||||
import { generateMediaLabel } from './helpers.js';
|
||||
|
||||
const { show_artist, truncation, truncation_size, show_label, show_active_only, rightClick, middleClick } =
|
||||
const { truncation, truncation_size, show_label, show_active_only, rightClick, middleClick, format } =
|
||||
options.bar.media;
|
||||
|
||||
const Media = (): BarBoxChild => {
|
||||
@@ -25,41 +26,10 @@ const Media = (): BarBoxChild => {
|
||||
isVis.value = !show_active_only.value || mpris.players.length > 0;
|
||||
});
|
||||
|
||||
const getIconForPlayer = (playerName: string): string => {
|
||||
const windowTitleMap = [
|
||||
['Firefox', ''],
|
||||
['Microsoft Edge', ''],
|
||||
['Discord', ''],
|
||||
['Plex', ''],
|
||||
['Spotify', ''],
|
||||
['(.*)', ''],
|
||||
];
|
||||
|
||||
const foundMatch = windowTitleMap.find((wt) => RegExp(wt[0], 'i').test(playerName));
|
||||
|
||||
return foundMatch ? foundMatch[1] : '';
|
||||
};
|
||||
|
||||
const songIcon = Variable('');
|
||||
|
||||
const mediaLabel = Utils.watch('Media', [mpris, show_artist, truncation, truncation_size, show_label], () => {
|
||||
if (activePlayer.value && show_label.value) {
|
||||
const { track_title, identity, track_artists } = activePlayer.value;
|
||||
songIcon.value = getIconForPlayer(identity);
|
||||
const trackArtist = show_artist.value ? ` - ${track_artists.join(', ')}` : ``;
|
||||
const truncatedLabel = truncation.value
|
||||
? `${track_title + trackArtist}`.substring(0, truncation_size.value)
|
||||
: `${track_title + trackArtist}`;
|
||||
|
||||
return track_title.length === 0
|
||||
? `No media playing...`
|
||||
: truncatedLabel.length < truncation_size.value || !truncation.value
|
||||
? `${truncatedLabel}`
|
||||
: `${truncatedLabel.substring(0, truncatedLabel.length - 3)}...`;
|
||||
} else {
|
||||
songIcon.value = getIconForPlayer(activePlayer.value?.identity || '');
|
||||
return `Media`;
|
||||
}
|
||||
const mediaLabel = Utils.watch('Media', [mpris, truncation, truncation_size, show_label, format], () => {
|
||||
return generateMediaLabel(truncation_size, show_label, format, songIcon, activePlayer);
|
||||
});
|
||||
|
||||
return {
|
||||
|
||||
@@ -2,6 +2,9 @@ import { BoxWidget } from 'lib/types/widget';
|
||||
import { songName } from './name/index';
|
||||
import { songAuthor } from './author/index';
|
||||
import { songAlbum } from './album/index';
|
||||
import options from 'options';
|
||||
|
||||
const { hideAlbum, hideAuthor } = options.menus.media;
|
||||
|
||||
export const MediaInfo = (): BoxWidget => {
|
||||
return Widget.Box({
|
||||
@@ -9,6 +12,8 @@ export const MediaInfo = (): BoxWidget => {
|
||||
hpack: 'center',
|
||||
hexpand: true,
|
||||
vertical: true,
|
||||
children: [songName(), songAuthor(), songAlbum()],
|
||||
children: Utils.merge([hideAlbum.bind('value'), hideAuthor.bind('value')], (hidAlbum, hidAuthor) => {
|
||||
return [songName(), ...(hidAuthor ? [] : [songAuthor()]), ...(hidAlbum ? [] : [songAlbum()])];
|
||||
}),
|
||||
});
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user