chore(deps): upgrade prettier, and tailwind (#2351)

This commit is contained in:
fallenbagel
2026-01-29 11:48:34 +05:00
committed by GitHub
parent 5bd31040c0
commit 8b41685b31
159 changed files with 1022 additions and 910 deletions

View File

@@ -4,15 +4,17 @@ dist/
config/ config/
pnpm-lock.yaml pnpm-lock.yaml
cypress/config/settings.cypress.json cypress/config/settings.cypress.json
.github
.vscode
# assets # assets
src/assets/ src/assets/
public/
!public/sw.js
docs/ docs/
!/public/ public/*
/public/* !public/sw.js
!/public/sw.js
# helm charts # helm charts
**/charts **/charts
# Prettier breaks GitHub alert syntax in markdown
*.md

View File

@@ -1,5 +1,5 @@
module.exports = { module.exports = {
plugins: [require('./merged-prettier-plugin.js')], plugins: ['prettier-plugin-organize-imports', 'prettier-plugin-tailwindcss'],
singleQuote: true, singleQuote: true,
trailingComma: 'es5', trailingComma: 'es5',
overrides: [ overrides: [
@@ -27,5 +27,11 @@ module.exports = {
rangeEnd: 0, rangeEnd: 0,
}, },
}, },
{
files: 'public/offline.html',
options: {
rangeEnd: 0,
},
},
], ],
}; };

View File

@@ -60,12 +60,12 @@
.table-of-contents__link--active, .table-of-contents__link--active,
a:not( a:not(
.card, .card,
.menu__link, .menu__link,
.menu__link--sublist, .menu__link--sublist,
.menu__link--sublist-item, .menu__link--sublist-item,
.table-of-contents__link .table-of-contents__link
) { ) {
/* color: #793ae8; */ /* color: #793ae8; */
color: #6366f1; color: #6366f1;
} }

View File

@@ -1,21 +0,0 @@
/* eslint-disable */
const tailwind = require('prettier-plugin-tailwindcss');
const organizeImports = require('prettier-plugin-organize-imports');
const combinedFormatter = {
...tailwind,
parsers: {
...tailwind.parsers,
...Object.keys(organizeImports.parsers).reduce((acc, key) => {
acc[key] = {
...tailwind.parsers[key],
preprocess(code, options) {
return organizeImports.parsers[key].preprocess(code, options);
},
};
return acc;
}, {}),
},
};
module.exports = combinedFormatter;

View File

@@ -16,7 +16,7 @@
"migration:generate": "ts-node -r tsconfig-paths/register --project server/tsconfig.json ./node_modules/typeorm/cli.js migration:generate -d server/datasource.ts", "migration:generate": "ts-node -r tsconfig-paths/register --project server/tsconfig.json ./node_modules/typeorm/cli.js migration:generate -d server/datasource.ts",
"migration:create": "ts-node -r tsconfig-paths/register --project server/tsconfig.json ./node_modules/typeorm/cli.js migration:create -d server/datasource.ts", "migration:create": "ts-node -r tsconfig-paths/register --project server/tsconfig.json ./node_modules/typeorm/cli.js migration:create -d server/datasource.ts",
"migration:run": "ts-node -r tsconfig-paths/register --project server/tsconfig.json ./node_modules/typeorm/cli.js migration:run -d server/datasource.ts", "migration:run": "ts-node -r tsconfig-paths/register --project server/tsconfig.json ./node_modules/typeorm/cli.js migration:run -d server/datasource.ts",
"format": "prettier --loglevel warn --write --cache .", "format": "prettier --log-level warn --write --cache .",
"format:check": "prettier --check --cache .", "format:check": "prettier --check --cache .",
"typecheck": "pnpm typecheck:server && pnpm typecheck:client", "typecheck": "pnpm typecheck:server && pnpm typecheck:client",
"typecheck:server": "tsc --project server/tsconfig.json --noEmit", "typecheck:server": "tsc --project server/tsconfig.json --noEmit",
@@ -116,9 +116,9 @@
"devDependencies": { "devDependencies": {
"@commitlint/cli": "17.4.4", "@commitlint/cli": "17.4.4",
"@commitlint/config-conventional": "17.4.4", "@commitlint/config-conventional": "17.4.4",
"@tailwindcss/aspect-ratio": "0.4.2", "@tailwindcss/aspect-ratio": "^0.4.2",
"@tailwindcss/forms": "0.5.10", "@tailwindcss/forms": "^0.5.10",
"@tailwindcss/typography": "0.5.16", "@tailwindcss/typography": "^0.5.16",
"@types/bcrypt": "6.0.0", "@types/bcrypt": "6.0.0",
"@types/cookie-parser": "1.4.10", "@types/cookie-parser": "1.4.10",
"@types/country-flag-icons": "1.2.2", "@types/country-flag-icons": "1.2.2",
@@ -144,7 +144,7 @@
"@types/yup": "0.29.14", "@types/yup": "0.29.14",
"@typescript-eslint/eslint-plugin": "7.18.0", "@typescript-eslint/eslint-plugin": "7.18.0",
"@typescript-eslint/parser": "7.18.0", "@typescript-eslint/parser": "7.18.0",
"autoprefixer": "10.4.23", "autoprefixer": "^10.4.23",
"baseline-browser-mapping": "^2.8.32", "baseline-browser-mapping": "^2.8.32",
"commitizen": "4.3.1", "commitizen": "4.3.1",
"copyfiles": "2.4.1", "copyfiles": "2.4.1",
@@ -152,7 +152,7 @@
"cypress": "14.5.4", "cypress": "14.5.4",
"cz-conventional-changelog": "3.3.0", "cz-conventional-changelog": "3.3.0",
"eslint": "8.57.1", "eslint": "8.57.1",
"eslint-config-next": "^14.2.4", "eslint-config-next": "^14.2.35",
"eslint-config-prettier": "8.6.0", "eslint-config-prettier": "8.6.0",
"eslint-plugin-formatjs": "4.9.0", "eslint-plugin-formatjs": "4.9.0",
"eslint-plugin-jsx-a11y": "6.10.2", "eslint-plugin-jsx-a11y": "6.10.2",
@@ -163,11 +163,11 @@
"husky": "8.0.3", "husky": "8.0.3",
"lint-staged": "13.1.2", "lint-staged": "13.1.2",
"nodemon": "3.1.11", "nodemon": "3.1.11",
"postcss": "8.5.6", "postcss": "^8.5.6",
"prettier": "2.8.4", "prettier": "3.8.1",
"prettier-plugin-organize-imports": "3.2.2", "prettier-plugin-organize-imports": "4.3.0",
"prettier-plugin-tailwindcss": "0.2.3", "prettier-plugin-tailwindcss": "0.6.14",
"tailwindcss": "3.2.7", "tailwindcss": "3.4.19",
"ts-node": "10.9.2", "ts-node": "10.9.2",
"tsc-alias": "1.8.16", "tsc-alias": "1.8.16",
"tsconfig-paths": "4.2.0", "tsconfig-paths": "4.2.0",

568
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -57,7 +57,7 @@ interface GithubCommit {
sha: string; sha: string;
url: string; url: string;
html_url: string; html_url: string;
} },
]; ];
} }

View File

@@ -420,7 +420,7 @@ class JellyfinAPI extends ExternalAPI {
} }
public async getEpisodes< public async getEpisodes<
T extends { includeMediaInfo?: boolean } | undefined = undefined T extends { includeMediaInfo?: boolean } | undefined = undefined,
>( >(
seriesID: string, seriesID: string,
seasonID: string, seasonID: string,

View File

@@ -21,7 +21,7 @@ export const mapSounds = (sounds: {
({ ({
name, name,
description, description,
} as PushoverSound) }) as PushoverSound
); );
class PushoverAPI extends ExternalAPI { class PushoverAPI extends ExternalAPI {

View File

@@ -157,8 +157,8 @@ class RottenTomatoes extends ExternalAPI {
criticsRating: movie.rottenTomatoes.certifiedFresh criticsRating: movie.rottenTomatoes.certifiedFresh
? 'Certified Fresh' ? 'Certified Fresh'
: movie.rottenTomatoes.criticsScore >= 60 : movie.rottenTomatoes.criticsScore >= 60
? 'Fresh' ? 'Fresh'
: 'Rotten', : 'Rotten',
criticsScore: movie.rottenTomatoes.criticsScore, criticsScore: movie.rottenTomatoes.criticsScore,
audienceRating: audienceRating:
movie.rottenTomatoes.audienceScore >= 60 ? 'Upright' : 'Spilled', movie.rottenTomatoes.audienceScore >= 60 ? 'Upright' : 'Spilled',

View File

@@ -269,8 +269,8 @@ class TautulliAPI {
recordA.grandparent_rating_key && recordB.grandparent_rating_key recordA.grandparent_rating_key && recordB.grandparent_rating_key
? recordA.grandparent_rating_key === recordB.grandparent_rating_key ? recordA.grandparent_rating_key === recordB.grandparent_rating_key
: recordA.parent_rating_key && recordB.parent_rating_key : recordA.parent_rating_key && recordB.parent_rating_key
? recordA.parent_rating_key === recordB.parent_rating_key ? recordA.parent_rating_key === recordB.parent_rating_key
: recordA.rating_key === recordB.rating_key : recordA.rating_key === recordB.rating_key
); );
start += take; start += take;

View File

@@ -536,8 +536,8 @@ class TheMovieDb extends ExternalAPI implements TvShowProvider {
originalLanguage && originalLanguage !== 'all' originalLanguage && originalLanguage !== 'all'
? originalLanguage ? originalLanguage
: originalLanguage === 'all' : originalLanguage === 'all'
? undefined ? undefined
: this.originalLanguage, : this.originalLanguage,
// Set our release date values, but check if one is set and not the other, // Set our release date values, but check if one is set and not the other,
// so we can force a past date or a future date. TMDB Requires both values if one is set! // so we can force a past date or a future date. TMDB Requires both values if one is set!
'primary_release_date.gte': 'primary_release_date.gte':
@@ -630,8 +630,8 @@ class TheMovieDb extends ExternalAPI implements TvShowProvider {
originalLanguage && originalLanguage !== 'all' originalLanguage && originalLanguage !== 'all'
? originalLanguage ? originalLanguage
: originalLanguage === 'all' : originalLanguage === 'all'
? undefined ? undefined
: this.originalLanguage, : this.originalLanguage,
include_null_first_air_dates: includeEmptyReleaseDate, include_null_first_air_dates: includeEmptyReleaseDate,
with_genres: genre, with_genres: genre,
with_networks: network, with_networks: network,

View File

@@ -392,8 +392,10 @@ export interface TmdbPersonCombinedCredits {
crew: TmdbPersonCreditCrew[]; crew: TmdbPersonCreditCrew[];
} }
export interface TmdbSeasonWithEpisodes export interface TmdbSeasonWithEpisodes extends Omit<
extends Omit<TmdbTvSeasonResult, 'episode_count'> { TmdbTvSeasonResult,
'episode_count'
> {
episodes: TmdbTvEpisodeResult[]; episodes: TmdbTvEpisodeResult[];
external_ids: TmdbExternalIds; external_ids: TmdbExternalIds;
} }

View File

@@ -271,7 +271,7 @@ export class User {
}); });
const movieQuotaLimit = !canBypass const movieQuotaLimit = !canBypass
? this.movieQuotaLimit ?? defaultQuotas.movie.quotaLimit ? (this.movieQuotaLimit ?? defaultQuotas.movie.quotaLimit)
: 0; : 0;
const movieQuotaDays = this.movieQuotaDays ?? defaultQuotas.movie.quotaDays; const movieQuotaDays = this.movieQuotaDays ?? defaultQuotas.movie.quotaDays;
@@ -295,7 +295,7 @@ export class User {
: 0; : 0;
const tvQuotaLimit = !canBypass const tvQuotaLimit = !canBypass
? this.tvQuotaLimit ?? defaultQuotas.tv.quotaLimit ? (this.tvQuotaLimit ?? defaultQuotas.tv.quotaLimit)
: 0; : 0;
const tvQuotaDays = this.tvQuotaDays ?? defaultQuotas.tv.quotaDays; const tvQuotaDays = this.tvQuotaDays ?? defaultQuotas.tv.quotaDays;

View File

@@ -513,8 +513,8 @@ class AvailabilitySync {
mediaServerType === MediaServerType.PLEX mediaServerType === MediaServerType.PLEX
? 'plex' ? 'plex'
: mediaServerType === MediaServerType.JELLYFIN : mediaServerType === MediaServerType.JELLYFIN
? 'jellyfin' ? 'jellyfin'
: 'emby' : 'emby'
} instance. Status will be changed to deleted.`, } instance. Status will be changed to deleted.`,
{ label: 'AvailabilitySync' } { label: 'AvailabilitySync' }
); );
@@ -588,8 +588,8 @@ class AvailabilitySync {
mediaServerType === MediaServerType.PLEX mediaServerType === MediaServerType.PLEX
? 'plex' ? 'plex'
: mediaServerType === MediaServerType.JELLYFIN : mediaServerType === MediaServerType.JELLYFIN
? 'jellyfin' ? 'jellyfin'
: 'emby' : 'emby'
} instance. Status will be changed to deleted.`, } instance. Status will be changed to deleted.`,
{ label: 'AvailabilitySync' } { label: 'AvailabilitySync' }
); );

