1
0
Fork 0
mirror of https://github.com/jellyfin/jellyfin-web synced 2025-03-30 19:56:21 +00:00

Merge branch 'master' into chapter-markers

This commit is contained in:
Viperinius 2022-09-17 12:04:18 +02:00 committed by GitHub
commit 33fe2c51d6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
160 changed files with 23903 additions and 4619 deletions

View file

@ -0,0 +1,41 @@
import React, { FunctionComponent } from 'react';
import globalize from '../scripts/globalize';
const createButtonElement = ({ type, id, className, title, leftIcon, rightIcon }: IProps) => ({
__html: `<button
is="emby-button"
type="${type}"
${id}
class="${className}"
>
${leftIcon}
<span>${title}</span>
${rightIcon}
</button>`
});
type IProps = {
type?: string;
id?: string;
className?: string;
title?: string;
leftIcon?: string;
rightIcon?: string;
}
const ButtonElement: FunctionComponent<IProps> = ({ type, id, className, title, leftIcon, rightIcon }: IProps) => {
return (
<div
dangerouslySetInnerHTML={createButtonElement({
type: type,
id: id ? `id="${id}"` : '',
className: className,
title: globalize.translate(title),
leftIcon: leftIcon ? `<span class="material-icons ${leftIcon}" aria-hidden="true"></span>` : '',
rightIcon: rightIcon ? `<span class="material-icons ${rightIcon}" aria-hidden="true"></span>` : ''
})}
/>
);
};
export default ButtonElement;

View file

@ -0,0 +1,57 @@
import escapeHTML from 'escape-html';
import React, { FunctionComponent } from 'react';
import globalize from '../scripts/globalize';
const createCheckBoxElement = ({ labelClassName, className, id, dataFilter, dataItemType, dataId, checkedAttribute, renderContent }: { labelClassName?: string, type?: string, className?: string, id?: string, dataFilter?: string, dataItemType?: string, dataId?: string, checkedAttribute?: string, renderContent?: string }) => ({
__html: `<label ${labelClassName}>
<input
is="emby-checkbox"
type="checkbox"
class="${className}"
${id}
${dataFilter}
${dataItemType}
${dataId}
${checkedAttribute}
/>
${renderContent}
</label>`
});
type IProps = {
labelClassName?: string;
className?: string;
elementId?: string;
dataFilter?: string;
itemType?: string;
itemId?: string;
itemAppName?: string;
itemCheckedAttribute?: string;
itemName?: string
title?: string
}
const CheckBoxElement: FunctionComponent<IProps> = ({ labelClassName, className, elementId, dataFilter, itemType, itemId, itemAppName, itemCheckedAttribute, itemName, title }: IProps) => {
const appName = itemAppName ? `- ${itemAppName}` : '';
const renderContent = itemName ?
`<span>${escapeHTML(itemName || '')} ${appName}</span>` :
`<span>${globalize.translate(title)}</span>`;
return (
<div
className='sectioncheckbox'
dangerouslySetInnerHTML={createCheckBoxElement({
labelClassName: labelClassName ? `class='${labelClassName}'` : '',
className: className,
id: elementId ? `id='${elementId}'` : '',
dataFilter: dataFilter ? `data-filter='${dataFilter}'` : '',
dataItemType: itemType ? `data-itemtype='${itemType}'` : '',
dataId: itemId ? `data-id='${itemId}'` : '',
checkedAttribute: itemCheckedAttribute ? itemCheckedAttribute : '',
renderContent: renderContent
})}
/>
);
};
export default CheckBoxElement;

View file

@ -0,0 +1,47 @@
import React, { FunctionComponent } from 'react';
import globalize from '../scripts/globalize';
type IProps = {
is?: string;
id?: string;
title?: string;
className?: string;
icon?: string,
dataIndex?: string | number;
dataTag?: string | number;
dataProfileid?: string | number;
}
const createIconButtonElement = ({ is, id, className, title, icon, dataIndex, dataTag, dataProfileid }: IProps) => ({
__html: `<button
is="${is}"
type="button"
${id}
class="${className}"
${title}
${dataIndex}
${dataTag}
${dataProfileid}
>
<span class="material-icons ${icon}" aria-hidden="true"></span>
</button>`
});
const IconButtonElement: FunctionComponent<IProps> = ({ is, id, className, title, icon, dataIndex, dataTag, dataProfileid }: IProps) => {
return (
<div
dangerouslySetInnerHTML={createIconButtonElement({
is: is,
id: id ? `id="${id}"` : '',
className: className,
title: title ? `title="${globalize.translate(title)}"` : '',
icon: icon,
dataIndex: dataIndex ? `data-index="${dataIndex}"` : '',
dataTag: dataTag ? `data-tag="${dataTag}"` : '',
dataProfileid: dataProfileid ? `data-profileid="${dataProfileid}"` : ''
})}
/>
);
};
export default IconButtonElement;

