mirror of
https://github.com/jellyfin/jellyfin.org.git
synced 2026-09-03 05:30:05 +03:00
Merge pull request #85 from thornbill/downloads-redux
Redesign the downloads page to match the clients page design
This commit is contained in:
@@ -1,80 +0,0 @@
|
||||
/* stylelint-disable docusaurus/copyright-header */
|
||||
|
||||
.client__header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.client__header__start {
|
||||
flex-grow: 1;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.client__header__start h3 {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.client__header__start__badges {
|
||||
margin-left: 1rem;
|
||||
}
|
||||
|
||||
.client__footer {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.client__platform-icon {
|
||||
margin-left: 1rem;
|
||||
}
|
||||
|
||||
.client__footer .button {
|
||||
margin-left: 1rem;
|
||||
}
|
||||
|
||||
.client__footer .button:first-of-type {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
@media (max-width: 420px) {
|
||||
.client__header {
|
||||
flex-direction: column;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.client__platform-icon {
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
|
||||
.client__platform-icon:first-of-type {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
.card__body {
|
||||
padding-top: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 560px) {
|
||||
.client__header__start {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.client__header__start__badges {
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
|
||||
.client__header__start__badges:first-of-type {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
.client__footer {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.client__footer .button {
|
||||
margin: 1rem 0 0;
|
||||
}
|
||||
|
||||
.client__footer .button:first-of-type {
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,9 @@
|
||||
import React from 'react';
|
||||
|
||||
import DetailsCard from './common/DetailsCard';
|
||||
import PlatformIcon from './PlatformIcon';
|
||||
import { Client, ClientType, LicenseType } from '../data/clients';
|
||||
|
||||
import './ClientDetails.css';
|
||||
|
||||
const ClientTypeBadge = ({ clientType }: { clientType: ClientType }) => {
|
||||
if (clientType === ClientType.Official) {
|
||||
return <span className='badge badge--primary margin-right--sm'>Official</span>;
|
||||
@@ -22,36 +21,29 @@ const LicenseTypeBadge = ({ licenseType }: { licenseType: LicenseType }) => {
|
||||
};
|
||||
|
||||
const ClientDetails = ({ client }: { client: Client }) => (
|
||||
<div className='card client margin-bottom--md'>
|
||||
<div className='card__header client__header'>
|
||||
<div className='client__header__start'>
|
||||
<h3>{client.name}</h3>
|
||||
<div className='client__header__start__badges'>
|
||||
<ClientTypeBadge clientType={client.clientType} />
|
||||
<LicenseTypeBadge licenseType={client.licenseType} />
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
{client.platforms.map((platform, index) => (
|
||||
<PlatformIcon key={`${platform}-${index}`} platform={platform} size={36} className='client__platform-icon' />
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
<div className='card__body padding-top--sm'>{client.description}</div>
|
||||
<div className='card__footer client__footer'>
|
||||
{client.secondaryLinks?.map(({ id, url, name }) => (
|
||||
<a key={id} href={url} className='button button--outline button--primary'>
|
||||
{name}
|
||||
</a>
|
||||
))}
|
||||
<div style={{ flexGrow: 1 }} />
|
||||
{client.primaryLinks.map(({ id, url, name }) => (
|
||||
<a key={id} href={url} className='button button--primary'>
|
||||
{name}
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
<DetailsCard
|
||||
title={client.name}
|
||||
description={client.description}
|
||||
badges={
|
||||
<>
|
||||
<ClientTypeBadge clientType={client.clientType} />
|
||||
<LicenseTypeBadge licenseType={client.licenseType} />
|
||||
</>
|
||||
}
|
||||
icons={client.platforms.map((platform, index) => (
|
||||
<PlatformIcon key={`${platform}-${index}`} platform={platform} size={36} className='client__platform-icon' />
|
||||
))}
|
||||
primaryButtons={client.primaryLinks.map(({ id, url, name }) => (
|
||||
<a key={id} href={url} className='button button--primary'>
|
||||
{name}
|
||||
</a>
|
||||
))}
|
||||
secondaryButtons={client.secondaryLinks?.map(({ id, url, name }) => (
|
||||
<a key={id} href={url} className='button button--outline button--primary'>
|
||||
{name}
|
||||
</a>
|
||||
))}
|
||||
/>
|
||||
);
|
||||
|
||||
export default ClientDetails;
|
||||
|
||||
@@ -1,18 +1,29 @@
|
||||
import {
|
||||
Amazonfiretv,
|
||||
Android,
|
||||
Apple,
|
||||
Appletv,
|
||||
Archlinux,
|
||||
Centos,
|
||||
Debian,
|
||||
Discord,
|
||||
Docker,
|
||||
Dotnet,
|
||||
Fedora,
|
||||
Gentoo,
|
||||
Ios,
|
||||
Kodi,
|
||||
Lg,
|
||||
Linux,
|
||||
Roku,
|
||||
Sailfishos
|
||||
Sailfishos,
|
||||
Ubuntu,
|
||||
Windows
|
||||
} from '@icons-pack/react-simple-icons';
|
||||
import clsx from 'clsx';
|
||||
import React from 'react';
|
||||
|
||||
import { Platform } from '../data/clients';
|
||||
import Platform from '../data/platform';
|
||||
import Desktop from '../../static/images/icons/monitor.svg';
|
||||
import Web from '../../static/images/icons/web.svg';
|
||||
|
||||
@@ -28,28 +39,56 @@ const PlatformIcon = ({
|
||||
className = clsx(className, 'fill--white');
|
||||
|
||||
switch (platform) {
|
||||
// TODO: AndroidTV should have a unique icon
|
||||
case Platform.Android:
|
||||
case Platform.AndroidTV:
|
||||
return <Android size={size} className={className} />;
|
||||
|
||||
case Platform.Arch:
|
||||
return <Archlinux size={size} className={className} />;
|
||||
|
||||
case Platform.Browser:
|
||||
return <Web width={size} height={size} className={className} />;
|
||||
|
||||
case Platform.CentOS:
|
||||
return <Centos size={size} className={className} />;
|
||||
|
||||
case Platform.Desktop:
|
||||
return <Desktop width={size} height={size} className={className} />;
|
||||
|
||||
case Platform.Debian:
|
||||
return <Debian size={size} className={className} />;
|
||||
|
||||
case Platform.Discord:
|
||||
return <Discord size={size} className={className} />;
|
||||
|
||||
case Platform.Docker:
|
||||
return <Docker size={size} className={className} />;
|
||||
|
||||
case Platform.DotNet:
|
||||
return <Dotnet size={size} className={className} />;
|
||||
|
||||
case Platform.Fedora:
|
||||
return <Fedora size={size} className={className} />;
|
||||
|
||||
case Platform.FireOS:
|
||||
return <Amazonfiretv size={size} className={className} />;
|
||||
|
||||
case Platform.Gentoo:
|
||||
return <Gentoo size={size} className={className} />;
|
||||
|
||||
case Platform.IOS:
|
||||
return <Ios size={size} className={className} />;
|
||||
|
||||
case Platform.Kodi:
|
||||
return <Kodi size={size} className={className} />;
|
||||
|
||||
case Platform.Linux:
|
||||
return <Linux size={size} className={className} />;
|
||||
|
||||
case Platform.MacOS:
|
||||
return <Apple size={size} className={className} />;
|
||||
|
||||
case Platform.Roku:
|
||||
return <Roku size={size} className={className} />;
|
||||
|
||||
@@ -59,9 +98,15 @@ const PlatformIcon = ({
|
||||
case Platform.TVOS:
|
||||
return <Appletv size={size} className={className} />;
|
||||
|
||||
case Platform.Ubuntu:
|
||||
return <Ubuntu size={size} className={className} />;
|
||||
|
||||
case Platform.WebOS:
|
||||
return <Lg size={size} className={className} />;
|
||||
|
||||
case Platform.Windows:
|
||||
return <Windows size={size} className={className} />;
|
||||
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
/* stylelint-disable docusaurus/copyright-header */
|
||||
|
||||
.details-card__header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.details-card__header__start {
|
||||
flex-grow: 1;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.details-card__header__start h3 {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.details-card__header__start__badges {
|
||||
margin-left: 1rem;
|
||||
}
|
||||
|
||||
.details-card__header__start__badges .badge {
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.details-card__footer__buttons {
|
||||
display: flex;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
.details-card__footer .row {
|
||||
margin-top: var(--ifm-card-vertical-spacing);
|
||||
}
|
||||
|
||||
.details-card__footer .row:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.details-card__icons > * {
|
||||
margin-left: 1rem;
|
||||
}
|
||||
|
||||
.details-card__footer .button {
|
||||
margin-left: 1rem;
|
||||
}
|
||||
|
||||
.details-card__footer .button:first-child {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
@media (max-width: 420px) {
|
||||
.details-card__header {
|
||||
flex-direction: column;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.details-card__icons > * {
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
|
||||
.details-card__icons > *:first-child {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
.details-card .card__body {
|
||||
padding-top: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 560px) {
|
||||
.details-card__header__start {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.details-card__header__start__badges {
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
|
||||
.details-card__header__start__badges:first-of-type {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
.details-card__footer__buttons {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.details-card__footer .button {
|
||||
margin: 1rem 0 0;
|
||||
}
|
||||
|
||||
.details-card__footer .button:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
import React, { FunctionComponent, ReactNode } from 'react';
|
||||
|
||||
import './DetailsCard.css';
|
||||
|
||||
type DetailsCardProps = {
|
||||
title: string;
|
||||
description: ReactNode;
|
||||
badges?: ReactNode;
|
||||
icons?: ReactNode;
|
||||
primaryButtons?: Array<ReactNode>;
|
||||
secondaryButtons?: Array<ReactNode>;
|
||||
footerDetails?: ReactNode;
|
||||
};
|
||||
|
||||
const DetailsCard: FunctionComponent<DetailsCardProps> = ({
|
||||
title,
|
||||
description,
|
||||
badges = [],
|
||||
icons = [],
|
||||
primaryButtons = [],
|
||||
secondaryButtons = [],
|
||||
footerDetails
|
||||
}) => (
|
||||
<div className='card details-card margin-bottom--md'>
|
||||
<div className='card__header details-card__header'>
|
||||
<div className='details-card__header__start'>
|
||||
<h3>{title}</h3>
|
||||
<div className='details-card__header__start__badges'>{badges}</div>
|
||||
</div>
|
||||
<div className='details-card__icons'>{icons}</div>
|
||||
</div>
|
||||
<div className='card__body padding-top--sm'>{description}</div>
|
||||
<div className='card__footer details-card__footer container'>
|
||||
<div className='row'>
|
||||
<div className='details-card__footer__buttons col'>
|
||||
{secondaryButtons}
|
||||
<div style={{ flex: 1 }} />
|
||||
{primaryButtons}
|
||||
</div>
|
||||
</div>
|
||||
{footerDetails && (
|
||||
<div className='row'>
|
||||
<div className='col'>{footerDetails}</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
export default DetailsCard;
|
||||
@@ -0,0 +1,120 @@
|
||||
import React, { Dispatch, SetStateAction } from 'react';
|
||||
import clsx from 'clsx';
|
||||
|
||||
import DetailsCard from '../common/DetailsCard';
|
||||
import { Download, DownloadStatus, Feature } from '../../data/downloads';
|
||||
import PlatformIcon from '../PlatformIcon';
|
||||
|
||||
type DownloadButtonProps = {
|
||||
name: string;
|
||||
url?: string;
|
||||
onClick?(): void;
|
||||
active?: boolean;
|
||||
primary?: boolean;
|
||||
outline?: boolean;
|
||||
};
|
||||
|
||||
const DownloadButton = ({
|
||||
name,
|
||||
url,
|
||||
onClick,
|
||||
active = false,
|
||||
primary = true,
|
||||
outline = false
|
||||
}: DownloadButtonProps) => {
|
||||
const className = clsx('button', {
|
||||
'button--active': active,
|
||||
'button--primary': primary,
|
||||
'button--secondary': !primary,
|
||||
'button--outline': outline
|
||||
});
|
||||
|
||||
if (url) {
|
||||
return (
|
||||
<a href={url} className={className}>
|
||||
{name}
|
||||
</a>
|
||||
);
|
||||
} else if (onClick) {
|
||||
return (
|
||||
<button onClick={onClick} className={className}>
|
||||
{name}
|
||||
</button>
|
||||
);
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
const StatusBadge = ({ status }: { status: DownloadStatus }) => {
|
||||
if (status === DownloadStatus.Official) {
|
||||
return <span className='badge badge--primary margin-right--sm'>Official</span>;
|
||||
} else if (status === DownloadStatus.Community) {
|
||||
return <span className='badge badge--secondary margin-right--sm'>Community</span>;
|
||||
} else if (status === DownloadStatus.OsPackage) {
|
||||
return <span className='badge badge--info margin-right--sm'>OS Package</span>;
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
const FfmpegBadge = ({ features }: { features: Array<Feature> }) => {
|
||||
if (!features.includes(Feature.CustomFfmpeg)) {
|
||||
return (
|
||||
<span
|
||||
className='badge badge--warning margin-right--sm'
|
||||
title='Jellyfin's custom build of ffmpeg is not available for this platform. Some features like tonemapping may
|
||||
not work correctly without this.'
|
||||
>
|
||||
Custom ffmpeg Unavailable
|
||||
</span>
|
||||
);
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
type DownloadDetailsProps = {
|
||||
download: Download;
|
||||
isStableLinks: boolean;
|
||||
activeButton?: string;
|
||||
setActiveButton: Dispatch<SetStateAction<string>>;
|
||||
};
|
||||
|
||||
const DownloadDetails = ({ download, isStableLinks, activeButton, setActiveButton }: DownloadDetailsProps) => (
|
||||
<DetailsCard
|
||||
title={download.name}
|
||||
description={download.description}
|
||||
badges={
|
||||
<>
|
||||
<StatusBadge status={download.status} />
|
||||
<FfmpegBadge features={download.features} />
|
||||
</>
|
||||
}
|
||||
icons={download.platforms.map((platform, index) => (
|
||||
<PlatformIcon key={`${platform}-${index}`} platform={platform} size={36} />
|
||||
))}
|
||||
primaryButtons={
|
||||
!isStableLinks && download.unstableButtons.length === 0
|
||||
? ['Unstable Unavailable']
|
||||
: (isStableLinks ? download.stableButtons : download.unstableButtons).map((button) => (
|
||||
<DownloadButton
|
||||
key={button.id}
|
||||
name={button.name || 'Downloads'}
|
||||
url={button.url}
|
||||
onClick={() => {
|
||||
setActiveButton(button.id);
|
||||
}}
|
||||
active={activeButton === button.id}
|
||||
/>
|
||||
))
|
||||
}
|
||||
secondaryButtons={download.otherButtons.map((button) => (
|
||||
<DownloadButton key={button.id} name={button.name || 'All Versions'} url={button.url} outline />
|
||||
))}
|
||||
footerDetails={
|
||||
[...download.stableButtons, ...download.unstableButtons, ...download.otherButtons].find(
|
||||
(button) => button.id === activeButton
|
||||
)?.details
|
||||
}
|
||||
/>
|
||||
);
|
||||
|
||||
export default DownloadDetails;
|
||||
+17
-11
@@ -5,20 +5,20 @@
|
||||
* work well for content-centric websites.
|
||||
*/
|
||||
|
||||
html {
|
||||
html {
|
||||
font-size: 15px;
|
||||
line-height: 1.7;
|
||||
font-weight: 400;
|
||||
text-rendering: optimizeLegibility;
|
||||
-moz-font-feature-settings: "liga" on;
|
||||
font-feature-settings: "liga";
|
||||
-moz-font-feature-settings: 'liga' on;
|
||||
font-feature-settings: 'liga';
|
||||
}
|
||||
|
||||
:root {
|
||||
--ifm-font-color-base: #ffffff;
|
||||
--ifm-button-color: #ffffff;
|
||||
--ifm-button-border-radius: 30px;
|
||||
--ifm-color-primary: #007CA6;
|
||||
--ifm-color-primary: #007ca6;
|
||||
--ifm-color-primary-dark: #00749b;
|
||||
--ifm-color-primary-darker: #006b90;
|
||||
--ifm-color-primary-darkest: #006385;
|
||||
@@ -32,7 +32,7 @@
|
||||
--ifm-card-background-color: #172138;
|
||||
--ifm-footer-background-color: #333c44;
|
||||
--ifm-pills-color-background-active: #172138;
|
||||
--ifm-font-family-base: "Noto Sans", sans-serif;
|
||||
--ifm-font-family-base: 'Noto Sans', sans-serif;
|
||||
--ifm-h1-font-size: 2.074em;
|
||||
--ifm-h2-font-size: 1.728em;
|
||||
--ifm-footer-link-color: #ffffff;
|
||||
@@ -48,6 +48,12 @@ h2 {
|
||||
line-height: 1.35;
|
||||
}
|
||||
|
||||
/* The default text color for this badge is very low contrast */
|
||||
.badge--info,
|
||||
.badge--warning {
|
||||
color: var(--ifm-color-black);
|
||||
}
|
||||
|
||||
.docusaurus-highlight-code-line {
|
||||
background-color: rgb(72, 77, 91);
|
||||
display: block;
|
||||
@@ -60,21 +66,21 @@ h2 {
|
||||
}
|
||||
|
||||
.landing-section {
|
||||
padding:24pt 0
|
||||
padding: 24pt 0;
|
||||
}
|
||||
|
||||
.landing-section:first-child {
|
||||
border-top:1px solid #eee;
|
||||
border-top: 1px solid #eee;
|
||||
}
|
||||
|
||||
.landing-section:nth-child(even) {
|
||||
background-color:#172138;
|
||||
border-top:1px solid #eee;
|
||||
border-bottom:1px solid #eee
|
||||
background-color: #172138;
|
||||
border-top: 1px solid #eee;
|
||||
border-bottom: 1px solid #eee;
|
||||
}
|
||||
|
||||
.landing-section:last-child {
|
||||
border-bottom:1px solid #eee
|
||||
border-bottom: 1px solid #eee;
|
||||
}
|
||||
|
||||
.display--flex {
|
||||
|
||||
+2
-15
@@ -1,3 +1,5 @@
|
||||
import Platform from './platform';
|
||||
|
||||
export enum ClientType {
|
||||
Official,
|
||||
ThirdParty
|
||||
@@ -14,21 +16,6 @@ export enum LicenseType {
|
||||
Proprietary
|
||||
}
|
||||
|
||||
export enum Platform {
|
||||
Android,
|
||||
AndroidTV,
|
||||
Browser,
|
||||
Desktop,
|
||||
Discord,
|
||||
FireOS,
|
||||
IOS,
|
||||
Kodi,
|
||||
Roku,
|
||||
SailfishOS,
|
||||
TVOS,
|
||||
WebOS
|
||||
}
|
||||
|
||||
type Link = {
|
||||
id: string;
|
||||
name: string;
|
||||
|
||||
@@ -0,0 +1,347 @@
|
||||
import React, { ReactNode } from 'react';
|
||||
|
||||
import Platform from './platform';
|
||||
|
||||
export enum DownloadStatus {
|
||||
Official,
|
||||
Community,
|
||||
OsPackage
|
||||
}
|
||||
|
||||
export enum Feature {
|
||||
CustomFfmpeg
|
||||
}
|
||||
|
||||
export enum OsType {
|
||||
Docker,
|
||||
Linux,
|
||||
MacOS,
|
||||
Windows
|
||||
}
|
||||
|
||||
export type Button = {
|
||||
id: string;
|
||||
name?: string;
|
||||
url?: string;
|
||||
details?: ReactNode;
|
||||
};
|
||||
|
||||
export type Download = {
|
||||
id: string;
|
||||
name: string;
|
||||
description: ReactNode;
|
||||
osTypes: Array<OsType>;
|
||||
status: DownloadStatus;
|
||||
features: Array<Feature>;
|
||||
platforms: Array<Platform>;
|
||||
stableButtons: Array<Button>;
|
||||
unstableButtons: Array<Button>;
|
||||
otherButtons: Array<Button>;
|
||||
};
|
||||
|
||||
export const Downloads: Array<Download> = [
|
||||
{
|
||||
id: 'debian',
|
||||
name: 'Debian and Ubuntu',
|
||||
osTypes: [OsType.Linux],
|
||||
status: DownloadStatus.Official,
|
||||
features: [Feature.CustomFfmpeg],
|
||||
platforms: [Platform.Debian, Platform.Ubuntu],
|
||||
description: 'Install Jellyfin via our Apt repository or via manual archives (.deb).',
|
||||
stableButtons: [
|
||||
{
|
||||
id: 'debian-stable-button',
|
||||
name: 'Install Instructions',
|
||||
details: (
|
||||
<pre className='margin-bottom--none'>
|
||||
<code>
|
||||
{`sudo apt install curl gnupg
|
||||
curl -fsSL https://repo.jellyfin.org/ubuntu/jellyfin_team.gpg.key | sudo gpg --dearmor -o /etc/apt/trusted.gpg.d/jellyfin.gpg
|
||||
echo "deb [arch=$( dpkg --print-architecture )] https://repo.jellyfin.org/$( awk -F'=' '/^ID=/{ print $NF }' /etc/os-release ) $( awk -F'=' '/^VERSION_CODENAME=/{ print $NF }' /etc/os-release ) main" | sudo tee /etc/apt/sources.list.d/jellyfin.list
|
||||
sudo apt update
|
||||
sudo apt install jellyfin`}
|
||||
</code>
|
||||
</pre>
|
||||
)
|
||||
}
|
||||
],
|
||||
unstableButtons: [
|
||||
{
|
||||
id: 'debian-unstable-button',
|
||||
name: 'Install Instructions',
|
||||
details: (
|
||||
<pre className='margin-bottom--none'>
|
||||
<code>
|
||||
{`sudo apt install curl gnupg
|
||||
curl -fsSL https://repo.jellyfin.org/ubuntu/jellyfin_team.gpg.key | gpg --dearmor -o /etc/apt/trusted.gpg.d/jellyfin.gpg
|
||||
echo "deb [arch=$( dpkg --print-architecture )] https://repo.jellyfin.org/$( awk -F'=' '/^ID=/{ print $NF }' /etc/os-release ) $( awk -F'=' '/^VERSION_CODENAME=/{ print $NF }' /etc/os-release ) main unstable" | sudo tee /etc/apt/sources.list.d/jellyfin.list
|
||||
sudo apt update
|
||||
sudo apt install jellyfin`}
|
||||
</code>
|
||||
</pre>
|
||||
)
|
||||
}
|
||||
],
|
||||
otherButtons: [
|
||||
{
|
||||
id: 'debian-all-link',
|
||||
name: 'All Debian Versions',
|
||||
url: 'https://repo.jellyfin.org/releases/server/debian/versions'
|
||||
},
|
||||
{
|
||||
id: 'ubuntu-all-link',
|
||||
name: 'All Ubuntu Versions',
|
||||
url: 'https://repo.jellyfin.org/releases/server/ubuntu/versions'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'arch',
|
||||
name: 'Arch Linux',
|
||||
osTypes: [OsType.Linux],
|
||||
status: DownloadStatus.Community,
|
||||
features: [Feature.CustomFfmpeg],
|
||||
platforms: [Platform.Arch],
|
||||
description: 'Install Jellyfin via the Arch User Repository.',
|
||||
stableButtons: [
|
||||
{
|
||||
id: 'arch-stable-button',
|
||||
name: 'Install Instructions',
|
||||
details: (
|
||||
<>
|
||||
<pre>
|
||||
<code>
|
||||
{`git clone https://aur.archlinux.org/jellyfin.git
|
||||
cd jellyfin
|
||||
makepkg -si`}
|
||||
</code>
|
||||
</pre>
|
||||
<p>
|
||||
<b>Note:</b> The third command should give you output similar to{' '}
|
||||
<code>deb [arch=(architecture)] https://repo.jellyfin.org/(distribution) (release) main</code>. We support{' '}
|
||||
<code>amd64</code>, <code>armhf</code>, and <code>arm64</code> for architectures, <code>debian</code> and{' '}
|
||||
<code>ubuntu</code> for distributions, <code>buster</code> and <code>bullseye</code> for Debian releases
|
||||
and <code>bionic</code>, <code>focal</code>, <code>impish</code> and <code>jammy</code> for Ubuntu
|
||||
releases. If you see something different in your output, you might need to manually modify it. Use the
|
||||
closest equivalent Debian or Ubuntu version instead.
|
||||
</p>
|
||||
<p className='margin-bottom--none'>
|
||||
Once installed, Jellyfin will be running as a service. Manage it with{' '}
|
||||
<code>{'sudo systemctl {action} jellyfin.service'}</code> or{' '}
|
||||
<code>{'sudo service jellyfin {action}'}</code>.
|
||||
</p>
|
||||
</>
|
||||
)
|
||||
}
|
||||
],
|
||||
unstableButtons: [
|
||||
{
|
||||
id: 'arch-unstable-button',
|
||||
name: 'Install Instructions',
|
||||
details: (
|
||||
<>
|
||||
<pre>
|
||||
<code>
|
||||
{`git clone https://aur.archlinux.org/jellyfin-git.git
|
||||
cd jellyfin-git
|
||||
makepkg -si`}
|
||||
</code>
|
||||
</pre>
|
||||
<p>
|
||||
<b>Note:</b> The third command should give you output similar to{' '}
|
||||
<code>deb [arch=(architecture)] https://repo.jellyfin.org/(distribution) (release) main</code>. We support{' '}
|
||||
<code>amd64</code>, <code>armhf</code>, and <code>arm64</code> for architectures, <code>debian</code> and{' '}
|
||||
<code>ubuntu</code> for distributions, <code>buster</code> and <code>bullseye</code> for Debian releases
|
||||
and <code>bionic</code>, <code>focal</code>, <code>impish</code> and <code>jammy</code> for Ubuntu
|
||||
releases. If you see something different in your output, you might need to manually modify it. Use the
|
||||
closest equivalent Debian or Ubuntu version instead.
|
||||
</p>
|
||||
<p>
|
||||
<b>Note:</b> Both the <code>main</code> and <code>unstable</code> are needed as the{' '}
|
||||
<code>jellyfin-ffmpeg</code> package is only in the <code>main</code> component.
|
||||
</p>
|
||||
<p className='margin-bottom--none'>
|
||||
Once installed, Jellyfin will be running as a service. Manage it with{' '}
|
||||
<code>{'sudo systemctl {action} jellyfin.service'}</code> or{' '}
|
||||
<code>{'sudo service jellyfin {action}'}</code>.
|
||||
</p>
|
||||
</>
|
||||
)
|
||||
}
|
||||
],
|
||||
otherButtons: [
|
||||
{
|
||||
id: 'arch-aur-link',
|
||||
name: 'AUR',
|
||||
url: 'https://aur.archlinux.org/packages/?K=jellyfin'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'fedora',
|
||||
name: 'Fedora and CentOS',
|
||||
osTypes: [OsType.Linux],
|
||||
status: DownloadStatus.Community,
|
||||
features: [],
|
||||
platforms: [Platform.Fedora, Platform.CentOS],
|
||||
description: 'RPM archives for both Fedora and CentOS are provided.',
|
||||
stableButtons: [
|
||||
{
|
||||
id: 'fedora-stable-link',
|
||||
name: 'Fedora Downloads',
|
||||
url: 'https://repo.jellyfin.org/releases/server/fedora/stable'
|
||||
},
|
||||
{
|
||||
id: 'centos-stable-link',
|
||||
name: 'CentOS Downloads',
|
||||
url: 'https://repo.jellyfin.org/releases/server/centos/stable'
|
||||
}
|
||||
],
|
||||
unstableButtons: [
|
||||
{
|
||||
id: 'fedora-unstable-link',
|
||||
name: 'Fedora Downloads',
|
||||
url: 'https://repo.jellyfin.org/releases/server/fedora/unstable'
|
||||
},
|
||||
{
|
||||
id: 'centos-unstable-link',
|
||||
name: 'CentOS Downloads',
|
||||
url: 'https://repo.jellyfin.org/releases/server/centos/unstable'
|
||||
}
|
||||
],
|
||||
otherButtons: [
|
||||
{
|
||||
id: 'fedora-all-link',
|
||||
name: 'All Fedora Versions',
|
||||
url: 'https://repo.jellyfin.org/releases/server/fedora/versions'
|
||||
},
|
||||
{
|
||||
id: 'centos-all-link',
|
||||
name: 'All CentOS Versions',
|
||||
url: 'https://repo.jellyfin.org/releases/server/centos/versions'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'gentoo',
|
||||
name: 'Gentoo Linux',
|
||||
osTypes: [OsType.Linux],
|
||||
status: DownloadStatus.OsPackage,
|
||||
features: [],
|
||||
platforms: [Platform.Gentoo],
|
||||
description: 'Install Jellyfin via the Gentoo Repository.',
|
||||
stableButtons: [
|
||||
{
|
||||
id: 'gentoo-stable-button',
|
||||
name: 'Install Instructions',
|
||||
details: (
|
||||
<>
|
||||
<pre>
|
||||
<code>emerge www-apps/jellyfin</code>
|
||||
</pre>
|
||||
<p className='margin-bottom--none'>
|
||||
Once installed, Jellyfin will be running as a service. Manage it with{' '}
|
||||
<code>{'sudo systemctl {action} jellyfin.service'}</code> or{' '}
|
||||
<code>{'sudo rc-service jellyfin {action}'}</code>
|
||||
</p>
|
||||
</>
|
||||
)
|
||||
}
|
||||
],
|
||||
unstableButtons: [],
|
||||
otherButtons: []
|
||||
},
|
||||
{
|
||||
id: 'generic-linux',
|
||||
name: 'Generic Linux',
|
||||
osTypes: [OsType.Linux],
|
||||
status: DownloadStatus.Official,
|
||||
features: [],
|
||||
platforms: [Platform.Linux],
|
||||
description: 'Linux self-contained binary TAR archives (.tar.gz) are provided.',
|
||||
stableButtons: [{ id: 'linux-stable-link', url: 'https://repo.jellyfin.org/releases/server/linux/stable' }],
|
||||
unstableButtons: [{ id: 'linux-unstable-link', url: 'https://repo.jellyfin.org/releases/server/linux/unstable' }],
|
||||
otherButtons: [{ id: 'linux-all-link', url: 'https://repo.jellyfin.org/releases/server/linux/versions' }]
|
||||
},
|
||||
{
|
||||
id: 'windows',
|
||||
name: 'Windows',
|
||||
osTypes: [OsType.Windows],
|
||||
status: DownloadStatus.Official,
|
||||
features: [Feature.CustomFfmpeg],
|
||||
platforms: [Platform.Windows],
|
||||
description: 'Both installers (.exe) and manual ZIP archives (.zip) are provided.',
|
||||
stableButtons: [{ id: 'windows-stable-link', url: 'https://repo.jellyfin.org/releases/server/windows/stable' }],
|
||||
unstableButtons: [
|
||||
{ id: 'windows-unstable-link', url: 'https://repo.jellyfin.org/releases/server/windows/unstable' }
|
||||
],
|
||||
otherButtons: [{ id: 'windows-all-link', url: 'https://repo.jellyfin.org/releases/server/windows/versions' }]
|
||||
},
|
||||
{
|
||||
id: 'macos',
|
||||
name: 'MacOS',
|
||||
osTypes: [OsType.MacOS],
|
||||
status: DownloadStatus.Official,
|
||||
features: [Feature.CustomFfmpeg],
|
||||
platforms: [Platform.MacOS],
|
||||
description: 'Both installers (.dmg) and manual ZIP archives (.tar.gz) are provided.',
|
||||
stableButtons: [{ id: 'macos-stable-link', url: 'https://repo.jellyfin.org/releases/server/macos/stable' }],
|
||||
unstableButtons: [{ id: 'macos-unstable-link', url: 'https://repo.jellyfin.org/releases/server/macos/unstable' }],
|
||||
otherButtons: [{ id: 'macos-all-link', url: 'https://repo.jellyfin.org/releases/server/macos/versions' }]
|
||||
},
|
||||
{
|
||||
id: 'docker',
|
||||
name: 'Docker',
|
||||
osTypes: [OsType.Docker],
|
||||
status: DownloadStatus.Official,
|
||||
features: [Feature.CustomFfmpeg],
|
||||
platforms: [Platform.Docker],
|
||||
description: (
|
||||
<>
|
||||
Run Jellyfin in Docker. Example commands store data in <code>/srv/jellyfin</code> and assume your media is
|
||||
stored under <code>/media</code>.
|
||||
</>
|
||||
),
|
||||
stableButtons: [
|
||||
{
|
||||
id: 'docker-stable-button',
|
||||
name: 'Install Instructions',
|
||||
details: (
|
||||
<pre className='margin-bottom--none'>
|
||||
<code>{`docker pull jellyfin/jellyfin:latest
|
||||
mkdir -p /srv/jellyfin/{config,cache}
|
||||
docker run -d -v /srv/jellyfin/config:/config -v /srv/jellyfin/cache:/cache -v /media:/media --net=host jellyfin/jellyfin:latest`}</code>
|
||||
</pre>
|
||||
)
|
||||
}
|
||||
],
|
||||
unstableButtons: [
|
||||
{
|
||||
id: 'docker-unstable-button',
|
||||
name: 'Install Instructions',
|
||||
details: (
|
||||
<pre className='margin-bottom--none'>
|
||||
<code>{`docker pull jellyfin/jellyfin:unstable
|
||||
mkdir -p /srv/jellyfin/{config,cache}
|
||||
docker run -d -v /srv/jellyfin/config:/config -v /srv/jellyfin/cache:/cache -v /media:/media --net=host jellyfin/jellyfin:unstable`}</code>
|
||||
</pre>
|
||||
)
|
||||
}
|
||||
],
|
||||
otherButtons: [{ id: 'docker-hub-link', name: 'Docker Hub', url: 'https://hub.docker.com/r/jellyfin/jellyfin/' }]
|
||||
},
|
||||
{
|
||||
id: 'portable',
|
||||
name: 'Portable',
|
||||
osTypes: [OsType.Linux, OsType.MacOS, OsType.Windows],
|
||||
status: DownloadStatus.Official,
|
||||
features: [],
|
||||
platforms: [Platform.DotNet],
|
||||
description: 'The portable version can be run on any system with a .NET Core runtime.',
|
||||
stableButtons: [{ id: 'portable-stable-link', url: 'https://repo.jellyfin.org/releases/server/portable/stable' }],
|
||||
unstableButtons: [
|
||||
{ id: 'portable-unstable-link', url: 'https://repo.jellyfin.org/releases/server/portable/unstable' }
|
||||
],
|
||||
otherButtons: [{ id: 'portable-all-link', url: 'https://repo.jellyfin.org/releases/server/portable/versions' }]
|
||||
}
|
||||
];
|
||||
@@ -0,0 +1,30 @@
|
||||
const enum Platform {
|
||||
// Client platforms
|
||||
Android,
|
||||
AndroidTV,
|
||||
Browser,
|
||||
Desktop,
|
||||
Discord,
|
||||
FireOS,
|
||||
IOS,
|
||||
Kodi,
|
||||
Roku,
|
||||
SailfishOS,
|
||||
TVOS,
|
||||
WebOS,
|
||||
|
||||
// Server platforms
|
||||
Arch,
|
||||
CentOS,
|
||||
Debian,
|
||||
Docker,
|
||||
DotNet,
|
||||
Fedora,
|
||||
Gentoo,
|
||||
Linux,
|
||||
MacOS,
|
||||
Ubuntu,
|
||||
Windows
|
||||
}
|
||||
|
||||
export default Platform;
|
||||
@@ -3,7 +3,8 @@ import React, { useState } from 'react';
|
||||
|
||||
import ClientDetails from '../components/ClientDetails';
|
||||
import Pill from '../components/Pill';
|
||||
import { Clients, DeviceType, Platform } from '../data/clients';
|
||||
import { Clients, DeviceType } from '../data/clients';
|
||||
import Platform from '../data/platform';
|
||||
|
||||
type ClientFilter = {
|
||||
recommended: boolean;
|
||||
|
||||
+97
-368
@@ -1,388 +1,117 @@
|
||||
import React, { useState } from 'react';
|
||||
import Layout from '@theme/Layout';
|
||||
import clsx from 'clsx';
|
||||
import Hero from '../components/Hero';
|
||||
import Admonition from '@theme-original/Admonition';
|
||||
|
||||
enum InstallOption {
|
||||
DockerStable,
|
||||
DockerUnstable,
|
||||
DebianStable,
|
||||
DebianUnstable,
|
||||
ArchStable,
|
||||
ArchUnstable
|
||||
}
|
||||
import Pill from '../components/Pill';
|
||||
import DownloadDetails from '../components/downloads/DownloadDetails';
|
||||
import { Downloads, OsType } from '../data/downloads';
|
||||
|
||||
const InstallInstructions = {
|
||||
Docker: {
|
||||
Stable: `docker pull jellyfin/jellyfin:latest
|
||||
mkdir -p /srv/jellyfin/{config,cache}
|
||||
docker run -d -v /srv/jellyfin/config:/config -v /srv/jellyfin/cache:/cache -v /media:/media --net=host jellyfin/jellyfin:latest`,
|
||||
Unstable: `docker pull jellyfin/jellyfin:unstable
|
||||
mkdir -p /srv/jellyfin/{config,cache}
|
||||
docker run -d -v /srv/jellyfin/config:/config -v /srv/jellyfin/cache:/cache -v /media:/media --net=host jellyfin/jellyfin:unstable`
|
||||
},
|
||||
Debian: {
|
||||
Stable: `sudo apt install curl gnupg
|
||||
curl -fsSL https://repo.jellyfin.org/ubuntu/jellyfin_team.gpg.key | sudo gpg --dearmor -o /etc/apt/trusted.gpg.d/jellyfin.gpg
|
||||
echo "deb [arch=$( dpkg --print-architecture )] https://repo.jellyfin.org/$( awk -F'=' '/^ID=/{ print $NF }' /etc/os-release ) $( awk -F'=' '/^VERSION_CODENAME=/{ print $NF }' /etc/os-release ) main" | sudo tee /etc/apt/sources.list.d/jellyfin.list
|
||||
sudo apt update
|
||||
sudo apt install jellyfin`,
|
||||
Unstable: `sudo apt install curl gnupg
|
||||
curl -fsSL https://repo.jellyfin.org/ubuntu/jellyfin_team.gpg.key | gpg --dearmor -o /etc/apt/trusted.gpg.d/jellyfin.gpg
|
||||
echo "deb [arch=$( dpkg --print-architecture )] https://repo.jellyfin.org/$( awk -F'=' '/^ID=/{ print $NF }' /etc/os-release ) $( awk -F'=' '/^VERSION_CODENAME=/{ print $NF }' /etc/os-release ) main unstable" | sudo tee /etc/apt/sources.list.d/jellyfin.list
|
||||
sudo apt update
|
||||
sudo apt install jellyfin`
|
||||
},
|
||||
Arch: {
|
||||
Stable: `git clone https://aur.archlinux.org/jellyfin.git
|
||||
cd jellyfin
|
||||
makepkg -si`,
|
||||
Unstable: `git clone https://aur.archlinux.org/jellyfin-git.git
|
||||
cd jellyfin-git
|
||||
makepkg -si`
|
||||
}
|
||||
};
|
||||
export default function DownloadsPage() {
|
||||
const [osType, setOsType] = useState<OsType>(OsType.Linux);
|
||||
const [isStableLinks, setIsStableLinks] = useState<boolean>(true);
|
||||
const [isStableHelpVisible, setIsStableHelpVisible] = useState<boolean>(false);
|
||||
const [activeButton, setActiveButton] = useState<string>();
|
||||
|
||||
export default function Downloads() {
|
||||
const [installOption, setInstallOption] = useState<InstallOption>(null);
|
||||
return (
|
||||
<Layout title='Downloads'>
|
||||
<Hero title='Downloads'>
|
||||
<p className='hero__text'>You can download the latest releases of Jellyfin Server below!</p>
|
||||
</Hero>
|
||||
<h1 className='text--center'>Downloads</h1>
|
||||
|
||||
<main className='margin-vert--lg'>
|
||||
<section className='container'>
|
||||
<h2>Stable or Unstable?</h2>
|
||||
<p>
|
||||
Generally, if you're a new user or value stability use the stable version. It won't change very
|
||||
often. If you want to help test the latest improvements and features and can handle some occasional
|
||||
breakage, use the unstable version. Always back up your existing configuration before testing unstable
|
||||
releases.
|
||||
</p>
|
||||
<div className='row margin-bottom--md'>
|
||||
<div className='col'>
|
||||
<ul className='pills margin-bottom--none' style={{ overflowX: 'auto' }}>
|
||||
<Pill
|
||||
active={osType === OsType.Linux}
|
||||
onClick={() => {
|
||||
setOsType(OsType.Linux);
|
||||
}}
|
||||
>
|
||||
Linux
|
||||
</Pill>
|
||||
<Pill
|
||||
active={osType === OsType.Windows}
|
||||
onClick={() => {
|
||||
setOsType(OsType.Windows);
|
||||
}}
|
||||
>
|
||||
Windows
|
||||
</Pill>
|
||||
<Pill
|
||||
active={osType === OsType.MacOS}
|
||||
onClick={() => {
|
||||
setOsType(OsType.MacOS);
|
||||
}}
|
||||
>
|
||||
macOS
|
||||
</Pill>
|
||||
<Pill
|
||||
active={osType === OsType.Docker}
|
||||
onClick={() => {
|
||||
setOsType(OsType.Docker);
|
||||
}}
|
||||
>
|
||||
Docker
|
||||
</Pill>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<h3>
|
||||
Docker
|
||||
<span className='badge badge--success margin-left--sm'>Official</span>
|
||||
</h3>
|
||||
<p>
|
||||
Run Jellyfin in Docker. Example commands store data in <code>/srv/jellyfin</code> and assume your media is
|
||||
stored under <code>/media</code>.
|
||||
</p>
|
||||
<p>
|
||||
<button
|
||||
className={clsx('button button--primary margin-right--md margin-bottom--md', {
|
||||
'button--active': installOption === InstallOption.DockerStable
|
||||
})}
|
||||
onClick={() => {
|
||||
setInstallOption(InstallOption.DockerStable);
|
||||
}}
|
||||
>
|
||||
Stable
|
||||
</button>
|
||||
<button
|
||||
className={clsx('button button--secondary margin-right--md margin-bottom--md', {
|
||||
'button--active': installOption === InstallOption.DockerUnstable
|
||||
})}
|
||||
onClick={() => {
|
||||
setInstallOption(InstallOption.DockerUnstable);
|
||||
}}
|
||||
>
|
||||
Unstable
|
||||
</button>
|
||||
<a
|
||||
href='https://hub.docker.com/r/jellyfin/jellyfin/'
|
||||
className='button button--outline button--primary margin-bottom--md'
|
||||
>
|
||||
Docker Hub
|
||||
</a>
|
||||
{installOption === InstallOption.DockerStable && (
|
||||
<pre>
|
||||
<code>{InstallInstructions.Docker.Stable}</code>
|
||||
</pre>
|
||||
)}
|
||||
{installOption === InstallOption.DockerUnstable && (
|
||||
<pre>
|
||||
<code>{InstallInstructions.Docker.Unstable}</code>
|
||||
</pre>
|
||||
)}
|
||||
</p>
|
||||
<div className='col' style={{ textAlign: 'right' }}>
|
||||
<button
|
||||
className='button button--link'
|
||||
onClick={() => {
|
||||
setIsStableHelpVisible(!isStableHelpVisible);
|
||||
}}
|
||||
style={{
|
||||
verticalAlign: 'baseline'
|
||||
}}
|
||||
>
|
||||
Help?
|
||||
</button>
|
||||
|
||||
<h3>
|
||||
Debian and Ubuntu
|
||||
<span className='badge badge--success margin-left--sm'>Official</span>
|
||||
</h3>
|
||||
<p>Install Jellyfin via our Apt repository or via manual archives (.deb).</p>
|
||||
<p>
|
||||
<button
|
||||
className={clsx('button button--primary margin-right--md margin-bottom--md', {
|
||||
'button--active': installOption === InstallOption.DebianStable
|
||||
})}
|
||||
onClick={() => {
|
||||
setInstallOption(InstallOption.DebianStable);
|
||||
}}
|
||||
>
|
||||
Stable
|
||||
</button>
|
||||
<button
|
||||
className={clsx('button button--secondary margin-right--md margin-bottom--md', {
|
||||
'button--active': installOption === InstallOption.DebianUnstable
|
||||
})}
|
||||
onClick={() => {
|
||||
setInstallOption(InstallOption.DebianUnstable);
|
||||
}}
|
||||
>
|
||||
Unstable
|
||||
</button>
|
||||
<a
|
||||
href='https://repo.jellyfin.org/releases/server/debian/versions'
|
||||
className='button button--outline button--primary margin-right--md margin-bottom--md'
|
||||
>
|
||||
All Debian Versions
|
||||
</a>
|
||||
<a
|
||||
href='https://repo.jellyfin.org/releases/server/ubuntu/versions'
|
||||
className='button button--outline button--primary margin-bottom--md'
|
||||
>
|
||||
All Ubuntu Versions
|
||||
</a>
|
||||
{installOption === InstallOption.DebianStable && (
|
||||
<pre>
|
||||
<code>{InstallInstructions.Debian.Stable}</code>
|
||||
</pre>
|
||||
)}
|
||||
{installOption === InstallOption.DebianUnstable && (
|
||||
<pre>
|
||||
<code>{InstallInstructions.Debian.Unstable}</code>
|
||||
</pre>
|
||||
)}
|
||||
</p>
|
||||
<ul className='pills margin-bottom--none' style={{ display: 'inline-flex' }}>
|
||||
<Pill
|
||||
active={!isStableLinks}
|
||||
onClick={() => {
|
||||
setIsStableLinks(false);
|
||||
setActiveButton(null);
|
||||
}}
|
||||
>
|
||||
Unstable
|
||||
</Pill>
|
||||
<Pill
|
||||
active={isStableLinks}
|
||||
onClick={() => {
|
||||
setIsStableLinks(true);
|
||||
setActiveButton(null);
|
||||
}}
|
||||
>
|
||||
Stable
|
||||
</Pill>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h3>
|
||||
Arch Linux
|
||||
<span className='badge badge--info margin-left--sm'>Community</span>
|
||||
</h3>
|
||||
<p>Install Jellyfin via the Arch User Repository.</p>
|
||||
<p>
|
||||
<button
|
||||
className={clsx('button button--primary margin-right--md margin-bottom--md', {
|
||||
'button--active': installOption === InstallOption.ArchStable
|
||||
})}
|
||||
onClick={() => {
|
||||
setInstallOption(InstallOption.ArchStable);
|
||||
}}
|
||||
>
|
||||
Stable
|
||||
</button>
|
||||
<button
|
||||
className={clsx('button button--secondary margin-right--md margin-bottom--md', {
|
||||
'button--active': installOption === InstallOption.ArchUnstable
|
||||
})}
|
||||
onClick={() => {
|
||||
setInstallOption(InstallOption.ArchUnstable);
|
||||
}}
|
||||
>
|
||||
Unstable
|
||||
</button>
|
||||
<a
|
||||
href='https://aur.archlinux.org/packages/?K=jellyfin'
|
||||
className='button button--outline button--primary margin-bottom--md'
|
||||
>
|
||||
AUR
|
||||
</a>
|
||||
{installOption === InstallOption.ArchStable && (
|
||||
<pre>
|
||||
<code>{InstallInstructions.Arch.Stable}</code>
|
||||
</pre>
|
||||
)}
|
||||
{installOption === InstallOption.ArchUnstable && (
|
||||
<pre>
|
||||
<code>{InstallInstructions.Arch.Unstable}</code>
|
||||
</pre>
|
||||
)}
|
||||
</p>
|
||||
{installOption === InstallOption.ArchStable && (
|
||||
<>
|
||||
{isStableHelpVisible && (
|
||||
<Admonition type='tip' title='Stable or Unstable?'>
|
||||
<p>
|
||||
<b>Note:</b> The third command should give you output similar to{' '}
|
||||
<code>deb [arch=(architecture)] https://repo.jellyfin.org/(distribution) (release) main</code>. We
|
||||
support <code>amd64</code>, <code>armhf</code>, and <code>arm64</code> for architectures,{' '}
|
||||
<code>debian</code> and <code>ubuntu</code> for distributions, <code>buster</code> and{' '}
|
||||
<code>bullseye</code> for Debian releases and <code>bionic</code>, <code>focal</code>,{' '}
|
||||
<code>impish</code> and <code>jammy</code> for Ubuntu releases. If you see something different in your
|
||||
output, you might need to manually modify it. Use the closest equivalent Debian or Ubuntu version
|
||||
instead.
|
||||
Generally, if you're a new user or value stability use the stable version. It won't change
|
||||
very often. If you want to help test the latest improvements and features and can handle some occasional
|
||||
breakage, use the unstable version. Always back up your existing configuration before testing unstable
|
||||
releases.
|
||||
</p>
|
||||
<p>
|
||||
Once installed, Jellyfin will be running as a service. Manage it with{' '}
|
||||
<code>{'sudo systemctl {action} jellyfin.service'}</code> or{' '}
|
||||
<code>{'sudo service jellyfin {action}'}</code>.
|
||||
</p>
|
||||
</>
|
||||
)}
|
||||
{installOption === InstallOption.ArchUnstable && (
|
||||
<>
|
||||
<p>
|
||||
<b>Note:</b> The third command should give you output similar to{' '}
|
||||
<code>deb [arch=(architecture)] https://repo.jellyfin.org/(distribution) (release) main</code>. We
|
||||
support <code>amd64</code>, <code>armhf</code>, and <code>arm64</code> for architectures,{' '}
|
||||
<code>debian</code> and <code>ubuntu</code> for distributions, <code>buster</code> and{' '}
|
||||
<code>bullseye</code> for Debian releases and <code>bionic</code>, <code>focal</code>,{' '}
|
||||
<code>impish</code> and <code>jammy</code> for Ubuntu releases. If you see something different in your
|
||||
output, you might need to manually modify it. Use the closest equivalent Debian or Ubuntu version
|
||||
instead.
|
||||
</p>
|
||||
<p>
|
||||
<b>Note:</b> Both the <code>main</code> and <code>unstable</code> are needed as the{' '}
|
||||
<code>jellyfin-ffmpeg</code> package is only in the <code>main</code> component.
|
||||
</p>
|
||||
<p>
|
||||
Once installed, Jellyfin will be running as a service. Manage it with{' '}
|
||||
<code>{'sudo systemctl {action} jellyfin.service'}</code> or{' '}
|
||||
<code>{'sudo service jellyfin {action}'}</code>.
|
||||
</p>
|
||||
</>
|
||||
</Admonition>
|
||||
)}
|
||||
|
||||
<h3>
|
||||
Fedora and CentOS
|
||||
<span className='badge badge--info margin-left--sm'>Community</span>
|
||||
</h3>
|
||||
<p>RPM archives for both Fedora and CentOS are provided.</p>
|
||||
<p>
|
||||
<a
|
||||
href='https://repo.jellyfin.org/releases/server/fedora'
|
||||
className='button button--primary margin-right--md margin-bottom--md'
|
||||
>
|
||||
Stable Fedora
|
||||
</a>
|
||||
<a
|
||||
href='https://repo.jellyfin.org/releases/server/centos'
|
||||
className='button button--primary margin-right--md margin-bottom--md'
|
||||
>
|
||||
Stable CentOS
|
||||
</a>
|
||||
<a
|
||||
href='https://repo.jellyfin.org/releases/server/fedora/versions'
|
||||
className='button button--outline button--primary margin-right--md margin-bottom--md'
|
||||
>
|
||||
All Fedora Versions
|
||||
</a>
|
||||
<a
|
||||
href='https://repo.jellyfin.org/releases/server/centos/versions'
|
||||
className='button button--outline button--primary margin-bottom--md'
|
||||
>
|
||||
All CentOS Versions
|
||||
</a>
|
||||
</p>
|
||||
|
||||
<h3>
|
||||
Generic Linux
|
||||
<span className='badge badge--success margin-left--sm'>Official</span>
|
||||
</h3>
|
||||
<p>Linux self-contained binary TAR archives (.tar.gz) are provided.</p>
|
||||
<p>
|
||||
<a
|
||||
href='https://repo.jellyfin.org/releases/server/linux/stable'
|
||||
className='button button--primary margin-right--md margin-bottom--md'
|
||||
>
|
||||
Stable
|
||||
</a>
|
||||
<a
|
||||
href='https://repo.jellyfin.org/releases/server/linux/unstable'
|
||||
className='button button--secondary margin-right--md margin-bottom--md'
|
||||
>
|
||||
Unstable
|
||||
</a>
|
||||
<a
|
||||
href='https://repo.jellyfin.org/releases/server/linux/versions'
|
||||
className='button button--outline button--primary margin-bottom--md'
|
||||
>
|
||||
All Versions
|
||||
</a>
|
||||
</p>
|
||||
|
||||
<h3>
|
||||
MacOS
|
||||
<span className='badge badge--success margin-left--sm'>Official</span>
|
||||
</h3>
|
||||
<p>Both installers (.dmg) and manual ZIP archives (.tar.gz) are provided.</p>
|
||||
<p>
|
||||
<a
|
||||
href='https://repo.jellyfin.org/releases/server/macos/stable'
|
||||
className='button button--primary margin-right--md margin-bottom--md'
|
||||
>
|
||||
Stable
|
||||
</a>
|
||||
<a
|
||||
href='https://repo.jellyfin.org/releases/server/macos/unstable'
|
||||
className='button button--secondary margin-right--md margin-bottom--md'
|
||||
>
|
||||
Unstable
|
||||
</a>
|
||||
<a
|
||||
href='https://repo.jellyfin.org/releases/server/macos/versions'
|
||||
className='button button--outline button--primary margin-bottom--md'
|
||||
>
|
||||
All Versions
|
||||
</a>
|
||||
</p>
|
||||
|
||||
<h3>
|
||||
Windows
|
||||
<span className='badge badge--success margin-left--sm'>Official</span>
|
||||
</h3>
|
||||
<p>Both installers (.exe) and manual ZIP archives (.zip) are provided.</p>
|
||||
<p>
|
||||
When using the installer, please ensure you <i>fully uninstall</i> any ZIP archive versions you may have
|
||||
installed, or you may get duplicate services.
|
||||
</p>
|
||||
<p>
|
||||
<a
|
||||
href='https://repo.jellyfin.org/releases/server/windows/stable'
|
||||
className='button button--primary margin-right--md margin-bottom--md'
|
||||
>
|
||||
Stable
|
||||
</a>
|
||||
<a
|
||||
href='https://repo.jellyfin.org/releases/server/windows/unstable'
|
||||
className='button button--secondary margin-right--md margin-bottom--md'
|
||||
>
|
||||
Unstable
|
||||
</a>
|
||||
<a
|
||||
href='https://repo.jellyfin.org/releases/server/windows/versions'
|
||||
className='button button--outline button--primary margin-bottom--md'
|
||||
>
|
||||
All Versions
|
||||
</a>
|
||||
</p>
|
||||
|
||||
<h3>
|
||||
Portable
|
||||
<span className='badge badge--success margin-left--sm'>Official</span>
|
||||
</h3>
|
||||
<p>The portable version can be run on any system with a .NET Core runtime.</p>
|
||||
<p>
|
||||
<a
|
||||
href='https://repo.jellyfin.org/releases/server/portable/stable'
|
||||
className='button button--primary margin-right--md margin-bottom--md'
|
||||
>
|
||||
Stable
|
||||
</a>
|
||||
<a
|
||||
href='https://repo.jellyfin.org/releases/server/portable/unstable'
|
||||
className='button button--secondary margin-right--md margin-bottom--md'
|
||||
>
|
||||
Unstable
|
||||
</a>
|
||||
<a
|
||||
href='https://repo.jellyfin.org/releases/server/portable/versions'
|
||||
className='button button--outline button--primary margin-bottom--md'
|
||||
>
|
||||
All Versions
|
||||
</a>
|
||||
</p>
|
||||
{Downloads.filter((download) => download.osTypes.includes(osType)).map((download) => (
|
||||
<DownloadDetails
|
||||
key={download.id}
|
||||
download={download}
|
||||
isStableLinks={isStableLinks}
|
||||
activeButton={activeButton}
|
||||
setActiveButton={setActiveButton}
|
||||
/>
|
||||
))}
|
||||
</section>
|
||||
</main>
|
||||
</Layout>
|
||||
|
||||
Reference in New Issue
Block a user