View File

@@ -209,8 +209,8 @@ class DiscordAgent
? payload.issue ? payload.issue
? `${applicationUrl}/issues/${payload.issue.id}` ? `${applicationUrl}/issues/${payload.issue.id}`
: payload.media : payload.media
? `${applicationUrl}/${payload.media.mediaType}/${payload.media.tmdbId}` ? `${applicationUrl}/${payload.media.mediaType}/${payload.media.tmdbId}`
: undefined : undefined
: undefined; : undefined;
return { return {

View File

@@ -158,8 +158,8 @@ class PushoverAgent
? payload.issue ? payload.issue
? `${applicationUrl}/issues/${payload.issue.id}` ? `${applicationUrl}/issues/${payload.issue.id}`
: payload.media : payload.media
? `${applicationUrl}/${payload.media.mediaType}/${payload.media.tmdbId}` ? `${applicationUrl}/${payload.media.mediaType}/${payload.media.tmdbId}`
: undefined : undefined
: undefined; : undefined;
const url_title = url const url_title = url
? `View ${payload.issue ? 'Issue' : 'Media'} in ${applicationTitle}` ? `View ${payload.issue ? 'Issue' : 'Media'} in ${applicationTitle}`

View File

@@ -183,8 +183,8 @@ class SlackAgent
? payload.issue ? payload.issue
? `${applicationUrl}/issues/${payload.issue.id}` ? `${applicationUrl}/issues/${payload.issue.id}`
: payload.media : payload.media
? `${applicationUrl}/${payload.media.mediaType}/${payload.media.tmdbId}` ? `${applicationUrl}/${payload.media.mediaType}/${payload.media.tmdbId}`
: undefined : undefined
: undefined; : undefined;
if (url) { if (url) {

View File

@@ -133,8 +133,8 @@ class TelegramAgent
? payload.issue ? payload.issue
? `${applicationUrl}/issues/${payload.issue.id}` ? `${applicationUrl}/issues/${payload.issue.id}`
: payload.media : payload.media
? `${applicationUrl}/${payload.media.mediaType}/${payload.media.tmdbId}` ? `${applicationUrl}/${payload.media.mediaType}/${payload.media.tmdbId}`
: undefined : undefined
: undefined; : undefined;
if (url) { if (url) {

View File

@@ -122,7 +122,7 @@ class WebhookAgent
`{{${keymapKey}}}`, `{{${keymapKey}}}`,
typeof keymapValue === 'function' typeof keymapValue === 'function'
? keymapValue(payload, type) ? keymapValue(payload, type)
: get(payload, keymapValue) ?? '' : (get(payload, keymapValue) ?? '')
); );
}); });
} else if (finalPayload[key] && typeof finalPayload[key] === 'object') { } else if (finalPayload[key] && typeof finalPayload[key] === 'object') {
@@ -186,8 +186,8 @@ class WebhookAgent
type === Notification.TEST_NOTIFICATION type === Notification.TEST_NOTIFICATION
? 'test' ? 'test'
: typeof keymapValue === 'function' : typeof keymapValue === 'function'
? keymapValue(payload, type) ? keymapValue(payload, type)
: get(payload, keymapValue) || 'test'; : get(payload, keymapValue) || 'test';
webhookUrl = webhookUrl.replace( webhookUrl = webhookUrl.replace(
new RegExp(`{{${keymapKey}}}`, 'g'), new RegExp(`{{${keymapKey}}}`, 'g'),
encodeURIComponent(variableValue) encodeURIComponent(variableValue)

View File

@@ -128,8 +128,8 @@ class WebPushAgent
const actionUrl = payload.issue const actionUrl = payload.issue
? `/issues/${payload.issue.id}` ? `/issues/${payload.issue.id}`
: payload.media : payload.media
? `/${payload.media.mediaType}/${payload.media.tmdbId}` ? `/${payload.media.mediaType}/${payload.media.tmdbId}`
: undefined; : undefined;
const actionUrlTitle = actionUrl const actionUrlTitle = actionUrl
? `View ${payload.issue ? 'Issue' : 'Media'}` ? `View ${payload.issue ? 'Issue' : 'Media'}`

View File

@@ -118,8 +118,8 @@ class BaseScanner<T> {
existing[is4k ? 'status4k' : 'status'] = !processing existing[is4k ? 'status4k' : 'status'] = !processing
? MediaStatus.AVAILABLE ? MediaStatus.AVAILABLE
: existing[is4k ? 'status4k' : 'status'] === MediaStatus.DELETED : existing[is4k ? 'status4k' : 'status'] === MediaStatus.DELETED
? MediaStatus.DELETED ? MediaStatus.DELETED
: MediaStatus.PROCESSING; : MediaStatus.PROCESSING;
if (mediaAddedAt) { if (mediaAddedAt) {
existing.mediaAddedAt = mediaAddedAt; existing.mediaAddedAt = mediaAddedAt;
} }
@@ -200,14 +200,14 @@ class BaseScanner<T> {
!is4k && !processing !is4k && !processing
? MediaStatus.AVAILABLE ? MediaStatus.AVAILABLE
: !is4k && processing : !is4k && processing
? MediaStatus.PROCESSING ? MediaStatus.PROCESSING
: MediaStatus.UNKNOWN; : MediaStatus.UNKNOWN;
newMedia.status4k = newMedia.status4k =
is4k && this.enable4kMovie && !processing is4k && this.enable4kMovie && !processing
? MediaStatus.AVAILABLE ? MediaStatus.AVAILABLE
: is4k && this.enable4kMovie && processing : is4k && this.enable4kMovie && processing
? MediaStatus.PROCESSING ? MediaStatus.PROCESSING
: MediaStatus.UNKNOWN; : MediaStatus.UNKNOWN;
newMedia.mediaType = MediaType.MOVIE; newMedia.mediaType = MediaType.MOVIE;
newMedia.serviceId = !is4k ? serviceId : undefined; newMedia.serviceId = !is4k ? serviceId : undefined;
newMedia.serviceId4k = is4k ? serviceId : undefined; newMedia.serviceId4k = is4k ? serviceId : undefined;
@@ -327,17 +327,17 @@ class BaseScanner<T> {
existingSeason.status === MediaStatus.AVAILABLE existingSeason.status === MediaStatus.AVAILABLE
? MediaStatus.AVAILABLE ? MediaStatus.AVAILABLE
: season.episodes > 0 : season.episodes > 0
? MediaStatus.PARTIALLY_AVAILABLE ? MediaStatus.PARTIALLY_AVAILABLE
: !season.is4kOverride && : !season.is4kOverride &&
season.processing && season.processing &&
existingSeason.status !== MediaStatus.DELETED existingSeason.status !== MediaStatus.DELETED
? MediaStatus.PROCESSING ? MediaStatus.PROCESSING
: !season.is4kOverride && : !season.is4kOverride &&
!season.processing && !season.processing &&
season.episodes === 0 && season.episodes === 0 &&
existingSeason.status === MediaStatus.PROCESSING existingSeason.status === MediaStatus.PROCESSING
? MediaStatus.UNKNOWN ? MediaStatus.UNKNOWN
: existingSeason.status; : existingSeason.status;
// Same thing here, except we only do updates if 4k is enabled // Same thing here, except we only do updates if 4k is enabled
existingSeason.status4k = existingSeason.status4k =
@@ -347,17 +347,17 @@ class BaseScanner<T> {
existingSeason.status4k === MediaStatus.AVAILABLE existingSeason.status4k === MediaStatus.AVAILABLE
? MediaStatus.AVAILABLE ? MediaStatus.AVAILABLE
: this.enable4kShow && season.episodes4k > 0 : this.enable4kShow && season.episodes4k > 0
? MediaStatus.PARTIALLY_AVAILABLE ? MediaStatus.PARTIALLY_AVAILABLE
: season.is4kOverride && : season.is4kOverride &&
season.processing && season.processing &&
existingSeason.status4k !== MediaStatus.DELETED existingSeason.status4k !== MediaStatus.DELETED
? MediaStatus.PROCESSING ? MediaStatus.PROCESSING
: season.is4kOverride && : season.is4kOverride &&
!season.processing && !season.processing &&
season.episodes4k === 0 && season.episodes4k === 0 &&
existingSeason.status4k === MediaStatus.PROCESSING existingSeason.status4k === MediaStatus.PROCESSING
? MediaStatus.UNKNOWN ? MediaStatus.UNKNOWN
: existingSeason.status4k; : existingSeason.status4k;
} else { } else {
newSeasons.push( newSeasons.push(
new Season({ new Season({
@@ -366,20 +366,20 @@ class BaseScanner<T> {
season.totalEpisodes === season.episodes && season.episodes > 0 season.totalEpisodes === season.episodes && season.episodes > 0
? MediaStatus.AVAILABLE ? MediaStatus.AVAILABLE
: season.episodes > 0 : season.episodes > 0
? MediaStatus.PARTIALLY_AVAILABLE ? MediaStatus.PARTIALLY_AVAILABLE
: !season.is4kOverride && season.processing : !season.is4kOverride && season.processing
? MediaStatus.PROCESSING ? MediaStatus.PROCESSING
: MediaStatus.UNKNOWN, : MediaStatus.UNKNOWN,
status4k: status4k:
this.enable4kShow && this.enable4kShow &&
season.totalEpisodes === season.episodes4k && season.totalEpisodes === season.episodes4k &&
season.episodes4k > 0 season.episodes4k > 0
? MediaStatus.AVAILABLE ? MediaStatus.AVAILABLE
: this.enable4kShow && season.episodes4k > 0 : this.enable4kShow && season.episodes4k > 0
? MediaStatus.PARTIALLY_AVAILABLE ? MediaStatus.PARTIALLY_AVAILABLE
: season.is4kOverride && season.processing : season.is4kOverride && season.processing
? MediaStatus.PROCESSING ? MediaStatus.PROCESSING
: MediaStatus.UNKNOWN, : MediaStatus.UNKNOWN,
}) })
); );
} }
@@ -486,37 +486,37 @@ class BaseScanner<T> {
isAllStandardSeasons || shouldStayAvailable isAllStandardSeasons || shouldStayAvailable
? MediaStatus.AVAILABLE ? MediaStatus.AVAILABLE
: media.seasons.some( : media.seasons.some(
(season) => (season) =>
season.status === MediaStatus.PARTIALLY_AVAILABLE || season.status === MediaStatus.PARTIALLY_AVAILABLE ||
season.status === MediaStatus.AVAILABLE season.status === MediaStatus.AVAILABLE
) )
? MediaStatus.PARTIALLY_AVAILABLE ? MediaStatus.PARTIALLY_AVAILABLE
: (!seasons.length && media.status !== MediaStatus.DELETED) || : (!seasons.length && media.status !== MediaStatus.DELETED) ||
media.seasons.some( media.seasons.some(
(season) => season.status === MediaStatus.PROCESSING (season) => season.status === MediaStatus.PROCESSING
) )
? MediaStatus.PROCESSING ? MediaStatus.PROCESSING
: media.status === MediaStatus.DELETED : media.status === MediaStatus.DELETED
? MediaStatus.DELETED ? MediaStatus.DELETED
: MediaStatus.UNKNOWN; : MediaStatus.UNKNOWN;
media.status4k = media.status4k =
(isAll4kSeasons || shouldStayAvailable4k) && this.enable4kShow (isAll4kSeasons || shouldStayAvailable4k) && this.enable4kShow
? MediaStatus.AVAILABLE ? MediaStatus.AVAILABLE
: this.enable4kShow && : this.enable4kShow &&
media.seasons.some( media.seasons.some(
(season) => (season) =>
season.status4k === MediaStatus.PARTIALLY_AVAILABLE || season.status4k === MediaStatus.PARTIALLY_AVAILABLE ||
season.status4k === MediaStatus.AVAILABLE season.status4k === MediaStatus.AVAILABLE
) )
? MediaStatus.PARTIALLY_AVAILABLE ? MediaStatus.PARTIALLY_AVAILABLE
: (!seasons.length && media.status4k !== MediaStatus.DELETED) || : (!seasons.length && media.status4k !== MediaStatus.DELETED) ||
media.seasons.some( media.seasons.some(
(season) => season.status4k === MediaStatus.PROCESSING (season) => season.status4k === MediaStatus.PROCESSING
) )
? MediaStatus.PROCESSING ? MediaStatus.PROCESSING
: media.status4k === MediaStatus.DELETED : media.status4k === MediaStatus.DELETED
? MediaStatus.DELETED ? MediaStatus.DELETED
: MediaStatus.UNKNOWN; : MediaStatus.UNKNOWN;
await mediaRepository.save(media); await mediaRepository.save(media);
this.log(`Updating existing title: ${title}`); this.log(`Updating existing title: ${title}`);
} else { } else {
@@ -567,31 +567,31 @@ class BaseScanner<T> {
status: isAllStandardSeasons status: isAllStandardSeasons
? MediaStatus.AVAILABLE ? MediaStatus.AVAILABLE
: newSeasons.some( : newSeasons.some(
(season) => (season) =>
season.status === MediaStatus.PARTIALLY_AVAILABLE || season.status === MediaStatus.PARTIALLY_AVAILABLE ||
season.status === MediaStatus.AVAILABLE season.status === MediaStatus.AVAILABLE
) )
? MediaStatus.PARTIALLY_AVAILABLE ? MediaStatus.PARTIALLY_AVAILABLE
: newSeasons.some( : newSeasons.some(
(season) => season.status === MediaStatus.PROCESSING (season) => season.status === MediaStatus.PROCESSING
) )
? MediaStatus.PROCESSING ? MediaStatus.PROCESSING
: MediaStatus.UNKNOWN, : MediaStatus.UNKNOWN,
status4k: status4k:
isAll4kSeasons && this.enable4kShow isAll4kSeasons && this.enable4kShow
? MediaStatus.AVAILABLE ? MediaStatus.AVAILABLE
: this.enable4kShow && : this.enable4kShow &&
newSeasons.some( newSeasons.some(
(season) => (season) =>
season.status4k === MediaStatus.PARTIALLY_AVAILABLE || season.status4k === MediaStatus.PARTIALLY_AVAILABLE ||
season.status4k === MediaStatus.AVAILABLE season.status4k === MediaStatus.AVAILABLE
) )
? MediaStatus.PARTIALLY_AVAILABLE ? MediaStatus.PARTIALLY_AVAILABLE
: newSeasons.some( : newSeasons.some(
(season) => season.status4k === MediaStatus.PROCESSING (season) => season.status4k === MediaStatus.PROCESSING
) )
? MediaStatus.PROCESSING ? MediaStatus.PROCESSING
: MediaStatus.UNKNOWN, : MediaStatus.UNKNOWN,
}); });
await mediaRepository.save(newMedia); await mediaRepository.save(newMedia);
this.log(`Saved ${title}`); this.log(`Saved ${title}`);

View File

@@ -59,12 +59,11 @@ searchProviders.push({
const successfulResponses = responses.filter( const successfulResponses = responses.filter(
(r) => r.status === 'fulfilled' (r) => r.status === 'fulfilled'
) as ) as (
| ( | PromiseFulfilledResult<TmdbMovieDetails>
| PromiseFulfilledResult<TmdbMovieDetails> | PromiseFulfilledResult<TmdbTvDetails>
| PromiseFulfilledResult<TmdbTvDetails> | PromiseFulfilledResult<TmdbPersonDetails>
| PromiseFulfilledResult<TmdbPersonDetails> )[];
)[];
const results: (TmdbMovieResult | TmdbTvResult | TmdbPersonResult)[] = []; const results: (TmdbMovieResult | TmdbTvResult | TmdbPersonResult)[] = [];
@@ -185,11 +184,10 @@ searchProviders.push({
const successfulResponses = responses.filter( const successfulResponses = responses.filter(
(r) => r.status === 'fulfilled' (r) => r.status === 'fulfilled'
) as ) as (
| ( | PromiseFulfilledResult<TmdbSearchMovieResponse>
| PromiseFulfilledResult<TmdbSearchMovieResponse> | PromiseFulfilledResult<TmdbSearchTvResponse>
| PromiseFulfilledResult<TmdbSearchTvResponse> )[];
)[];
const results: (TmdbMovieResult | TmdbTvResult)[] = []; const results: (TmdbMovieResult | TmdbTvResult)[] = [];

View File

@@ -1,8 +1,6 @@
import type { MigrationInterface, QueryRunner } from 'typeorm'; import type { MigrationInterface, QueryRunner } from 'typeorm';
export class AddTelegramMessageThreadId1734786596045 export class AddTelegramMessageThreadId1734786596045 implements MigrationInterface {
implements MigrationInterface
{
name = 'AddTelegramMessageThreadId1734786596045'; name = 'AddTelegramMessageThreadId1734786596045';
public async up(queryRunner: QueryRunner): Promise<void> { public async up(queryRunner: QueryRunner): Promise<void> {

View File

@@ -1,8 +1,6 @@
import type { MigrationInterface, QueryRunner } from 'typeorm'; import type { MigrationInterface, QueryRunner } from 'typeorm';
export class AddUserAvatarCacheFields1743107707465 export class AddUserAvatarCacheFields1743107707465 implements MigrationInterface {
implements MigrationInterface
{
name = 'AddUserAvatarCacheFields1743107707465'; name = 'AddUserAvatarCacheFields1743107707465';
public async up(queryRunner: QueryRunner): Promise<void> { public async up(queryRunner: QueryRunner): Promise<void> {

View File

@@ -1,8 +1,6 @@
import type { MigrationInterface, QueryRunner } from 'typeorm'; import type { MigrationInterface, QueryRunner } from 'typeorm';
export class AddUniqueConstraintToPushSubscription1765233385034 export class AddUniqueConstraintToPushSubscription1765233385034 implements MigrationInterface {
implements MigrationInterface
{
name = 'AddUniqueConstraintToPushSubscription1765233385034'; name = 'AddUniqueConstraintToPushSubscription1765233385034';
public async up(queryRunner: QueryRunner): Promise<void> { public async up(queryRunner: QueryRunner): Promise<void> {

View File

@@ -1,8 +1,6 @@
import type { MigrationInterface, QueryRunner } from 'typeorm'; import type { MigrationInterface, QueryRunner } from 'typeorm';
export class AddUserRequestDeleteCascades1608219049304 export class AddUserRequestDeleteCascades1608219049304 implements MigrationInterface {
implements MigrationInterface
{
name = 'AddUserRequestDeleteCascades1608219049304'; name = 'AddUserRequestDeleteCascades1608219049304';
public async up(queryRunner: QueryRunner): Promise<void> { public async up(queryRunner: QueryRunner): Promise<void> {

View File

@@ -1,8 +1,6 @@
import type { MigrationInterface, QueryRunner } from 'typeorm'; import type { MigrationInterface, QueryRunner } from 'typeorm';
export class AddLastSeasonChangeMedia1608477467935 export class AddLastSeasonChangeMedia1608477467935 implements MigrationInterface {
implements MigrationInterface
{
name = 'AddLastSeasonChangeMedia1608477467935'; name = 'AddLastSeasonChangeMedia1608477467935';
public async up(queryRunner: QueryRunner): Promise<void> { public async up(queryRunner: QueryRunner): Promise<void> {

View File

@@ -1,8 +1,6 @@
import type { MigrationInterface, QueryRunner } from 'typeorm'; import type { MigrationInterface, QueryRunner } from 'typeorm';
export class ForceDropImdbUniqueConstraint1608477467935 export class ForceDropImdbUniqueConstraint1608477467935 implements MigrationInterface {
implements MigrationInterface
{
name = 'ForceDropImdbUniqueConstraint1608477467936'; name = 'ForceDropImdbUniqueConstraint1608477467936';
public async up(queryRunner: QueryRunner): Promise<void> { public async up(queryRunner: QueryRunner): Promise<void> {

View File

@@ -1,8 +1,6 @@
import type { MigrationInterface, QueryRunner } from 'typeorm'; import type { MigrationInterface, QueryRunner } from 'typeorm';
export class RemoveTmdbIdUniqueConstraint1609236552057 export class RemoveTmdbIdUniqueConstraint1609236552057 implements MigrationInterface {
implements MigrationInterface
{
name = 'RemoveTmdbIdUniqueConstraint1609236552057'; name = 'RemoveTmdbIdUniqueConstraint1609236552057';
public async up(queryRunner: QueryRunner): Promise<void> { public async up(queryRunner: QueryRunner): Promise<void> {

View File

@@ -1,8 +1,6 @@
import type { MigrationInterface, QueryRunner } from 'typeorm'; import type { MigrationInterface, QueryRunner } from 'typeorm';
export class AddMediaAddedFieldToMedia1610522845513 export class AddMediaAddedFieldToMedia1610522845513 implements MigrationInterface {
implements MigrationInterface
{
name = 'AddMediaAddedFieldToMedia1610522845513'; name = 'AddMediaAddedFieldToMedia1610522845513';
public async up(queryRunner: QueryRunner): Promise<void> { public async up(queryRunner: QueryRunner): Promise<void> {

View File

@@ -1,8 +1,6 @@
import type { MigrationInterface, QueryRunner } from 'typeorm'; import type { MigrationInterface, QueryRunner } from 'typeorm';
export class SonarrRadarrSyncServiceFields1611757511674 export class SonarrRadarrSyncServiceFields1611757511674 implements MigrationInterface {
implements MigrationInterface
{
name = 'SonarrRadarrSyncServiceFields1611757511674'; name = 'SonarrRadarrSyncServiceFields1611757511674';
public async up(queryRunner: QueryRunner): Promise<void> { public async up(queryRunner: QueryRunner): Promise<void> {

View File

@@ -1,8 +1,6 @@
import type { MigrationInterface, QueryRunner } from 'typeorm'; import type { MigrationInterface, QueryRunner } from 'typeorm';
export class AddResetPasswordGuidAndExpiryDate1612482778137 export class AddResetPasswordGuidAndExpiryDate1612482778137 implements MigrationInterface {
implements MigrationInterface
{
name = 'AddResetPasswordGuidAndExpiryDate1612482778137'; name = 'AddResetPasswordGuidAndExpiryDate1612482778137';
public async up(queryRunner: QueryRunner): Promise<void> { public async up(queryRunner: QueryRunner): Promise<void> {

View File

@@ -1,8 +1,6 @@
import type { MigrationInterface, QueryRunner } from 'typeorm'; import type { MigrationInterface, QueryRunner } from 'typeorm';
export class UpdateUserSettingsRegions1613955393450 export class UpdateUserSettingsRegions1613955393450 implements MigrationInterface {
implements MigrationInterface
{
name = 'UpdateUserSettingsRegions1613955393450'; name = 'UpdateUserSettingsRegions1613955393450';
public async up(queryRunner: QueryRunner): Promise<void> { public async up(queryRunner: QueryRunner): Promise<void> {

View File

@@ -1,8 +1,6 @@
import type { MigrationInterface, QueryRunner } from 'typeorm'; import type { MigrationInterface, QueryRunner } from 'typeorm';
export class AddTelegramSettingsToUserSettings1614334195680 export class AddTelegramSettingsToUserSettings1614334195680 implements MigrationInterface {
implements MigrationInterface
{
name = 'AddTelegramSettingsToUserSettings1614334195680'; name = 'AddTelegramSettingsToUserSettings1614334195680';
public async up(queryRunner: QueryRunner): Promise<void> { public async up(queryRunner: QueryRunner): Promise<void> {

View File

@@ -1,8 +1,6 @@
import type { MigrationInterface, QueryRunner } from 'typeorm'; import type { MigrationInterface, QueryRunner } from 'typeorm';
export class CreateTagsFieldonMediaRequest1617624225464 export class CreateTagsFieldonMediaRequest1617624225464 implements MigrationInterface {
implements MigrationInterface
{
name = 'CreateTagsFieldonMediaRequest1617624225464'; name = 'CreateTagsFieldonMediaRequest1617624225464';
public async up(queryRunner: QueryRunner): Promise<void> { public async up(queryRunner: QueryRunner): Promise<void> {

View File

@@ -1,8 +1,6 @@
import type { MigrationInterface, QueryRunner } from 'typeorm'; import type { MigrationInterface, QueryRunner } from 'typeorm';
export class AddUserSettingsNotificationAgentsField1617730837489 export class AddUserSettingsNotificationAgentsField1617730837489 implements MigrationInterface {
implements MigrationInterface
{
name = 'AddUserSettingsNotificationAgentsField1617730837489'; name = 'AddUserSettingsNotificationAgentsField1617730837489';
public async up(queryRunner: QueryRunner): Promise<void> { public async up(queryRunner: QueryRunner): Promise<void> {

View File

@@ -1,8 +1,6 @@
import type { MigrationInterface, QueryRunner } from 'typeorm'; import type { MigrationInterface, QueryRunner } from 'typeorm';
export class CreateUserPushSubscriptions1618912653565 export class CreateUserPushSubscriptions1618912653565 implements MigrationInterface {
implements MigrationInterface
{
name = 'CreateUserPushSubscriptions1618912653565'; name = 'CreateUserPushSubscriptions1618912653565';
public async up(queryRunner: QueryRunner): Promise<void> { public async up(queryRunner: QueryRunner): Promise<void> {

View File

@@ -1,8 +1,6 @@
import type { MigrationInterface, QueryRunner } from 'typeorm'; import type { MigrationInterface, QueryRunner } from 'typeorm';
export class AddUserSettingsNotificationTypes1619339817343 export class AddUserSettingsNotificationTypes1619339817343 implements MigrationInterface {
implements MigrationInterface
{
name = 'AddUserSettingsNotificationTypes1619339817343'; name = 'AddUserSettingsNotificationTypes1619339817343';
public async up(queryRunner: QueryRunner): Promise<void> { public async up(queryRunner: QueryRunner): Promise<void> {

View File

@@ -1,8 +1,6 @@
import type { MigrationInterface, QueryRunner } from 'typeorm'; import type { MigrationInterface, QueryRunner } from 'typeorm';
export class AddPushbulletPushoverUserSettings1635079863457 export class AddPushbulletPushoverUserSettings1635079863457 implements MigrationInterface {
implements MigrationInterface
{
name = 'AddPushbulletPushoverUserSettings1635079863457'; name = 'AddPushbulletPushoverUserSettings1635079863457';
public async up(queryRunner: QueryRunner): Promise<void> { public async up(queryRunner: QueryRunner): Promise<void> {

View File

@@ -1,8 +1,6 @@
import type { MigrationInterface, QueryRunner } from 'typeorm'; import type { MigrationInterface, QueryRunner } from 'typeorm';
export class AddWatchlistSyncUserSetting1660632269368 export class AddWatchlistSyncUserSetting1660632269368 implements MigrationInterface {
implements MigrationInterface
{
name = 'AddWatchlistSyncUserSetting1660632269368'; name = 'AddWatchlistSyncUserSetting1660632269368';
public async up(queryRunner: QueryRunner): Promise<void> { public async up(queryRunner: QueryRunner): Promise<void> {

View File

@@ -1,8 +1,6 @@
import type { MigrationInterface, QueryRunner } from 'typeorm'; import type { MigrationInterface, QueryRunner } from 'typeorm';
export class AddMediaRequestIsAutoRequestedField1660714479373 export class AddMediaRequestIsAutoRequestedField1660714479373 implements MigrationInterface {
implements MigrationInterface
{
name = 'AddMediaRequestIsAutoRequestedField1660714479373'; name = 'AddMediaRequestIsAutoRequestedField1660714479373';
public async up(queryRunner: QueryRunner): Promise<void> { public async up(queryRunner: QueryRunner): Promise<void> {

View File

@@ -1,8 +1,6 @@
import type { MigrationInterface, QueryRunner } from 'typeorm'; import type { MigrationInterface, QueryRunner } from 'typeorm';
export class AddUserSettingsStreamingRegion1727907530757 export class AddUserSettingsStreamingRegion1727907530757 implements MigrationInterface {
implements MigrationInterface
{
name = 'AddUserSettingsStreamingRegion1727907530757'; name = 'AddUserSettingsStreamingRegion1727907530757';
public async up(queryRunner: QueryRunner): Promise<void> { public async up(queryRunner: QueryRunner): Promise<void> {

View File

@@ -1,8 +1,6 @@
import type { MigrationInterface, QueryRunner } from 'typeorm'; import type { MigrationInterface, QueryRunner } from 'typeorm';
export class AddTelegramMessageThreadId1734287582736 export class AddTelegramMessageThreadId1734287582736 implements MigrationInterface {
implements MigrationInterface
{
name = 'AddTelegramMessageThreadId1734287582736'; name = 'AddTelegramMessageThreadId1734287582736';
public async up(queryRunner: QueryRunner): Promise<void> { public async up(queryRunner: QueryRunner): Promise<void> {

View File

@@ -1,8 +1,6 @@
import type { MigrationInterface, QueryRunner } from 'typeorm'; import type { MigrationInterface, QueryRunner } from 'typeorm';
export class AddUserAvatarCacheFields1743107645301 export class AddUserAvatarCacheFields1743107645301 implements MigrationInterface {
implements MigrationInterface
{
name = 'AddUserAvatarCacheFields1743107645301'; name = 'AddUserAvatarCacheFields1743107645301';
public async up(queryRunner: QueryRunner): Promise<void> { public async up(queryRunner: QueryRunner): Promise<void> {

View File

@@ -1,8 +1,6 @@
import type { MigrationInterface, QueryRunner } from 'typeorm'; import type { MigrationInterface, QueryRunner } from 'typeorm';
export class AddUniqueConstraintToPushSubscription1765233385034 export class AddUniqueConstraintToPushSubscription1765233385034 implements MigrationInterface {
implements MigrationInterface
{
name = 'AddUniqueConstraintToPushSubscription1765233385034'; name = 'AddUniqueConstraintToPushSubscription1765233385034';
public async up(queryRunner: QueryRunner): Promise<void> { public async up(queryRunner: QueryRunner): Promise<void> {

View File

@@ -149,7 +149,7 @@ export const mapWatchProviders = (watchProvidersResult: {
link: provider.link, link: provider.link,
buy: mapWatchProviderDetails(provider.buy ?? []), buy: mapWatchProviderDetails(provider.buy ?? []),
flatrate: mapWatchProviderDetails(provider.flatrate ?? []), flatrate: mapWatchProviderDetails(provider.flatrate ?? []),
} as WatchProviders) }) as WatchProviders
); );
export const mapWatchProviderDetails = ( export const mapWatchProviderDetails = (
@@ -162,10 +162,10 @@ export const mapWatchProviderDetails = (
logoPath: provider.logo_path, logoPath: provider.logo_path,
id: provider.provider_id, id: provider.provider_id,
name: provider.provider_name, name: provider.provider_name,
} as WatchProviderDetails) }) as WatchProviderDetails
); );
const siteUrlCreator = (site: Video['site'], key: string): string => const siteUrlCreator = (site: Video['site'], key: string): string =>
({ ({
YouTube: `https://www.youtube.com/watch?v=${key}`, YouTube: `https://www.youtube.com/watch?v=${key}`,
}[site]); })[site];

View File

@@ -33,15 +33,15 @@ export const createTmdbWithRegionLanguage = (user?: User): TheMovieDb => {
user?.settings?.streamingRegion === 'all' user?.settings?.streamingRegion === 'all'
? '' ? ''
: user?.settings?.streamingRegion : user?.settings?.streamingRegion
? user?.settings?.streamingRegion ? user?.settings?.streamingRegion
: settings.main.discoverRegion; : settings.main.discoverRegion;
const originalLanguage = const originalLanguage =
user?.settings?.originalLanguage === 'all' user?.settings?.originalLanguage === 'all'
? '' ? ''
: user?.settings?.originalLanguage : user?.settings?.originalLanguage
? user?.settings?.originalLanguage ? user?.settings?.originalLanguage
: settings.main.originalLanguage; : settings.main.originalLanguage;
return new TheMovieDb({ return new TheMovieDb({
discoverRegion, discoverRegion,
@@ -697,16 +697,16 @@ discoverRoutes.get('/trending', async (req, res, next) => {
) )
) )
: isPerson(result) : isPerson(result)
? mapPersonResult(result) ? mapPersonResult(result)
: isCollection(result) : isCollection(result)
? mapCollectionResult(result) ? mapCollectionResult(result)
: mapTvResult( : mapTvResult(
result, result,
media.find( media.find(
(med) => (med) =>
med.tmdbId === result.id && med.mediaType === MediaType.TV med.tmdbId === result.id && med.mediaType === MediaType.TV
) )
) )
), ),
}); });
} catch (e) { } catch (e) {

View File

@@ -13,9 +13,7 @@ import type { EntitySubscriberInterface, InsertEvent } from 'typeorm';
import { EventSubscriber } from 'typeorm'; import { EventSubscriber } from 'typeorm';
@EventSubscriber() @EventSubscriber()
export class IssueCommentSubscriber export class IssueCommentSubscriber implements EntitySubscriberInterface<IssueComment> {
implements EntitySubscriberInterface<IssueComment>
{
public listenTo(): typeof IssueComment { public listenTo(): typeof IssueComment {
return IssueComment; return IssueComment;
} }

View File

@@ -67,16 +67,16 @@ export class IssueSubscriber implements EntitySubscriberInterface<Issue> {
: '' : ''
}Issue Reported` }Issue Reported`
: type === Notification.ISSUE_RESOLVED : type === Notification.ISSUE_RESOLVED
? `${ ? `${
entity.issueType !== IssueType.OTHER entity.issueType !== IssueType.OTHER
? `${IssueTypeName[entity.issueType]} ` ? `${IssueTypeName[entity.issueType]} `
: '' : ''
}Issue Resolved` }Issue Resolved`
: `${ : `${
entity.issueType !== IssueType.OTHER entity.issueType !== IssueType.OTHER
? `${IssueTypeName[entity.issueType]} ` ? `${IssueTypeName[entity.issueType]} `
: '' : ''
}Issue Reopened`, }Issue Reopened`,
subject: title, subject: title,
message: firstComment.message, message: firstComment.message,
issue: entity, issue: entity,

View File

@@ -40,9 +40,7 @@ const sanitizeDisplayName = (displayName: string): string => {
}; };
@EventSubscriber() @EventSubscriber()
export class MediaRequestSubscriber export class MediaRequestSubscriber implements EntitySubscriberInterface<MediaRequest> {
implements EntitySubscriberInterface<MediaRequest>
{
private async notifyAvailableMovie( private async notifyAvailableMovie(
entity: MediaRequest, entity: MediaRequest,
event?: UpdateEvent<MediaRequest> event?: UpdateEvent<MediaRequest>
@@ -573,8 +571,8 @@ export class MediaRequestSubscriber
? [...sonarrSettings.animeTags] ? [...sonarrSettings.animeTags]
: [] : []
: sonarrSettings.tags : sonarrSettings.tags
? [...sonarrSettings.tags] ? [...sonarrSettings.tags]
: []; : [];
if ( if (
entity.rootFolder && entity.rootFolder &&

View File

@@ -1,7 +1,10 @@
import type { ApiErrorCode } from '@server/constants/error'; import type { ApiErrorCode } from '@server/constants/error';
export class ApiError extends Error { export class ApiError extends Error {
constructor(public statusCode: number, public errorCode: ApiErrorCode) { constructor(
public statusCode: number,
public errorCode: ApiErrorCode
) {
super(); super();
this.name = 'apiError'; this.name = 'apiError';

View File

@@ -385,7 +385,7 @@ const BlacklistedItem = ({ item, revalidateList }: BlacklistedItemProps) => {
</div> </div>
</div> </div>
<div className="z-10 mt-4 ml-4 flex w-full flex-col justify-center overflow-hidden pr-4 text-sm sm:ml-2 sm:mt-0 xl:flex-1 xl:pr-0"> <div className="z-10 ml-4 mt-4 flex w-full flex-col justify-center overflow-hidden pr-4 text-sm sm:ml-2 sm:mt-0 xl:flex-1 xl:pr-0">
<div className="card-field"> <div className="card-field">
<span className="card-field-name">Status</span> <span className="card-field-name">Status</span>
<Badge badgeType="danger"> <Badge badgeType="danger">

View File

@@ -329,7 +329,7 @@ const BlacklistedTagImportForm = forwardRef<
const VerifyClearIndicator = < const VerifyClearIndicator = <
Option, Option,
IsMuti extends boolean, IsMuti extends boolean,
Group extends GroupBase<Option> Group extends GroupBase<Option>,
>( >(
props: ClearIndicatorProps<Option, IsMuti, Group> props: ClearIndicatorProps<Option, IsMuti, Group>
) => { ) => {

View File

@@ -13,7 +13,7 @@ export type ButtonType =
// Helper type to override types (overrides onClick) // Helper type to override types (overrides onClick)
type MergeElementProps< type MergeElementProps<
T extends React.ElementType, T extends React.ElementType,
P extends Record<string, unknown> P extends Record<string, unknown>,
> = Omit<React.ComponentProps<T>, keyof P> & P; > = Omit<React.ComponentProps<T>, keyof P> & P;
type ElementTypes = 'button' | 'a'; type ElementTypes = 'button' | 'a';

View File

@@ -57,7 +57,7 @@ const DropdownItems = ({
> >
<Menu.Items <Menu.Items
className={[ className={[
'absolute right-0 z-40 mt-2 -mr-1 w-56 origin-top-right rounded-md p-1 shadow-lg', 'absolute right-0 z-40 -mr-1 mt-2 w-56 origin-top-right rounded-md p-1 shadow-lg',
dropdownType === 'ghost' dropdownType === 'ghost'
? 'border border-gray-700 bg-gray-800 bg-opacity-80 backdrop-blur' ? 'border border-gray-700 bg-gray-800 bg-opacity-80 backdrop-blur'
: 'bg-indigo-600', : 'bg-indigo-600',

View File

@@ -91,7 +91,7 @@ const Modal = React.forwardRef<HTMLDivElement, ModalProps>(
<Transition.Child <Transition.Child
appear appear
as="div" as="div"
className="fixed top-0 bottom-0 left-0 right-0 z-50 flex h-full w-full items-center justify-center bg-gray-800 bg-opacity-70" className="fixed bottom-0 left-0 right-0 top-0 z-50 flex h-full w-full items-center justify-center bg-gray-800 bg-opacity-70"
enter="transition-opacity duration-300" enter="transition-opacity duration-300"
enterFrom="opacity-0" enterFrom="opacity-0"
enterTo="opacity-100" enterTo="opacity-100"
@@ -116,7 +116,7 @@ const Modal = React.forwardRef<HTMLDivElement, ModalProps>(
</div> </div>
</Transition> </Transition>
<Transition <Transition
className={`hide-scrollbar relative inline-block w-full overflow-auto bg-gray-800 px-4 pt-4 pb-4 text-left align-bottom shadow-xl ring-1 ring-gray-700 transition-all sm:my-8 sm:max-w-3xl sm:rounded-lg sm:align-middle ${dialogClass}`} className={`hide-scrollbar relative inline-block w-full overflow-auto bg-gray-800 px-4 pb-4 pt-4 text-left align-bottom shadow-xl ring-1 ring-gray-700 transition-all sm:my-8 sm:max-w-3xl sm:rounded-lg sm:align-middle ${dialogClass}`}
role="dialog" role="dialog"
aria-modal="true" aria-modal="true"
aria-labelledby="modal-headline" aria-labelledby="modal-headline"
@@ -135,7 +135,7 @@ const Modal = React.forwardRef<HTMLDivElement, ModalProps>(
ref={modalRef} ref={modalRef}
> >
{backdrop && ( {backdrop && (
<div className="absolute top-0 left-0 right-0 z-0 h-64 max-h-full w-full"> <div className="absolute left-0 right-0 top-0 z-0 h-64 max-h-full w-full">
<CachedImage <CachedImage
type="tmdb" type="tmdb"
alt="" alt=""

View File

@@ -83,7 +83,7 @@ const MultiRangeSlider = ({
max={max} max={max}
value={valueMax} value={valueMax}
step="1" step="1"
className={`pointer-events-none absolute top-0 left-0 right-0 z-20 h-2 w-full cursor-pointer appearance-none rounded-lg bg-transparent`} className={`pointer-events-none absolute left-0 right-0 top-0 z-20 h-2 w-full cursor-pointer appearance-none rounded-lg bg-transparent`}
onChange={(e) => { onChange={(e) => {
const value = Number(e.target.value); const value = Number(e.target.value);

View File

@@ -35,8 +35,8 @@ const SensitiveInput = ({ as = 'input', ...props }: SensitiveInputProps) => {
isHidden isHidden
? 'password' ? 'password'
: props.type !== 'password' : props.type !== 'password'
? props.type ?? 'text' ? (props.type ?? 'text')
: 'text' : 'text'
} }
/> />
<button <button

View File

@@ -72,7 +72,7 @@ const SlideOver = ({
onClick={(e) => e.stopPropagation()} onClick={(e) => e.stopPropagation()}
> >
<div className="flex h-full flex-col rounded-lg bg-gray-800 bg-opacity-80 shadow-xl ring-1 ring-gray-700 backdrop-blur"> <div className="flex h-full flex-col rounded-lg bg-gray-800 bg-opacity-80 shadow-xl ring-1 ring-gray-700 backdrop-blur">
<header className="space-y-1 border-b border-gray-700 py-4 px-4"> <header className="space-y-1 border-b border-gray-700 px-4 py-4">
<div className="flex items-center justify-between space-x-3"> <div className="flex items-center justify-between space-x-3">
<h2 className="text-overseerr text-2xl font-bold leading-7"> <h2 className="text-overseerr text-2xl font-bold leading-7">
{title} {title}

View File

@@ -78,7 +78,7 @@ type TableProps = {
const Table = ({ children }: TableProps) => { const Table = ({ children }: TableProps) => {
return ( return (
<div className="flex flex-col"> <div className="flex flex-col">
<div className="my-2 -mx-4 overflow-x-auto md:mx-0 lg:mx-0"> <div className="-mx-4 my-2 overflow-x-auto md:mx-0 lg:mx-0">
<div className="inline-block min-w-full py-2 align-middle"> <div className="inline-block min-w-full py-2 align-middle">
<div className="overflow-hidden rounded-lg shadow md:mx-0 lg:mx-0"> <div className="overflow-hidden rounded-lg shadow md:mx-0 lg:mx-0">
<table className="min-w-full">{children}</table> <table className="min-w-full">{children}</table>

View File

@@ -43,7 +43,7 @@ const DiscoverMovieGenre = () => {
return ( return (
<> <>
<PageTitle title={title} /> <PageTitle title={title} />
<div className="mt-1 mb-5"> <div className="mb-5 mt-1">
<Header>{title}</Header> <Header>{title}</Header>
</div> </div>
<ListView <ListView

View File

@@ -49,7 +49,7 @@ const DiscoverMovieKeyword = () => {
return ( return (
<> <>
<PageTitle title={title} /> <PageTitle title={title} />
<div className="mt-1 mb-5"> <div className="mb-5 mt-1">
<Header>{title}</Header> <Header>{title}</Header>
</div> </div>
<ListView <ListView

View File

@@ -52,7 +52,7 @@ const DiscoverMovieLanguage = () => {
return ( return (
<> <>
<PageTitle title={title} /> <PageTitle title={title} />
<div className="mt-1 mb-5"> <div className="mb-5 mt-1">
<Header>{title}</Header> <Header>{title}</Header>
</div> </div>
<ListView <ListView

View File

@@ -45,7 +45,7 @@ const DiscoverTvNetwork = () => {
return ( return (
<> <>
<PageTitle title={title} /> <PageTitle title={title} />
<div className="mt-1 mb-5"> <div className="mb-5 mt-1">
<Header> <Header>
{firstResultData?.network.logoPath ? ( {firstResultData?.network.logoPath ? (
<div className="relative mb-6 flex h-24 justify-center sm:h-32"> <div className="relative mb-6 flex h-24 justify-center sm:h-32">

View File

@@ -195,7 +195,7 @@ const DiscoverSliderEdit = ({
className={`absolute -bottom-2 left-0 w-full border-t-4 border-indigo-500`} className={`absolute -bottom-2 left-0 w-full border-t-4 border-indigo-500`}
/> />
)} )}
<div className="flex w-full flex-col rounded-t-lg border-t border-l border-r border-gray-800 bg-gray-900 p-4 text-gray-400 md:flex-row md:items-center md:space-x-2"> <div className="flex w-full flex-col rounded-t-lg border-l border-r border-t border-gray-800 bg-gray-900 p-4 text-gray-400 md:flex-row md:items-center md:space-x-2">
<div <div
className={`${slider.data ? 'mb-4' : 'mb-0'} flex space-x-2 md:mb-0`} className={`${slider.data ? 'mb-4' : 'mb-0'} flex space-x-2 md:mb-0`}
> >
@@ -285,7 +285,7 @@ const DiscoverSliderEdit = ({
</Button> </Button>
</> </>
)} )}
<div className="absolute right-14 top-4 flex px-2 md:relative md:top-0 md:right-0"> <div className="absolute right-14 top-4 flex px-2 md:relative md:right-0 md:top-0">
<button <button
className={'hover:text-white disabled:text-gray-800'} className={'hover:text-white disabled:text-gray-800'}
onClick={() => onClick={() =>
@@ -305,7 +305,7 @@ const DiscoverSliderEdit = ({
<ChevronDownIcon className="h-7 w-7 md:h-6 md:w-6" /> <ChevronDownIcon className="h-7 w-7 md:h-6 md:w-6" />
</button> </button>
</div> </div>
<div className="absolute top-4 right-4 flex-1 text-right md:relative md:top-0 md:right-0"> <div className="absolute right-4 top-4 flex-1 text-right md:relative md:right-0 md:top-0">
<Tooltip content={intl.formatMessage(messages.enable)}> <Tooltip content={intl.formatMessage(messages.enable)}>
<div> <div>
<SlideCheckbox <SlideCheckbox

View File

@@ -45,7 +45,7 @@ const DiscoverMovieStudio = () => {
return ( return (
<> <>
<PageTitle title={title} /> <PageTitle title={title} />
<div className="mt-1 mb-5"> <div className="mb-5 mt-1">
<Header> <Header>
{firstResultData?.studio.logoPath ? ( {firstResultData?.studio.logoPath ? (
<div className="relative mb-6 flex h-24 justify-center sm:h-32"> <div className="relative mb-6 flex h-24 justify-center sm:h-32">

View File

@@ -43,7 +43,7 @@ const DiscoverTvGenre = () => {
return ( return (
<> <>
<PageTitle title={title} /> <PageTitle title={title} />
<div className="mt-1 mb-5"> <div className="mb-5 mt-1">
<Header>{title}</Header> <Header>{title}</Header>
</div> </div>
<ListView <ListView

View File

@@ -49,7 +49,7 @@ const DiscoverTvKeyword = () => {
return ( return (
<> <>
<PageTitle title={title} /> <PageTitle title={title} />
<div className="mt-1 mb-5"> <div className="mb-5 mt-1">
<Header>{title}</Header> <Header>{title}</Header>
</div> </div>
<ListView <ListView

View File

@@ -52,7 +52,7 @@ const DiscoverTvLanguage = () => {
return ( return (
<> <>
<PageTitle title={title} /> <PageTitle title={title} />
<div className="mt-1 mb-5"> <div className="mb-5 mt-1">
<Header>{title}</Header> <Header>{title}</Header>
</div> </div>
<ListView <ListView

View File

@@ -31,7 +31,7 @@ const DiscoverTvUpcoming = () => {
return ( return (
<> <>
<PageTitle title={intl.formatMessage(messages.upcomingtv)} /> <PageTitle title={intl.formatMessage(messages.upcomingtv)} />
<div className="mt-1 mb-5"> <div className="mb-5 mt-1">
<Header>{intl.formatMessage(messages.upcomingtv)}</Header> <Header>{intl.formatMessage(messages.upcomingtv)}</Header>
</div> </div>
<ListView <ListView

View File

@@ -37,8 +37,8 @@ const DiscoverWatchlist = () => {
router.pathname.startsWith('/profile') router.pathname.startsWith('/profile')
? `user/${currentUser?.id}` ? `user/${currentUser?.id}`
: router.query.userId : router.query.userId
? `user/${router.query.userId}` ? `user/${router.query.userId}`
: 'discover' : 'discover'
}/watchlist` }/watchlist`
); );
@@ -55,7 +55,7 @@ const DiscoverWatchlist = () => {
<PageTitle <PageTitle
title={[title, router.query.userId ? user?.displayName : '']} title={[title, router.query.userId ? user?.displayName : '']}
/> />
<div className="mt-1 mb-5"> <div className="mb-5 mt-1">
<Header <Header
subtext={ subtext={
router.query.userId ? ( router.query.userId ? (

View File

@@ -30,7 +30,7 @@ const MovieGenreList = () => {
return ( return (
<> <>
<PageTitle title={intl.formatMessage(messages.moviegenres)} /> <PageTitle title={intl.formatMessage(messages.moviegenres)} />
<div className="mt-1 mb-5"> <div className="mb-5 mt-1">
<Header>{intl.formatMessage(messages.moviegenres)}</Header> <Header>{intl.formatMessage(messages.moviegenres)}</Header>
</div> </div>
<ul className="cards-horizontal"> <ul className="cards-horizontal">

View File

@@ -36,7 +36,7 @@ const Trending = () => {
return ( return (
<> <>
<PageTitle title={intl.formatMessage(messages.trending)} /> <PageTitle title={intl.formatMessage(messages.trending)} />
<div className="mt-1 mb-5"> <div className="mb-5 mt-1">
<Header>{intl.formatMessage(messages.trending)}</Header> <Header>{intl.formatMessage(messages.trending)}</Header>
</div> </div>
<ListView <ListView

View File

@@ -30,7 +30,7 @@ const TvGenreList = () => {
return ( return (
<> <>
<PageTitle title={intl.formatMessage(messages.seriesgenres)} /> <PageTitle title={intl.formatMessage(messages.seriesgenres)} />
<div className="mt-1 mb-5"> <div className="mb-5 mt-1">
<Header>{intl.formatMessage(messages.seriesgenres)}</Header> <Header>{intl.formatMessage(messages.seriesgenres)}</Header>
</div> </div>
<ul className="cards-horizontal"> <ul className="cards-horizontal">

View File

@@ -31,7 +31,7 @@ const UpcomingMovies = () => {
return ( return (
<> <>
<PageTitle title={intl.formatMessage(messages.upcomingmovies)} /> <PageTitle title={intl.formatMessage(messages.upcomingmovies)} />
<div className="mt-1 mb-5"> <div className="mb-5 mt-1">
<Header>{intl.formatMessage(messages.upcomingmovies)}</Header> <Header>{intl.formatMessage(messages.upcomingmovies)}</Header>
</div> </div>
<ListView <ListView

View File

@@ -127,7 +127,7 @@ const Discover = () => {
<> <>
{isEditing && ( {isEditing && (
<div className="my-6 rounded-lg bg-gray-800"> <div className="my-6 rounded-lg bg-gray-800">
<div className="flex items-center space-x-2 rounded-t-lg border-t border-l border-r border-gray-800 bg-gray-900 p-4 text-lg font-semibold text-gray-400"> <div className="flex items-center space-x-2 rounded-t-lg border-l border-r border-t border-gray-800 bg-gray-900 p-4 text-lg font-semibold text-gray-400">
<PlusIcon className="w-6" /> <PlusIcon className="w-6" />
<span data-testid="create-slider-header"> <span data-testid="create-slider-header">
{intl.formatMessage(messages.createnewslider)} {intl.formatMessage(messages.createnewslider)}
@@ -172,7 +172,7 @@ const Discover = () => {
leave="transition duration-300" leave="transition duration-300"
leaveFrom="opacity-100 translate-y-0" leaveFrom="opacity-100 translate-y-0"
leaveTo="opacity-0 translate-y-6" leaveTo="opacity-0 translate-y-6"
className="safe-shift-edit-menu fixed right-0 left-0 z-50 flex flex-col items-center justify-end space-x-0 space-y-2 border-t border-gray-700 bg-gray-800 bg-opacity-80 p-4 backdrop-blur sm:bottom-0 sm:flex-row sm:space-y-0 sm:space-x-3" className="safe-shift-edit-menu fixed left-0 right-0 z-50 flex flex-col items-center justify-end space-x-0 space-y-2 border-t border-gray-700 bg-gray-800 bg-opacity-80 p-4 backdrop-blur sm:bottom-0 sm:flex-row sm:space-x-3 sm:space-y-0"
> >
<Button <Button
buttonType="default" buttonType="default"

View File

@@ -29,12 +29,12 @@ const DownloadBlock = ({
{hasPermission(Permission.ADMIN) {hasPermission(Permission.ADMIN)
? downloadItem.title ? downloadItem.title
: downloadItem.episode : downloadItem.episode
? intl.formatMessage(messages.formattedTitle, { ? intl.formatMessage(messages.formattedTitle, {
title, title,
seasonNumber: downloadItem?.episode?.seasonNumber, seasonNumber: downloadItem?.episode?.seasonNumber,
episodeNumber: downloadItem?.episode?.episodeNumber, episodeNumber: downloadItem?.episode?.episodeNumber,
}) })
: title} : title}
</div> </div>
<div className="relative mb-2 h-6 min-w-0 overflow-hidden rounded-full bg-gray-700"> <div className="relative mb-2 h-6 min-w-0 overflow-hidden rounded-full bg-gray-700">
<div <div

View File

@@ -101,7 +101,7 @@ const IssueComment = ({
{(isActiveUser || hasPermission(Permission.MANAGE_ISSUES)) && ( {(isActiveUser || hasPermission(Permission.MANAGE_ISSUES)) && (
<Menu <Menu
as="div" as="div"
className="absolute top-2 right-1 z-40 inline-block text-left" className="absolute right-1 top-2 z-40 inline-block text-left"
> >
{({ open }) => ( {({ open }) => (
<> <>

View File

@@ -370,7 +370,7 @@ const IssueDetails = () => {
</span> </span>
</div> </div>
</div> </div>
<div className="mt-4 mb-6 flex flex-col space-y-2"> <div className="mb-6 mt-4 flex flex-col space-y-2">
{issueData?.media.mediaUrl && ( {issueData?.media.mediaUrl && (
<Button <Button
as="a" as="a"
@@ -388,13 +388,13 @@ const IssueDetails = () => {
mediaServerName: 'Emby', mediaServerName: 'Emby',
}) })
: settings.currentSettings.mediaServerType === : settings.currentSettings.mediaServerType ===
MediaServerType.PLEX MediaServerType.PLEX
? intl.formatMessage(messages.playonplex, { ? intl.formatMessage(messages.playonplex, {
mediaServerName: 'Plex', mediaServerName: 'Plex',
}) })
: intl.formatMessage(messages.playonplex, { : intl.formatMessage(messages.playonplex, {
mediaServerName: 'Jellyfin', mediaServerName: 'Jellyfin',
})} })}
</span> </span>
</Button> </Button>
)} )}
@@ -436,13 +436,13 @@ const IssueDetails = () => {
mediaServerName: 'Emby', mediaServerName: 'Emby',
}) })
: settings.currentSettings.mediaServerType === : settings.currentSettings.mediaServerType ===
MediaServerType.PLEX MediaServerType.PLEX
? intl.formatMessage(messages.play4konplex, { ? intl.formatMessage(messages.play4konplex, {
mediaServerName: 'Plex', mediaServerName: 'Plex',
}) })
: intl.formatMessage(messages.play4konplex, { : intl.formatMessage(messages.play4konplex, {
mediaServerName: 'Jellyfin', mediaServerName: 'Jellyfin',
})} })}
</span> </span>
</Button> </Button>
)} )}
@@ -483,7 +483,7 @@ const IssueDetails = () => {
/> />
))} ))}
{otherComments.length === 0 && ( {otherComments.length === 0 && (
<div className="mt-4 mb-10 text-gray-400"> <div className="mb-10 mt-4 text-gray-400">
<span>{intl.formatMessage(messages.nocomments)}</span> <span>{intl.formatMessage(messages.nocomments)}</span>
</div> </div>
)} )}
@@ -636,7 +636,7 @@ const IssueDetails = () => {
</span> </span>
</div> </div>
</div> </div>
<div className="mt-4 mb-6 flex flex-col space-y-2"> <div className="mb-6 mt-4 flex flex-col space-y-2">
{issueData?.media.mediaUrl && ( {issueData?.media.mediaUrl && (
<Button <Button
as="a" as="a"
@@ -654,13 +654,13 @@ const IssueDetails = () => {
mediaServerName: 'Emby', mediaServerName: 'Emby',
}) })
: settings.currentSettings.mediaServerType === : settings.currentSettings.mediaServerType ===
MediaServerType.PLEX MediaServerType.PLEX
? intl.formatMessage(messages.playonplex, { ? intl.formatMessage(messages.playonplex, {
mediaServerName: 'Plex', mediaServerName: 'Plex',
}) })
: intl.formatMessage(messages.playonplex, { : intl.formatMessage(messages.playonplex, {
mediaServerName: 'Jellyfin', mediaServerName: 'Jellyfin',
})} })}
</span> </span>
</Button> </Button>
)} )}
@@ -701,13 +701,13 @@ const IssueDetails = () => {
mediaServerName: 'Emby', mediaServerName: 'Emby',
}) })
: settings.currentSettings.mediaServerType === : settings.currentSettings.mediaServerType ===
MediaServerType.PLEX MediaServerType.PLEX
? intl.formatMessage(messages.play4konplex, { ? intl.formatMessage(messages.play4konplex, {
mediaServerName: 'Plex', mediaServerName: 'Plex',
}) })
: intl.formatMessage(messages.play4konplex, { : intl.formatMessage(messages.play4konplex, {
mediaServerName: 'Jellyfin', mediaServerName: 'Jellyfin',
})} })}
</span> </span>
</Button> </Button>
)} )}

View File

@@ -216,7 +216,7 @@ const IssueItem = ({ issue }: IssueItemProps) => {
)} )}
</div> </div>
</div> </div>
<div className="z-10 mt-4 ml-4 flex w-full flex-col justify-center overflow-hidden pr-4 text-sm sm:ml-2 sm:mt-0 xl:flex-1 xl:pr-0"> <div className="z-10 ml-4 mt-4 flex w-full flex-col justify-center overflow-hidden pr-4 text-sm sm:ml-2 sm:mt-0 xl:flex-1 xl:pr-0">
<div className="card-field"> <div className="card-field">
<span className="card-field-name"> <span className="card-field-name">
{intl.formatMessage(messages.issuestatus)} {intl.formatMessage(messages.issuestatus)}

View File

@@ -109,40 +109,40 @@ const LanguageSelector = ({
isFixed: true, isFixed: true,
} }
: (value === '' || !value || value === 'server') && isUserSettings : (value === '' || !value || value === 'server') && isUserSettings
? { ? {
value: 'server', value: 'server',
label: intl.formatMessage(messages.languageServerDefault, { label: intl.formatMessage(messages.languageServerDefault, {
language: serverValue language: serverValue
? serverValue ? serverValue
.split('|') .split('|')
.map((value) => languageName(value)) .map((value) => languageName(value))
.reduce((prev, curr) => .reduce((prev, curr) =>
intl.formatMessage(globalMessages.delimitedlist, { intl.formatMessage(globalMessages.delimitedlist, {
a: prev, a: prev,
b: curr, b: curr,
}) })
) )
: intl.formatMessage(messages.originalLanguageDefault), : intl.formatMessage(messages.originalLanguageDefault),
}), }),
isFixed: true, isFixed: true,
} }
: (value : (value
?.split('|') ?.split('|')
.map((code) => { .map((code) => {
const matchedLanguage = sortedLanguages?.find( const matchedLanguage = sortedLanguages?.find(
(lang) => lang.iso_639_1 === code (lang) => lang.iso_639_1 === code
); );
if (!matchedLanguage) { if (!matchedLanguage) {
return undefined; return undefined;
} }
return { return {
label: matchedLanguage.name, label: matchedLanguage.name,
value: matchedLanguage.iso_639_1, value: matchedLanguage.iso_639_1,
}; };
}) })
.filter((option) => option !== undefined) as OptionType[]) .filter((option) => option !== undefined) as OptionType[])
} }
onChange={(value, options) => { onChange={(value, options) => {
if ( if (

View File

@@ -179,7 +179,7 @@ const MobileMenu = ({
leave="transition duration-500" leave="transition duration-500"
leaveFrom="opacity-100 -translate-y-full" leaveFrom="opacity-100 -translate-y-full"
leaveTo="opacity-0 translate-y-0" leaveTo="opacity-0 translate-y-0"
className="absolute top-0 left-0 right-0 flex w-full -translate-y-full flex-col space-y-6 border-t border-gray-600 bg-gray-900 bg-opacity-90 px-6 py-6 font-semibold text-gray-100 backdrop-blur" className="absolute left-0 right-0 top-0 flex w-full -translate-y-full flex-col space-y-6 border-t border-gray-600 bg-gray-900 bg-opacity-90 px-6 py-6 font-semibold text-gray-100 backdrop-blur"
> >
{filteredLinks.map((link) => { {filteredLinks.map((link) => {
const isActive = router.pathname.match(link.activeRegExp); const isActive = router.pathname.match(link.activeRegExp);
@@ -249,7 +249,7 @@ const MobileMenu = ({
{link.href === '/requests' && {link.href === '/requests' &&
pendingRequestsCount > 0 && pendingRequestsCount > 0 &&
hasPermission(Permission.MANAGE_REQUESTS) && ( hasPermission(Permission.MANAGE_REQUESTS) && (
<div className="absolute left-3 bottom-3"> <div className="absolute bottom-3 left-3">
<Badge <Badge
className={`bg-gradient-to-br ${ className={`bg-gradient-to-br ${
router.pathname.match(link.activeRegExp) router.pathname.match(link.activeRegExp)
@@ -257,7 +257,7 @@ const MobileMenu = ({
: 'border-indigo-500 from-indigo-600 to-purple-600' : 'border-indigo-500 from-indigo-600 to-purple-600'
} flex ${ } flex ${
pendingRequestsCount > 99 ? 'w-6' : 'w-4' pendingRequestsCount > 99 ? 'w-6' : 'w-4'
} h-4 items-center justify-center !px-[5px] !py-[7px] text-[8px]`} } h-4 items-center justify-center !px-[5px] !py-[7px] text-[8px]`}
> >
{pendingRequestsCount > 99 {pendingRequestsCount > 99
? '99+' ? '99+'

View File

@@ -110,8 +110,8 @@ const PullToRefresh = () => {
pullDownIconLocation < pullDownStopThreshold && pullDownInitThreshold pullDownIconLocation < pullDownStopThreshold && pullDownInitThreshold
? pullDownIconLocation ? pullDownIconLocation
: pullDownInitThreshold : pullDownInitThreshold
? pullDownStopThreshold ? pullDownStopThreshold
: '', : '',
}} }}
> >
<div <div

View File

@@ -188,7 +188,7 @@ const Sidebar = ({
</div> </div>
<div <div
ref={navRef} ref={navRef}
className="flex flex-1 flex-col overflow-y-auto pt-4 pb-8 sm:pb-4" className="flex flex-1 flex-col overflow-y-auto pb-8 pt-4 sm:pb-4"
> >
<div className="flex flex-shrink-0 items-center px-2"> <div className="flex flex-shrink-0 items-center px-2">
<span className="w-full px-4 text-xl text-gray-50"> <span className="w-full px-4 text-xl text-gray-50">
@@ -218,13 +218,11 @@ const Sidebar = ({
}} }}
role="button" role="button"
tabIndex={0} tabIndex={0}
className={`flex items-center rounded-md px-2 py-2 text-base font-medium leading-6 text-white transition duration-150 ease-in-out focus:outline-none className={`flex items-center rounded-md px-2 py-2 text-base font-medium leading-6 text-white transition duration-150 ease-in-out focus:outline-none ${
${
router.pathname.match(sidebarLink.activeRegExp) router.pathname.match(sidebarLink.activeRegExp)
? 'bg-gradient-to-br from-indigo-600 to-purple-600 hover:from-indigo-500 hover:to-purple-500' ? 'bg-gradient-to-br from-indigo-600 to-purple-600 hover:from-indigo-500 hover:to-purple-500'
: 'hover:bg-gray-700 focus:bg-gray-700' : 'hover:bg-gray-700 focus:bg-gray-700'
} } `}
`}
data-testid={`${sidebarLink.dataTestId}-mobile`} data-testid={`${sidebarLink.dataTestId}-mobile`}
> >
{sidebarLink.svgIcon} {sidebarLink.svgIcon}
@@ -255,7 +253,7 @@ const Sidebar = ({
</Transition> </Transition>
</div> </div>
<div className="fixed top-0 bottom-0 left-0 z-30 hidden lg:flex lg:flex-shrink-0"> <div className="fixed bottom-0 left-0 top-0 z-30 hidden lg:flex lg:flex-shrink-0">
<div className="sidebar flex w-64 flex-col"> <div className="sidebar flex w-64 flex-col">
<div className="flex h-0 flex-1 flex-col"> <div className="flex h-0 flex-1 flex-col">
<div className="flex flex-1 flex-col overflow-y-auto pb-4"> <div className="flex flex-1 flex-col overflow-y-auto pb-4">
@@ -279,13 +277,11 @@ const Sidebar = ({
key={`desktop-${sidebarLink.messagesKey}`} key={`desktop-${sidebarLink.messagesKey}`}
href={sidebarLink.href} href={sidebarLink.href}
as={sidebarLink.as} as={sidebarLink.as}
className={`group flex items-center rounded-md px-2 py-2 text-lg font-medium leading-6 text-white transition duration-150 ease-in-out focus:outline-none className={`group flex items-center rounded-md px-2 py-2 text-lg font-medium leading-6 text-white transition duration-150 ease-in-out focus:outline-none ${
${ router.pathname.match(sidebarLink.activeRegExp)
router.pathname.match(sidebarLink.activeRegExp) ? 'bg-gradient-to-br from-indigo-600 to-purple-600 hover:from-indigo-500 hover:to-purple-500'
? 'bg-gradient-to-br from-indigo-600 to-purple-600 hover:from-indigo-500 hover:to-purple-500' : 'hover:bg-gray-700 focus:bg-gray-700'
: 'hover:bg-gray-700 focus:bg-gray-700' } `}
}
`}
data-testid={sidebarLink.dataTestId} data-testid={sidebarLink.dataTestId}
> >
{sidebarLink.svgIcon} {sidebarLink.svgIcon}

View File

@@ -39,7 +39,7 @@ const MiniQuotaDisplay = ({ userId }: MiniQuotaDisplayProps) => {
{intl.formatMessage(messages.movierequests)} {intl.formatMessage(messages.movierequests)}
</div> </div>
<div className="flex h-full items-center space-x-2 text-gray-200"> <div className="flex h-full items-center space-x-2 text-gray-200">
{data?.movie.limit ?? 0 > 0 ? ( {(data?.movie.limit ?? 0) > 0 ? (
<> <>
<ProgressCircle <ProgressCircle
className="h-8 w-8" className="h-8 w-8"
@@ -67,7 +67,7 @@ const MiniQuotaDisplay = ({ userId }: MiniQuotaDisplayProps) => {
{intl.formatMessage(messages.seriesrequests)} {intl.formatMessage(messages.seriesrequests)}
</div> </div>
<div className="flex h-full items-center space-x-2 text-gray-200"> <div className="flex h-full items-center space-x-2 text-gray-200">
{data?.tv.limit ?? 0 > 0 ? ( {(data?.tv.limit ?? 0) > 0 ? (
<> <>
<ProgressCircle <ProgressCircle
className="h-8 w-8" className="h-8 w-8"

View File

@@ -36,8 +36,8 @@ const VersionStatus = ({ onClick }: VersionStatusProps) => {
data.commitTag === 'local' data.commitTag === 'local'
? 'Keep it up! 👍' ? 'Keep it up! 👍'
: data.version.startsWith('develop-') : data.version.startsWith('develop-')
? intl.formatMessage(messages.streamdevelop) ? intl.formatMessage(messages.streamdevelop)
: intl.formatMessage(messages.streamstable); : intl.formatMessage(messages.streamstable);
return ( return (
<Link <Link

View File

@@ -96,7 +96,7 @@ const Layout = ({ children }: LayoutProps) => {
WebkitBackdropFilter: isScrolled ? 'blur(5px)' : undefined, WebkitBackdropFilter: isScrolled ? 'blur(5px)' : undefined,
}} }}
> >
<div className="flex flex-1 items-center justify-between px-4 md:pr-4 md:pl-4"> <div className="flex flex-1 items-center justify-between px-4 md:pl-4 md:pr-4">
<button <button
className={`mr-2 hidden text-white sm:block ${ className={`mr-2 hidden text-white sm:block ${
isScrolled ? 'opacity-90' : 'opacity-70' isScrolled ? 'opacity-90' : 'opacity-70'

View File

@@ -11,7 +11,7 @@ interface BarProps {
const Bar = ({ progress, isFinished }: BarProps) => { const Bar = ({ progress, isFinished }: BarProps) => {
return ( return (
<div <div
className={`duration-400 fixed top-0 left-0 z-50 w-full transition-opacity ease-out ${ className={`duration-400 fixed left-0 top-0 z-50 w-full transition-opacity ease-out ${
isFinished ? 'opacity-0' : 'opacity-100' isFinished ? 'opacity-0' : 'opacity-100'
}`} }`}
> >

View File

@@ -95,7 +95,7 @@ const AddEmailModal: React.FC<AddEmailModalProps> = ({
<label htmlFor="email" className="text-label"> <label htmlFor="email" className="text-label">
{intl.formatMessage(messages.email)} {intl.formatMessage(messages.email)}
</label> </label>
<div className="mt-1 mb-2 sm:col-span-2 sm:mt-0"> <div className="mb-2 mt-1 sm:col-span-2 sm:mt-0">
<div className="flex rounded-md shadow-sm"> <div className="flex rounded-md shadow-sm">
<Field <Field
id="email" id="email"

View File

@@ -45,8 +45,8 @@ const JellyfinLogin: React.FC<JellyfinLoginProps> = ({
serverType === MediaServerType.JELLYFIN serverType === MediaServerType.JELLYFIN
? ServerType.JELLYFIN ? ServerType.JELLYFIN
: serverType === MediaServerType.EMBY : serverType === MediaServerType.EMBY
? ServerType.EMBY ? ServerType.EMBY
: 'Media Server', : 'Media Server',
}; };
const LoginSchema = Yup.object().shape({ const LoginSchema = Yup.object().shape({
@@ -113,13 +113,13 @@ const JellyfinLogin: React.FC<JellyfinLoginProps> = ({
<> <>
<Form data-form-type="login"> <Form data-form-type="login">
<div> <div>
<h2 className="mb-6 -mt-1 text-center text-lg font-bold text-neutral-200"> <h2 className="-mt-1 mb-6 text-center text-lg font-bold text-neutral-200">
{intl.formatMessage(messages.loginwithapp, { {intl.formatMessage(messages.loginwithapp, {
appName: mediaServerFormatValues.mediaServerName, appName: mediaServerFormatValues.mediaServerName,
})} })}
</h2> </h2>
<div className="mt-1 mb-4"> <div className="mb-4 mt-1">
<div className="form-input-field"> <div className="form-input-field">
<Field <Field
id="username" id="username"
@@ -135,7 +135,7 @@ const JellyfinLogin: React.FC<JellyfinLoginProps> = ({
)} )}
</div> </div>
<div className="mt-1 mb-2"> <div className="mb-2 mt-1">
<div className="form-input-field"> <div className="form-input-field">
<SensitiveInput <SensitiveInput
as="field" as="field"

View File

@@ -71,13 +71,13 @@ const LocalLogin = ({ revalidate }: LocalLoginProps) => {
<> <>
<Form data-form-type="login"> <Form data-form-type="login">
<div> <div>
<h2 className="mb-6 -mt-1 text-center text-lg font-bold text-neutral-200"> <h2 className="-mt-1 mb-6 text-center text-lg font-bold text-neutral-200">
{intl.formatMessage(messages.loginwithapp, { {intl.formatMessage(messages.loginwithapp, {
appName: settings.currentSettings.applicationTitle, appName: settings.currentSettings.applicationTitle,
})} })}
</h2> </h2>
<div className="mt-1 mb-4"> <div className="mb-4 mt-1">
<div className="form-input-field"> <div className="form-input-field">
<Field <Field
id="email" id="email"
@@ -98,7 +98,7 @@ const LocalLogin = ({ revalidate }: LocalLoginProps) => {
<div className="error">{errors.email}</div> <div className="error">{errors.email}</div>
)} )}
</div> </div>
<div className="mt-1 mb-2"> <div className="mb-2 mt-1">
<div className="form-input-field"> <div className="form-input-field">
<SensitiveInput <SensitiveInput
as="field" as="field"
@@ -132,7 +132,7 @@ const LocalLogin = ({ revalidate }: LocalLoginProps) => {
</div> </div>
</div> </div>
{loginError && ( {loginError && (
<div className="mt-1 mb-2 sm:col-span-2 sm:mt-0"> <div className="mb-2 mt-1 sm:col-span-2 sm:mt-0">
<div className="error">{loginError}</div> <div className="error">{loginError}</div>
</div> </div>
)} )}

View File

@@ -42,7 +42,7 @@ const PlexLoginButton = ({
<FormattedMessage <FormattedMessage
{...messages.loginwithapp} {...messages.loginwithapp}
values={{ values={{
appName: <PlexIcon className="mt-[2px] ml-[0.35em] w-8" />, appName: <PlexIcon className="ml-[0.35em] mt-[2px] w-8" />,
}} }}
> >
{(chunks) => ( {(chunks) => (

View File

@@ -85,19 +85,19 @@ const Login = () => {
settings.currentSettings.mediaServerType === MediaServerType.PLEX settings.currentSettings.mediaServerType === MediaServerType.PLEX
? 'Plex' ? 'Plex'
: settings.currentSettings.mediaServerType === MediaServerType.JELLYFIN : settings.currentSettings.mediaServerType === MediaServerType.JELLYFIN
? 'Jellyfin' ? 'Jellyfin'
: settings.currentSettings.mediaServerType === MediaServerType.EMBY : settings.currentSettings.mediaServerType === MediaServerType.EMBY
? 'Emby' ? 'Emby'
: undefined; : undefined;
const MediaServerLogo = const MediaServerLogo =
settings.currentSettings.mediaServerType === MediaServerType.PLEX settings.currentSettings.mediaServerType === MediaServerType.PLEX
? PlexLogo ? PlexLogo
: settings.currentSettings.mediaServerType === MediaServerType.JELLYFIN : settings.currentSettings.mediaServerType === MediaServerType.JELLYFIN
? JellyfinLogo ? JellyfinLogo
: settings.currentSettings.mediaServerType === MediaServerType.EMBY : settings.currentSettings.mediaServerType === MediaServerType.EMBY
? EmbyLogo ? EmbyLogo
: undefined; : undefined;
const isJellyfin = const isJellyfin =
settings.currentSettings.mediaServerType === MediaServerType.JELLYFIN || settings.currentSettings.mediaServerType === MediaServerType.JELLYFIN ||
@@ -159,7 +159,7 @@ const Login = () => {
) ?? [] ) ?? []
} }
/> />
<div className="absolute top-4 right-4 z-50"> <div className="absolute right-4 top-4 z-50">
<LanguagePicker /> <LanguagePicker />
</div> </div>
<div className="relative z-40 mt-10 flex flex-col items-center px-4 sm:mx-auto sm:w-full sm:max-w-md"> <div className="relative z-40 mt-10 flex flex-col items-center px-4 sm:mx-auto sm:w-full sm:max-w-md">

View File

@@ -378,7 +378,7 @@ const ManageSlideOver = ({
</div> </div>
</div> </div>
{!!watchData.data.users.length && ( {!!watchData.data.users.length && (
<div className="flex flex-row space-x-2 px-4 pt-3 pb-2"> <div className="flex flex-row space-x-2 px-4 pb-2 pt-3">
<span className="shrink-0 font-bold leading-8"> <span className="shrink-0 font-bold leading-8">
{intl.formatMessage(messages.playedby)} {intl.formatMessage(messages.playedby)}
</span> </span>
@@ -391,7 +391,7 @@ const ManageSlideOver = ({
: `/users/${user.id}` : `/users/${user.id}`
} }
key={`watch-user-${user.id}`} key={`watch-user-${user.id}`}
className="z-0 mb-1 -mr-2 shrink-0 hover:z-50" className="z-0 -mr-2 mb-1 shrink-0 hover:z-50"
> >
<Tooltip <Tooltip
key={`watch-user-${user.id}`} key={`watch-user-${user.id}`}
@@ -540,7 +540,7 @@ const ManageSlideOver = ({
</div> </div>
</div> </div>
{!!watchData.data4k.users.length && ( {!!watchData.data4k.users.length && (
<div className="flex flex-row space-x-2 px-4 pt-3 pb-2"> <div className="flex flex-row space-x-2 px-4 pb-2 pt-3">
<span className="shrink-0 font-bold leading-8"> <span className="shrink-0 font-bold leading-8">
{intl.formatMessage(messages.playedby)} {intl.formatMessage(messages.playedby)}
</span> </span>
@@ -553,7 +553,7 @@ const ManageSlideOver = ({
: `/users/${user.id}` : `/users/${user.id}`
} }
key={`watch-user-${user.id}`} key={`watch-user-${user.id}`}
className="z-0 mb-1 -mr-2 shrink-0 hover:z-50" className="z-0 -mr-2 mb-1 shrink-0 hover:z-50"
> >
<Tooltip <Tooltip
key={`watch-user-${user.id}`} key={`watch-user-${user.id}`}
@@ -711,9 +711,9 @@ const ManageSlideOver = ({
MediaServerType.EMBY MediaServerType.EMBY
? 'Emby' ? 'Emby'
: settings.currentSettings.mediaServerType === : settings.currentSettings.mediaServerType ===
MediaServerType.PLEX MediaServerType.PLEX
? 'Plex' ? 'Plex'
: 'Jellyfin', : 'Jellyfin',
})} })}
</div> </div>
</div> </div>

View File

@@ -48,12 +48,11 @@ const ShowMoreCard = ({ url, posters }: ShowMoreCardProps) => {
tabIndex={0} tabIndex={0}
> >
<div <div
className={`relative w-36 transform-gpu cursor-pointer className={`relative w-36 transform-gpu cursor-pointer overflow-hidden rounded-xl text-white shadow-lg ring-1 transition duration-150 ease-in-out sm:w-36 md:w-44 ${
overflow-hidden rounded-xl text-white shadow-lg ring-1 transition duration-150 ease-in-out sm:w-36 md:w-44 ${ isHovered
isHovered ? 'scale-105 bg-gray-600 ring-gray-500'
? 'scale-105 bg-gray-600 ring-gray-500' : 'scale-100 bg-gray-800 ring-gray-700'
: 'scale-100 bg-gray-800 ring-gray-700' }`}
}`}
> >
<div style={{ paddingBottom: '150%' }}> <div style={{ paddingBottom: '150%' }}>
<div className="absolute inset-0 flex h-full w-full flex-col items-center p-2"> <div className="absolute inset-0 flex h-full w-full flex-col items-center p-2">

View File

@@ -32,7 +32,7 @@ const MovieCast = () => {
return ( return (
<> <>
<PageTitle title={[intl.formatMessage(messages.fullcast), data.title]} /> <PageTitle title={[intl.formatMessage(messages.fullcast), data.title]} />
<div className="mt-1 mb-5"> <div className="mb-5 mt-1">
<Header <Header
subtext={ subtext={
<Link href={`/movie/${data.id}`} className="hover:underline"> <Link href={`/movie/${data.id}`} className="hover:underline">

View File

@@ -32,7 +32,7 @@ const MovieCrew = () => {
return ( return (
<> <>
<PageTitle title={[intl.formatMessage(messages.fullcrew), data.title]} /> <PageTitle title={[intl.formatMessage(messages.fullcrew), data.title]} />
<div className="mt-1 mb-5"> <div className="mb-5 mt-1">
<Header <Header
subtext={ subtext={
<Link href={`/movie/${data.id}`} className="hover:underline"> <Link href={`/movie/${data.id}`} className="hover:underline">

View File

@@ -42,7 +42,7 @@ const MovieRecommendations = () => {
<PageTitle <PageTitle
title={[intl.formatMessage(messages.recommendations), movieData?.title]} title={[intl.formatMessage(messages.recommendations), movieData?.title]}
/> />
<div className="mt-1 mb-5"> <div className="mb-5 mt-1">
<Header <Header
subtext={ subtext={
<Link href={`/movie/${movieData?.id}`} className="hover:underline"> <Link href={`/movie/${movieData?.id}`} className="hover:underline">

View File

@@ -40,7 +40,7 @@ const MovieSimilar = () => {
<PageTitle <PageTitle
title={[intl.formatMessage(messages.similar), movieData?.title]} title={[intl.formatMessage(messages.similar), movieData?.title]}
/> />
<div className="mt-1 mb-5"> <div className="mb-5 mt-1">
<Header <Header
subtext={ subtext={
<Link href={`/movie/${movieData?.id}`} className="hover:underline"> <Link href={`/movie/${movieData?.id}`} className="hover:underline">

Some files were not shown because too many files have changed in this diff Show More