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:
Rubin Bhandari
2024-10-31 14:51:53 +05:45
committed by GitHub
parent 8893122006
commit da1784d486
8 changed files with 124 additions and 39 deletions

View 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`;
}
};

View File

@@ -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 {

View File

@@ -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()])];
}),
});
};