Add eslint rules for sonar issues
This commit is contained in:
parent
2690b90d84
commit
19f416580c
12 changed files with 45 additions and 30 deletions
16
.eslintrc.js
16
.eslintrc.js
|
@ -56,6 +56,7 @@ module.exports = {
|
|||
'no-return-assign': ['error'],
|
||||
'no-return-await': ['error'],
|
||||
'no-sequences': ['error', { 'allowInParentheses': false }],
|
||||
'no-shadow': ['error'],
|
||||
'no-trailing-spaces': ['error'],
|
||||
'@babel/no-unused-expressions': ['error', { 'allowShortCircuit': true, 'allowTernary': true, 'allowTaggedTemplates': true }],
|
||||
'no-useless-constructor': ['error'],
|
||||
|
@ -70,12 +71,15 @@ module.exports = {
|
|||
'space-before-blocks': ['error'],
|
||||
'space-infix-ops': 'error',
|
||||
'yoda': 'error',
|
||||
'@typescript-eslint/no-shadow': 'error',
|
||||
|
||||
'react/jsx-filename-extension': ['error', { 'extensions': ['.jsx', '.tsx'] }],
|
||||
'react/jsx-no-bind': ['error'],
|
||||
'react/jsx-no-constructed-context-values': ['error'],
|
||||
'react/no-array-index-key': ['error'],
|
||||
|
||||
'sonarjs/cognitive-complexity': ['warn'],
|
||||
'sonarjs/no-inverted-boolean-check': ['error'],
|
||||
// TODO: Enable the following rules and fix issues
|
||||
'sonarjs/cognitive-complexity': ['off'],
|
||||
'sonarjs/no-duplicate-string': ['off']
|
||||
},
|
||||
settings: {
|
||||
|
@ -255,8 +259,14 @@ module.exports = {
|
|||
'plugin:jsx-a11y/recommended'
|
||||
],
|
||||
rules: {
|
||||
// Use TypeScript equivalent rules when required
|
||||
'no-shadow': ['off'],
|
||||
'@typescript-eslint/no-shadow': ['error'],
|
||||
'no-useless-constructor': ['off'],
|
||||
'@typescript-eslint/no-useless-constructor': ['error']
|
||||
'@typescript-eslint/no-useless-constructor': ['error'],
|
||||
|
||||
'max-params': ['error', 7],
|
||||
'sonarjs/cognitive-complexity': ['warn']
|
||||
}
|
||||
}
|
||||
]
|
||||
|
|
|
@ -90,8 +90,8 @@ const GenresItemsContainer: FC<GenresItemsContainerProps> = ({
|
|||
<h1>{globalize.translate('MessageNothingHere')}</h1>
|
||||
<p>{globalize.translate('MessageNoGenresAvailable')}</p>
|
||||
</div>
|
||||
) : items.map((item, index) => (
|
||||
<div key={index} className='verticalSection'>
|
||||
) : items.map(item => (
|
||||
<div key={item.Id} className='verticalSection'>
|
||||
<div
|
||||
className='sectionTitleContainer sectionTitleContainer-cards padded-left'
|
||||
dangerouslySetInnerHTML={createLinkElement({
|
||||
|
|
|
@ -610,7 +610,7 @@ export default function () {
|
|||
function onTimeUpdate() {
|
||||
const now = new Date().getTime();
|
||||
|
||||
if (!(now - lastUpdateTime < 700)) {
|
||||
if (now - lastUpdateTime >= 700) {
|
||||
lastUpdateTime = now;
|
||||
const player = this;
|
||||
currentRuntimeTicks = playbackManager.duration(player);
|
||||
|
|
|
@ -125,7 +125,7 @@ const LiveTVSearchResults: FunctionComponent<LiveTVSearchResultsProps> = ({ serv
|
|||
'searchResults',
|
||||
'padded-bottom-page',
|
||||
'padded-top',
|
||||
{ 'hide': !query || !(collectionType === 'livetv') }
|
||||
{ 'hide': !query || collectionType !== 'livetv' }
|
||||
)}
|
||||
>
|
||||
<SearchResultsRow
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import debounce from 'lodash-es/debounce';
|
||||
import React, { FunctionComponent, useEffect, useMemo, useRef } from 'react';
|
||||
import React, { FunctionComponent, useCallback, useEffect, useMemo, useRef } from 'react';
|
||||
|
||||
import AlphaPicker from '../alphaPicker/AlphaPickerComponent';
|
||||
import globalize from '../../scripts/globalize';
|
||||
|
@ -53,7 +53,7 @@ const SearchFields: FunctionComponent<SearchFieldsProps> = ({ onSearch = () => {
|
|||
};
|
||||
}, [debouncedOnSearch]);
|
||||
|
||||
const onAlphaPicked = (e: Event) => {
|
||||
const onAlphaPicked = useCallback((e: Event) => {
|
||||
const value = (e as CustomEvent).detail.value;
|
||||
const searchInput = getSearchInput();
|
||||
|
||||
|
@ -70,7 +70,7 @@ const SearchFields: FunctionComponent<SearchFieldsProps> = ({ onSearch = () => {
|
|||
}
|
||||
|
||||
searchInput.dispatchEvent(new CustomEvent('input', { bubbles: true }));
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div
|
||||
|
|
|
@ -1106,7 +1106,7 @@ class ItemsView {
|
|||
const filters = [];
|
||||
const params = this.params;
|
||||
|
||||
if (!(params.type === 'nextup')) {
|
||||
if (params.type !== 'nextup') {
|
||||
if (params.type === 'Programs') {
|
||||
filters.push('Genres');
|
||||
} else {
|
||||
|
|
|
@ -585,7 +585,7 @@ import { setBackdropTransparency, TRANSPARENCY_LEVEL } from '../../../components
|
|||
if (isEnabled && currentItem) {
|
||||
const now = new Date().getTime();
|
||||
|
||||
if (!(now - lastUpdateTime < 700)) {
|
||||
if (now - lastUpdateTime >= 700) {
|
||||
lastUpdateTime = now;
|
||||
const player = this;
|
||||
currentRuntimeTicks = playbackManager.duration(player);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import React, { AnchorHTMLAttributes, DetailedHTMLProps, MouseEvent } from 'react';
|
||||
import React, { AnchorHTMLAttributes, DetailedHTMLProps, MouseEvent, useCallback } from 'react';
|
||||
import classNames from 'classnames';
|
||||
import layoutManager from '../../components/layoutManager';
|
||||
import shell from '../../scripts/shell';
|
||||
|
@ -23,7 +23,7 @@ const LinkButton: React.FC<LinkButtonProps> = ({
|
|||
children,
|
||||
...rest
|
||||
}) => {
|
||||
const onAnchorClick = (e: MouseEvent<HTMLAnchorElement>) => {
|
||||
const onAnchorClick = useCallback((e: MouseEvent<HTMLAnchorElement>) => {
|
||||
const url = href || '';
|
||||
if (url !== '#') {
|
||||
if (target) {
|
||||
|
@ -38,7 +38,7 @@ const LinkButton: React.FC<LinkButtonProps> = ({
|
|||
} else {
|
||||
e.preventDefault();
|
||||
}
|
||||
};
|
||||
}, [ href, target ]);
|
||||
|
||||
if (isAutoHideEnabled === true && !appHost.supports('externallinks')) {
|
||||
return null;
|
||||
|
|
|
@ -29,7 +29,7 @@ const ScrollButtons: FC<ScrollButtonsProps> = ({ scrollerFactoryRef, scrollState
|
|||
}
|
||||
}, [scrollerFactoryRef]);
|
||||
|
||||
const onScrollButtonClick = (direction: Direction) => {
|
||||
const onScrollButtonClick = useCallback((direction: Direction) => {
|
||||
let newPos;
|
||||
if (direction === Direction.LEFT) {
|
||||
newPos = Math.max(0, scrollState.scrollPos - scrollState.scrollSize);
|
||||
|
@ -44,7 +44,10 @@ const ScrollButtons: FC<ScrollButtonsProps> = ({ scrollerFactoryRef, scrollState
|
|||
}
|
||||
|
||||
scrollToPosition(newPos, false);
|
||||
};
|
||||
}, [ scrollState.scrollPos, scrollState.scrollSize, scrollToPosition ]);
|
||||
|
||||
const triggerScrollLeft = useCallback(() => onScrollButtonClick(Direction.LEFT), [ onScrollButtonClick ]);
|
||||
const triggerScrollRight = useCallback(() => onScrollButtonClick(Direction.RIGHT), [ onScrollButtonClick ]);
|
||||
|
||||
useEffect(() => {
|
||||
const parent = scrollButtonsRef.current?.parentNode as HTMLDivElement;
|
||||
|
@ -63,7 +66,7 @@ const ScrollButtons: FC<ScrollButtonsProps> = ({ scrollerFactoryRef, scrollState
|
|||
<IconButton
|
||||
type='button'
|
||||
className='emby-scrollbuttons-button btnPrev'
|
||||
onClick={() => onScrollButtonClick(Direction.LEFT)}
|
||||
onClick={triggerScrollLeft}
|
||||
icon='chevron_left'
|
||||
disabled={localeScrollPos > 0 ? false : true}
|
||||
/>
|
||||
|
@ -71,7 +74,7 @@ const ScrollButtons: FC<ScrollButtonsProps> = ({ scrollerFactoryRef, scrollState
|
|||
<IconButton
|
||||
type='button'
|
||||
className='emby-scrollbuttons-button btnNext'
|
||||
onClick={() => onScrollButtonClick(Direction.RIGHT)}
|
||||
onClick={triggerScrollRight}
|
||||
icon='chevron_right'
|
||||
disabled={scrollState.scrollWidth > 0 && localeScrollPos + scrollState.scrollSize >= scrollState.scrollWidth ? true : false}
|
||||
/>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import type { Api } from '@jellyfin/sdk';
|
||||
import type { UserDto } from '@jellyfin/sdk/lib/generated-client';
|
||||
import type { ApiClient, Event } from 'jellyfin-apiclient';
|
||||
import React, { createContext, FC, useContext, useEffect, useState } from 'react';
|
||||
import React, { createContext, FC, useContext, useEffect, useMemo, useState } from 'react';
|
||||
|
||||
import ServerConnections from '../components/ServerConnections';
|
||||
import events from '../utils/events';
|
||||
|
@ -21,6 +21,12 @@ export const ApiProvider: FC = ({ children }) => {
|
|||
const [ api, setApi ] = useState<Api>();
|
||||
const [ user, setUser ] = useState<UserDto>();
|
||||
|
||||
const context = useMemo(() => ({
|
||||
__legacyApiClient__: legacyApiClient,
|
||||
api,
|
||||
user
|
||||
}), [ api, legacyApiClient, user ]);
|
||||
|
||||
useEffect(() => {
|
||||
ServerConnections.currentApiClient()
|
||||
?.getCurrentUser()
|
||||
|
@ -56,11 +62,7 @@ export const ApiProvider: FC = ({ children }) => {
|
|||
}, [ legacyApiClient, setApi ]);
|
||||
|
||||
return (
|
||||
<ApiContext.Provider value={{
|
||||
__legacyApiClient__: legacyApiClient,
|
||||
api,
|
||||
user
|
||||
}}>
|
||||
<ApiContext.Provider value={context}>
|
||||
{children}
|
||||
</ApiContext.Provider>
|
||||
);
|
||||
|
|
|
@ -143,8 +143,8 @@ const SuggestionsView: FC<LibraryViewProps> = ({topParentId}) => {
|
|||
{!recommendations.length ? <div className='noItemsMessage centerMessage'>
|
||||
<h1>{globalize.translate('MessageNothingHere')}</h1>
|
||||
<p>{globalize.translate('MessageNoMovieSuggestionsAvailable')}</p>
|
||||
</div> : recommendations.map((recommendation, index) => {
|
||||
return <RecommendationContainer key={index} getPortraitShape={getPortraitShape} enableScrollX={enableScrollX} recommendation={recommendation} />;
|
||||
</div> : recommendations.map(recommendation => {
|
||||
return <RecommendationContainer key={recommendation.CategoryId} getPortraitShape={getPortraitShape} enableScrollX={enableScrollX} recommendation={recommendation} />;
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -379,9 +379,9 @@ const UserParentalControl: FunctionComponent = () => {
|
|||
isLinkVisible={false}
|
||||
/>
|
||||
<div className='blockedTags' style={{marginTop: '.5em'}}>
|
||||
{blockedTags.map((tag, index) => {
|
||||
{blockedTags.map(tag => {
|
||||
return <BlockedTagList
|
||||
key={index}
|
||||
key={tag}
|
||||
tag={tag}
|
||||
/>;
|
||||
})}
|
||||
|
@ -401,7 +401,7 @@ const UserParentalControl: FunctionComponent = () => {
|
|||
<div className='accessScheduleList paperList'>
|
||||
{accessSchedules.map((accessSchedule, index) => {
|
||||
return <AccessScheduleList
|
||||
key={index}
|
||||
key={accessSchedule.Id}
|
||||
index={index}
|
||||
Id={accessSchedule.Id}
|
||||
DayOfWeek={accessSchedule.DayOfWeek}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue