Skip to content

Commit

Permalink
MBS-12205: Add "play on ListenBrainz" button
Browse files Browse the repository at this point in the history
This mostly copies the functionality
of the existing script
(https://gist.github.com/MonkeyDo/6b919302e97dc979f8277b9c71ff82ab).
It shows a "Play on ListenBrainz" button on the right side of releases,
recordings, recording collections and release groups that sends
the user to play the release or a custom grouping of recordings
with BrainzPlayer.
It only shows on overview pages for recording collections and RGs,
but that's also true of the script so hopefully not a problem.
Ideally, LB would support passing an RG or collection MBID directly.

Keep in mind this doesn't hit LB and doesn't know whether LB can
actually play the music (I'm not sure even hitting LB would help
since LB might also not know until it tries).
  • Loading branch information
reosarevok committed Dec 27, 2022
1 parent dc3d5b0 commit 314e3f2
Show file tree
Hide file tree
Showing 11 changed files with 148 additions and 4 deletions.
11 changes: 10 additions & 1 deletion root/collection/CollectionIndex.js
Original file line number Diff line number Diff line change
Expand Up @@ -172,8 +172,17 @@ React.Element<typeof CollectionLayout> => {
(user.id === collection.editor.id ||
collection.collaborators.some(x => x.id === user.id));

const recordingMbids = props.collectionEntityType === 'recording' &&
props.entities.length > 0
? props.entities.map(entity => entity.gid)
: null;

return (
<CollectionLayout entity={collection} page="index">
<CollectionLayout
entity={collection}
page="index"
recordingMbids={recordingMbids}
>
<div className="description">
{collection.description_html ? (
<>
Expand Down
9 changes: 8 additions & 1 deletion root/collection/CollectionLayout.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ type Props = {
+entity: CollectionT,
+fullWidth?: boolean,
+page: string,
+recordingMbids?: $ReadOnlyArray<string> | null,
+title?: string,
};

Expand All @@ -28,6 +29,7 @@ const CollectionLayout = ({
entity: collection,
fullWidth = false,
page,
recordingMbids,
title,
}: Props): React.Element<typeof Layout> => {
const mainTitle = texp.l(
Expand All @@ -46,7 +48,12 @@ const CollectionLayout = ({
/>
{children}
</div>
{fullWidth ? null : <CollectionSidebar collection={collection} />}
{fullWidth ? null : (
<CollectionSidebar
collection={collection}
recordingMbids={recordingMbids}
/>
)}
</Layout>
);
};
Expand Down
10 changes: 10 additions & 0 deletions root/layout/components/sidebar/CollectionSidebar.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,17 @@ import {formatCount} from '../../../statistics/utilities.js';
import {returnToCurrentPage} from '../../../utility/returnUri.js';

import MergeLink from './MergeLink.js';
import PlayOnListenBrainzButton from './PlayOnListenBrainzButton.js';
import {SidebarProperties, SidebarProperty} from './SidebarProperties.js';

type Props = {
+collection: CollectionT,
+recordingMbids?: $ReadOnlyArray<string> | null,
};

const CollectionSidebar = ({
collection,
recordingMbids,
}: Props): React.Element<'div'> => {
const $c = React.useContext(CatalystContext);
const typeName = collection.typeName;
Expand All @@ -36,6 +39,13 @@ const CollectionSidebar = ({

return (
<div id="sidebar">
{recordingMbids == null ? null : (
<PlayOnListenBrainzButton
entityType="recording"
mbids={recordingMbids}
/>
)}

<h2 className="collection-information">
{l('Collection information')}
</h2>
Expand Down
71 changes: 71 additions & 0 deletions root/layout/components/sidebar/PlayOnListenBrainzButton.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/*
* @flow strict
* Copyright (C) 2017 MetaBrainz Foundation
*
* This file is part of MusicBrainz, the open internet music database,
* and is licensed under the GPL version 2, or (at your option) any
* later version: http://www.gnu.org/licenses/gpl-2.0.txt
*/

import * as React from 'react';

import listenBrainzIconUrl
from '../../../static/images/icons/listenbrainz.png';

type Props = {
+entityType: 'release' | 'recording',
+mbids: string | $ReadOnlyArray<string>,
};

function getListenBrainzLink(
entityType: 'release' | 'recording',
mbids: string | $ReadOnlyArray<string>,
): string | null {
let formattedMbids;

if (Array.isArray(mbids)) {
formattedMbids = mbids.join(',');
} else {
formattedMbids = mbids;
}

if (entityType === 'release') {
return `//listenbrainz.org/player/release/${formattedMbids}`;
}

if (entityType === 'recording') {
return `//listenbrainz.org/player?recording_mbids=${formattedMbids}`;
}

return null;
}

const PlayOnListenBrainzButton = ({
entityType,
mbids,
}: Props): React.Element<'a'> | null => {
const link = getListenBrainzLink(entityType, mbids);

if (link == null) {
return null;
}

return (
<a
className="styled-button listenbrainz-button"
href={link}
rel="noreferrer"
target="_blank"
>
<img
alt={l('ListenBrainz')}
className="warning"
src={listenBrainzIconUrl}
/>
{' '}
{l('Play on ListenBrainz')}
</a>
);
};

export default PlayOnListenBrainzButton;
6 changes: 6 additions & 0 deletions root/layout/components/sidebar/RecordingSidebar.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import CollectionLinks from './CollectionLinks.js';
import EditLinks from './EditLinks.js';
import LastUpdated from './LastUpdated.js';
import MergeLink from './MergeLink.js';
import PlayOnListenBrainzButton from './PlayOnListenBrainzButton.js';
import RemoveLink from './RemoveLink.js';
import SidebarLicenses from './SidebarLicenses.js';
import {SidebarProperty, SidebarProperties} from './SidebarProperties.js';
Expand All @@ -37,6 +38,11 @@ const RecordingSidebar = ({recording}: Props): React.Element<'div'> => {

return (
<div id="sidebar">
<PlayOnListenBrainzButton
entityType="recording"
mbids={recording.gid}
/>

<h2 className="recording-information">
{l('Recording information')}
</h2>
Expand Down
14 changes: 13 additions & 1 deletion root/layout/components/sidebar/ReleaseGroupSidebar.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,21 @@ import CollectionLinks from './CollectionLinks.js';
import EditLinks from './EditLinks.js';
import LastUpdated from './LastUpdated.js';
import MergeLink from './MergeLink.js';
import PlayOnListenBrainzButton from './PlayOnListenBrainzButton.js';
import SidebarLicenses from './SidebarLicenses.js';
import {SidebarProperty, SidebarProperties} from './SidebarProperties.js';
import SidebarRating from './SidebarRating.js';
import SidebarTags from './SidebarTags.js';

type Props = {
+firstReleaseGid?: string | null,
+releaseGroup: ReleaseGroupT,
};

const ReleaseGroupSidebar = ({releaseGroup}: Props): React.Element<'div'> => {
const ReleaseGroupSidebar = ({
firstReleaseGid,
releaseGroup,
}: Props): React.Element<'div'> => {
const gid = encodeURIComponent(releaseGroup.gid);
const typeName = releaseGroupType(releaseGroup);

Expand All @@ -42,6 +47,13 @@ const ReleaseGroupSidebar = ({releaseGroup}: Props): React.Element<'div'> => {
</div>
) : null}

{nonEmpty(firstReleaseGid) ? (
<PlayOnListenBrainzButton
entityType="release"
mbids={firstReleaseGid}
/>
) : null}

<h2 className="release-group-information">
{l('Release group information')}
</h2>
Expand Down
6 changes: 6 additions & 0 deletions root/layout/components/sidebar/ReleaseSidebar.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import CollectionLinks from './CollectionLinks.js';
import EditLinks from './EditLinks.js';
import LastUpdated from './LastUpdated.js';
import MergeLink from './MergeLink.js';
import PlayOnListenBrainzButton from './PlayOnListenBrainzButton.js';
import RemoveLink from './RemoveLink.js';
import SidebarDataQuality from './SidebarDataQuality.js';
import SidebarLicenses from './SidebarLicenses.js';
Expand Down Expand Up @@ -108,6 +109,11 @@ const ReleaseSidebar = ({release}: Props): React.Element<'div'> | null => {
)}
</div>

<PlayOnListenBrainzButton
entityType="release"
mbids={release.gid}
/>

<h2 className="release-information">
{l('Release information')}
</h2>
Expand Down
3 changes: 3 additions & 0 deletions root/release_group/ReleaseGroupIndex.js
Original file line number Diff line number Diff line change
Expand Up @@ -119,9 +119,12 @@ const ReleaseGroupIndex = ({
wikipediaExtract,
}: Props): React.Element<typeof ReleaseGroupLayout> => {
const $c = React.useContext(CatalystContext);
const firstReleaseGid = releases.length ? releases[0][0].gid : null;

return (
<ReleaseGroupLayout
entity={releaseGroup}
firstReleaseGid={firstReleaseGid}
page="index"
>
{eligibleForCleanup ? (
Expand Down
9 changes: 8 additions & 1 deletion root/release_group/ReleaseGroupLayout.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import ReleaseGroupHeader from './ReleaseGroupHeader.js';
type Props = {
+children: React.Node,
+entity: ReleaseGroupT,
+firstReleaseGid?: string | null,
+fullWidth?: boolean,
+page: string,
+title?: string,
Expand All @@ -28,6 +29,7 @@ type Props = {
const ReleaseGroupLayout = ({
children,
entity: releaseGroup,
firstReleaseGid,
fullWidth = false,
page,
title,
Expand All @@ -44,7 +46,12 @@ const ReleaseGroupLayout = ({
<ReleaseGroupHeader page={page} releaseGroup={releaseGroup} />
{children}
</div>
{fullWidth ? null : <ReleaseGroupSidebar releaseGroup={releaseGroup} />}
{fullWidth ? null : (
<ReleaseGroupSidebar
firstReleaseGid={firstReleaseGid}
releaseGroup={releaseGroup}
/>
)}
</Layout>
);
};
Expand Down
Binary file added root/static/images/icons/listenbrainz.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
13 changes: 13 additions & 0 deletions root/static/styles/layout.less
Original file line number Diff line number Diff line change
Expand Up @@ -470,6 +470,19 @@ div.warning img.warning {
text-align: center;
}

#sidebar .listenbrainz-button {
color: @button-text;
display: block;
margin-bottom: 0.5rem;
text-align: center;
text-decoration: none;
}

#sidebar .listenbrainz-button img {
vertical-align: bottom;
max-height: 16px;
}

#sidebar .cover-art img, #sidebar .picture img {
max-height: 300px;
max-width: 218px; /* references #sidebar's width */
Expand Down

0 comments on commit 314e3f2

Please sign in to comment.