View file

@ -0,0 +1,34 @@
import React, { FunctionComponent } from 'react';
import globalize from '../scripts/globalize';
const createInputElement = ({ type, id, label, options }: { type?: string, id?: string, label?: string, options?: string }) => ({
__html: `<input
is="emby-input"
type="${type}"
id="${id}"
label="${label}"
${options}
/>`
});
type IProps = {
type?: string;
id?: string;
label?: string;
options?: string
}
const InputElement: FunctionComponent<IProps> = ({ type, id, label, options }: IProps) => {
return (
<div
dangerouslySetInnerHTML={createInputElement({
type: type,
id: id,
label: globalize.translate(label),
options: options ? options : ''
})}
/>
);
};
export default InputElement;

View file

@ -0,0 +1,41 @@
import React, { FunctionComponent } from 'react';
import IconButtonElement from './IconButtonElement';
import SectionTitleLinkElement from './SectionTitleLinkElement';
type IProps = {
SectionClassName?: string;
title?: string;
isBtnVisible?: boolean;
btnId?: string;
btnClassName?: string;
btnTitle?: string;
btnIcon?: string;
isLinkVisible?: boolean;
url?: string;
}
const SectionTitleContainer: FunctionComponent<IProps> = ({SectionClassName, title, isBtnVisible = false, btnId, btnClassName, btnTitle, btnIcon, isLinkVisible = true, url}: IProps) => {
return (
<div className={`${SectionClassName} sectionTitleContainer flex align-items-center`}>
<h2 className='sectionTitle'>
{title}
</h2>
{isBtnVisible && <IconButtonElement
is='emby-button'
id={btnId}
className={btnClassName}
title={btnTitle}
icon={btnIcon}
/>}
{isLinkVisible && <SectionTitleLinkElement
className='raised button-alt headerHelpButton'
title='Help'
url={url}
/>}
</div>
);
};
export default SectionTitleContainer;

View file

@ -0,0 +1,34 @@
import React, { FunctionComponent } from 'react';
import globalize from '../scripts/globalize';
const createLinkElement = ({ className, title, href }: { className?: string, title?: string, href?: string }) => ({
__html: `<a
is="emby-linkbutton"
rel="noopener noreferrer"
class="${className}"
target="_blank"
href="${href}"
>
${title}
</a>`
});
type IProps = {
title?: string;
className?: string;
url?: string
}
const SectionTitleLinkElement: FunctionComponent<IProps> = ({ className, title, url }: IProps) => {
return (
<div
dangerouslySetInnerHTML={createLinkElement({
className: className,
title: globalize.translate(title),
href: url
})}
/>
);
};
export default SectionTitleLinkElement;

View file

@ -0,0 +1,38 @@
import React, { FunctionComponent } from 'react';
import globalize from '../scripts/globalize';
const createSelectElement = ({ name, id, required, label, option }: { name?: string, id?: string, required?: string, label?: string, option?: React.ReactNode }) => ({
__html: `<select
is="emby-select"
${name}
id="${id}"
${required}
label="${label}"
>
${option}
</select>`
});
type IProps = {
name?: string;
id?: string;
required?: string;
label?: string;
children?: React.ReactNode
}
const SelectElement: FunctionComponent<IProps> = ({ name, id, required, label, children }: IProps) => {
return (
<div
dangerouslySetInnerHTML={createSelectElement({
name: name ? `name='${name}'` : '',
id: id,
required: required ? `required='${required}'` : '',
label: globalize.translate(label),
option: children
})}
/>
);
};
export default SelectElement;

View file

@ -45,6 +45,9 @@ const EmbyScrollButtonsPrototype = Object.create(HTMLDivElement.prototype);
if (scrollWidth <= scrollSize + 20) {
scrollButtons.scrollButtonsLeft.classList.add('hide');
scrollButtons.scrollButtonsRight.classList.add('hide');
} else {
scrollButtons.scrollButtonsLeft.classList.remove('hide');
scrollButtons.scrollButtonsRight.classList.remove('hide');
}
if (scrollPos > 0) {

View file

@ -4,7 +4,9 @@
.emby-scroller {
margin-left: 3.3%;
margin-left: max(env(safe-area-inset-left), 3.3%);
margin-right: 3.3%;
margin-right: max(env(safe-area-inset-right), 3.3%);
}
/* align first card in scroller to heading */
@ -21,7 +23,9 @@
.layout-tv .emby-scroller,
.layout-mobile .emby-scroller {
padding-left: 3.3%;
padding-left: max(env(safe-area-inset-left), 3.3%);
padding-right: 3.3%;
padding-right: max(env(safe-area-inset-right), 3.3%);
margin-left: 0;
margin-right: 0;
}