fix(frontend): add Jellyfin logo to ExternalLinkBlock

This commit is contained in:
Aiden Vigue
2021-02-18 11:54:36 -05:00
parent fb51ce5570
commit 107b766c44
6 changed files with 89 additions and 145 deletions

View File

@@ -209,7 +209,7 @@ authRoutes.post('/jellyfin', async (req, res, next) => {
}
// Update the users avatar with their jellyfin profile pic (incase it changed)
if (typeof account.User.PrimaryImageTag !== undefined) {
if (account.User.PrimaryImageTag) {
user.avatar = `${hostname}/Users/${account.User.Id}/Images/Primary/?tag=${account.User.PrimaryImageTag}&quality=90`;
} else {
user.avatar = '/os_logo_square.png';
@@ -233,10 +233,9 @@ authRoutes.post('/jellyfin', async (req, res, next) => {
jellyfinDeviceId: deviceId,
jellyfinAuthToken: account.AccessToken,
permissions: Permission.ADMIN,
avatar:
typeof account.User.PrimaryImageTag !== undefined
? `${hostname}/Users/${account.User.Id}/Images/Primary/?tag=${account.User.PrimaryImageTag}&quality=90`
: '/os_logo_square.png',
avatar: account.User.PrimaryImageTag
? `${hostname}/Users/${account.User.Id}/Images/Primary/?tag=${account.User.PrimaryImageTag}&quality=90`
: '/os_logo_square.png',
userType: UserType.JELLYFIN,
});
await userRepository.save(user);
@@ -263,10 +262,9 @@ authRoutes.post('/jellyfin', async (req, res, next) => {
jellyfinDeviceId: deviceId,
jellyfinAuthToken: account.AccessToken,
permissions: settings.main.defaultPermissions,
avatar:
typeof account.User.PrimaryImageTag !== undefined
? `${hostname}/Users/${account.User.Id}/Images/Primary/?tag=${account.User.PrimaryImageTag}&quality=90`
: '/os_logo_square.png',
avatar: account.User.PrimaryImageTag
? `${hostname}/Users/${account.User.Id}/Images/Primary/?tag=${account.User.PrimaryImageTag}&quality=90`
: '/os_logo_square.png',
userType: UserType.JELLYFIN,
});
await userRepository.save(user);

View File

@@ -0,0 +1,24 @@
<svg id="banner-dark" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 1536 512">
<defs>
<linearGradient id="linear-gradient" x1="110.25" y1="213.3" x2="496.14" y2="436.09" gradientUnits="userSpaceOnUse">
<stop offset="0" stop-color="#aa5cc3"/>
<stop offset="1" stop-color="#00a4dc"/>
</linearGradient>
</defs>
<title>banner-dark</title>
<g id="banner-dark">
<g id="banner-dark-icon">
<path id="inner-shape" d="M261.42,201.62c-20.44,0-86.24,119.29-76.2,139.43s142.48,19.92,152.4,0S281.86,201.63,261.42,201.62Z" fill="url(#linear-gradient)"/>
<path id="outer-shape" d="M261.42,23.3C199.83,23.3,1.57,382.73,31.8,443.43s429.34,60,459.24,0S323,23.3,261.42,23.3ZM411.9,390.76c-19.59,39.33-281.08,39.77-300.9,0S221.1,115.48,261.45,115.48,431.49,351.42,411.9,390.76Z" fill="url(#linear-gradient)"/>
</g>
<g id="jellyfin-light-outlines" style="isolation:isolate" transform="translate(43.8)">
<path d="M556.64,350.75a67,67,0,0,1-22.87-27.47,8.91,8.91,0,0,1-1.49-4.75,7.42,7.42,0,0,1,2.83-5.94,9.25,9.25,0,0,1,6.09-2.38c3.16,0,5.94,1.69,8.31,5.05a48.09,48.09,0,0,0,16.34,20.34,40.59,40.59,0,0,0,24,7.58q20.51,0,33.27-12.62t12.77-33.12V159a8.44,8.44,0,0,1,2.67-6.39,9.56,9.56,0,0,1,6.83-2.52,9,9,0,0,1,6.68,2.52,8.7,8.7,0,0,1,2.53,6.39v138.4a64.7,64.7,0,0,1-8.32,32.67,59,59,0,0,1-23,22.72Q608.62,361,589.9,361A57.21,57.21,0,0,1,556.64,350.75Z" fill="#fff"/>
<path d="M831.66,279.47a8.77,8.77,0,0,1-6.24,2.53H713.16q0,17.82,7.27,31.92a54.91,54.91,0,0,0,20.79,22.28q13.51,8.18,31.93,8.17a54,54,0,0,0,25.54-5.94,52.7,52.7,0,0,0,18.12-15.15,10,10,0,0,1,6.24-2.67,8.14,8.14,0,0,1,7.72,7.72,8.81,8.81,0,0,1-3,6.24,74.7,74.7,0,0,1-23.91,19A65.56,65.56,0,0,1,773.45,361q-22.87,0-40.4-9.8a69.51,69.51,0,0,1-27.32-27.48q-9.79-17.66-9.8-40.83,0-24.36,9.65-42.62t25.69-27.92a65.2,65.2,0,0,1,34.16-9.65A70,70,0,0,1,798.84,211a65.78,65.78,0,0,1,25.39,24.36q9.81,16,10.1,38A8.07,8.07,0,0,1,831.66,279.47ZM733.5,231.8Q718.8,243.68,714.64,266H815.92v-2.38A46.91,46.91,0,0,0,807,240.27a48.47,48.47,0,0,0-18.56-15.15,54,54,0,0,0-23-5.2Q748.2,219.92,733.5,231.8Z" fill="#fff"/>
<path d="M888.24,355.5a8.92,8.92,0,0,1-15.3-6.38v-202a8.91,8.91,0,1,1,17.82,0v202A8.65,8.65,0,0,1,888.24,355.5Z" fill="#fff"/>
<path d="M956.55,355.5a8.92,8.92,0,0,1-15.3-6.38v-202a8.91,8.91,0,1,1,17.82,0v202A8.65,8.65,0,0,1,956.55,355.5Z" fill="#fff"/>
<path d="M1122.86,206.11a8.7,8.7,0,0,1,2.53,6.39v131q0,23.44-9.21,40.09a61.58,61.58,0,0,1-25.54,25.25q-16.34,8.61-36.83,8.61a96.73,96.73,0,0,1-23.31-2.68,61.72,61.72,0,0,1-18-7.12q-6.24-3.87-6.24-8.62a17.94,17.94,0,0,1,.6-3,8.06,8.06,0,0,1,3-4.45,7.49,7.49,0,0,1,4.45-1.49,7.91,7.91,0,0,1,3.56.89q19,10.39,36.24,10.4,24.65,0,39.06-15.44t14.4-42.18V333.38a54.37,54.37,0,0,1-21.38,20,62.55,62.55,0,0,1-30.3,7.58q-25.83,0-39.2-15.45t-13.37-41.87V212.5a8.91,8.91,0,1,1,17.82,0V301q0,21.39,9.36,32.38t29.25,11a48,48,0,0,0,23.32-6.09,49.88,49.88,0,0,0,17.82-16,37.44,37.44,0,0,0,6.68-21.24V212.5a9,9,0,0,1,15.29-6.39Z" fill="#fff"/>
<path d="M1210.18,161.41q-5.21,6.24-5.2,17.23v30.59h33.27a8.19,8.19,0,0,1,5.79,2.38,8.26,8.26,0,0,1,0,11.88,8.22,8.22,0,0,1-5.79,2.37H1205V349.12a8.91,8.91,0,1,1-17.82,0V225.86h-21.68a7.83,7.83,0,0,1-5.94-2.52,8.21,8.21,0,0,1-2.37-5.79,8,8,0,0,1,2.37-6.09,8.33,8.33,0,0,1,5.94-2.23h21.68V178.64q0-18.7,10.84-29t29-10.24a46.1,46.1,0,0,1,15.45,2.52q7.13,2.53,7.12,8.17a8.07,8.07,0,0,1-2.37,5.94,7.37,7.37,0,0,1-5.35,2.37,18.81,18.81,0,0,1-6.53-1.48,42,42,0,0,0-10.4-1.78Q1215.37,155.18,1210.18,161.41ZM1276,180.87c-2.19-1.88-3.27-4.61-3.27-8.17v-3q0-5.34,3.41-8.17t9.36-2.82q11.88,0,11.88,11v3c0,3.56-1,6.29-3.12,8.17s-5.1,2.82-9.06,2.82S1278.14,182.75,1276,180.87Zm15.59,174.63a8.92,8.92,0,0,1-15.3-6.38V212.5a8.91,8.91,0,1,1,17.82,0V349.12A8.65,8.65,0,0,1,1291.56,355.5Z" fill="#fff"/>
<path d="M1452.53,218.88q12.92,16.2,12.92,42.92v87.32a8.4,8.4,0,0,1-2.67,6.38,8.8,8.8,0,0,1-6.24,2.53,8.64,8.64,0,0,1-8.91-8.91V262.69q0-19.31-9.65-31.33t-29.85-12a53.28,53.28,0,0,0-42.77,21.83,36.24,36.24,0,0,0-7.13,21.53v86.43a8.91,8.91,0,1,1-17.82,0V216.06a8.91,8.91,0,1,1,17.82,0V232.4q8-12.77,23-21.24A61.84,61.84,0,0,1,1412,202.7Q1439.61,202.7,1452.53,218.88Z" fill="#fff"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.3 KiB

View File

@@ -4,7 +4,10 @@ import TvdbLogo from '../../assets/services/tvdb.svg';
import ImdbLogo from '../../assets/services/imdb.svg';
import RTLogo from '../../assets/services/rt.svg';
import PlexLogo from '../../assets/services/plex.svg';
import JellyfinLogo from '../../assets/services/jellyfin.svg';
import { MediaType } from '../../../server/constants/media';
import useSettings from '../../hooks/useSettings';
import { MediaServerType } from '../../../server/constants/server';
interface ExternalLinkBlockProps {
mediaType: 'movie' | 'tv';
@@ -12,7 +15,7 @@ interface ExternalLinkBlockProps {
tvdbId?: number;
imdbId?: string;
rtUrl?: string;
plexUrl?: string;
mediaUrl?: string;
}
const ExternalLinkBlock: React.FC<ExternalLinkBlockProps> = ({
@@ -21,18 +24,27 @@ const ExternalLinkBlock: React.FC<ExternalLinkBlockProps> = ({
tvdbId,
imdbId,
rtUrl,
plexUrl,
mediaUrl,
}) => {
const settings = useSettings();
return (
<div className="flex items-center justify-end">
{plexUrl && (
{mediaUrl && (
<a
href={plexUrl}
className="w-8 mx-2 transition duration-300 opacity-50 hover:opacity-100"
href={mediaUrl}
className={`${
settings.currentSettings.mediaServerType === MediaServerType.PLEX
? 'w-8'
: 'w-14'
} mx-2 transition duration-300 opacity-50 hover:opacity-100`}
target="_blank"
rel="noreferrer"
>
<PlexLogo />
{settings.currentSettings.mediaServerType === MediaServerType.PLEX ? (
<PlexLogo />
) : (
<JellyfinLogo />
)}
</a>
)}
{tmdbId && (

View File

@@ -35,11 +35,8 @@ import ConfirmButton from '../Common/ConfirmButton';
import DownloadBlock from '../DownloadBlock';
import PageTitle from '../Common/PageTitle';
import useSettings from '../../hooks/useSettings';
<<<<<<< HEAD
import PlayButton, { PlayButtonLink } from '../Common/PlayButton';
=======
import { MediaServerType } from '../../../server/constants/server';
>>>>>>> 2fe4add... feat(rebase): rebase
const messages = defineMessages({
releasedate: 'Release Date',
@@ -117,22 +114,28 @@ const MovieDetails: React.FC<MovieDetailsProps> = ({ movie }) => {
const mediaLinks: PlayButtonLink[] = [];
if (data.mediaInfo?.plexUrl) {
if (data.mediaInfo?.mediaUrl) {
mediaLinks.push({
text: intl.formatMessage(messages.playonplex),
url: data.mediaInfo?.plexUrl,
text:
settings.currentSettings.mediaServerType === MediaServerType.JELLYFIN
? intl.formatMessage(messages.play, { mediaServerName: 'Jellyfin' })
: intl.formatMessage(messages.play, { mediaServerName: 'Plex' }),
url: data.mediaInfo?.mediaUrl,
});
}
if (
data.mediaInfo?.plexUrl4k &&
hasPermission([Permission.REQUEST_4K, Permission.REQUEST_4K_MOVIE], {
data.mediaInfo?.mediaUrl4k &&
hasPermission([Permission.REQUEST_4K, Permission.REQUEST_4K_TV], {
type: 'or',
})
) {
mediaLinks.push({
text: intl.formatMessage(messages.play4konplex),
url: data.mediaInfo?.plexUrl4k,
text:
settings.currentSettings.mediaServerType === MediaServerType.JELLYFIN
? intl.formatMessage(messages.play4k, { mediaServerName: 'Jellyfin' })
: intl.formatMessage(messages.play4k, { mediaServerName: 'Plex' }),
url: data.mediaInfo?.mediaUrl4k,
});
}
@@ -451,117 +454,9 @@ const MovieDetails: React.FC<MovieDetailsProps> = ({ movie }) => {
</span>
</div>
<div className="relative z-10 flex flex-wrap justify-center flex-shrink-0 mt-4 sm:justify-end sm:flex-nowrap lg:mt-0">
<<<<<<< HEAD
<div className="mb-3 sm:mb-0">
<PlayButton links={mediaLinks} />
</div>
=======
{trailerUrl ||
data.mediaInfo?.mediaUrl ||
data.mediaInfo?.mediaUrl4k ? (
<ButtonWithDropdown
buttonType="ghost"
text={
<>
<svg
className="w-5 h-5 mr-1"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M14.752 11.168l-3.197-2.132A1 1 0 0010 9.87v4.263a1 1 0 001.555.832l3.197-2.132a1 1 0 000-1.664z"
/>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
/>
</svg>
<span>
{data.mediaInfo?.mediaUrl || data.mediaInfo?.mediaUrl4k
? intl.formatMessage(messages.play, {
mediaServerName:
settings.currentSettings.mediaServerType ===
MediaServerType.PLEX
? 'Plex'
: 'Jellyfin',
})
: data.mediaInfo?.mediaUrl4k &&
(hasPermission(Permission.REQUEST_4K) ||
hasPermission(Permission.REQUEST_4K_MOVIE))
? intl.formatMessage(messages.play4k, {
mediaServerName:
settings.currentSettings.mediaServerType ===
MediaServerType.PLEX
? 'Plex'
: 'Jellyfin',
})
: intl.formatMessage(messages.watchtrailer)}
</span>
</>
}
onClick={() => {
if (data.mediaInfo?.mediaUrl) {
window.open(data.mediaInfo?.mediaUrl, '_blank');
} else if (data.mediaInfo?.mediaUrl4k) {
window.open(data.mediaInfo?.mediaUrl4k, '_blank');
} else if (trailerUrl) {
window.open(trailerUrl, '_blank');
}
}}
>
{(
trailerUrl
? data.mediaInfo?.mediaUrl ||
(data.mediaInfo?.mediaUrl4k &&
(hasPermission(Permission.REQUEST_4K) ||
hasPermission(Permission.REQUEST_4K_MOVIE)))
: data.mediaInfo?.mediaUrl &&
data.mediaInfo?.mediaUrl4k &&
(hasPermission(Permission.REQUEST_4K) ||
hasPermission(Permission.REQUEST_4K_MOVIE))
) ? (
<>
{data.mediaInfo?.mediaUrl &&
data.mediaInfo?.mediaUrl4k &&
(hasPermission(Permission.REQUEST_4K) ||
hasPermission(Permission.REQUEST_4K_MOVIE)) && (
<ButtonWithDropdown.Item
onClick={() => {
window.open(data.mediaInfo?.mediaUrl4k, '_blank');
}}
buttonType="ghost"
>
{intl.formatMessage(messages.play4k, {
mediaServerName:
settings.currentSettings.mediaServerType ===
MediaServerType.PLEX
? 'Plex'
: 'Jellyfin',
})}
</ButtonWithDropdown.Item>
)}
{trailerUrl && (
<ButtonWithDropdown.Item
onClick={() => {
window.open(trailerUrl, '_blank');
}}
buttonType="ghost"
>
{intl.formatMessage(messages.watchtrailer)}
</ButtonWithDropdown.Item>
)}
</>
) : null}
</ButtonWithDropdown>
) : null}
>>>>>>> 2fe4add... feat(rebase): rebase
<div className="mb-3 sm:mb-0">
<RequestButton
mediaType="movie"
@@ -802,7 +697,7 @@ const MovieDetails: React.FC<MovieDetailsProps> = ({ movie }) => {
tvdbId={data.externalIds.tvdbId}
imdbId={data.externalIds.imdbId}
rtUrl={ratingData?.url}
plexUrl={data.mediaInfo?.mediaUrl ?? data.mediaInfo?.mediaUrl4k}
mediaUrl={data.mediaInfo?.mediaUrl ?? data.mediaInfo?.mediaUrl4k}
/>
</div>
</div>

View File

@@ -34,6 +34,7 @@ import DownloadBlock from '../DownloadBlock';
import PageTitle from '../Common/PageTitle';
import useSettings from '../../hooks/useSettings';
import PlayButton, { PlayButtonLink } from '../Common/PlayButton';
import { MediaServerType } from '../../../server/constants/server';
const messages = defineMessages({
firstAirDate: 'First Air Date',
@@ -112,22 +113,28 @@ const TvDetails: React.FC<TvDetailsProps> = ({ tv }) => {
const mediaLinks: PlayButtonLink[] = [];
if (data.mediaInfo?.plexUrl) {
if (data.mediaInfo?.mediaUrl) {
mediaLinks.push({
text: intl.formatMessage(messages.playonplex),
url: data.mediaInfo?.plexUrl,
text:
settings.currentSettings.mediaServerType === MediaServerType.JELLYFIN
? intl.formatMessage(messages.play, { mediaServerName: 'Jellyfin' })
: intl.formatMessage(messages.play, { mediaServerName: 'Plex' }),
url: data.mediaInfo?.mediaUrl,
});
}
if (
data.mediaInfo?.plexUrl4k &&
data.mediaInfo?.mediaUrl4k &&
hasPermission([Permission.REQUEST_4K, Permission.REQUEST_4K_TV], {
type: 'or',
})
) {
mediaLinks.push({
text: intl.formatMessage(messages.play4konplex),
url: data.mediaInfo?.plexUrl4k,
text:
settings.currentSettings.mediaServerType === MediaServerType.JELLYFIN
? intl.formatMessage(messages.play4k, { mediaServerName: 'Jellyfin' })
: intl.formatMessage(messages.play4k, { mediaServerName: 'Plex' }),
url: data.mediaInfo?.mediaUrl4k,
});
}
@@ -703,7 +710,7 @@ const TvDetails: React.FC<TvDetailsProps> = ({ tv }) => {
tvdbId={data.externalIds.tvdbId}
imdbId={data.externalIds.imdbId}
rtUrl={ratingData?.url}
plexUrl={data.mediaInfo?.mediaUrl ?? data.mediaInfo?.mediaUrl4k}
mediaUrl={data.mediaInfo?.mediaUrl ?? data.mediaInfo?.mediaUrl4k}
/>
</div>
</div>

View File

@@ -6,6 +6,7 @@ import { defineMessages, useIntl } from 'react-intl';
import { useToasts } from 'react-toast-notifications';
import useSWR from 'swr';
import { Language } from '../../../../../server/lib/settings';
import { MediaServerType } from '../../../../../server/constants/server';
import useSettings from '../../../../hooks/useSettings';
import { UserType, useUser } from '../../../../hooks/useUser';
import Error from '../../../../pages/_error';
@@ -19,7 +20,7 @@ const messages = defineMessages({
displayName: 'Display Name',
save: 'Save Changes',
saving: 'Saving…',
plexuser: 'Plex User',
mediaServerUser: '{mediaServerName} User',
localuser: 'Local User',
toastSettingsSuccess: 'Settings successfully saved!',
toastSettingsFailure: 'Something went wrong while saving settings.',
@@ -35,6 +36,7 @@ const messages = defineMessages({
const UserGeneralSettings: React.FC = () => {
const intl = useIntl();
const settings = useSettings();
const { addToast } = useToasts();
const router = useRouter();
const { user, mutate } = useUser({ id: Number(router.query.userId) });
@@ -105,13 +107,19 @@ const UserGeneralSettings: React.FC = () => {
<div className="text-label">Account Type</div>
<div className="mb-1 text-sm font-medium leading-5 text-gray-400 sm:mt-2">
<div className="flex items-center max-w-lg">
{user?.userType === UserType.PLEX ? (
{user?.userType === UserType.LOCAL ? (
<Badge badgeType="warning">
{intl.formatMessage(messages.plexuser)}
{intl.formatMessage(messages.localuser)}
</Badge>
) : (
<Badge badgeType="default">
{intl.formatMessage(messages.localuser)}
{intl.formatMessage(messages.mediaServerUser, {
mediaServerName:
settings.currentSettings.mediaServerType ===
MediaServerType.PLEX
? 'Plex'
: 'Jellyfin',
})}
</Badge>
)}
</div>