1
0
mirror of https://github.com/Radarr/Radarr.git synced 2026-03-22 17:04:39 -04:00

Compare commits

..

16 Commits

Author SHA1 Message Date
Qstick
155b8f774b New: Rework Movie Details view 2022-04-12 22:44:20 -05:00
Qstick
5acd41a7ea fixup! 2022-04-12 19:24:04 -05:00
Qstick
dc41fa125c fixup! 2022-04-12 19:14:25 -05:00
Qstick
52e0daed14 fixup! 2022-04-11 21:44:08 -05:00
Qstick
4ee71156ed fixup! 2022-04-11 21:19:24 -05:00
Qstick
106a234151 fixup! 2022-04-11 20:53:31 -05:00
Qstick
6266511b45 fixup! 2022-04-11 19:49:38 -05:00
Qstick
aadd70bbf7 fixup! 2022-04-10 23:03:53 -05:00
Qstick
737790ca6a fixup! 2022-04-10 22:44:32 -05:00
Qstick
133bfa68ea fixup! 2022-04-10 22:22:30 -05:00
Qstick
8723b0f4be fixup! 2022-04-10 21:32:45 -05:00
Qstick
fb7ab09f57 fixup! 2022-04-10 21:30:25 -05:00
Qstick
b6f94855eb fixup! 2022-04-10 19:13:49 -05:00
Qstick
a936ab2504 fixup! 2022-04-10 18:11:45 -05:00
Qstick
8a3622fd82 New: Collections View 2022-04-10 18:11:11 -05:00
Qstick
10ebb33c9b Rework Movie Metadata data model 2022-04-10 18:06:56 -05:00
194 changed files with 1959 additions and 4056 deletions

View File

@@ -9,13 +9,13 @@ variables:
testsFolder: './_tests'
yarnCacheFolder: $(Pipeline.Workspace)/.yarn
nugetCacheFolder: $(Pipeline.Workspace)/.nuget/packages
majorVersion: '4.2.0'
majorVersion: '4.1.0'
minorVersion: $[counter('minorVersion', 2000)]
radarrVersion: '$(majorVersion).$(minorVersion)'
buildName: '$(Build.SourceBranchName).$(radarrVersion)'
sentryOrg: 'servarr'
sentryUrl: 'https://sentry.servarr.com'
dotnetVersion: '6.0.300'
dotnetVersion: '6.0.201'
nodeVersion: '16.X'
innoVersion: '6.2.0'
windowsImage: 'windows-2022'
@@ -97,14 +97,15 @@ stages:
- bash: |
BUNDLEDVERSIONS=${AGENT_TOOLSDIRECTORY}/dotnet/sdk/${DOTNETVERSION}/Microsoft.NETCoreSdk.BundledVersions.props
echo $BUNDLEDVERSIONS
grep osx-x64 $BUNDLEDVERSIONS
if grep -q freebsd-x64 $BUNDLEDVERSIONS; then
echo "Extra platforms already enabled"
echo "BSD already enabled"
else
echo "Enabling extra platform support"
sed -i.ORI 's/osx-x64/osx-x64;freebsd-x64;linux-x86/' $BUNDLEDVERSIONS
echo "Enabling BSD support"
sed -i.ORI 's/osx-x64/osx-x64;freebsd-x64/' $BUNDLEDVERSIONS
fi
displayName: Enable Extra Platform Support
- bash: ./build.sh --backend --enable-extra-platforms
displayName: Enable FreeBSD Support
- bash: ./build.sh --backend --enable-bsd
displayName: Build Radarr Backend
- bash: |
find ${OUTPUTFOLDER} -type f ! -path "*/publish/*" -exec rm -rf {} \;
@@ -118,28 +119,24 @@ stages:
displayName: Publish Backend
condition: and(succeeded(), eq(variables['osName'], 'Windows'))
- publish: '$(testsFolder)/net6.0/win-x64/publish'
artifact: win-x64-tests
displayName: Publish win-x64 Test Package
artifact: WindowsCoreTests
displayName: Publish Windows Test Package
condition: and(succeeded(), eq(variables['osName'], 'Windows'))
- publish: '$(testsFolder)/net6.0/linux-x64/publish'
artifact: linux-x64-tests
displayName: Publish linux-x64 Test Package
condition: and(succeeded(), eq(variables['osName'], 'Windows'))
- publish: '$(testsFolder)/net6.0/linux-x86/publish'
artifact: linux-x86-tests
displayName: Publish linux-x86 Test Package
artifact: LinuxCoreTests
displayName: Publish Linux Test Package
condition: and(succeeded(), eq(variables['osName'], 'Windows'))
- publish: '$(testsFolder)/net6.0/linux-musl-x64/publish'
artifact: linux-musl-x64-tests
displayName: Publish linux-musl-x64 Test Package
artifact: LinuxMuslCoreTests
displayName: Publish Linux Musl Test Package
condition: and(succeeded(), eq(variables['osName'], 'Windows'))
- publish: '$(testsFolder)/net6.0/freebsd-x64/publish'
artifact: freebsd-x64-tests
displayName: Publish freebsd-x64 Test Package
artifact: FreebsdCoreTests
displayName: Publish FreeBSD Test Package
condition: and(succeeded(), eq(variables['osName'], 'Windows'))
- publish: '$(testsFolder)/net6.0/osx-x64/publish'
artifact: osx-x64-tests
displayName: Publish osx-x64 Test Package
artifact: MacCoreTests
displayName: Publish MacOS Test Package
condition: and(succeeded(), eq(variables['osName'], 'Windows'))
- stage: Build_Frontend
@@ -243,7 +240,7 @@ stages:
artifactName: WindowsFrontend
targetPath: _output
displayName: Fetch Frontend
- bash: ./build.sh --packages --enable-extra-platforms
- bash: ./build.sh --packages --enable-bsd
displayName: Create Packages
- bash: |
find . -name "ffprobe" -exec chmod a+x {} \;
@@ -251,28 +248,28 @@ stages:
find . -name "Radarr.Update" -exec chmod a+x {} \;
displayName: Set executable bits
- task: ArchiveFiles@2
displayName: Create win-x64 zip
displayName: Create Windows Core zip
inputs:
archiveFile: '$(Build.ArtifactStagingDirectory)/Radarr.$(buildName).windows-core-x64.zip'
archiveType: 'zip'
includeRootFolder: false
rootFolderOrFile: $(artifactsFolder)/win-x64/net6.0
- task: ArchiveFiles@2
displayName: Create win-x86 zip
displayName: Create Windows x86 Core zip
inputs:
archiveFile: '$(Build.ArtifactStagingDirectory)/Radarr.$(buildName).windows-core-x86.zip'
archiveType: 'zip'
includeRootFolder: false
rootFolderOrFile: $(artifactsFolder)/win-x86/net6.0
- task: ArchiveFiles@2
displayName: Create osx-x64 app
displayName: Create MacOS x64 Core app
inputs:
archiveFile: '$(Build.ArtifactStagingDirectory)/Radarr.$(buildName).osx-app-core-x64.zip'
archiveType: 'zip'
includeRootFolder: false
rootFolderOrFile: $(artifactsFolder)/osx-x64-app/net6.0
- task: ArchiveFiles@2
displayName: Create osx-x64 tar
displayName: Create MacOS x64 Core tar
inputs:
archiveFile: '$(Build.ArtifactStagingDirectory)/Radarr.$(buildName).osx-core-x64.tar.gz'
archiveType: 'tar'
@@ -280,14 +277,14 @@ stages:
includeRootFolder: false
rootFolderOrFile: $(artifactsFolder)/osx-x64/net6.0
- task: ArchiveFiles@2
displayName: Create osx-arm64 app
displayName: Create MacOS arm64 Core app
inputs:
archiveFile: '$(Build.ArtifactStagingDirectory)/Radarr.$(buildName).osx-app-core-arm64.zip'
archiveType: 'zip'
includeRootFolder: false
rootFolderOrFile: $(artifactsFolder)/osx-arm64-app/net6.0
- task: ArchiveFiles@2
displayName: Create osx-arm64 tar
displayName: Create MacOS arm64 Core tar
inputs:
archiveFile: '$(Build.ArtifactStagingDirectory)/Radarr.$(buildName).osx-core-arm64.tar.gz'
archiveType: 'tar'
@@ -295,7 +292,7 @@ stages:
includeRootFolder: false
rootFolderOrFile: $(artifactsFolder)/osx-arm64/net6.0
- task: ArchiveFiles@2
displayName: Create linux-x64 tar
displayName: Create Linux Core tar
inputs:
archiveFile: '$(Build.ArtifactStagingDirectory)/Radarr.$(buildName).linux-core-x64.tar.gz'
archiveType: 'tar'
@@ -303,7 +300,7 @@ stages:
includeRootFolder: false
rootFolderOrFile: $(artifactsFolder)/linux-x64/net6.0
- task: ArchiveFiles@2
displayName: Create linux-musl-x64 tar
displayName: Create Linux Musl Core tar
inputs:
archiveFile: '$(Build.ArtifactStagingDirectory)/Radarr.$(buildName).linux-musl-core-x64.tar.gz'
archiveType: 'tar'
@@ -311,15 +308,7 @@ stages:
includeRootFolder: false
rootFolderOrFile: $(artifactsFolder)/linux-musl-x64/net6.0
- task: ArchiveFiles@2
displayName: Create linux-x86 tar
inputs:
archiveFile: '$(Build.ArtifactStagingDirectory)/Radarr.$(buildName).linux-core-x86.tar.gz'
archiveType: 'tar'
tarCompression: 'gz'
includeRootFolder: false
rootFolderOrFile: $(artifactsFolder)/linux-x86/net6.0
- task: ArchiveFiles@2
displayName: Create linux-arm tar
displayName: Create ARM32 Linux Core tar
inputs:
archiveFile: '$(Build.ArtifactStagingDirectory)/Radarr.$(buildName).linux-core-arm.tar.gz'
archiveType: 'tar'
@@ -327,7 +316,7 @@ stages:
includeRootFolder: false
rootFolderOrFile: $(artifactsFolder)/linux-arm/net6.0
- task: ArchiveFiles@2
displayName: Create linux-musl-arm tar
displayName: Create ARM32 Linux Musl Core tar
inputs:
archiveFile: '$(Build.ArtifactStagingDirectory)/Radarr.$(buildName).linux-musl-core-arm.tar.gz'
archiveType: 'tar'
@@ -335,7 +324,7 @@ stages:
includeRootFolder: false
rootFolderOrFile: $(artifactsFolder)/linux-musl-arm/net6.0
- task: ArchiveFiles@2
displayName: Create linux-arm64 tar
displayName: Create ARM64 Linux Core tar
inputs:
archiveFile: '$(Build.ArtifactStagingDirectory)/Radarr.$(buildName).linux-core-arm64.tar.gz'
archiveType: 'tar'
@@ -343,7 +332,7 @@ stages:
includeRootFolder: false
rootFolderOrFile: $(artifactsFolder)/linux-arm64/net6.0
- task: ArchiveFiles@2
displayName: Create linux-musl-arm64 tar
displayName: Create ARM64 Linux Musl Core tar
inputs:
archiveFile: '$(Build.ArtifactStagingDirectory)/Radarr.$(buildName).linux-musl-core-arm64.tar.gz'
archiveType: 'tar'
@@ -351,7 +340,7 @@ stages:
includeRootFolder: false
rootFolderOrFile: $(artifactsFolder)/linux-musl-arm64/net6.0
- task: ArchiveFiles@2
displayName: Create freebsd-x64 tar
displayName: Create FreeBSD Core Core tar
inputs:
archiveFile: '$(Build.ArtifactStagingDirectory)/Radarr.$(buildName).freebsd-core-x64.tar.gz'
archiveType: 'tar'
@@ -418,22 +407,22 @@ stages:
matrix:
MacCore:
osName: 'Mac'
testName: 'osx-x64'
testName: 'MacCore'
poolName: 'Azure Pipelines'
imageName: ${{ variables.macImage }}
WindowsCore:
osName: 'Windows'
testName: 'win-x64'
testName: 'WindowsCore'
poolName: 'Azure Pipelines'
imageName: ${{ variables.windowsImage }}
LinuxCore:
osName: 'Linux'
testName: 'linux-x64'
testName: 'LinuxCore'
poolName: 'Azure Pipelines'
imageName: ${{ variables.linuxImage }}
FreebsdCore:
osName: 'Linux'
testName: 'freebsd-x64'
testName: 'FreebsdCore'
poolName: 'FreeBSD'
imageName:
@@ -452,7 +441,7 @@ stages:
displayName: Download Test Artifact
inputs:
buildType: 'current'
artifactName: '$(testName)-tests'
artifactName: '$(testName)Tests'
targetPath: $(testsFolder)
- powershell: Set-Service SCardSvr -StartupType Manual
displayName: Enable Windows Test Service
@@ -486,12 +475,8 @@ stages:
matrix:
alpine:
testName: 'Musl Net Core'
artifactName: linux-musl-x64-tests
artifactName: LinuxMuslCoreTests
containerImage: ghcr.io/servarr/testimages:alpine
linux-x86:
testName: 'linux-x86'
artifactName: linux-x86-tests
containerImage: ghcr.io/servarr/testimages:linux-x86
pool:
vmImage: ${{ variables.linuxImage }}
@@ -502,15 +487,9 @@ stages:
steps:
- task: UseDotNet@2
displayName: 'Install .NET'
displayName: 'Install .net core'
inputs:
version: $(dotnetVersion)
condition: and(succeeded(), ne(variables['testName'], 'linux-x86'))
- bash: |
SDKURL=$(curl -s https://api.github.com/repos/Servarr/dotnet-linux-x86/releases | jq -rc '.[].assets[].browser_download_url' | grep sdk-${DOTNETVERSION}.*gz$)
curl -fsSL $SDKURL | tar xzf - -C /opt/dotnet
displayName: 'Install .NET'
condition: and(succeeded(), eq(variables['testName'], 'linux-x86'))
- checkout: none
- task: DownloadPipelineArtifact@2
displayName: Download Test Artifact
@@ -543,7 +522,7 @@ stages:
condition: and(succeeded(), eq(dependencies.Prepare.outputs['setVar.backendNotUpdated'], '0'))
variables:
pattern: 'Radarr.*.linux-core-x64.tar.gz'
artifactName: linux-x64-tests
artifactName: LinuxCoreTests
Radarr__Postgres__Host: 'localhost'
Radarr__Postgres__Port: '5432'
Radarr__Postgres__User: 'radarr'
@@ -618,17 +597,17 @@ stages:
matrix:
MacCore:
osName: 'Mac'
testName: 'osx-x64'
testName: 'MacCore'
imageName: ${{ variables.macImage }}
pattern: 'Radarr.*.osx-core-x64.tar.gz'
WindowsCore:
osName: 'Windows'
testName: 'win-x64'
testName: 'WindowsCore'
imageName: ${{ variables.windowsImage }}
pattern: 'Radarr.*.windows-core-x64.zip'
LinuxCore:
osName: 'Linux'
testName: 'linux-x64'
testName: 'LinuxCore'
imageName: ${{ variables.linuxImage }}
pattern: 'Radarr.*.linux-core-x64.tar.gz'
@@ -645,7 +624,7 @@ stages:
displayName: Download Test Artifact
inputs:
buildType: 'current'
artifactName: '$(testName)-tests'
artifactName: '$(testName)Tests'
targetPath: $(testsFolder)
- task: DownloadPipelineArtifact@2
displayName: Download Build Artifact
@@ -699,7 +678,7 @@ stages:
displayName: Download Test Artifact
inputs:
buildType: 'current'
artifactName: 'linux-x64-tests'
artifactName: 'LinuxCoreTests'
targetPath: $(testsFolder)
- task: DownloadPipelineArtifact@2
displayName: Download Build Artifact
@@ -753,7 +732,7 @@ stages:
displayName: Download Test Artifact
inputs:
buildType: 'current'
artifactName: 'freebsd-x64-tests'
artifactName: 'FreebsdCoreTests'
targetPath: $(testsFolder)
- task: DownloadPipelineArtifact@2
displayName: Download Build Artifact
@@ -789,15 +768,10 @@ stages:
strategy:
matrix:
alpine:
testName: 'linux-musl-x64'
artifactName: linux-musl-x64-tests
testName: 'Musl Net Core'
artifactName: LinuxMuslCoreTests
containerImage: ghcr.io/servarr/testimages:alpine
pattern: 'Radarr.*.linux-musl-core-x64.tar.gz'
linux-x86:
testName: 'linux-x86'
artifactName: linux-x86-tests
containerImage: ghcr.io/servarr/testimages:linux-x86
pattern: 'Radarr.*.linux-core-x86.tar.gz'
pool:
vmImage: ${{ variables.linuxImage }}
@@ -807,15 +781,9 @@ stages:
steps:
- task: UseDotNet@2
displayName: 'Install .NET'
displayName: 'Install .net core'
inputs:
version: $(dotnetVersion)
condition: and(succeeded(), ne(variables['testName'], 'linux-x86'))
- bash: |
SDKURL=$(curl -s https://api.github.com/repos/Servarr/dotnet-linux-x86/releases | jq -rc '.[].assets[].browser_download_url' | grep sdk-${DOTNETVERSION}.*gz$)
curl -fsSL $SDKURL | tar xzf - -C /opt/dotnet
displayName: 'Install .NET'
condition: and(succeeded(), eq(variables['testName'], 'linux-x86'))
- checkout: none
- task: DownloadPipelineArtifact@2
displayName: Download Test Artifact
@@ -861,19 +829,16 @@ stages:
matrix:
Linux:
osName: 'Linux'
artifactName: 'linux-x64'
imageName: ${{ variables.linuxImage }}
pattern: 'Radarr.*.linux-core-x64.tar.gz'
failBuild: true
Mac:
osName: 'Mac'
artifactName: 'osx-x64'
imageName: ${{ variables.macImage }}
pattern: 'Radarr.*.osx-core-x64.tar.gz'
failBuild: true
Windows:
osName: 'Windows'
artifactName: 'win-x64'
imageName: ${{ variables.windowsImage }}
pattern: 'Radarr.*.windows-core-x64.zip'
failBuild: true
@@ -891,7 +856,7 @@ stages:
displayName: Download Test Artifact
inputs:
buildType: 'current'
artifactName: '$(artifactName)-tests'
artifactName: '$(osName)CoreTests'
targetPath: $(testsFolder)
- task: DownloadPipelineArtifact@2
displayName: Download Build Artifact

View File

@@ -25,22 +25,14 @@ UpdateVersionNumber()
fi
}
EnableExtraPlatformsInSDK()
EnableBsdSupport()
{
SDK_PATH=$(dotnet --list-sdks | grep -P '6\.\d\.\d+' | head -1 | sed 's/\(6\.[0-9]*\.[0-9]*\).*\[\(.*\)\]/\2\/\1/g')
BUNDLEDVERSIONS="${SDK_PATH}/Microsoft.NETCoreSdk.BundledVersions.props"
if grep -q freebsd-x64 $BUNDLEDVERSIONS; then
echo "Extra platforms already enabled"
else
echo "Enabling extra platform support"
sed -i.ORI 's/osx-x64/osx-x64;freebsd-x64;linux-x86/' $BUNDLEDVERSIONS
fi
}
#todo enable sdk with
#SDK_PATH=$(dotnet --list-sdks | grep -P '5\.\d\.\d+' | head -1 | sed 's/\(5\.[0-9]*\.[0-9]*\).*\[\(.*\)\]/\2\/\1/g')
# BUNDLED_VERSIONS="${SDK_PATH}/Microsoft.NETCoreSdk.BundledVersions.props"
EnableExtraPlatforms()
{
if grep -qv freebsd-x64 src/Directory.Build.props; then
sed -i'' -e "s^<RuntimeIdentifiers>\(.*\)</RuntimeIdentifiers>^<RuntimeIdentifiers>\1;freebsd-x64;linux-x86</RuntimeIdentifiers>^g" src/Directory.Build.props
sed -i'' -e "s^<RuntimeIdentifiers>\(.*\)</RuntimeIdentifiers>^<RuntimeIdentifiers>\1;freebsd-x64</RuntimeIdentifiers>^g" src/Directory.Build.props
fi
}
@@ -300,8 +292,7 @@ if [ $# -eq 0 ]; then
PACKAGES=YES
INSTALLER=NO
LINT=YES
ENABLE_EXTRA_PLATFORMS=NO
ENABLE_EXTRA_PLATFORMS_IN_SDK=NO
ENABLE_BSD=NO
fi
while [[ $# -gt 0 ]]
@@ -313,12 +304,8 @@ case $key in
BACKEND=YES
shift # past argument
;;
--enable-bsd|--enable-extra-platforms)
ENABLE_EXTRA_PLATFORMS=YES
shift # past argument
;;
--enable-extra-platforms-in-sdk)
ENABLE_EXTRA_PLATFORMS_IN_SDK=YES
--enable-bsd)
ENABLE_BSD=YES
shift # past argument
;;
-r|--runtime)
@@ -362,17 +349,12 @@ esac
done
set -- "${POSITIONAL[@]}" # restore positional parameters
if [ "$ENABLE_EXTRA_PLATFORMS_IN_SDK" = "YES" ];
then
EnableExtraPlatformsInSDK
fi
if [ "$BACKEND" = "YES" ];
then
UpdateVersionNumber
if [ "$ENABLE_EXTRA_PLATFORMS" = "YES" ];
if [ "$ENABLE_BSD" = "YES" ];
then
EnableExtraPlatforms
EnableBsdSupport
fi
Build
if [[ -z "$RID" || -z "$FRAMEWORK" ]];
@@ -382,10 +364,9 @@ then
PackageTests "net6.0" "linux-x64"
PackageTests "net6.0" "linux-musl-x64"
PackageTests "net6.0" "osx-x64"
if [ "$ENABLE_EXTRA_PLATFORMS" = "YES" ];
if [ "$ENABLE_BSD" = "YES" ];
then
PackageTests "net6.0" "freebsd-x64"
PackageTests "net6.0" "linux-x86"
fi
else
PackageTests "$FRAMEWORK" "$RID"
@@ -424,10 +405,9 @@ then
Package "net6.0" "linux-musl-arm"
Package "net6.0" "osx-x64"
Package "net6.0" "osx-arm64"
if [ "$ENABLE_EXTRA_PLATFORMS" = "YES" ];
if [ "$ENABLE_BSD" = "YES" ];
then
Package "net6.0" "freebsd-x64"
Package "net6.0" "linux-x86"
fi
else
Package "$FRAMEWORK" "$RID"

View File

@@ -179,16 +179,6 @@ class HistoryRow extends Component {
);
}
if (name === 'sourceTitle') {
return (
<TableRowCell
key={name}
>
{sourceTitle}
</TableRowCell>
);
}
if (name === 'details') {
return (
<TableRowCell

View File

@@ -8,7 +8,7 @@ import AppRoutes from './AppRoutes';
function App({ store, history }) {
return (
<DocumentTitle title={window.Radarr.instanceName}>
<DocumentTitle title="Radarr">
<Provider store={store}>
<ConnectedRouter history={history}>
<PageConnector>

View File

@@ -89,12 +89,12 @@ function AppUpdatedModalContent(props) {
<UpdateChanges
title={translate('New')}
changes={Array.from(new Set(update.changes.new))}
changes={update.changes.new}
/>
<UpdateChanges
title={translate('Fixed')}
changes={Array.from(new Set(update.changes.fixed))}
changes={update.changes.fixed}
/>
</div>
}

View File

@@ -86,7 +86,7 @@ class CollectionFooter extends Component {
} = this.state;
const monitoredOptions = [
{ key: NO_CHANGE, value: translate('NoChange'), disabled: true },
{ key: NO_CHANGE, value: translate('No Change'), disabled: true },
{ key: 'monitored', value: translate('Monitored') },
{ key: 'unmonitored', value: translate('Unmonitored') }
];

View File

@@ -1,50 +0,0 @@
.movie {
display: flex;
align-items: stretch;
overflow: hidden;
margin: 2px 4px;
border: 1px solid $borderColor;
border-radius: 4px;
background-color: #eee;
cursor: default;
}
.movieTitle {
padding: 0 4px;
}
.movieStatus {
padding: 0 4px;
border-left: 4px;
border-left-style: solid;
background-color: $white;
color: $defaultColor;
}
.primary {
border-color: $primaryColor;
}
.danger {
border-color: $dangerColor;
}
.success {
border-color: $successColor;
}
.purple {
border-color: $purple;
}
.warning {
border-color: $warningColor;
}
.info {
border-color: $infoColor;
}
.queue {
border-color: $queueColor;
}

View File

@@ -1,84 +0,0 @@
import classNames from 'classnames';
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import MonitorToggleButton from 'Components/MonitorToggleButton';
import getStatusStyle from 'Utilities/Movie/getStatusStyle';
import translate from 'Utilities/String/translate';
import styles from './CollectionMovieLabel.css';
class CollectionMovieLabel extends Component {
//
// Render
render() {
const {
id,
title,
status,
monitored,
isAvailable,
hasFile,
onMonitorTogglePress,
isSaving
} = this.props;
return (
<div className={styles.movie}>
<div className={styles.movieTitle}>
{
id &&
<MonitorToggleButton
monitored={monitored}
isSaving={isSaving}
onPress={onMonitorTogglePress}
/>
}
<span>
{
title
}
</span>
</div>
{
id &&
<div
className={classNames(
styles.movieStatus,
styles[getStatusStyle(status, monitored, hasFile, isAvailable, 'kinds')]
)}
>
{
hasFile ? translate('Downloaded') : translate('Missing')
}
</div>
}
</div>
);
}
}
CollectionMovieLabel.propTypes = {
id: PropTypes.number,
title: PropTypes.string.isRequired,
status: PropTypes.string,
isAvailable: PropTypes.bool,
monitored: PropTypes.bool,
hasFile: PropTypes.bool,
isSaving: PropTypes.bool.isRequired,
movieFile: PropTypes.object,
movieFileId: PropTypes.number,
onMonitorTogglePress: PropTypes.func.isRequired
};
CollectionMovieLabel.defaultProps = {
isSaving: false,
statistics: {
episodeFileCount: 0,
totalEpisodeCount: 0,
percentOfEpisodes: 0
}
};
export default CollectionMovieLabel;

View File

@@ -1,59 +0,0 @@
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { createSelector } from 'reselect';
import { toggleMovieMonitored } from 'Store/Actions/movieActions';
import createCollectionExistingMovieSelector from 'Store/Selectors/createCollectionExistingMovieSelector';
import createDimensionsSelector from 'Store/Selectors/createDimensionsSelector';
import CollectionMovieLabel from './CollectionMovieLabel';
function createMapStateToProps() {
return createSelector(
createDimensionsSelector(),
createCollectionExistingMovieSelector(),
(dimensions, existingMovie) => {
return {
isSmallScreen: dimensions.isSmallScreen,
isExistingMovie: !!existingMovie,
...existingMovie
};
}
);
}
const mapDispatchToProps = {
toggleMovieMonitored
};
class CollectionMovieLabelConnector extends Component {
//
// Listeners
onMonitorTogglePress = (monitored) => {
this.props.toggleMovieMonitored({
movieId: this.props.id,
monitored
});
};
//
// Render
render() {
return (
<CollectionMovieLabel
{...this.props}
onMonitorTogglePress={this.onMonitorTogglePress}
/>
);
}
}
CollectionMovieLabelConnector.propTypes = {
id: PropTypes.number,
monitored: PropTypes.bool,
toggleMovieMonitored: PropTypes.func.isRequired
};
export default connect(createMapStateToProps, mapDispatchToProps)(CollectionMovieLabelConnector);

View File

@@ -32,11 +32,6 @@ $hoverScale: 1.05;
display: block;
}
.labelsContainer {
display: flex;
flex-wrap: wrap;
}
.moviesContainer {
margin-bottom: 5px;
}

View File

@@ -1,8 +1,8 @@
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import Slider from 'react-slick';
import TextTruncate from 'react-text-truncate';
import EditCollectionModalConnector from 'Collection/Edit/EditCollectionModalConnector';
import Carousel from 'Components/Carousel';
import CheckInput from 'Components/Form/CheckInput';
import Icon from 'Components/Icon';
import Label from 'Components/Label';
@@ -14,12 +14,8 @@ import dimensions from 'Styles/Variables/dimensions';
import fonts from 'Styles/Variables/fonts';
import translate from 'Utilities/String/translate';
import CollectionMovieConnector from './CollectionMovieConnector';
import CollectionMovieLabelConnector from './CollectionMovieLabelConnector';
import styles from './CollectionOverview.css';
import 'slick-carousel/slick/slick.css';
import 'slick-carousel/slick/slick-theme.css';
const columnPadding = parseInt(dimensions.movieIndexColumnPadding);
const columnPaddingSmallScreen = parseInt(dimensions.movieIndexColumnPaddingSmallScreen);
const defaultFontSize = parseInt(fonts.defaultFontSize);
@@ -109,7 +105,6 @@ class CollectionOverview extends Component {
const {
showDetails,
showOverview,
showPosters,
detailedProgressBar
} = this.props.overviewOptions;
@@ -120,15 +115,6 @@ class CollectionOverview extends Component {
const contentHeight = getContentHeight(rowHeight, isSmallScreen);
const overviewHeight = contentHeight - titleRowHeight - posterHeight;
const sliderSettings = {
arrows: false,
dots: false,
infinite: false,
slidesToShow: 1,
slidesToScroll: 1,
variableWidth: true
};
return (
<div className={styles.container}>
<div className={styles.content}>
@@ -163,25 +149,21 @@ class CollectionOverview extends Component {
/>
</div>
{
showPosters &&
<div className={styles.navigationButtons}>
<IconButton
name={icons.ARROW_LEFT}
title={translate('ScrollMovies')}
onPress={this.state.slider?.slickPrev}
size={20}
/>
<IconButton
name={icons.ARROW_RIGHT}
title={translate('ScrollMovies')}
onPress={this.state.slider?.slickNext}
size={20}
/>
</div>
}
<div className={styles.navigationButtons}>
<IconButton
name={icons.ARROW_LEFT}
title={translate('ScrollMovies')}
onPress={this.state.slider?.slickPrev}
size={20}
/>
<IconButton
name={icons.ARROW_RIGHT}
title={translate('ScrollMovies')}
onPress={this.state.slider?.slickNext}
size={20}
/>
</div>
</div>
{
@@ -267,35 +249,22 @@ class CollectionOverview extends Component {
</div>
}
{
showPosters ?
<div className={styles.sliderContainer}>
<Slider ref={this.setSliderRef} {...sliderSettings}>
{movies.map((movie) => (
<div className={styles.movie} key={movie.tmdbId}>
<CollectionMovieConnector
key={movie.tmdbId}
posterWidth={posterWidth}
posterHeight={posterHeight}
detailedProgressBar={detailedProgressBar}
collectionId={id}
{...movie}
/>
</div>
))}
</Slider>
</div> :
<div className={styles.labelsContainer}>
{movies.map((movie) => (
<CollectionMovieLabelConnector
<div className={styles.sliderContainer}>
<Carousel setRef={this.setSliderRef}>
{movies.map((movie) => (
<div className={styles.movie} key={movie.tmdbId}>
<CollectionMovieConnector
key={movie.tmdbId}
posterWidth={posterWidth}
posterHeight={posterHeight}
detailedProgressBar={detailedProgressBar}
collectionId={id}
{...movie}
/>
))}
</div>
}
</div>
))}
</Carousel>
</div>
</div>
</div>

View File

@@ -30,7 +30,7 @@ function calculatePosterWidth(posterSize, isSmallScreen) {
function calculateRowHeight(posterHeight, sortKey, isSmallScreen, overviewOptions) {
const heights = [
overviewOptions.showPosters ? posterHeight : 75,
posterHeight,
isSmallScreen ? columnPaddingSmallScreen : columnPadding
];

View File

@@ -31,8 +31,7 @@ class CollectionOverviewOptionsModalContent extends Component {
detailedProgressBar: props.detailedProgressBar,
size: props.size,
showDetails: props.showDetails,
showOverview: props.showOverview,
showPosters: props.showPosters
showOverview: props.showOverview
};
}
@@ -41,8 +40,7 @@ class CollectionOverviewOptionsModalContent extends Component {
detailedProgressBar,
size,
showDetails,
showOverview,
showPosters
showOverview
} = this.props;
const state = {};
@@ -63,10 +61,6 @@ class CollectionOverviewOptionsModalContent extends Component {
state.showOverview = showOverview;
}
if (showPosters !== prevProps.showPosters) {
state.showPosters = showPosters;
}
if (!_.isEmpty(state)) {
this.setState(state);
}
@@ -105,14 +99,13 @@ class CollectionOverviewOptionsModalContent extends Component {
size,
detailedProgressBar,
showDetails,
showPosters,
showOverview
} = this.state;
return (
<ModalContent onModalClose={onModalClose}>
<ModalHeader>
{translate('CollectionOptions')}
Overview Options
</ModalHeader>
<ModalBody>
@@ -148,7 +141,6 @@ class CollectionOverviewOptionsModalContent extends Component {
type={inputTypes.CHECK}
name="showDetails"
value={showDetails}
helpText={translate('CollectionShowDetailsHelpText')}
onChange={this.onChangeOverviewOption}
/>
</FormGroup>
@@ -160,19 +152,6 @@ class CollectionOverviewOptionsModalContent extends Component {
type={inputTypes.CHECK}
name="showOverview"
value={showOverview}
helpText={translate('CollectionShowOverviewsHelpText')}
onChange={this.onChangeOverviewOption}
/>
</FormGroup>
<FormGroup>
<FormLabel>{translate('ShowPosters')}</FormLabel>
<FormInputGroup
type={inputTypes.CHECK}
name="showPosters"
value={showPosters}
helpText={translate('CollectionShowPostersHelpText')}
onChange={this.onChangeOverviewOption}
/>
</FormGroup>
@@ -196,7 +175,6 @@ CollectionOverviewOptionsModalContent.propTypes = {
size: PropTypes.string.isRequired,
showDetails: PropTypes.bool.isRequired,
showOverview: PropTypes.bool.isRequired,
showPosters: PropTypes.bool.isRequired,
onChangeOverviewOption: PropTypes.func.isRequired,
onChangeOption: PropTypes.func.isRequired,
onModalClose: PropTypes.func.isRequired

View File

@@ -0,0 +1,37 @@
import PropTypes from 'prop-types';
import React from 'react';
import Slider from 'react-slick';
import styles from './Alert.css';
import 'slick-carousel/slick/slick.css';
import 'slick-carousel/slick/slick-theme.css';
function Carousel({ className, setRef, children, ...otherProps }) {
const sliderSettings = {
arrows: false,
dots: false,
infinite: false,
slidesToShow: 1,
slidesToScroll: 1,
variableWidth: true
};
return (
<Slider ref={setRef} {...sliderSettings}>
{children}
</Slider>
);
}
Carousel.propTypes = {
className: PropTypes.string.isRequired,
setRef: PropTypes.func.isRequired,
children: PropTypes.node.isRequired
};
Carousel.defaultProps = {
className: styles.alert
};
export default Carousel;

View File

@@ -14,7 +14,7 @@ function PageContent(props) {
return (
<ErrorBoundary errorComponent={PageContentError}>
<DocumentTitle title={title ? `${title} - ${window.Radarr.instanceName}` : window.Radarr.instanceName}>
<DocumentTitle title={title ? `${title} - Radarr` : 'Radarr'}>
<div className={className}>
{children}
</div>

View File

@@ -9,7 +9,6 @@ import SelectInput from 'Components/Form/SelectInput';
import SpinnerButton from 'Components/Link/SpinnerButton';
import PageContentFooter from 'Components/Page/PageContentFooter';
import { kinds } from 'Helpers/Props';
import monitorOptions from 'Utilities/Movie/monitorOptions';
import translate from 'Utilities/String/translate';
import DiscoverMovieFooterLabel from './DiscoverMovieFooterLabel';
import ExcludeMovieModal from './Exclusion/ExcludeMovieModal';
@@ -138,6 +137,11 @@ class DiscoverMovieFooter extends Component {
isExcludeMovieModalOpen
} = this.state;
const monitoredOptions = [
{ key: true, value: translate('Monitored') },
{ key: false, value: translate('Unmonitored') }
];
return (
<PageContentFooter>
<div className={styles.inputContainer}>
@@ -149,7 +153,7 @@ class DiscoverMovieFooter extends Component {
<SelectInput
name="monitor"
value={monitor}
values={monitorOptions}
values={monitoredOptions}
isDisabled={!selectedCount}
onChange={onInputChange}
/>

View File

@@ -81,7 +81,6 @@ const filterExistingFilesOptions = {
};
const importModeOptions = [
{ key: 'chooseImportMode', value: translate('ChooseImportMode'), disabled: true },
{ key: 'move', value: translate('MoveFiles') },
{ key: 'copy', value: translate('HardlinkCopyFiles') }
];

View File

@@ -1,3 +1,4 @@
import _ from 'lodash';
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import { connect } from 'react-redux';
@@ -100,18 +101,9 @@ class InteractiveImportModalContentConnector extends Component {
};
onImportSelectedPress = (selected, importMode) => {
const {
items
} = this.props;
const files = [];
if (importMode === 'chooseImportMode') {
this.setState({ interactiveImportErrorMessage: 'An import mode must be selected' });
return;
}
items.forEach((item) => {
_.forEach(this.props.items, (item) => {
const isSelected = selected.indexOf(item.id) > -1;
if (isSelected) {

View File

@@ -7,9 +7,3 @@
.filteredMessage {
margin-top: 10px;
}
.blankpad {
padding-top: 10px;
padding-bottom: 10px;
padding-left: 2em;
}

View File

@@ -2,12 +2,15 @@ import PropTypes from 'prop-types';
import React from 'react';
import Icon from 'Components/Icon';
import LoadingIndicator from 'Components/Loading/LoadingIndicator';
import FilterMenu from 'Components/Menu/FilterMenu';
import PageMenuButton from 'Components/Menu/PageMenuButton';
import Table from 'Components/Table/Table';
import TableBody from 'Components/Table/TableBody';
import { icons, sortDirections } from 'Helpers/Props';
import { align, icons, sortDirections } from 'Helpers/Props';
import translate from 'Utilities/String/translate';
import InteractiveSearchFilterModalConnector from './InteractiveSearchFilterModalConnector';
import InteractiveSearchRowConnector from './InteractiveSearchRowConnector';
import styles from './InteractiveSearchContent.css';
import styles from './InteractiveSearch.css';
const columns = [
{
@@ -22,20 +25,6 @@ const columns = [
isSortable: true,
isVisible: true
},
{
name: 'releaseWeight',
label: React.createElement(Icon, { name: icons.DOWNLOAD }),
isSortable: true,
fixedSortDirection: sortDirections.ASCENDING,
isVisible: true
},
{
name: 'rejections',
label: React.createElement(Icon, { name: icons.DANGER }),
isSortable: true,
fixedSortDirection: sortDirections.ASCENDING,
isVisible: true
},
{
name: 'title',
label: translate('Title'),
@@ -99,10 +88,24 @@ const columns = [
label: React.createElement(Icon, { name: icons.FLAG }),
isSortable: true,
isVisible: true
},
{
name: 'rejections',
label: React.createElement(Icon, { name: icons.DANGER }),
isSortable: true,
fixedSortDirection: sortDirections.ASCENDING,
isVisible: true
},
{
name: 'releaseWeight',
label: React.createElement(Icon, { name: icons.DOWNLOAD }),
isSortable: true,
fixedSortDirection: sortDirections.ASCENDING,
isVisible: true
}
];
function InteractiveSearchContent(props) {
function InteractiveSearch(props) {
const {
searchPayload,
isFetching,
@@ -110,44 +113,63 @@ function InteractiveSearchContent(props) {
error,
totalReleasesCount,
items,
selectedFilterKey,
filters,
customFilters,
sortKey,
sortDirection,
longDateFormat,
timeFormat,
onSortPress,
onFilterSelect,
onGrabPress
} = props;
return (
<div>
<div className={styles.filterMenuContainer}>
<FilterMenu
alignMenu={align.RIGHT}
selectedFilterKey={selectedFilterKey}
filters={filters}
customFilters={customFilters}
buttonComponent={PageMenuButton}
filterModalConnectorComponent={InteractiveSearchFilterModalConnector}
filterModalConnectorComponentProps={'movies'}
onFilterSelect={onFilterSelect}
/>
</div>
{
isFetching &&
<LoadingIndicator />
isFetching ? <LoadingIndicator /> : null
}
{
!isFetching && !!error &&
<div className={styles.blankpad}>
!isFetching && error ?
<div>
{translate('UnableToLoadResultsIntSearch')}
</div>
</div> :
null
}
{
!isFetching && isPopulated && !totalReleasesCount &&
<div className={styles.blankpad}>
!isFetching && isPopulated && !totalReleasesCount ?
<div>
{translate('NoResultsFound')}
</div>
</div> :
null
}
{
!!totalReleasesCount && isPopulated && !items.length &&
<div className={styles.blankpad}>
!!totalReleasesCount && isPopulated && !items.length ?
<div>
{translate('AllResultsHiddenFilter')}
</div>
</div> :
null
}
{
isPopulated && !!items.length &&
isPopulated && !!items.length ?
<Table
columns={columns}
sortKey={sortKey}
@@ -159,7 +181,7 @@ function InteractiveSearchContent(props) {
items.map((item) => {
return (
<InteractiveSearchRowConnector
key={`${item.indexerId}-${item.guid}`}
key={item.guid}
{...item}
searchPayload={searchPayload}
longDateFormat={longDateFormat}
@@ -170,32 +192,38 @@ function InteractiveSearchContent(props) {
})
}
</TableBody>
</Table>
</Table> :
null
}
{
totalReleasesCount !== items.length && !!items.length &&
totalReleasesCount !== items.length && !!items.length ?
<div className={styles.filteredMessage}>
{translate('SomeResultsHiddenFilter')}
</div>
</div> :
null
}
</div>
);
}
InteractiveSearchContent.propTypes = {
InteractiveSearch.propTypes = {
searchPayload: PropTypes.object.isRequired,
isFetching: PropTypes.bool.isRequired,
isPopulated: PropTypes.bool.isRequired,
error: PropTypes.object,
totalReleasesCount: PropTypes.number.isRequired,
items: PropTypes.arrayOf(PropTypes.object).isRequired,
selectedFilterKey: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,
filters: PropTypes.arrayOf(PropTypes.object).isRequired,
customFilters: PropTypes.arrayOf(PropTypes.object).isRequired,
sortKey: PropTypes.string,
sortDirection: PropTypes.string,
longDateFormat: PropTypes.string.isRequired,
timeFormat: PropTypes.string.isRequired,
onSortPress: PropTypes.func.isRequired,
onFilterSelect: PropTypes.func.isRequired,
onGrabPress: PropTypes.func.isRequired
};
export default InteractiveSearchContent;
export default InteractiveSearch;

View File

@@ -5,7 +5,7 @@ import { createSelector } from 'reselect';
import * as releaseActions from 'Store/Actions/releaseActions';
import createClientSideCollectionSelector from 'Store/Selectors/createClientSideCollectionSelector';
import createUISettingsSelector from 'Store/Selectors/createUISettingsSelector';
import InteractiveSearchContent from './InteractiveSearchContent';
import InteractiveSearch from './InteractiveSearch';
function createMapStateToProps(appState) {
return createSelector(
@@ -48,7 +48,7 @@ function createMapDispatchToProps(dispatch, props) {
};
}
class InteractiveSearchContentConnector extends Component {
class InteractiveSearchConnector extends Component {
//
// Lifecycle
@@ -79,18 +79,18 @@ class InteractiveSearchContentConnector extends Component {
return (
<InteractiveSearchContent
<InteractiveSearch
{...otherProps}
/>
);
}
}
InteractiveSearchContentConnector.propTypes = {
InteractiveSearchConnector.propTypes = {
searchPayload: PropTypes.object.isRequired,
isPopulated: PropTypes.bool.isRequired,
dispatchFetchReleases: PropTypes.func.isRequired,
dispatchClearReleases: PropTypes.func.isRequired
};
export default connect(createMapStateToProps, createMapDispatchToProps)(InteractiveSearchContentConnector);
export default connect(createMapStateToProps, createMapDispatchToProps)(InteractiveSearchConnector);

View File

@@ -1,15 +1,20 @@
.cell {
composes: cell from '~Components/Table/Cells/TableRowCell.css';
}
.protocol {
composes: cell;
composes: cell from '~Components/Table/Cells/TableRowCell.css';
width: 80px;
}
.title {
composes: cell from '~Components/Table/Cells/TableRowCell.css';
display: flex;
align-items: center;
justify-content: space-between;
word-break: break-all;
}
.indexer {
composes: cell;
composes: cell from '~Components/Table/Cells/TableRowCell.css';
width: 85px;
}
@@ -17,7 +22,9 @@
.quality,
.customFormat,
.language {
composes: cell;
composes: cell from '~Components/Table/Cells/TableRowCell.css';
text-align: center;
}
.language {
@@ -25,7 +32,7 @@
}
.customFormatScore {
composes: cell;
composes: cell from '~Components/Table/Cells/TableRowCell.css';
width: 55px;
font-weight: bold;
@@ -35,34 +42,26 @@
.rejected,
.indexerFlags,
.download {
composes: cell;
composes: cell from '~Components/Table/Cells/TableRowCell.css';
width: 50px;
}
.age,
.size {
composes: cell;
composes: cell from '~Components/Table/Cells/TableRowCell.css';
white-space: nowrap;
}
.peers {
composes: cell;
composes: cell from '~Components/Table/Cells/TableRowCell.css';
width: 75px;
}
.title {
composes: cell;
}
.title div {
overflow-wrap: break-word;
}
.history {
composes: cell;
composes: cell from '~Components/Table/Cells/TableRowCell.css';
width: 75px;
}

View File

@@ -145,46 +145,6 @@ class InteractiveSearchRow extends Component {
{formatAge(age, ageHours, ageMinutes)}
</TableRowCell>
<TableRowCell className={styles.download}>
<SpinnerIconButton
name={getDownloadIcon(isGrabbing, isGrabbed, grabError)}
kind={grabError ? kinds.DANGER : kinds.DEFAULT}
title={getDownloadTooltip(isGrabbing, isGrabbed, grabError)}
isDisabled={isGrabbed}
isSpinning={isGrabbing}
onPress={downloadAllowed ? this.onGrabPress : this.onConfirmGrabPress}
/>
</TableRowCell>
<TableRowCell className={styles.rejected}>
{
!!rejections.length &&
<Popover
anchor={
<Icon
name={icons.DANGER}
kind={kinds.DANGER}
/>
}
title={translate('ReleaseRejected')}
body={
<ul>
{
rejections.map((rejection, index) => {
return (
<li key={index}>
{rejection}
</li>
);
})
}
</ul>
}
position={tooltipPositions.BOTTOM}
/>
}
</TableRowCell>
<TableRowCell className={styles.title}>
<Link
to={infoUrl}
@@ -297,6 +257,46 @@ class InteractiveSearchRow extends Component {
}
</TableRowCell>
<TableRowCell className={styles.rejected}>
{
!!rejections.length &&
<Popover
anchor={
<Icon
name={icons.DANGER}
kind={kinds.DANGER}
/>
}
title={translate('ReleaseRejected')}
body={
<ul>
{
rejections.map((rejection, index) => {
return (
<li key={index}>
{rejection}
</li>
);
})
}
</ul>
}
position={tooltipPositions.LEFT}
/>
}
</TableRowCell>
<TableRowCell className={styles.download}>
<SpinnerIconButton
name={getDownloadIcon(isGrabbing, isGrabbed, grabError)}
kind={grabError ? kinds.DANGER : kinds.DEFAULT}
title={getDownloadTooltip(isGrabbing, isGrabbed, grabError)}
isDisabled={isGrabbed}
isSpinning={isGrabbing}
onPress={downloadAllowed ? this.onGrabPress : this.onConfirmGrabPress}
/>
</TableRowCell>
<ConfirmModal
isOpen={this.state.isConfirmGrabModalOpen}
kind={kinds.WARNING}

View File

@@ -1,16 +0,0 @@
import React from 'react';
import InteractiveSearchContentConnector from './InteractiveSearchContentConnector';
function InteractiveSearchTable(props) {
return (
<InteractiveSearchContentConnector
searchPayload={props}
/>
);
}
InteractiveSearchTable.propTypes = {
};
export default InteractiveSearchTable;

View File

@@ -69,7 +69,8 @@ class MovieCastPoster extends Component {
const elementStyle = {
width: `${posterWidth}px`,
height: `${posterHeight}px`
height: `${posterHeight}px`,
borderRadius: '5px'
};
const contentStyle = {

View File

@@ -69,7 +69,8 @@ class MovieCrewPoster extends Component {
const elementStyle = {
width: `${posterWidth}px`,
height: `${posterHeight}px`
height: `${posterHeight}px`,
borderRadius: '5px'
};
const contentStyle = {

View File

@@ -1,6 +1,7 @@
$hoverScale: 1.05;
.content {
border-radius: 5px;
transition: all 200ms ease-in;
&:hover {

View File

@@ -2,6 +2,10 @@
flex: 1 0 auto;
}
.movie {
padding: 10px;
}
.container {
padding: 10px;
}

View File

@@ -1,7 +1,6 @@
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import { Grid, WindowScroller } from 'react-virtualized';
import Measure from 'Components/Measure';
import Carousel from 'Components/Carousel';
import dimensions from 'Styles/Variables/dimensions';
import hasDifferentItemsOrOrder from 'Utilities/Object/hasDifferentItemsOrOrder';
import MovieCreditPosterConnector from './MovieCreditPosterConnector';
@@ -169,56 +168,36 @@ class MovieCreditPosters extends Component {
render() {
const {
items
items,
itemComponent
} = this.props;
const {
width,
columnWidth,
columnCount,
rowHeight
posterWidth,
posterHeight
} = this.state;
const rowCount = Math.ceil(items.length / columnCount);
return (
<Measure
whitelist={['width']}
onMeasure={this.onMeasure}
>
<WindowScroller
scrollElement={undefined}
>
{({ height, registerChild, onChildScroll, scrollTop }) => {
if (!height) {
return <div />;
}
return (
<div ref={registerChild}>
<Grid
ref={this.setGridRef}
className={styles.grid}
autoHeight={true}
height={height}
columnCount={columnCount}
columnWidth={columnWidth}
rowCount={rowCount}
rowHeight={rowHeight}
width={width}
onScroll={onChildScroll}
scrollTop={scrollTop}
overscanRowCount={2}
cellRenderer={this.cellRenderer}
scrollToAlignment={'start'}
isScrollingOptOut={true}
/>
</div>
);
}
}
</WindowScroller>
</Measure>
<div className={styles.sliderContainer}>
<Carousel setRef={this.setSliderRef}>
{items.map((movie) => (
<div className={styles.movie} key={movie.tmdbId}>
<MovieCreditPosterConnector
key={movie.order}
component={itemComponent}
posterWidth={posterWidth}
posterHeight={posterHeight}
tmdbId={movie.personTmdbId}
personName={movie.personName}
job={movie.job}
character={movie.character}
images={movie.images}
/>
</div>
))}
</Carousel>
</div>
);
}
}

View File

@@ -1,3 +0,0 @@
.alternateTitle {
white-space: nowrap;
}

View File

@@ -1,28 +0,0 @@
import PropTypes from 'prop-types';
import React from 'react';
import styles from './MovieAlternateTitles.css';
function MovieAlternateTitles({ alternateTitles }) {
return (
<ul>
{
alternateTitles.filter((x, i, a) => a.indexOf(x) === i).map((alternateTitle) => {
return (
<li
key={alternateTitle}
className={styles.alternateTitle}
>
{alternateTitle}
</li>
);
})
}
</ul>
);
}
MovieAlternateTitles.propTypes = {
alternateTitles: PropTypes.arrayOf(PropTypes.string).isRequired
};
export default MovieAlternateTitles;

View File

@@ -5,7 +5,7 @@
.header {
position: relative;
width: 100%;
height: 375px;
height: 425px;
}
.errorMessage {
@@ -39,10 +39,11 @@
}
.poster {
z-index: 2;
flex-shrink: 0;
margin-right: 35px;
width: 217px;
height: 319px;
width: 250px;
height: 368px;
}
.info {

View File

@@ -1,8 +1,8 @@
import _ from 'lodash';
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import { Tab, TabList, TabPanel, Tabs } from 'react-tabs';
import TextTruncate from 'react-text-truncate';
import FieldSet from 'Components/FieldSet';
import Icon from 'Components/Icon';
import ImdbRating from 'Components/ImdbRating';
import InfoLabel from 'Components/InfoLabel';
@@ -22,12 +22,11 @@ import Popover from 'Components/Tooltip/Popover';
import Tooltip from 'Components/Tooltip/Tooltip';
import { icons, kinds, sizes, tooltipPositions } from 'Helpers/Props';
import InteractiveImportModal from 'InteractiveImport/InteractiveImportModal';
import InteractiveSearchFilterMenuConnector from 'InteractiveSearch/InteractiveSearchFilterMenuConnector';
import InteractiveSearchTable from 'InteractiveSearch/InteractiveSearchTable';
import DeleteMovieModal from 'Movie/Delete/DeleteMovieModal';
import EditMovieModalConnector from 'Movie/Edit/EditMovieModalConnector';
import MovieHistoryTable from 'Movie/History/MovieHistoryTable';
import MoviePoster from 'Movie/MoviePoster';
import MovieInteractiveSearchModalConnector from 'Movie/Search/MovieInteractiveSearchModalConnector';
import MovieFileEditorTable from 'MovieFile/Editor/MovieFileEditorTable';
import ExtraFileTable from 'MovieFile/Extras/ExtraFileTable';
import OrganizePreviewModalConnector from 'Organize/OrganizePreviewModalConnector';
@@ -81,10 +80,10 @@ class MovieDetails extends Component {
isEditMovieModalOpen: false,
isDeleteMovieModalOpen: false,
isInteractiveImportModalOpen: false,
isInteractiveSearchModalOpen: false,
allExpanded: false,
allCollapsed: false,
expandedState: {},
selectedTabIndex: 0,
overviewHeight: 0,
titleWidth: 0
};
@@ -137,6 +136,14 @@ class MovieDetails extends Component {
this.setState({ isEditMovieModalOpen: false });
};
onInteractiveSearchPress = () => {
this.setState({ isInteractiveSearchModalOpen: true });
};
onInteractiveSearchModalClose = () => {
this.setState({ isInteractiveSearchModalOpen: false });
};
onDeleteMoviePress = () => {
this.setState({
isEditMovieModalOpen: false,
@@ -298,9 +305,9 @@ class MovieDetails extends Component {
isEditMovieModalOpen,
isDeleteMovieModalOpen,
isInteractiveImportModalOpen,
isInteractiveSearchModalOpen,
overviewHeight,
titleWidth,
selectedTabIndex
titleWidth
} = this.state;
const marqueeWidth = isSmallScreen ? titleWidth : (titleWidth - 150);
@@ -326,6 +333,14 @@ class MovieDetails extends Component {
onPress={onSearchPress}
/>
<PageToolbarButton
label={translate('InteractiveSearch')}
iconName={icons.INTERACTIVE}
isSpinning={isSearching}
title={undefined}
onPress={this.onInteractiveSearchPress}
/>
<PageToolbarSeparator />
<PageToolbarButton
@@ -651,101 +666,39 @@ class MovieDetails extends Component {
</div>
}
<Tabs selectedIndex={this.state.tabIndex} onSelect={this.onTabSelect}>
<TabList
className={styles.tabList}
>
<Tab
className={styles.tab}
selectedClassName={styles.selectedTab}
>
{translate('History')}
</Tab>
<FieldSet legend={translate('History')}>
<MovieHistoryTable
movieId={id}
/>
</FieldSet>
<Tab
className={styles.tab}
selectedClassName={styles.selectedTab}
>
{translate('Search')}
</Tab>
<FieldSet legend={translate('Files')}>
<MovieFileEditorTable
movieId={id}
/>
<Tab
className={styles.tab}
selectedClassName={styles.selectedTab}
>
{translate('Files')}
</Tab>
<ExtraFileTable
movieId={id}
/>
</FieldSet>
<Tab
className={styles.tab}
selectedClassName={styles.selectedTab}
>
{translate('Titles')}
</Tab>
<FieldSet legend={translate('Cast')}>
<MovieCastPostersConnector
isSmallScreen={isSmallScreen}
/>
</FieldSet>
<Tab
className={styles.tab}
selectedClassName={styles.selectedTab}
>
{translate('Cast')}
</Tab>
<Tab
className={styles.tab}
selectedClassName={styles.selectedTab}
>
{translate('Crew')}
</Tab>
{
selectedTabIndex === 1 &&
<div className={styles.filterIcon}>
<InteractiveSearchFilterMenuConnector />
</div>
}
</TabList>
<TabPanel>
<MovieHistoryTable
movieId={id}
/>
</TabPanel>
<TabPanel>
<InteractiveSearchTable
movieId={id}
/>
</TabPanel>
<TabPanel>
<MovieFileEditorTable
movieId={id}
/>
<ExtraFileTable
movieId={id}
/>
</TabPanel>
<TabPanel>
<MovieTitlesTable
movieId={id}
/>
</TabPanel>
<TabPanel>
<MovieCastPostersConnector
isSmallScreen={isSmallScreen}
/>
</TabPanel>
<TabPanel>
<MovieCrewPostersConnector
isSmallScreen={isSmallScreen}
/>
</TabPanel>
</Tabs>
<FieldSet legend={translate('Crew')}>
<MovieCrewPostersConnector
isSmallScreen={isSmallScreen}
/>
</FieldSet>
<FieldSet legend={translate('Titles')}>
<MovieTitlesTable
movieId={id}
/>
</FieldSet>
</div>
<OrganizePreviewModalConnector
@@ -777,6 +730,12 @@ class MovieDetails extends Component {
showImportMode={false}
onModalClose={this.onInteractiveImportModalClose}
/>
<MovieInteractiveSearchModalConnector
isOpen={isInteractiveSearchModalOpen}
movieId={id}
onModalClose={this.onInteractiveSearchModalClose}
/>
</PageContentBody>
</PageContent>
);

View File

@@ -0,0 +1,9 @@
.container {
border: 1px solid $borderColor;
border-radius: 4px;
background-color: $white;
&:last-of-type {
margin-bottom: 0;
}
}

View File

@@ -1,5 +1,6 @@
import React from 'react';
import MovieTitlesTableContentConnector from './MovieTitlesTableContentConnector';
import styles from './MovieTitlesTable.css';
function MovieTitlesTable(props) {
const {
@@ -7,9 +8,11 @@ function MovieTitlesTable(props) {
} = props;
return (
<MovieTitlesTableContentConnector
{...otherProps}
/>
<div className={styles.container}>
<MovieTitlesTableContentConnector
{...otherProps}
/>
</div>
);
}

View File

@@ -0,0 +1,9 @@
.container {
border: 1px solid $borderColor;
border-radius: 4px;
background-color: $white;
&:last-of-type {
margin-bottom: 0;
}
}

View File

@@ -1,5 +1,6 @@
import React from 'react';
import MovieHistoryTableContentConnector from './MovieHistoryTableContentConnector';
import styles from './MovieHistoryTable.css';
function MovieHistoryTable(props) {
const {
@@ -7,9 +8,11 @@ function MovieHistoryTable(props) {
} = props;
return (
<MovieHistoryTableContentConnector
{...otherProps}
/>
<div className={styles.container}>
<MovieHistoryTableContentConnector
{...otherProps}
/>
</div>
);
}

View File

@@ -0,0 +1,35 @@
import PropTypes from 'prop-types';
import React from 'react';
import Modal from 'Components/Modal/Modal';
import { sizes } from 'Helpers/Props';
import MovieInteractiveSearchModalContent from './MovieInteractiveSearchModalContent';
function MovieInteractiveSearchModal(props) {
const {
isOpen,
movieId,
onModalClose
} = props;
return (
<Modal
isOpen={isOpen}
closeOnBackgroundClick={false}
onModalClose={onModalClose}
size={sizes.EXTRA_LARGE}
>
<MovieInteractiveSearchModalContent
movieId={movieId}
onModalClose={onModalClose}
/>
</Modal>
);
}
MovieInteractiveSearchModal.propTypes = {
isOpen: PropTypes.bool.isRequired,
movieId: PropTypes.number.isRequired,
onModalClose: PropTypes.func.isRequired
};
export default MovieInteractiveSearchModal;

View File

@@ -0,0 +1,15 @@
import { connect } from 'react-redux';
import { cancelFetchReleases, clearReleases } from 'Store/Actions/releaseActions';
import MovieInteractiveSearchModal from './MovieInteractiveSearchModal';
function createMapDispatchToProps(dispatch, props) {
return {
onModalClose() {
dispatch(cancelFetchReleases());
dispatch(clearReleases());
props.onModalClose();
}
};
}
export default connect(null, createMapDispatchToProps)(MovieInteractiveSearchModal);

View File

@@ -0,0 +1,45 @@
import PropTypes from 'prop-types';
import React from 'react';
import Button from 'Components/Link/Button';
import ModalBody from 'Components/Modal/ModalBody';
import ModalContent from 'Components/Modal/ModalContent';
import ModalFooter from 'Components/Modal/ModalFooter';
import ModalHeader from 'Components/Modal/ModalHeader';
import { scrollDirections } from 'Helpers/Props';
import InteractiveSearchConnector from 'InteractiveSearch/InteractiveSearchConnector';
function MovieInteractiveSearchModalContent(props) {
const {
movieId,
onModalClose
} = props;
return (
<ModalContent onModalClose={onModalClose}>
<ModalHeader>
Interactive Search
</ModalHeader>
<ModalBody scrollDirection={scrollDirections.BOTH}>
<InteractiveSearchConnector
searchPayload={{
movieId
}}
/>
</ModalBody>
<ModalFooter>
<Button onPress={onModalClose}>
Close
</Button>
</ModalFooter>
</ModalContent>
);
}
MovieInteractiveSearchModalContent.propTypes = {
movieId: PropTypes.number.isRequired,
onModalClose: PropTypes.func.isRequired
};
export default MovieInteractiveSearchModalContent;

View File

@@ -1,5 +1,4 @@
.container {
margin-top: 20px;
border: 1px solid $borderColor;
border-radius: 4px;
background-color: $white;

View File

@@ -65,10 +65,10 @@ function DownloadClientOptions(props) {
<FormInputGroup
type={inputTypes.NUMBER}
name="checkForFinishedDownloadInterval"
min={1}
min={0}
max={120}
unit="minutes"
helpText={translate('RefreshMonitoredIntervalHelpText')}
helpText={translate('HelpText')}
onChange={onInputChange}
{...settings.checkForFinishedDownloadInterval}
/>

View File

@@ -20,7 +20,6 @@ function HostSettings(props) {
bindAddress,
port,
urlBase,
instanceName,
enableSsl,
sslPort,
sslCertPath,
@@ -74,22 +73,6 @@ function HostSettings(props) {
/>
</FormGroup>
<FormGroup
advancedSettings={advancedSettings}
isAdvanced={true}
>
<FormLabel>{translate('InstanceName')}</FormLabel>
<FormInputGroup
type={inputTypes.TEXT}
name="instanceName"
helpText={translate('InstanceNameHelpText')}
helpTextWarning={translate('RestartRequiredHelpTextWarning')}
onChange={onInputChange}
{...instanceName}
/>
</FormGroup>
<FormGroup
advancedSettings={advancedSettings}
isAdvanced={true}

View File

@@ -116,7 +116,7 @@ function IndexerOptions(props) {
min={0}
max={120}
unit="minutes"
helpText={translate('RssSyncHelpText')}
helpText={translate('HelpText')}
helpTextWarning={translate('RSSSyncIntervalHelpTextWarning')}
helpLink="https://wiki.servarr.com/radarr/faq#how-does-radarr-work"
onChange={onInputChange}

View File

@@ -59,7 +59,6 @@ class Notification extends Component {
onDownload,
onUpgrade,
onRename,
onMovieAdded,
onMovieDelete,
onMovieFileDelete,
onMovieFileDeleteForUpgrade,
@@ -69,7 +68,6 @@ class Notification extends Component {
supportsOnDownload,
supportsOnUpgrade,
supportsOnRename,
supportsOnMovieAdded,
supportsOnMovieDelete,
supportsOnMovieFileDelete,
supportsOnMovieFileDeleteForUpgrade,
@@ -119,14 +117,6 @@ class Notification extends Component {
null
}
{
supportsOnMovieAdded && onMovieAdded ?
<Label kind={kinds.SUCCESS}>
{translate('OnMovieAdded')}
</Label> :
null
}
{
supportsOnHealthIssue && onHealthIssue ?
<Label kind={kinds.SUCCESS}>
@@ -206,7 +196,6 @@ Notification.propTypes = {
onDownload: PropTypes.bool.isRequired,
onUpgrade: PropTypes.bool.isRequired,
onRename: PropTypes.bool.isRequired,
onMovieAdded: PropTypes.bool.isRequired,
onMovieDelete: PropTypes.bool.isRequired,
onMovieFileDelete: PropTypes.bool.isRequired,
onMovieFileDeleteForUpgrade: PropTypes.bool.isRequired,
@@ -219,7 +208,6 @@ Notification.propTypes = {
supportsOnMovieFileDeleteForUpgrade: PropTypes.bool.isRequired,
supportsOnUpgrade: PropTypes.bool.isRequired,
supportsOnRename: PropTypes.bool.isRequired,
supportsOnMovieAdded: PropTypes.bool.isRequired,
supportsOnHealthIssue: PropTypes.bool.isRequired,
supportsOnApplicationUpdate: PropTypes.bool.isRequired,
onConfirmDeleteNotification: PropTypes.func.isRequired

View File

@@ -19,7 +19,6 @@ function NotificationEventItems(props) {
onDownload,
onUpgrade,
onRename,
onMovieAdded,
onMovieDelete,
onMovieFileDelete,
onMovieFileDeleteForUpgrade,
@@ -29,7 +28,6 @@ function NotificationEventItems(props) {
supportsOnDownload,
supportsOnUpgrade,
supportsOnRename,
supportsOnMovieAdded,
supportsOnMovieDelete,
supportsOnMovieFileDelete,
supportsOnMovieFileDeleteForUpgrade,
@@ -94,17 +92,6 @@ function NotificationEventItems(props) {
/>
</div>
<div>
<FormInputGroup
type={inputTypes.CHECK}
name="onMovieAdded"
helpText={translate('OnMovieAddedHelpText')}
isDisabled={!supportsOnMovieAdded.value}
{...onMovieAdded}
onChange={onInputChange}
/>
</div>
<div>
<FormInputGroup
type={inputTypes.CHECK}

View File

@@ -106,7 +106,6 @@ export default {
selectedSchema.onDownload = selectedSchema.supportsOnDownload;
selectedSchema.onUpgrade = selectedSchema.supportsOnUpgrade;
selectedSchema.onRename = selectedSchema.supportsOnRename;
selectedSchema.onMovieAdded = selectedSchema.supportsOnMovieAdded;
selectedSchema.onMovieDelete = selectedSchema.supportsOnMovieDelete;
selectedSchema.onMovieFileDelete = selectedSchema.supportsOnMovieFileDelete;
selectedSchema.onMovieFileDeleteForUpgrade = selectedSchema.supportsOnMovieFileDeleteForUpgrade;

View File

@@ -79,11 +79,6 @@ export const defaultState = {
label: translate('ReleaseGroup'),
isVisible: false
},
{
name: 'sourceTitle',
label: translate('SourceTitle'),
isVisible: false
},
{
name: 'details',
columnLabel: translate('Details'),

View File

@@ -30,7 +30,7 @@ export const defaultState = {
sortKey: 'quality',
sortDirection: sortDirections.DESCENDING,
recentFolders: [],
importMode: 'chooseImportMode',
importMode: 'move',
sortPredicates: {
relativePath: function(item, direction) {
const relativePath = item.relativePath;

View File

@@ -40,8 +40,7 @@ export const defaultState = {
detailedProgressBar: false,
size: 'medium',
showDetails: true,
showOverview: true,
showPosters: true
showOverview: true
},
defaults: {

View File

@@ -1,9 +1,7 @@
import migrateBlacklistToBlocklist from './migrateBlacklistToBlocklist';
import migrateMonitorToEnum from './migrateMonitorToEnum';
import migratePreDbToReleased from './migratePreDbToReleased';
export default function migrate(persistedState) {
migrateBlacklistToBlocklist(persistedState);
migratePreDbToReleased(persistedState);
migrateMonitorToEnum(persistedState);
}

View File

@@ -1,26 +1,26 @@
import _ from 'lodash';
import get from 'lodash';
export default function migrateMonitorToEnum(persistedState) {
const addMovie = _.get(persistedState, 'addMovie.defaults.monitor');
const discoverMovie = _.get(persistedState, 'discoverMovie.defaults.monitor');
const addMovie = get(persistedState, 'addMovie.defaults.monitor');
const discoverMovie = get(persistedState, 'discoverMovie.defaults.monitor');
if (addMovie) {
if (addMovie === 'true') {
persistedState.addMovie.defaults.monitor = 'movieOnly';
}
if (addMovie === 'false') {
persistedState.addMovie.defaults.monitor = 'none';
}
if (!addMovie && !discoverMovie) {
return;
}
if (discoverMovie) {
if (discoverMovie === 'true') {
persistedState.discoverMovie.defaults.monitor = 'movieOnly';
}
if (addMovie === true) {
persistedState.addMovie.defaults.monitor = 'movieOnly';
}
if (discoverMovie === 'false') {
persistedState.discoverMovie.defaults.monitor = 'none';
}
if (discoverMovie === true) {
persistedState.discoverMovie.defaults.monitor = 'movieOnly';
}
if (addMovie === false) {
persistedState.addMovie.defaults.minimumAvailability = 'none';
}
if (discoverMovie === false) {
persistedState.discoverMovie.defaults.minimumAvailability = 'none';
}
}

View File

@@ -1,8 +1,8 @@
import _ from 'lodash';
import get from 'lodash';
export default function migratePreDbToReleased(persistedState) {
const addMovie = _.get(persistedState, 'addMovie.defaults.minimumAvailability');
const discoverMovie = _.get(persistedState, 'discoverMovie.defaults.minimumAvailability');
const addMovie = get(persistedState, 'addMovie.defaults.minimumAvailability');
const discoverMovie = get(persistedState, 'discoverMovie.defaults.minimumAvailability');
if (!addMovie && !discoverMovie) {
return;

View File

@@ -44,14 +44,7 @@ function filter(items, state) {
const predicate = filterPredicates[key];
if (Array.isArray(value)) {
if (
type === filterTypes.NOT_CONTAINS ||
type === filterTypes.NOT_EQUAL
) {
accepted = value.every((v) => predicate(item, v, type));
} else {
accepted = value.some((v) => predicate(item, v, type));
}
accepted = value.some((v) => predicate(item, v, type));
} else {
accepted = predicate(item, value, type);
}

View File

@@ -30,7 +30,7 @@
"@fortawesome/free-regular-svg-icons": "6.1.0",
"@fortawesome/free-solid-svg-icons": "6.1.0",
"@fortawesome/react-fontawesome": "0.1.18",
"@microsoft/signalr": "6.0.5",
"@microsoft/signalr": "6.0.3",
"@sentry/browser": "6.18.2",
"@sentry/integrations": "6.18.2",
"classnames": "2.3.1",
@@ -45,7 +45,7 @@
"jquery": "3.6.0",
"lodash": "4.17.21",
"mobile-detect": "1.4.5",
"moment": "2.29.2",
"moment": "2.29.1",
"mousetrap": "1.6.5",
"normalize.css": "8.0.1",
"prop-types": "15.7.2",
@@ -101,8 +101,8 @@
"babel-loader": "8.2.3",
"babel-plugin-inline-classnames": "2.0.1",
"babel-plugin-transform-react-remove-prop-types": "0.4.24",
"core-js": "3.12.1",
"css-loader": "6.5.1",
"core-js": "3.11.0",
"css-loader": "5.2.4",
"eslint": "8.11.0",
"eslint-plugin-filenames": "1.3.2",
"eslint-plugin-import": "2.25.4",
@@ -117,22 +117,22 @@
"mini-css-extract-plugin": "1.5.0",
"postcss": "8.2.12",
"postcss-color-function": "4.1.0",
"postcss-loader": "6.2.0",
"postcss-mixins": "8.1.0",
"postcss-nested": "5.0.6",
"postcss-loader": "5.2.0",
"postcss-mixins": "7.0.3",
"postcss-nested": "5.0.5",
"postcss-simple-vars": "6.0.3",
"postcss-url": "10.1.3",
"require-nocache": "1.0.0",
"rimraf": "3.0.2",
"run-sequence": "2.2.1",
"streamqueue": "1.1.2",
"style-loader": "3.3.1",
"style-loader": "2.0.0",
"stylelint": "14.6.0",
"stylelint-order": "5.0.0",
"url-loader": "4.1.1",
"webpack": "5.64.2",
"webpack-cli": "4.9.1",
"webpack-livereload-plugin": "3.0.2",
"webpack": "5.35.1",
"webpack-cli": "4.6.0",
"webpack-livereload-plugin": "3.0.1",
"worker-loader": "3.0.8"
}
}

View File

@@ -90,7 +90,7 @@
<!-- Standard testing packages -->
<ItemGroup Condition="'$(TestProject)'=='true'">
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.2.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.1.0" />
<PackageReference Include="NUnit" Version="3.13.2" />
<PackageReference Include="NUnit3TestAdapter" Version="4.1.0" />
<PackageReference Include="NunitXml.TestLogger" Version="3.0.117" />

View File

@@ -1,4 +1,5 @@
using System;
using Microsoft.Win32;
namespace NzbDrone.Common.EnvironmentInfo
{
@@ -50,5 +51,78 @@ namespace NzbDrone.Common.EnvironmentInfo
{
return _version;
}
private static Version GetDotNetVersion()
{
try
{
const string subkey = @"SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full\";
using (var ndpKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32).OpenSubKey(subkey))
{
if (ndpKey == null)
{
return new Version(4, 0);
}
var releaseKey = (int)ndpKey.GetValue("Release");
if (releaseKey >= 528040)
{
return new Version(4, 8, 0);
}
if (releaseKey >= 461808)
{
return new Version(4, 7, 2);
}
if (releaseKey >= 461308)
{
return new Version(4, 7, 1);
}
if (releaseKey >= 460798)
{
return new Version(4, 7);
}
if (releaseKey >= 394802)
{
return new Version(4, 6, 2);
}
if (releaseKey >= 394254)
{
return new Version(4, 6, 1);
}
if (releaseKey >= 393295)
{
return new Version(4, 6);
}
if (releaseKey >= 379893)
{
return new Version(4, 5, 2);
}
if (releaseKey >= 378675)
{
return new Version(4, 5, 1);
}
if (releaseKey >= 378389)
{
return new Version(4, 5);
}
}
}
catch (Exception ex)
{
Console.WriteLine("Couldnt get .NET framework version: " + ex.ToString());
}
return new Version(4, 0);
}
}
}

View File

@@ -13,13 +13,14 @@
<PackageReference Include="Sentry" Version="3.15.0" />
<PackageReference Include="NLog.Targets.Syslog" Version="6.0.3" />
<PackageReference Include="SharpZipLib" Version="1.3.3" />
<PackageReference Include="System.Text.Json" Version="6.0.4" />
<PackageReference Include="System.Text.Json" Version="6.0.2" />
<PackageReference Include="System.ValueTuple" Version="4.5.0" />
<PackageReference Include="System.Data.SQLite.Core.Servarr" Version="1.0.115.5-18" />
<PackageReference Include="System.Configuration.ConfigurationManager" Version="6.0.0" />
<PackageReference Include="System.IO.FileSystem.AccessControl" Version="5.0.0" />
<PackageReference Include="System.Runtime.Loader" Version="4.3.0" />
<PackageReference Include="System.ServiceProcess.ServiceController" Version="6.0.0" />
<PackageReference Include="Microsoft.Win32.Registry" Version="5.0.0" />
</ItemGroup>
<ItemGroup>
<Compile Update="EnsureThat\Resources\ExceptionMessages.Designer.cs">

View File

@@ -1,347 +0,0 @@
using System;
using System.Linq;
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Common.Serializer;
using NzbDrone.Core.Datastore.Migration;
using NzbDrone.Core.Test.Framework;
namespace NzbDrone.Core.Test.Datastore.Migration
{
[TestFixture]
public class movie_metadataFixture : MigrationTest<movie_metadata>
{
[Test]
public void should_add_metadata_from_movie_and_link_back_to_movie()
{
var db = WithMigrationTestDb(c =>
{
c.Insert.IntoTable("Movies").Row(new
{
Monitored = true,
Title = "Title",
CleanTitle = "CleanTitle",
Status = 3,
MinimumAvailability = 4,
Images = new[] { new { CoverType = "Poster" } }.ToJson(),
Recommendations = new[] { 1 }.ToJson(),
Runtime = 90,
OriginalLanguage = 1,
ProfileId = 1,
MovieFileId = 0,
Path = string.Format("/Movies/{0}", "Title"),
TitleSlug = 123456,
TmdbId = 132456,
Added = DateTime.UtcNow,
Collection = new { Name = "Some Collection", TmdbId = 11 }.ToJson(),
LastInfoSync = DateTime.UtcNow,
});
});
var metadata = db.Query<MovieMetadata207>("SELECT \"Id\", \"Title\", \"TmdbId\" FROM \"MovieMetadata\"");
metadata.Should().HaveCount(1);
metadata.First().TmdbId.Should().Be(132456);
metadata.First().Title.Should().Be("Title");
var movies = db.Query<Movie207>("SELECT \"Id\", \"MovieMetadataId\" FROM \"Movies\"");
movies.Should().HaveCount(1);
movies.First().MovieMetadataId.Should().Be(metadata.First().Id);
}
[Test]
public void should_link_metadata_to_credits()
{
var db = WithMigrationTestDb(c =>
{
c.Insert.IntoTable("Movies").Row(new
{
Id = 5,
Monitored = true,
Title = "Title",
CleanTitle = "CleanTitle",
Status = 3,
MinimumAvailability = 4,
Images = new[] { new { CoverType = "Poster" } }.ToJson(),
Recommendations = new[] { 1 }.ToJson(),
Runtime = 90,
OriginalLanguage = 1,
ProfileId = 1,
MovieFileId = 0,
Path = string.Format("/Movies/{0}", "Title"),
TitleSlug = 123456,
TmdbId = 132456,
Added = DateTime.UtcNow,
Collection = new { Name = "Some Collection", TmdbId = 11 }.ToJson(),
LastInfoSync = DateTime.UtcNow,
});
c.Insert.IntoTable("Credits").Row(new
{
MovieId = 5,
CreditTmdbId = 123,
PersonTmdbId = 456,
Order = 1,
Type = 1,
Name = "Some Person",
Images = new[] { new { CoverType = "Poster" } }.ToJson()
});
});
var metadata = db.Query<MovieMetadata207>("SELECT \"Id\", \"Title\", \"TmdbId\" FROM \"MovieMetadata\"");
metadata.Should().HaveCount(1);
metadata.First().TmdbId.Should().Be(132456);
metadata.First().Title.Should().Be("Title");
var movies = db.Query<Movie207>("SELECT \"Id\", \"MovieMetadataId\" FROM \"Credits\"");
movies.Should().HaveCount(1);
movies.First().MovieMetadataId.Should().Be(metadata.First().Id);
}
[Test]
public void should_link_metadata_to_alt_title()
{
var db = WithMigrationTestDb(c =>
{
c.Insert.IntoTable("Movies").Row(new
{
Id = 5,
Monitored = true,
Title = "Title",
CleanTitle = "CleanTitle",
Status = 3,
MinimumAvailability = 4,
Images = new[] { new { CoverType = "Poster" } }.ToJson(),
Recommendations = new[] { 1 }.ToJson(),
Runtime = 90,
OriginalLanguage = 1,
ProfileId = 1,
MovieFileId = 0,
Path = string.Format("/Movies/{0}", "Title"),
TitleSlug = 123456,
TmdbId = 132456,
Added = DateTime.UtcNow,
Collection = new { Name = "Some Collection", TmdbId = 11 }.ToJson(),
LastInfoSync = DateTime.UtcNow,
});
c.Insert.IntoTable("AlternativeTitles").Row(new
{
MovieId = 5,
Title = "Some Alt",
CleanTitle = "somealt",
SourceType = 1,
SourceId = 1,
Votes = 0,
VoteCount = 0,
Language = 1
});
});
var metadata = db.Query<MovieMetadata207>("SELECT \"Id\", \"Title\", \"TmdbId\" FROM \"MovieMetadata\"");
metadata.Should().HaveCount(1);
metadata.First().TmdbId.Should().Be(132456);
metadata.First().Title.Should().Be("Title");
var movies = db.Query<Movie207>("SELECT \"Id\", \"MovieMetadataId\" FROM \"AlternativeTitles\"");
movies.Should().HaveCount(1);
movies.First().MovieMetadataId.Should().Be(metadata.First().Id);
}
[Test]
public void should_link_metadata_to_translation()
{
var db = WithMigrationTestDb(c =>
{
c.Insert.IntoTable("Movies").Row(new
{
Id = 5,
Monitored = true,
Title = "Title",
CleanTitle = "CleanTitle",
Status = 3,
MinimumAvailability = 4,
Images = new[] { new { CoverType = "Poster" } }.ToJson(),
Recommendations = new[] { 1 }.ToJson(),
Runtime = 90,
OriginalLanguage = 1,
ProfileId = 1,
MovieFileId = 0,
Path = string.Format("/Movies/{0}", "Title"),
TitleSlug = 123456,
TmdbId = 132456,
Added = DateTime.UtcNow,
Collection = new { Name = "Some Collection", TmdbId = 11 }.ToJson(),
LastInfoSync = DateTime.UtcNow,
});
c.Insert.IntoTable("MovieTranslations").Row(new
{
MovieId = 5,
Title = "Some Trans",
Language = 1
});
});
var metadata = db.Query<MovieMetadata207>("SELECT \"Id\", \"Title\", \"TmdbId\" FROM \"MovieMetadata\"");
metadata.Should().HaveCount(1);
metadata.First().TmdbId.Should().Be(132456);
metadata.First().Title.Should().Be("Title");
var movies = db.Query<Movie207>("SELECT \"Id\", \"MovieMetadataId\" FROM \"MovieTranslations\"");
movies.Should().HaveCount(1);
movies.First().MovieMetadataId.Should().Be(metadata.First().Id);
}
[Test]
public void should_add_metadata_from_list_and_link_back()
{
var db = WithMigrationTestDb(c =>
{
c.Insert.IntoTable("ImportListMovies").Row(new
{
Title = "Title",
Status = 3,
Images = new[] { new { CoverType = "Poster" } }.ToJson(),
Runtime = 90,
TmdbId = 123456,
ListId = 4,
Translations = new[] { new { } }.ToJson(),
Collection = new { Name = "Some Collection", TmdbId = 11 }.ToJson(),
});
});
var metadata = db.Query<MovieMetadata207>("SELECT \"Id\", \"Title\", \"TmdbId\" FROM \"MovieMetadata\"");
metadata.Should().HaveCount(1);
metadata.First().TmdbId.Should().Be(123456);
metadata.First().Title.Should().Be("Title");
var movies = db.Query<Movie207>("SELECT \"Id\", \"MovieMetadataId\" FROM \"ImportListMovies\"");
movies.Should().HaveCount(1);
movies.First().MovieMetadataId.Should().Be(metadata.First().Id);
}
[Test]
public void should_not_duplicate_metadata()
{
var db = WithMigrationTestDb(c =>
{
c.Insert.IntoTable("Movies").Row(new
{
Monitored = true,
Title = "Title",
CleanTitle = "CleanTitle",
Status = 3,
MinimumAvailability = 4,
Images = new[] { new { CoverType = "Poster" } }.ToJson(),
Recommendations = new[] { 1 }.ToJson(),
Runtime = 90,
OriginalLanguage = 1,
ProfileId = 1,
MovieFileId = 0,
Path = string.Format("/Movies/{0}", "Title"),
TitleSlug = 123456,
TmdbId = 123456,
Added = DateTime.UtcNow,
Collection = new { Name = "Some Collection", TmdbId = 11 }.ToJson(),
LastInfoSync = DateTime.UtcNow,
});
c.Insert.IntoTable("ImportListMovies").Row(new
{
Title = "Title",
Status = 3,
Images = new[] { new { CoverType = "Poster" } }.ToJson(),
Runtime = 90,
TmdbId = 123456,
ListId = 4,
Translations = new[] { new { } }.ToJson(),
Collection = new { Name = "Some Collection", TmdbId = 11 }.ToJson(),
});
});
var metadata = db.Query<MovieMetadata207>("SELECT \"Id\", \"Title\", \"TmdbId\" FROM \"MovieMetadata\"");
metadata.Should().HaveCount(1);
metadata.First().TmdbId.Should().Be(123456);
metadata.First().Title.Should().Be("Title");
var movies = db.Query<Movie207>("SELECT \"Id\", \"MovieMetadataId\" FROM \"Movies\"");
movies.Should().HaveCount(1);
movies.First().MovieMetadataId.Should().Be(metadata.First().Id);
var listMovies = db.Query<Movie207>("SELECT \"Id\", \"MovieMetadataId\" FROM \"ImportListMovies\"");
listMovies.Should().HaveCount(1);
listMovies.First().MovieMetadataId.Should().Be(metadata.First().Id);
}
[Test]
public void should_not_duplicate_metadata_from_lists()
{
var db = WithMigrationTestDb(c =>
{
c.Insert.IntoTable("ImportListMovies").Row(new
{
Title = "Title",
Overview = "Overview 1",
Status = 3,
Images = new[] { new { CoverType = "Poster" } }.ToJson(),
Runtime = 90,
TmdbId = 123456,
ListId = 4,
Translations = new[] { new { } }.ToJson(),
Collection = new { Name = "Some Collection", TmdbId = 11 }.ToJson(),
});
c.Insert.IntoTable("ImportListMovies").Row(new
{
Title = "Title",
Overview = "Overview 2",
Status = 3,
Images = new[] { new { CoverType = "Poster" } }.ToJson(),
Runtime = 90,
TmdbId = 123456,
ListId = 5,
Translations = new[] { new { } }.ToJson(),
Collection = new { Name = "Some Collection", TmdbId = 11 }.ToJson(),
});
});
var metadata = db.Query<MovieMetadata207>("SELECT \"Id\", \"Title\", \"TmdbId\" FROM \"MovieMetadata\"");
metadata.Should().HaveCount(1);
metadata.First().TmdbId.Should().Be(123456);
metadata.First().Title.Should().Be("Title");
var listMovies = db.Query<Movie207>("SELECT \"Id\", \"MovieMetadataId\" FROM \"ImportListMovies\"");
listMovies.Should().HaveCount(2);
listMovies.First().MovieMetadataId.Should().Be(metadata.First().Id);
}
}
public class MovieMetadata207
{
public int Id { get; set; }
public int TmdbId { get; set; }
public string Title { get; set; }
public bool Monitored { get; set; }
}
public class Movie207
{
public int Id { get; set; }
public int MovieMetadataId { get; set; }
}
}

View File

@@ -1,66 +0,0 @@
<rss xmlns:atom="http://www.w3.org/2005/Atom"
xmlns:nyaa="https://nyaa.si/xmlns/nyaa" version="2.0">
<channel>
<title>Nyaa - Home - Torrent File RSS</title>
<description>RSS Feed for Home</description>
<link>https://nyaa.si/</link>
<atom:link href="https://nyaa.si/?page=rss" rel="self" type="application/rss+xml"/>
<item>
<title>[Foxy-Subs] Mahouka Koukou no Yuutousei - 08 [720p] [3194D881].mkv</title>
<link>https://nyaa.si/download/1424896.torrent</link>
<guid isPermaLink="true">https://nyaa.si/view/1424896</guid>
<pubDate>Tue, 24 Aug 2021 22:18:46 -0000</pubDate>
<nyaa:seeders>4</nyaa:seeders>
<nyaa:leechers>3</nyaa:leechers>
<nyaa:downloads>2</nyaa:downloads>
<nyaa:infoHash>e8ca5e20eca876339f41c3d9e95ea66c1d7caaee</nyaa:infoHash>
<nyaa:categoryId>1_3</nyaa:categoryId>
<nyaa:category>Anime - Non-English-translated</nyaa:category>
<nyaa:size>609.6 MiB</nyaa:size>
<nyaa:comments>0</nyaa:comments>
<nyaa:trusted>No</nyaa:trusted>
<nyaa:remake>No</nyaa:remake>
<description>
<![CDATA[ <a href="https://nyaa.si/view/1424896">#1424896 | [Foxy-Subs] Mahouka Koukou no Yuutousei - 08 [720p] [3194D881].mkv</a> | 609.6 MiB | Anime - Non-English-translated | E8CA5E20ECA876339F41C3D9E95EA66C1D7CAAEE ]]>
</description>
</item>
<item>
<title>Macross Zero (BDRip 1920x1080p x265 HEVC TrueHD, FLAC 5.1+2.0)[sxales]</title>
<link>https://nyaa.si/download/1424895.torrent</link>
<guid isPermaLink="true">https://nyaa.si/view/1424895</guid>
<pubDate>Tue, 24 Aug 2021 22:03:11 -0000</pubDate>
<nyaa:seeders>23</nyaa:seeders>
<nyaa:leechers>32</nyaa:leechers>
<nyaa:downloads>17</nyaa:downloads>
<nyaa:infoHash>26f37f26d5b3475b41a98dc575fabfa6f8d32a76</nyaa:infoHash>
<nyaa:categoryId>1_2</nyaa:categoryId>
<nyaa:category>Anime - English-translated</nyaa:category>
<nyaa:size>5.7 GiB</nyaa:size>
<nyaa:comments>2</nyaa:comments>
<nyaa:trusted>No</nyaa:trusted>
<nyaa:remake>No</nyaa:remake>
<description>
<![CDATA[ <a href="https://nyaa.si/view/1424895">#1424895 | Macross Zero (BDRip 1920x1080p x265 HEVC TrueHD, FLAC 5.1+2.0)[sxales]</a> | 5.7 GiB | Anime - English-translated | 26F37F26D5B3475B41A98DC575FABFA6F8D32A76 ]]>
</description>
</item>
<item>
<title>Fumetsu no Anata e - 19 [WEBDL 1080p] Ukr DVO</title>
<link>https://nyaa.si/download/1424887.torrent</link>
<guid isPermaLink="true">https://nyaa.si/view/1424887</guid>
<pubDate>Tue, 24 Aug 2021 21:23:06 -0000</pubDate>
<nyaa:seeders>5</nyaa:seeders>
<nyaa:leechers>4</nyaa:leechers>
<nyaa:downloads>4</nyaa:downloads>
<nyaa:infoHash>3e4300e24b39983802162877755aab4380bd137a</nyaa:infoHash>
<nyaa:categoryId>1_3</nyaa:categoryId>
<nyaa:category>Anime - Non-English-translated</nyaa:category>
<nyaa:size>1.4 GiB</nyaa:size>
<nyaa:comments>0</nyaa:comments>
<nyaa:trusted>No</nyaa:trusted>
<nyaa:remake>No</nyaa:remake>
<description>
<![CDATA[ <a href="https://nyaa.si/view/1424887">#1424887 | Fumetsu no Anata e - 19 [WEBDL 1080p] Ukr DVO</a> | 1.4 GiB | Anime - Non-English-translated | 3E4300E24B39983802162877755AAB4380BD137A ]]>
</description>
</item>
</channel>
</rss>

View File

@@ -35,11 +35,6 @@
"title": "Avengers: Endgame",
"year": 2019,
"Guid": []
},
{
"type": "movie",
"title": "Avengers",
"year": 2005
}
]
}

View File

@@ -26,7 +26,7 @@ namespace NzbDrone.Core.Test.Housekeeping.Housekeepers
}
[Test]
public void should_not_delete_unorphaned_collection_items()
public void should_not_delete_unorphaned_credit_items()
{
var collection = Builder<MovieCollection>.CreateNew()
.With(h => h.Id = 3)

View File

@@ -45,7 +45,7 @@ namespace NzbDrone.Core.Test.IndexerSearchTests
.Returns(_movie);
Mocker.GetMock<IMovieTranslationService>()
.Setup(s => s.GetAllTranslationsForMovieMetadata(It.IsAny<int>()))
.Setup(s => s.GetAllTranslationsForMovie(It.IsAny<int>()))
.Returns(new List<MovieTranslation>());
}

View File

@@ -25,9 +25,7 @@ namespace NzbDrone.Core.Test.IndexerTests.NyaaTests
};
}
/* [Test]
// Legacy Nyaa feed test
[Test]
public void should_parse_recent_feed_from_Nyaa()
{
var recentFeed = ReadAllText(@"Files/Indexers/Nyaa/Nyaa.xml");
@@ -55,35 +53,6 @@ namespace NzbDrone.Core.Test.IndexerTests.NyaaTests
torrentInfo.MagnetUrl.Should().Be(null);
torrentInfo.Peers.Should().Be(2 + 1);
torrentInfo.Seeders.Should().Be(1);
}*/
[Test]
public void should_parse_2021_recent_feed_from_Nyaa()
{
var recentFeed = ReadAllText(@"Files/Indexers/Nyaa/Nyaa2021.xml");
Mocker.GetMock<IHttpClient>()
.Setup(o => o.Execute(It.Is<HttpRequest>(v => v.Method == HttpMethod.Get)))
.Returns<HttpRequest>(r => new HttpResponse(r, new HttpHeader(), recentFeed));
var releases = Subject.FetchRecent();
releases.Should().HaveCount(3);
releases.First().Should().BeOfType<TorrentInfo>();
var torrentInfo = releases.First() as TorrentInfo;
torrentInfo.Title.Should().Be("[Foxy-Subs] Mahouka Koukou no Yuutousei - 08 [720p] [3194D881].mkv");
torrentInfo.DownloadProtocol.Should().Be(DownloadProtocol.Torrent);
torrentInfo.DownloadUrl.Should().Be("https://nyaa.si/download/1424896.torrent");
torrentInfo.InfoUrl.Should().Be("https://nyaa.si/view/1424896");
torrentInfo.CommentUrl.Should().BeNullOrEmpty();
torrentInfo.Indexer.Should().Be(Subject.Definition.Name);
torrentInfo.PublishDate.Should().Be(DateTime.Parse("Tue, 24 Aug 2021 22:18:46"));
torrentInfo.Size.Should().Be(639211930); //609.6 MiB
torrentInfo.MagnetUrl.Should().Be(null);
torrentInfo.Seeders.Should().Be(4);
torrentInfo.Peers.Should().Be(3 + 4);
}
}
}

View File

@@ -8,7 +8,6 @@ using NzbDrone.Common.Extensions;
using NzbDrone.Core.Exceptions;
using NzbDrone.Core.MetadataSource;
using NzbDrone.Core.Movies;
using NzbDrone.Core.Movies.Collections;
using NzbDrone.Core.Movies.Commands;
using NzbDrone.Core.Movies.Credits;
using NzbDrone.Core.Test.Framework;
@@ -20,7 +19,6 @@ namespace NzbDrone.Core.Test.MovieTests
public class RefreshMovieServiceFixture : CoreTest<RefreshMovieService>
{
private MovieMetadata _movie;
private MovieCollection _movieCollection;
private Movie _existingMovie;
[SetUp]
@@ -30,9 +28,6 @@ namespace NzbDrone.Core.Test.MovieTests
.With(s => s.Status = MovieStatusType.Released)
.Build();
_movieCollection = Builder<MovieCollection>.CreateNew()
.Build();
_existingMovie = Builder<Movie>.CreateNew()
.With(s => s.MovieMetadata.Value.Status = MovieStatusType.Released)
.Build();
@@ -45,10 +40,6 @@ namespace NzbDrone.Core.Test.MovieTests
.Setup(s => s.Get(_movie.Id))
.Returns(_movie);
Mocker.GetMock<IAddMovieCollectionService>()
.Setup(v => v.AddMovieCollection(It.IsAny<MovieCollection>()))
.Returns(_movieCollection);
Mocker.GetMock<IProvideMovieInfo>()
.Setup(s => s.GetMovieInfo(It.IsAny<int>()))
.Callback<int>((i) => { throw new MovieNotFoundException(i); });

View File

@@ -64,11 +64,6 @@ namespace NzbDrone.Core.Test.NotificationTests
TestLogger.Info("OnRename was called");
}
public override void OnMovieAdded(Movie movie)
{
TestLogger.Info("OnMovieAdded was called");
}
public override void OnMovieFileDelete(MovieFileDeleteMessage message)
{
TestLogger.Info("OnMovieFileDelete was called");
@@ -122,7 +117,6 @@ namespace NzbDrone.Core.Test.NotificationTests
notification.SupportsOnDownload.Should().BeTrue();
notification.SupportsOnUpgrade.Should().BeTrue();
notification.SupportsOnRename.Should().BeTrue();
notification.SupportsOnMovieAdded.Should().BeTrue();
notification.SupportsOnMovieDelete.Should().BeTrue();
notification.SupportsOnMovieFileDelete.Should().BeTrue();
notification.SupportsOnMovieFileDeleteForUpgrade.Should().BeTrue();
@@ -139,7 +133,6 @@ namespace NzbDrone.Core.Test.NotificationTests
notification.SupportsOnDownload.Should().BeFalse();
notification.SupportsOnUpgrade.Should().BeFalse();
notification.SupportsOnRename.Should().BeFalse();
notification.SupportsOnMovieAdded.Should().BeFalse();
notification.SupportsOnMovieDelete.Should().BeFalse();
notification.SupportsOnMovieFileDelete.Should().BeFalse();
notification.SupportsOnMovieFileDeleteForUpgrade.Should().BeFalse();

View File

@@ -71,7 +71,7 @@ namespace NzbDrone.Core.Test.OrganizerTests.FileNameBuilderTests
.Returns(new List<CustomFormat>());
Mocker.GetMock<IMovieTranslationService>()
.Setup(v => v.GetAllTranslationsForMovieMetadata(It.IsAny<int>()))
.Setup(v => v.GetAllTranslationsForMovie(It.IsAny<int>()))
.Returns(_movieTranslations);
}

View File

@@ -163,7 +163,6 @@ namespace NzbDrone.Core.Test.ParserTests
[TestCase("Movie.Title.1994.Dublado.1080p.XviD-LOL")]
[TestCase("Movie.Title.2.2019.1080p.Bluray.Dublado.WWW.TPF.GRATIS")]
[TestCase("Movie.Title.2014.1080p.Bluray.Brazilian.WWW.TPF.GRATIS")]
public void should_parse_language_brazilian_portuguese(string postTitle)
{
var result = Parser.Parser.ParseMovieTitle(postTitle, true);

View File

@@ -261,7 +261,6 @@ namespace NzbDrone.Core.Test.ParserTests
[TestCase("Movie.Name.2016.German.DTS.DL.1080p.UHDBD.x265-TDO.mkv", false)]
[TestCase("Movie.Name.2021.1080p.BDLight.x265-AVCDVD", false)]
[TestCase("Random.Title.2010.1080p.HD.DVD.AVC.DDP.5.1-GRouP", false)]
[TestCase("Movie.Title.2012.German.DL.1080p.UHD2BD.x264-QfG", false)]
public void should_parse_bluray1080p_quality(string title, bool proper)
{
ParseAndVerifyQuality(title, Source.BLURAY, proper, Resolution.R1080p);

View File

@@ -99,7 +99,6 @@ namespace NzbDrone.Core.Test.ParserTests
[TestCase("Crappy Anime Movie Name 2017 [RH] [Blu-ray][MKV][h264 10-bit][1080p][FLAC 5.1][Dual Audio][Softsubs (RH)]", "RH")]
[TestCase("Yet Another Anime Movie 2012 [Kametsu] [Blu-ray][MKV][h264 10-bit][1080p][FLAC 5.1][Dual Audio][Softsubs (Kametsu)]", "Kametsu")]
[TestCase("Another.Anime.Film.Name.2016.JPN.Blu-Ray.Remux.AVC.DTS-MA.BluDragon", "BluDragon")]
[TestCase("A Movie in the Name (1964) (1080p BluRay x265 r00t)", "r00t")]
public void should_parse_exception_release_group(string title, string expected)
{
Parser.Parser.ParseReleaseGroup(title).Should().Be(expected);

View File

@@ -24,7 +24,6 @@ namespace NzbDrone.Core.Test.UpdateTests
Subject.GetLatestUpdate("develop", new Version(10, 0)).Should().BeNull();
}
[Ignore("Pending linux-x86 release")]
[Test]
public void finds_update_when_version_lower()
{
@@ -40,7 +39,6 @@ namespace NzbDrone.Core.Test.UpdateTests
Subject.GetLatestUpdate("invalid_branch", new Version(0, 2)).Should().NotBeNull();
}
[Ignore("Pending linux-x86 release")]
[Test]
public void should_get_recent_updates()
{

View File

@@ -45,13 +45,11 @@ namespace NzbDrone.Core.Configuration
string SslCertPassword { get; }
string UrlBase { get; }
string UiFolder { get; }
string InstanceName { get; }
bool UpdateAutomatically { get; }
UpdateMechanism UpdateMechanism { get; }
string UpdateScriptPath { get; }
string SyslogServer { get; }
int SyslogPort { get; }
string SyslogLevel { get; }
string PostgresHost { get; }
int PostgresPort { get; }
string PostgresUser { get; }
@@ -225,7 +223,6 @@ namespace NzbDrone.Core.Configuration
}
public string UiFolder => BuildInfo.IsDebug ? Path.Combine("..", "UI") : "UI";
public string InstanceName => GetValue("InstanceName", BuildInfo.AppName);
public bool UpdateAutomatically => GetValueBoolean("UpdateAutomatically", false, false);
@@ -234,11 +231,8 @@ namespace NzbDrone.Core.Configuration
public string UpdateScriptPath => GetValue("UpdateScriptPath", "", false);
public string SyslogServer => GetValue("SyslogServer", "", persist: false);
public int SyslogPort => GetValueInt("SyslogPort", 514, persist: false);
public string SyslogLevel => GetValue("SyslogLevel", LogLevel, false).ToLowerInvariant();
public int GetValueInt(string key, int defaultValue, bool persist = true)
{
return Convert.ToInt32(GetValue(key, defaultValue, persist));

View File

@@ -1,16 +0,0 @@
using NzbDrone.Core.Parser.Model;
namespace NzbDrone.Core.CustomFormats
{
public class ReleaseGroupSpecification : RegexSpecificationBase
{
public override int Order => 9;
public override string ImplementationName => "Release Group";
public override string InfoLink => "https://wiki.servarr.com/radarr/settings#custom-formats-2";
protected override bool IsSatisfiedByWithoutNegate(ParsedMovieInfo movieInfo)
{
return MatchString(movieInfo?.ReleaseGroup);
}
}
}

View File

@@ -15,9 +15,9 @@ namespace NzbDrone.Core.Datastore.Migration
.WithColumn("Genres").AsString().Nullable()
.WithColumn("Title").AsString()
.WithColumn("SortTitle").AsString().Nullable()
.WithColumn("CleanTitle").AsString().Nullable().Indexed()
.WithColumn("OriginalTitle").AsString().Nullable()
.WithColumn("CleanOriginalTitle").AsString().Nullable().Indexed()
.WithColumn("CleanTitle").AsString().Indexed()
.WithColumn("OriginalTitle").AsString()
.WithColumn("CleanOriginalTitle").AsString().Indexed()
.WithColumn("OriginalLanguage").AsInt32()
.WithColumn("Status").AsInt32()
.WithColumn("LastInfoSync").AsDateTime().Nullable()
@@ -28,7 +28,7 @@ namespace NzbDrone.Core.Datastore.Migration
.WithColumn("Year").AsInt32().Nullable()
.WithColumn("SecondaryYear").AsInt32().Nullable()
.WithColumn("Ratings").AsString().Nullable()
.WithColumn("Recommendations").AsString()
.WithColumn("Recommendations").AsString().Nullable()
.WithColumn("Certification").AsString().Nullable()
.WithColumn("YouTubeTrailerId").AsString().Nullable()
.WithColumn("Collection").AsString().Nullable()
@@ -43,11 +43,10 @@ namespace NzbDrone.Core.Datastore.Migration
FROM ""Movies""");
// Transfer metadata from ImportListMovies to MovieMetadata if not already in
Execute.Sql(@"INSERT INTO ""MovieMetadata"" (""TmdbId"", ""ImdbId"", ""Title"", ""SortTitle"", ""CleanTitle"", ""OriginalTitle"", ""CleanOriginalTitle"", ""OriginalLanguage"", ""Overview"", ""Status"", ""LastInfoSync"", ""Images"", ""Genres"", ""Ratings"", ""Runtime"", ""InCinemas"", ""PhysicalRelease"", ""DigitalRelease"", ""Year"", ""Recommendations"", ""Certification"", ""YouTubeTrailerId"", ""Studio"", ""Collection"", ""Website"")
SELECT ""TmdbId"", ""ImdbId"", ""Title"", ""SortTitle"", ""Title"", ""OriginalTitle"", ""OriginalTitle"", 1, ""Overview"", ""Status"", ""LastInfoSync"", ""Images"", ""Genres"", ""Ratings"", ""Runtime"", ""InCinemas"", ""PhysicalRelease"", ""DigitalRelease"", ""Year"", '[]', ""Certification"", ""YouTubeTrailerId"", ""Studio"", ""Collection"", ""Website""
Execute.Sql(@"INSERT INTO ""MovieMetadata"" (""TmdbId"", ""ImdbId"", ""Title"", ""SortTitle"", ""CleanTitle"", ""OriginalTitle"", ""CleanOriginalTitle"", ""OriginalLanguage"", ""Overview"", ""Status"", ""LastInfoSync"", ""Images"", ""Genres"", ""Ratings"", ""Runtime"", ""InCinemas"", ""PhysicalRelease"", ""DigitalRelease"", ""Year"", ""Certification"", ""YouTubeTrailerId"", ""Studio"", ""Collection"", ""Website"")
SELECT ""TmdbId"", ""ImdbId"", ""Title"", ""SortTitle"", ""Title"", ""OriginalTitle"", ""OriginalTitle"", 1, ""Overview"", ""Status"", ""LastInfoSync"", ""Images"", ""Genres"", ""Ratings"", ""Runtime"", ""InCinemas"", ""PhysicalRelease"", ""DigitalRelease"", ""Year"", ""Certification"", ""YouTubeTrailerId"", ""Studio"", ""Collection"", ""Website""
FROM ""ImportListMovies""
WHERE ""ImportListMovies"".""TmdbId"" NOT IN ( SELECT ""MovieMetadata"".""TmdbId"" FROM ""MovieMetadata"" )
AND ""ImportListMovies"".""Id"" IN ( SELECT MIN(""Id"") FROM ""ImportListMovies"" GROUP BY ""TmdbId"" )");
WHERE ""ImportListMovies"".""TmdbId"" NOT IN ( SELECT ""MovieMetadata"".""TmdbId"" FROM ""MovieMetadata"" )");
// Add an MovieMetadataId column to Movies
Alter.Table("Movies").AddColumn("MovieMetadataId").AsInt32().WithDefaultValue(0);

View File

@@ -1,15 +0,0 @@
using FluentMigrator;
using NzbDrone.Core.Datastore.Migration.Framework;
namespace NzbDrone.Core.Datastore.Migration
{
[Migration(209)]
public class movie_meta_collection_index : NzbDroneMigrationBase
{
protected override void MainDbUpgrade()
{
Create.Index("IX_MovieMetadata_CollectionTmdbId").OnTable("MovieMetadata").OnColumn("CollectionTmdbId");
Create.Index("IX_MovieTranslations_MovieMetadataId").OnTable("MovieTranslations").OnColumn("MovieMetadataId");
}
}
}

View File

@@ -1,14 +0,0 @@
using FluentMigrator;
using NzbDrone.Core.Datastore.Migration.Framework;
namespace NzbDrone.Core.Datastore.Migration
{
[Migration(210)]
public class movie_added_notifications : NzbDroneMigrationBase
{
protected override void MainDbUpgrade()
{
Alter.Table("Notifications").AddColumn("OnMovieAdded").AsBoolean().WithDefaultValue(false);
}
}
}

View File

@@ -88,7 +88,6 @@ namespace NzbDrone.Core.Datastore
.Ignore(i => i.SupportsOnDownload)
.Ignore(i => i.SupportsOnUpgrade)
.Ignore(i => i.SupportsOnRename)
.Ignore(i => i.SupportsOnMovieAdded)
.Ignore(i => i.SupportsOnMovieDelete)
.Ignore(i => i.SupportsOnMovieFileDelete)
.Ignore(i => i.SupportsOnMovieFileDeleteForUpgrade)

View File

@@ -288,8 +288,7 @@ namespace NzbDrone.Core.Download.Clients.QBittorrent
break;
case "forcedDL": // torrent is being downloaded, and was forced started
case "forcedMetaDL": // torrent metadata is being forcibly downloaded
case "forcedDL": //torrent is being downloaded, and was forced started
case "moving": // torrent is being moved from a folder
case "downloading": // torrent is being downloaded and data is being transferred
item.Status = DownloadItemStatus.Downloading;

View File

@@ -120,7 +120,7 @@ namespace NzbDrone.Core.Download
return;
}
var importResults = _downloadedMovieImportService.ProcessPath(outputPath, ImportMode.Auto, trackedDownload.RemoteMovie.Movie, trackedDownload.ImportItem);
var importResults = _downloadedMovieImportService.ProcessPath(outputPath, ImportMode.Auto, trackedDownload.RemoteMovie.Movie, trackedDownload.DownloadItem);
if (VerifyImport(trackedDownload, importResults))
{

View File

@@ -126,11 +126,11 @@ namespace NzbDrone.Core.Extras.Metadata.Consumers.Xbmc
(int)movie.MovieMetadata.Value.OriginalLanguage :
Settings.MovieMetadataLanguage;
var movieTranslations = _movieTranslationsService.GetAllTranslationsForMovieMetadata(movie.MovieMetadataId);
var movieTranslations = _movieTranslationsService.GetAllTranslationsForMovie(movie.Id);
var selectedSettingsLanguage = Language.FindById(movieMetadataLanguage);
var movieTranslation = movieTranslations.FirstOrDefault(mt => mt.Language == selectedSettingsLanguage);
var credits = _creditService.GetAllCreditsForMovieMetadata(movie.MovieMetadataId);
var credits = _creditService.GetAllCreditsForMovie(movie.MovieMetadataId);
var watched = GetExistingWatchedStatus(movie, movieFile.RelativePath);

View File

@@ -20,9 +20,8 @@ namespace NzbDrone.Core.Housekeeping.Housekeepers
WHERE ""Id"" IN (
SELECT ""MovieMetadata"".""Id"" FROM ""MovieMetadata""
LEFT OUTER JOIN ""Movies"" ON ""Movies"".""MovieMetadataId"" = ""MovieMetadata"".""Id""
LEFT OUTER JOIN ""Collections"" ON ""Collections"".""TmdbId"" = ""MovieMetadata"".""CollectionTmdbId""
LEFT OUTER JOIN ""ImportListMovies"" ON ""ImportListMovies"".""MovieMetadataId"" = ""MovieMetadata"".""Id""
WHERE ""Movies"".""Id"" IS NULL AND ""ImportListMovies"".""Id"" IS NULL AND ""Collections"".""Id"" IS NULL)");
WHERE ""Movies"".""Id"" IS NULL AND ""ImportListMovies"".""Id"" IS NULL)");
}
}
}

View File

@@ -177,12 +177,12 @@ namespace NzbDrone.Core.ImportLists
{
var mappedMovie = _movieSearch.MapMovieToTmdbMovie(new MovieMetadata { Title = report.Title, TmdbId = report.TmdbId, ImdbId = report.ImdbId, Year = report.Year });
_movieMetadataService.Upsert(mappedMovie);
var mappedListMovie = new ImportListMovie { ListId = report.ListId };
if (mappedMovie != null)
{
_movieMetadataService.Upsert(mappedMovie);
mappedListMovie.MovieMetadata = mappedMovie;
mappedListMovie.MovieMetadataId = mappedMovie.Id;
}

View File

@@ -107,8 +107,7 @@ namespace NzbDrone.Core.ImportLists
AddOptions = new AddMovieOptions
{
SearchForMovie = monitorType != MonitorTypes.None && importList.SearchOnAdd,
Monitor = monitorType,
AddMethod = AddMovieMethod.List
Monitor = monitorType
}
});
}

View File

@@ -73,7 +73,7 @@ namespace NzbDrone.Core.ImportLists.Plex
{
var scheme = $"{prefix}://";
return guids?.FirstOrDefault((guid) => guid.Id.StartsWith(scheme))?.Id.Replace(scheme, "");
return guids.FirstOrDefault((guid) => guid.Id.StartsWith(scheme))?.Id.Replace(scheme, "");
}
}
}

View File

@@ -49,7 +49,7 @@ namespace NzbDrone.Core.IndexerSearch
public List<DownloadDecision> MovieSearch(int movieId, bool userInvokedSearch, bool interactiveSearch)
{
var movie = _movieService.GetMovie(movieId);
movie.MovieMetadata.Value.Translations = _movieTranslationService.GetAllTranslationsForMovieMetadata(movie.MovieMetadataId);
movie.MovieMetadata.Value.Translations = _movieTranslationService.GetAllTranslationsForMovie(movie.Id);
return MovieSearch(movie, userInvokedSearch, interactiveSearch);
}
@@ -77,7 +77,7 @@ namespace NzbDrone.Core.IndexerSearch
};
var wantedLanguages = _profileService.GetAcceptableLanguages(movie.ProfileId);
var translations = _movieTranslationService.GetAllTranslationsForMovieMetadata(movie.MovieMetadataId);
var translations = _movieTranslationService.GetAllTranslationsForMovie(movie.Id);
var queryTranlations = new List<string>
{

View File

@@ -12,10 +12,6 @@ namespace NzbDrone.Core.Indexers
UseGuidInfoUrl = true;
UseEnclosureLength = false;
UseEnclosureUrl = true;
SeedsElementName = "seeds";
InfoHashElementName = "infoHash";
SizeElementName = "contentLength";
MagnetElementName = "magnetURI";
}
protected override bool PreProcess(IndexerResponse indexerResponse)
@@ -30,5 +26,51 @@ namespace NzbDrone.Core.Indexers
return base.PreProcess(indexerResponse);
}
protected override long GetSize(XElement item)
{
var contentLength = item.FindDecendants("contentLength").SingleOrDefault();
if (contentLength != null)
{
return (long)contentLength;
}
return base.GetSize(item);
}
protected override string GetInfoHash(XElement item)
{
var infoHash = item.FindDecendants("infoHash").SingleOrDefault();
return (string)infoHash;
}
protected override string GetMagnetUrl(XElement item)
{
var magnetURI = item.FindDecendants("magnetURI").SingleOrDefault();
return (string)magnetURI;
}
protected override int? GetSeeders(XElement item)
{
var seeds = item.FindDecendants("seeds").SingleOrDefault();
if (seeds != null)
{
return (int)seeds;
}
return base.GetSeeders(item);
}
protected override int? GetPeers(XElement item)
{
var peers = item.FindDecendants("peers").SingleOrDefault();
if (peers != null)
{
return (int)peers;
}
return base.GetPeers(item);
}
}
}

View File

@@ -24,7 +24,7 @@ namespace NzbDrone.Core.Indexers.Nyaa
public override IParseIndexerResponse GetParser()
{
return new TorrentRssParser() { UseGuidInfoUrl = true, SizeElementName = "size", InfoHashElementName = "infoHash", PeersElementName = "leechers", CalculatePeersAsSum = true, SeedsElementName = "seeders" };
return new TorrentRssParser() { UseGuidInfoUrl = true, ParseSizeInDescription = true, ParseSeedersInDescription = true };
}
}
}

View File

@@ -1,5 +1,4 @@
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using System.Xml.Linq;
using MonoTorrent;
@@ -10,27 +9,12 @@ namespace NzbDrone.Core.Indexers
{
public class TorrentRssParser : RssParser
{
// Use to sum/calculate Peers as Leechers+Seeders
public bool CalculatePeersAsSum { get; set; } = false;
// Use the specified element name to determine the Infohash
public string InfoHashElementName { get; set; }
// Parse various seeder/leecher/peers formats in the description element to determine number of seeders.
public bool ParseSeedersInDescription { get; set; }
// Use the specified element name to determine the Peers
public string PeersElementName { get; set; }
// Use the specified element name to determine the Seeds
public string SeedsElementName { get; set; }
// Use the specified element name to determine the Size
// Use the specified element name to determine the size
public string SizeElementName { get; set; }
// Use the specified element name to determine the Magnet link
public string MagnetElementName { get; set; }
public TorrentRssParser()
{
PreferredEnclosureMimeTypes = TorrentEnclosureMimeTypes;
@@ -56,28 +40,14 @@ namespace NzbDrone.Core.Indexers
result.InfoHash = GetInfoHash(item);
result.MagnetUrl = GetMagnetUrl(item);
result.Seeders = GetSeeders(item);
if (CalculatePeersAsSum)
{
result.Peers = GetPeers(item) + result.Seeders;
}
else
{
result.Peers = GetPeers(item);
}
result.Peers = GetPeers(item);
return result;
}
protected virtual string GetInfoHash(XElement item)
{
if (InfoHashElementName.IsNotNullOrWhiteSpace())
{
return item.FindDecendants(InfoHashElementName).FirstOrDefault().Value;
}
var magnetUrl = GetMagnetUrl(item);
if (magnetUrl.IsNotNullOrWhiteSpace())
{
try
@@ -94,21 +64,10 @@ namespace NzbDrone.Core.Indexers
protected virtual string GetMagnetUrl(XElement item)
{
if (MagnetElementName.IsNotNullOrWhiteSpace())
var downloadUrl = GetDownloadUrl(item);
if (downloadUrl.IsNotNullOrWhiteSpace() && downloadUrl.StartsWith("magnet:"))
{
var magnetURL = item.FindDecendants(MagnetElementName).FirstOrDefault().Value;
if (magnetURL.IsNotNullOrWhiteSpace() && magnetURL.StartsWith("magnet:"))
{
return magnetURL;
}
}
else
{
var downloadUrl = GetDownloadUrl(item);
if (downloadUrl.IsNotNullOrWhiteSpace() && downloadUrl.StartsWith("magnet:"))
{
return downloadUrl;
}
return downloadUrl;
}
return null;
@@ -116,8 +75,6 @@ namespace NzbDrone.Core.Indexers
protected virtual int? GetSeeders(XElement item)
{
// safe to always use the element if it's present (and valid)
// fall back to description if ParseSeedersInDescription is enabled
if (ParseSeedersInDescription && item.Element("description") != null)
{
var matchSeeders = ParseSeedersRegex.Match(item.Element("description").Value);
@@ -136,12 +93,6 @@ namespace NzbDrone.Core.Indexers
}
}
var seeds = item.FindDecendants(SeedsElementName).SingleOrDefault();
if (seeds != null)
{
return (int)seeds;
}
return null;
}
@@ -165,12 +116,6 @@ namespace NzbDrone.Core.Indexers
}
}
if (PeersElementName.IsNotNullOrWhiteSpace())
{
var itempeers = item.FindDecendants(PeersElementName).SingleOrDefault();
return int.Parse(itempeers.Value);
}
return null;
}
@@ -179,10 +124,9 @@ namespace NzbDrone.Core.Indexers
var size = base.GetSize(item);
if (size == 0 && SizeElementName.IsNotNullOrWhiteSpace())
{
var itemsize = item.FindDecendants(SizeElementName).SingleOrDefault();
if (itemsize != null)
if (item.Element(SizeElementName) != null)
{
size = ParseSize(itemsize.Value, true);
size = ParseSize(item.Element(SizeElementName).Value, true);
}
}

View File

@@ -44,8 +44,7 @@ namespace NzbDrone.Core.Instrumentation
if (_configFileProvider.SyslogServer.IsNotNullOrWhiteSpace())
{
var syslogLevel = LogLevel.FromString(_configFileProvider.SyslogLevel);
SetSyslogParameters(_configFileProvider.SyslogServer, _configFileProvider.SyslogPort, syslogLevel);
SetSyslogParameters(_configFileProvider.SyslogServer, _configFileProvider.SyslogPort, minimumLogLevel);
}
var rules = LogManager.Configuration.LoggingRules;
@@ -119,7 +118,7 @@ namespace NzbDrone.Core.Instrumentation
syslogTarget.MessageSend.Udp.Server = syslogServer;
syslogTarget.MessageSend.Udp.ReconnectInterval = 500;
syslogTarget.MessageCreation.Rfc = RfcNumber.Rfc5424;
syslogTarget.MessageCreation.Rfc5424.AppName = _configFileProvider.InstanceName;
syslogTarget.MessageCreation.Rfc5424.AppName = BuildInfo.AppName;
var loggingRule = new LoggingRule("*", minimumLogLevel, syslogTarget);

View File

@@ -127,7 +127,7 @@ namespace NzbDrone.Core.Jobs
new ScheduledTask
{
Interval = GetRefreshMonitoredInterval(),
Interval = Math.Max(_configService.CheckForFinishedDownloadInterval, 1),
TypeName = typeof(RefreshMonitoredDownloadsCommand).FullName,
Priority = CommandPriority.High
}
@@ -198,18 +198,6 @@ namespace NzbDrone.Core.Jobs
return interval;
}
private int GetRefreshMonitoredInterval()
{
var interval = _configService.CheckForFinishedDownloadInterval;
if (interval < 1)
{
return 1;
}
return interval;
}
private int GetImportListSyncInterval()
{
//Enforce 6 hour min on list sync
@@ -230,7 +218,6 @@ namespace NzbDrone.Core.Jobs
_scheduledTaskRepository.SetLastExecutionTime(scheduledTask.Id, lastExecution, message.Command.StartedAt.Value);
_cache.Find(scheduledTask.TypeName).LastExecution = lastExecution;
_cache.Find(scheduledTask.TypeName).LastStartTime = message.Command.StartedAt.Value;
}
}
@@ -246,14 +233,13 @@ namespace NzbDrone.Core.Jobs
backup.Interval = GetBackupInterval();
var refreshMonitoredDownloads = _scheduledTaskRepository.GetDefinition(typeof(RefreshMonitoredDownloadsCommand));
refreshMonitoredDownloads.Interval = GetRefreshMonitoredInterval();
refreshMonitoredDownloads.Interval = _configService.CheckForFinishedDownloadInterval;
_scheduledTaskRepository.UpdateMany(new List<ScheduledTask> { rss, importList, refreshMonitoredDownloads, backup });
_cache.Find(rss.TypeName).Interval = rss.Interval;
_cache.Find(importList.TypeName).Interval = importList.Interval;
_cache.Find(backup.TypeName).Interval = backup.Interval;
_cache.Find(refreshMonitoredDownloads.TypeName).Interval = refreshMonitoredDownloads.Interval;
}
}
}

View File

@@ -3,6 +3,7 @@
"Yesterday": "في الامس",
"YesMoveFiles": "نعم ، انقل الملفات",
"YesCancel": "نعم إلغاء",
"Yes": "نعم",
"Year": "عام",
"WouldYouLikeToRestoreBackup": "هل ترغب في استعادة النسخة الاحتياطية {0}؟",
"Wiki": "ويكي",
@@ -293,6 +294,7 @@
"NoChange": "لا تغيير",
"NoBackupsAreAvailable": "لا توجد نسخ احتياطية متاحة",
"NoAltTitle": "لا توجد عناوين بديلة.",
"No": "لا",
"NextExecution": "التنفيذ القادم",
"New": "جديد",
"NetCore": ".شبكة",
@@ -435,6 +437,7 @@
"History": "التاريخ",
"HideAdvanced": "إخفاء الإعدادات المتقدمة",
"HiddenClickToShow": "مخفي ، انقر للعرض",
"HelpText": "الفاصل بالدقائق. اضبط على صفر للتعطيل (سيؤدي هذا إلى إيقاف كل عمليات الاستيلاء على التحرير التلقائي)",
"HealthNoIssues": "لا مشاكل مع التكوين الخاص بك",
"Health": "الصحة",
"HaveNotAddedMovies": "لم تقم بإضافة أي أفلام بعد ، هل تريد استيراد بعض أو كل أفلامك أولاً؟",
@@ -1013,6 +1016,7 @@
"DownloadClientCheckNoneAvailableMessage": "لا يوجد عميل تنزيل متاح",
"AddNewMessage": "من السهل إضافة فيلم جديد ، فقط ابدأ بكتابة اسم الفيلم الذي تريد إضافته",
"AddNew": "اضف جديد",
"AddMoviesMonitored": "إضافة أفلام مراقبتها",
"AddMovies": "اضافة افلام",
"AddMovie": "اضافة فيلم",
"AddListExclusion": "إضافة استبعاد قائمة",
@@ -1058,10 +1062,5 @@
"Rating": "التقييمات",
"RemotePath": "مسار بعيد",
"Filters": "منقي",
"LocalPath": "مسار محلي",
"MonitorMovies": "مراقبة الفيلم",
"NoCollections": "لم يتم العثور على أفلام ، للبدء ، ستحتاج إلى إضافة فيلم جديد أو استيراد بعض الأفلام الموجودة.",
"RssSyncHelpText": "الفاصل بالدقائق. اضبط على صفر للتعطيل (سيؤدي هذا إلى إيقاف كل عمليات الاستيلاء على التحرير التلقائي)",
"AllCollectionsHiddenDueToFilter": "جميع الأفلام مخفية بسبب الفلتر المطبق.",
"Collections": "مجموعة"
"LocalPath": "مسار محلي"
}

View File

@@ -285,6 +285,7 @@
"HardlinkCopyFiles": "Твърда връзка / копиране на файлове",
"Health": "Здраве",
"HealthNoIssues": "Няма проблеми с вашата конфигурация",
"HelpText": "Интервал за минути. Задайте на нула, за да деактивирате (това ще спре всички автоматично хващане на освобождаване)",
"HiddenClickToShow": "Скрито, кликнете за показване",
"ImportExtraFiles": "Импортиране на допълнителни файлове",
"ImportFailed": "Неуспешно импортиране: {0}",
@@ -711,6 +712,7 @@
"Wiki": "Wiki",
"WouldYouLikeToRestoreBackup": "Искате ли да възстановите архива {0}?",
"Year": "Година",
"Yes": "Да",
"YesCancel": "Да, Отказ",
"YesMoveFiles": "Да, премести файловете",
"Yesterday": "Вчера",
@@ -767,6 +769,7 @@
"MovieIsMonitored": "Филмът се следи",
"RadarrUpdated": "Радар актуализиран",
"AddListExclusion": "Добавяне на изключване от списъка",
"AddMoviesMonitored": "Добавяне на контролирани филми",
"AddNewMovie": "Добавяне на нов филм",
"AddNewTmdbIdMessage": "Можете също да търсите с помощта на TMDb Id на филм. напр. 'tmdb: 71663'",
"AddRemotePathMapping": "Добавете отдалечено картографиране на пътя",
@@ -961,6 +964,7 @@
"MustNotContain": "Не трябва да съдържа",
"NamingSettings": "Настройки за именуване",
"NetCore": ".NET Core",
"No": "Не",
"NoBackupsAreAvailable": "Няма налични резервни копия",
"NoChange": "Няма промяна",
"NoHistory": "Няма история",
@@ -1057,10 +1061,5 @@
"RemotePath": "Отдалечен път",
"List": "Списъци",
"LocalPath": "Местен път",
"SelectLanguages": "Избери език",
"MonitorMovies": "Монитор на филм",
"AllCollectionsHiddenDueToFilter": "Всички филми са скрити поради приложен филтър.",
"Collections": "колекция",
"NoCollections": "Не са намерени филми, за да започнете, ще искате да добавите нов филм или да импортирате някои съществуващи.",
"RssSyncHelpText": "Интервал за минути. Задайте на нула, за да деактивирате (това ще спре всички автоматично хващане на освобождаване)"
"SelectLanguages": "Избери език"
}

View File

@@ -292,6 +292,7 @@
"ImportNotForDownloads": "Nepoužívejte k importu souborů ke stažení z vašeho klienta pro stahování, toto je pouze pro existující organizované knihovny, nikoli pro netříděné soubory.",
"GrabReleaseMessageText": "Radarr nebyl schopen určit, pro který film je toto vydání určeno. Radarr nemusí být schopen toto vydání automaticky importovat. Chcete chytit „{0}“?",
"GrabSelected": "Chyťte vybrané",
"HelpText": "Interval v minutách. Nastavením na nulu deaktivujete (tím se zastaví veškeré automatické uvolnění uvolnění)",
"HiddenClickToShow": "Skryté, kliknutím zobrazíte",
"ImportMechanismHealthCheckMessage": "Povolit zpracování dokončeného stahování",
"NoResultsFound": "Nebyly nalezeny žádné výsledky",
@@ -420,6 +421,7 @@
"MustNotContain": "Nesmí obsahovat",
"NamingSettings": "Nastavení pojmenování",
"NetCore": ".NET Core",
"No": "Ne",
"NoBackupsAreAvailable": "Nejsou k dispozici žádné zálohy",
"NoChange": "Žádná změna",
"NoHistory": "Žádná historie",
@@ -436,6 +438,7 @@
"Overview": "Přehled",
"Failed": "Selhalo",
"AddMovies": "Přidat filmy",
"AddMoviesMonitored": "Přidat sledované filmy",
"AddingTag": "Přidávání značky",
"AlternativeTitle": "Alternativní název",
"AnalyseVideoFiles": "Analyzujte video soubory",
@@ -1013,6 +1016,7 @@
"Wiki": "Wiki",
"WouldYouLikeToRestoreBackup": "Chcete obnovit zálohu {0}?",
"Year": "Rok",
"Yes": "Ano",
"YesCancel": "Ano, zrušit",
"YesMoveFiles": "Ano, přesuňte soubory",
"Yesterday": "Včera",
@@ -1057,10 +1061,5 @@
"RemotePath": "Vzdálená cesta",
"Rating": "Hodnocení",
"List": "Seznamy",
"SelectLanguages": "Zvolte jazyk",
"AllCollectionsHiddenDueToFilter": "Všechny filmy jsou skryty kvůli použitému filtru.",
"Collections": "Sbírka",
"MonitorMovies": "Monitorujte film",
"NoCollections": "Nebyly nalezeny žádné filmy. Chcete-li začít, budete chtít přidat nový film nebo importovat některé stávající.",
"RssSyncHelpText": "Interval v minutách. Nastavením na nulu deaktivujete (tím se zastaví veškeré automatické uvolnění uvolnění)"
"SelectLanguages": "Zvolte jazyk"
}

View File

@@ -408,6 +408,7 @@
"MovieIsUnmonitored": "Filmen overvåges ikke",
"Movies": "Film",
"NetCore": ".NET Core",
"No": "Ingen",
"OnHealthIssueHelpText": "Om sundhedsspørgsmål",
"OnRenameHelpText": "Om omdøb",
"OnUpgradeHelpText": "Ved opgradering",
@@ -456,6 +457,7 @@
"AlreadyInYourLibrary": "Allerede i dit bibliotek",
"RecycleBinCleanupDaysHelpTextWarning": "Filer i papirkurven, der er ældre end det valgte antal dage, renses automatisk",
"AddListExclusion": "Tilføj ekskludering af liste",
"AddMoviesMonitored": "Tilføj overvågede film",
"AddingTag": "Tilføjer tag",
"AgeWhenGrabbed": "Alder (når grebet)",
"RefreshAndScan": "Opdater & Scan",
@@ -639,6 +641,7 @@
"GrabRelease": "Grab Release",
"GrabReleaseMessageText": "Radarr var ikke i stand til at bestemme, hvilken film denne udgivelse var til. Radarr kan muligvis ikke automatisk importere denne udgivelse. Vil du hente '{0}'?",
"Group": "Gruppe",
"HelpText": "Interval på få minutter. Sæt til nul for at deaktivere (dette stopper al automatisk frigivelse)",
"HiddenClickToShow": "Skjult, klik for at vise",
"Host": "Vært",
"iCalLink": "iCal Link",
@@ -1013,6 +1016,7 @@
"Wiki": "Wiki",
"WouldYouLikeToRestoreBackup": "Vil du gendanne sikkerhedskopien {0}?",
"Year": "År",
"Yes": "Ja",
"YesCancel": "Ja, Annuller",
"YesMoveFiles": "Ja, flyt filerne",
"Yesterday": "I går",
@@ -1057,10 +1061,5 @@
"RemotePath": "Fjern sti",
"SelectLanguages": "Vælg sprog",
"List": "Lister",
"Rating": "Bedømmelser",
"RssSyncHelpText": "Interval på få minutter. Sæt til nul for at deaktivere (dette stopper al automatisk frigivelse)",
"MonitorMovies": "Overvåg film",
"NoCollections": "Ingen film fundet. For at komme i gang vil du tilføje en ny film eller importere nogle eksisterende.",
"AllCollectionsHiddenDueToFilter": "Alle film er gemt på grund af aktivt filter.",
"Collections": "Samling"
"Rating": "Bedømmelser"
}

View File

@@ -572,6 +572,8 @@
"EnableMediaInfoHelpText": "Videoinformationen wie Auflösung, Laufzeit und Codec aus Datien erkennen. Dazu ist es erforderlich, dass Radarr Teile der Datei liest, was zu hoher Festplatten- oder Netzwerkaktivität während der Scans führen kann.",
"ImportListSyncIntervalHelpText": "Wie oft die Listen synchronisiert werden sollen. Minimum 6 Stunden",
"AddListExclusion": "Listenausschluss hinzufügen",
"AddMoviesMonitored": "Filme beobachtet hinzufügen",
"HelpText": "Intervall in Minuten. Zum deaktivieren auf 0 setzen ( Dies wird das automatische Release erfassen deaktivieren )",
"RequiredHelpText": "Diese {0} Bedingungen müsen zutreffen damit das eigene Format zutrifft. Ansonsten reicht ein einzelner {1} Treffer.",
"AllowHardcodedSubsHelpText": "Filme mit hartcodierten Untertiteln werden auch automatisch heruntergeladen",
"ICalHttpUrlHelpText": "Füge diese URL in deinen Client ein oder klicke auf abonnieren wenn dein Browser Webcal untertützt",
@@ -821,6 +823,8 @@
"ListSyncLevelHelpTextWarning": "Filmdateien werden dauerhaft gelöcht, dies kann deine ganze Mediathek leeren wenn deine Listen leer sind",
"ConsideredAvailable": "Verfügbarkeit angenommen",
"Announced": "Angekündigt",
"Yes": "Ja",
"No": "Nein",
"MappedDrivesRunningAsService": "Zugeordnete Netzlaufwerke sind nicht verfügbar, wenn Radarr als Windows-Dienst ausgeführt wird. Bitte lesen Sie die FAQ für weitere Informationen",
"CouldNotConnectSignalR": "Es konnte keine Verbindung zu SignalR hergestellt werden, die Benutzeroberfläche wird nicht aktualisiert",
"ChmodGroupHelpTextWarning": "Dies funktioniert nur, wenn der Benutzer, der Radarr ausführt, der Eigentümer der Datei ist. Es ist besser, sicherzustellen, dass der Download-Client die gleiche Gruppe wie Radarr verwendet.",
@@ -1111,10 +1115,5 @@
"Waiting": "warten",
"OriginalTitle": "Originaler Titel",
"OriginalLanguage": "Originale Sprache",
"Database": "Datenbank",
"AllCollectionsHiddenDueToFilter": "Alle Filme sind wegen dem Filter ausgeblendet.",
"Collections": "Sammlung",
"MonitorMovies": "Film beobachten",
"NoCollections": "Keine Filme gefunden. Zum Starten solltest du einen Film hinzufügen oder vorhandene Importieren.",
"RssSyncHelpText": "Intervall in Minuten. Zum deaktivieren auf 0 setzen ( Dies wird das automatische Release erfassen deaktivieren )"
"Database": "Datenbank"
}

View File

@@ -115,6 +115,7 @@
"ForMoreInformationOnTheIndividualDownloadClients": "Για περισσότερες πληροφορίες σχετικά με τους μεμονωμένους πελάτες λήψης, κάντε κλικ στα κουμπιά πληροφοριών.",
"GrabReleaseMessageText": "Ο Radarr δεν μπόρεσε να προσδιορίσει ποια ταινία ήταν αυτή η κυκλοφορία. Το Radarr ενδέχεται να μην μπορεί να εισαγάγει αυτόματα αυτήν την κυκλοφορία. Θέλετε να τραβήξετε το \"{0}\";",
"HardlinkCopyFiles": "Hardlink / Αντιγραφή αρχείων",
"HelpText": "Διάστημα σε λεπτά. Ρυθμίστε στο μηδέν για απενεργοποίηση (αυτό θα σταματήσει όλες τις αυτόματες αρπάξεις απελευθέρωσης)",
"ImportRootPath": "Τοποθετήστε το Radarr στο φάκελο που περιέχει όλες τις ταινίες σας και όχι μια συγκεκριμένη ταινία. π.χ. {0} και όχι {1}. Επιπλέον, κάθε ταινία πρέπει να βρίσκεται στον δικό της φάκελο στον φάκελο root / library.",
"InCinemasDate": "Στους κινηματογράφους Ημερομηνία",
"IncludeRadarrRecommendations": "Συμπεριλάβετε τις προτάσεις Radarr",
@@ -415,6 +416,7 @@
"MustNotContain": "Δεν πρέπει να περιέχει",
"NamingSettings": "Ρυθμίσεις ονομάτων",
"NetCore": ".NET Core",
"No": "Οχι",
"NoBackupsAreAvailable": "Δεν υπάρχουν διαθέσιμα αντίγραφα ασφαλείας",
"NoChange": "Καμία αλλαγή",
"NoHistory": "Χωρίς ιστορία",
@@ -423,6 +425,7 @@
"OAuthPopupMessage": "Τα αναδυόμενα παράθυρα αποκλείονται από το πρόγραμμα περιήγησής σας",
"Ok": "Εντάξει",
"AddListExclusion": "Προσθήκη εξαίρεσης λίστας",
"AddMoviesMonitored": "Προσθήκη ταινιών που παρακολουθούνται",
"AgeWhenGrabbed": "Ηλικία (όταν αρπαχτεί)",
"OrganizeAndRename": "Οργάνωση & Μετονομασία",
"AllowHardcodedSubs": "Να επιτρέπονται οι συνδρομητές με κωδικοποίηση",
@@ -1013,6 +1016,7 @@
"Wiki": "Wiki",
"WouldYouLikeToRestoreBackup": "Θέλετε να επαναφέρετε το αντίγραφο ασφαλείας {0};",
"Year": "Ετος",
"Yes": "Ναί",
"YesCancel": "Ναι, Ακύρωση",
"YesMoveFiles": "Ναι, Μετακινήστε τα αρχεία",
"Yesterday": "Εχθές",
@@ -1057,10 +1061,5 @@
"SelectLanguages": "Επιλέξτε γλώσσα",
"List": "Τόπος αγώνων",
"Rating": "Ακροαματικότητα",
"Filters": "Φίλτρο",
"AllCollectionsHiddenDueToFilter": "Όλες οι ταινίες έχουν κρυφτεί λόγω εφαρμογής φίλτρου",
"Collections": "Συλλογή",
"MonitorMovies": "Παρακολούθηση ταινίας",
"NoCollections": "Δεν βρέθηκαν ταινίες, για να ξεκινήσετε θα θέλετε να προσθέσετε μια νέα ταινία ή να εισαγάγετε ορισμένες υπάρχουσες.",
"RssSyncHelpText": "Διάστημα σε λεπτά. Ρυθμίστε στο μηδέν για απενεργοποίηση (αυτό θα σταματήσει όλες τις αυτόματες αρπάξεις απελευθέρωσης)"
"Filters": "Φίλτρο"
}

View File

@@ -15,8 +15,10 @@
"AddingTag": "Adding tag",
"AddList": "Add List",
"AddListExclusion": "Add List Exclusion",
"AddMissingMovies": "Add Missing Movies",
"AddMovie": "Add Movie",
"AddMovies": "Add Movies",
"AddMoviesMonitored": "Add Movies Monitored",
"AddNew": "Add New",
"AddNewMessage": "It's easy to add a new movie, just start typing the name of the movie you want to add",
"AddNewMovie": "Add New Movie",
@@ -123,7 +125,6 @@
"ChmodGroupHelpText": "Group name or gid. Use gid for remote file systems.",
"ChmodGroupHelpTextWarning": "This only works if the user running Radarr is the owner of the file. It's better to ensure the download client uses the same group as Radarr.",
"ChooseAnotherFolder": "Choose Another Folder",
"ChooseImportMode": "Choose Import Mode",
"CleanLibraryLevel": "Clean Library Level",
"Clear": "Clear",
"ClickToChangeLanguage": "Click to change language",
@@ -138,11 +139,6 @@
"Close": "Close",
"CloseCurrentModal": "Close Current Modal",
"Collection": "Collection",
"CollectionOptions": "Collection Options",
"Collections": "Collections",
"CollectionShowDetailsHelpText": "Show collection status and properties",
"CollectionShowOverviewsHelpText": "Show collection overviews",
"CollectionShowPostersHelpText": "Show Collection item posters",
"CollectionsSelectedInterp": "{0} Collections(s) Selected",
"ColonReplacement": "Colon Replacement",
"ColonReplacementFormatHelpText": "Change how Radarr handles colon replacement",
@@ -273,7 +269,6 @@
"DownloadWarningCheckDownloadClientForMoreDetails": "Download warning: check download client for more details",
"Duration": "Duration",
"Edit": "Edit",
"EditCollection": "Edit Collection",
"EditCustomFormat": "Edit Custom Format",
"EditDelayProfile": "Edit Delay Profile",
"EditGroups": "Edit Groups",
@@ -372,6 +367,7 @@
"HaveNotAddedMovies": "You haven't added any movies yet, do you want to import some or all of your movies first?",
"Health": "Health",
"HealthNoIssues": "No issues with your configuration",
"HelpText": "Interval in minutes. Set to zero to disable (this will stop all automatic release grabbing)",
"HiddenClickToShow": "Hidden, click to show",
"HideAdvanced": "Hide Advanced",
"History": "History",
@@ -449,8 +445,6 @@
"IndexerTagHelpText": "Only use this indexer for movies with at least one matching tag. Leave blank to use with all movies.",
"Info": "Info",
"InstallLatest": "Install Latest",
"InstanceName": "Instance Name",
"InstanceNameHelpText": "Instance name in tab and for Syslog app name",
"InteractiveImport": "Interactive Import",
"InteractiveImportErrLanguage": "Language must be chosen for each selected file",
"InteractiveImportErrMovie": "Movie must be chosen for each selected file",
@@ -610,6 +604,7 @@
"Never": "Never",
"New": "New",
"NextExecution": "Next Execution",
"No": "No",
"NoAltTitle": "No alternative titles.",
"NoBackupsAreAvailable": "No backups are available",
"NoChange": "No Change",
@@ -648,8 +643,6 @@
"OnLatestVersion": "The latest version of Radarr is already installed",
"OnlyTorrent": "Only Torrent",
"OnlyUsenet": "Only Usenet",
"OnMovieAdded": "On Movie Added",
"OnMovieAddedHelpText": "On Movie Added",
"OnMovieDelete": "On Movie Delete",
"OnMovieDeleteHelpText": "On Movie Delete",
"OnMovieFileDelete": "On Movie File Delete",
@@ -769,7 +762,6 @@
"RefreshCollections": "Refresh Collections",
"RefreshInformationAndScanDisk": "Refresh information and scan disk",
"RefreshLists": "Refresh Lists",
"RefreshMonitoredIntervalHelpText": "How often to refresh monitored downloads from download clients, minimum 1 minute",
"RefreshMovie": "Refresh movie",
"RegularExpressionsCanBeTested": "Regular expressions can be tested ",
"RejectionCount": "Rejection Count",
@@ -862,7 +854,6 @@
"RSS": "RSS",
"RSSIsNotSupportedWithThisIndexer": "RSS is not supported with this indexer",
"RSSSync": "RSS Sync",
"RssSyncHelpText": "Interval in minutes. Set to zero to disable (this will stop all automatic release grabbing)",
"RSSSyncInterval": "RSS Sync Interval",
"RSSSyncIntervalHelpTextWarning": "This will apply to all indexers, please follow the rules set forth by them",
"Runtime": "Runtime",
@@ -873,7 +864,6 @@
"Score": "Score",
"Script": "Script",
"ScriptPath": "Script Path",
"ScrollMovies": "Scroll Movies",
"Search": "Search",
"SearchAll": "Search All",
"SearchCutoffUnmet": "Search Cutoff Unmet",
@@ -938,7 +928,6 @@
"ShownClickToHide": "Shown, click to hide",
"ShowOverview": "Show Overview",
"ShowPath": "Show Path",
"ShowPosters": "Show Posters",
"ShowQualityProfile": "Show Quality Profile",
"ShowQualityProfileHelpText": "Show quality profile under poster",
"ShowRatings": "Show Ratings",
@@ -1138,6 +1127,7 @@
"Wiki": "Wiki",
"WouldYouLikeToRestoreBackup": "Would you like to restore the backup {0} ?",
"Year": "Year",
"Yes": "Yes",
"YesCancel": "Yes, Cancel",
"YesMoveFiles": "Yes, Move the Files",
"Yesterday": "Yesterday",

View File

@@ -396,6 +396,7 @@
"AllowHardcodedSubs": "Permitir Hardcoded Subs",
"AgeWhenGrabbed": "Edad (cuando capturada)",
"AddImportExclusionHelpText": "Prevenir que la película sea añadida a Radarr mediante listas",
"AddMoviesMonitored": "Añadir Películas Monitoreadas",
"AddListExclusion": "Añadir Exclusión De Lista",
"YesCancel": "Si, cancelar",
"WhitelistedSubtitleTags": "Etiquetas de Subtítulos Permitidas",
@@ -595,6 +596,7 @@
"ICalHttpUrlHelpText": "Copia esta URL a tu gestor(es) o haz click en subscribir si tu navegador soporta webcal",
"ICalFeed": "iCal Feed",
"Hostname": "Nombre del Host",
"HelpText": "Intervalo en minutos. Ajustar a cero para inhabilitar (esto dentendrá toda captura de estrenos automática)",
"EnableSSL": "Habilitar SSL",
"EnableRSS": "Habilitar RSS",
"EnableInteractiveSearch": "Habilitar Búsqueda Interactiva",
@@ -905,6 +907,7 @@
"InCinemasMsg": "La película está en los cines",
"ListSyncLevelHelpTextWarning": "Los archivos de películas se eliminarán permanentemente, esto puede resultar en borrar su biblioteca si sus listas están vacías",
"RSS": "RSS",
"No": "No",
"EditDelayProfile": "Editar perfil de retraso",
"Connection": "Conexiones",
"ConsideredAvailable": "Considerado disponible",
@@ -921,7 +924,7 @@
"DeleteMovieFolderHelpText": "Eliminar la carpeta de películas y su contenido",
"DeleteSelectedMovie": "Eliminar película (s) seleccionada (s)",
"DeleteTheMovieFolder": "Se eliminará la carpeta de películas '{0}' y todo su contenido.",
"Discord": "Discord",
"Discord": "Discordia",
"Donations": "Donaciones",
"DoneEditingGroups": "Terminado de editar grupos",
"DoNotPrefer": "No prefiero",
@@ -1023,6 +1026,7 @@
"Weeks": "Semanas",
"Wiki": "Wiki",
"WouldYouLikeToRestoreBackup": "¿Le gustaría restaurar la copia de seguridad {0}?",
"Yes": "si",
"YesMoveFiles": "Sí, mover los archivos",
"Yesterday": "Ayer",
"MoveFolders2": "¿Le gustaría mover los archivos de película de '{0}' a '{1}'?",
@@ -1110,10 +1114,5 @@
"RemoveSelectedItems": "Eliminar los elementos seleccionados",
"SelectReleaseGroup": "Seleccionar el grupo de lanzamiento",
"SetReleaseGroup": "Configurar el grupo de lanzamiento",
"TaskUserAgentTooltip": "User-Agent proporcionado por la aplicación llamó a la API",
"RssSyncHelpText": "Intervalo en minutos. Ajustar a cero para inhabilitar (esto dentendrá toda captura de estrenos automática)",
"AllCollectionsHiddenDueToFilter": "Todas las películas están ocultas debido al filtro aplicado.",
"Collections": "Colección",
"MonitorMovies": "Monitorear Película",
"NoCollections": "No se encontraron películas, para comenzar, querrá agregar una nueva película o importar algunas existentes."
"TaskUserAgentTooltip": "User-Agent proporcionado por la aplicación llamó a la API"
}

View File

@@ -51,7 +51,7 @@
"LinkHere": "tässä",
"ListSyncLevelHelpText": "Kirjaston elokuvat poistetaan tai niiden valvonta lopetetaan, jollei niitä ole tuontilistallasi.",
"ManualImportSelectMovie": "Manuaalinen tuonti - Valitse elokuva",
"MappedDrivesRunningAsService": "Yhdistetyt verkkoasemat eivät ole käytettävissä, kun sovellus suoritetaan Windows-palveluna. Lisätietoja löydät UKK:stä.",
"MappedDrivesRunningAsService": "Yhdistetyt verkkoasemat eivät ole käytettävissä, kun niitä käytetään Windows-palveluna. Katso lisätietoja UKK: sta",
"MinimumAgeHelpText": "Vain Usenet: NZB: n vähimmäisikä minuutteina, ennen kuin heidät napataan. Käytä tätä antaaksesi uusille julkaisuille aikaa levittää usenet-palveluntarjoajallesi.",
"MinimumFreeSpaceWhenImportingHelpText": "Estä tuonti, jos vapaan levytilan määrä sen jälkeen jää tässä määritetyn arvon alle.",
"MonitoredHelpText": "Elokuvaa etsitään ja se ladataan, jos se on saatavilla.",
@@ -60,7 +60,7 @@
"MultiLanguage": "Monikielinen",
"OrganizeModalNamingPattern": "Nimimalli:",
"PosterOptions": "Julistevaihtoehdot",
"PreviewRenameHelpText": "Vihje: Esikatsellaksesi uudelleennimeämistä, valitse 'Peruuta' ja paina jonkin elokuvan otsikkoa ja käytä",
"PreviewRenameHelpText": "Vinkki: Jos haluat esikatsella uudelleennimeä ..., valitse Peruuta, napsauta mitä tahansa elokuvan otsikkoa ja käytä",
"ProxyCheckResolveIpMessage": "Määritetyn välityspalvelimen '{0}' IP-osoitteen selvitys epäonnistui.",
"ProxyUsernameHelpText": "Käyttäjätunnus ja salasana tulee syöttää vain tarvittaessa. Muussa tapauksessa jätä kentät tyhjiksi.",
"QualityOrLangCutoffHasNotBeenMet": "Laadun tai kielen raja-arvoa ei ole saavutettu",
@@ -87,12 +87,12 @@
"AddNew": "Lisää uusi",
"AudioInfo": "Äänitiedot",
"BeforeUpdate": "Ennen päivitystä",
"DownloadPropersAndRepacksHelpText2": "Käytä 'Älä suosi' -valintaa suosiaksesi mukautettujen muotojen pisteytystä Proper- ja Repack-merkintöjä enemmän.",
"DownloadPropersAndRepacksHelpText2": "Käytä 'Älä suosi' -valintaa lajitellaksesi proper- ja repack-julkaisut mukautetun muodon pisteytytyksen perusteella.",
"Day": "Päivä",
"DBMigration": "Tietokannan siirto",
"ApiKey": "API-avain",
"AcceptConfirmationModal": "Hyväksy vahvistus",
"ApplyTagsHelpTexts1": "Miten tunnisteita sovelletaan valittuihin elokuviin",
"ApplyTagsHelpTexts1": "Tunnisteisiin kohdistettavat toimenpiteet:",
"ApplyTagsHelpTexts2": " 'Lisää' syötetyt tunnisteet aiempiin tunnisteisiin",
"ApplyTagsHelpTexts3": " 'Poista' ainoastaan syötetyt tunnisteet",
"AvailabilityDelay": "Saatavuusviive",
@@ -210,7 +210,7 @@
"EnableInteractiveSearchHelpText": "Profiilia käytetään vuorovaikutteisen haun yhteydessä.",
"EnableSslHelpText": " Käyttöönotto edellyttää uudelleenkäynnistystä järjestelmänvalvojan oikeuksilla.",
"Medium": "Keskitaso",
"MinFormatScoreHelpText": "Mukautetun muodon vähimmäispisteytys, jonka perusteella ladataan.",
"MinFormatScoreHelpText": "Mukautetun muodon vähimmäispisteet voidaan ladata",
"MinimumAge": "Vähimmäisikä",
"MinimumFreeSpace": "Vapaan tallennustilan vähimmäismäärä",
"MinimumLimits": "Vähimmäismäärät",
@@ -226,7 +226,7 @@
"NoLinks": "Ei linkkejä",
"NoMinimumForAnyRuntime": "Ei toistoajan vähimmäiskestoa",
"NoMoveFilesSelf": " Ei, siirrän tiedostot itse",
"NoMoviesExist": "Elokuvia ei löytynyt. Aloita lisäämällä uusi elokuva tai tuo joitakin olemassa olevia.",
"NoMoviesExist": "Elokuvia ei löytynyt. Aloittaaksesi sinun kannattaa lisätä uusi elokuva tai tuoda joitain olemassa olevia.",
"NoResultsFound": "Ei tuloksia",
"BranchUpdate": "Sovelluksen versiopäivityksiin käytettävä kehityshaara.",
"BranchUpdateMechanism": "Ulkoisen päivitysratkaisun käyttämä kehityshaara.",
@@ -269,7 +269,7 @@
"Size": "Koko",
"SuggestTranslationChange": "Ehdota käännösmuutosta",
"Queued": "Jonossa",
"TMDb": "TMDB",
"TMDb": "TMDb",
"UnableToLoadAltTitle": "Vaihtoehtoisten nimikkeiden lataus epäonnistui.",
"Released": "Julkaistu",
"ReleasedMsg": "Elokuva julkaistaan",
@@ -286,7 +286,7 @@
"DetailedProgressBarHelpText": "Näytä teksti edistymispalkissa.",
"Failed": "Epäonnistui",
"InCinemas": "Teatterijulkaisu",
"IncludeCustomFormatWhenRenaming": "Sisällytä mukautetut muodot uudelleennimetessä",
"IncludeCustomFormatWhenRenaming": "Uudelleen nimeäminen",
"IndexerFlags": "Tietolähteen liput",
"IndexerLongTermStatusCheckSingleClientMessage": "Tietolähteet eivät ole käytettävissä yli 6 tuntia kestäneiden virheiden vuoksi: {0}",
"IndexerStatusCheckAllClientMessage": "Tietolähteet eivät ole käytettävissä virheiden vuoksi",
@@ -329,6 +329,7 @@
"Updates": "Päivitykset",
"AddListExclusion": "Lisää tuontilistojen poikkeussääntö",
"AddMovies": "Lisää elokuvia",
"AddMoviesMonitored": "Lisää elokuvat valvottuina",
"ChangeHasNotBeenSavedYet": "Muutosta ei ole vielä tallennettu",
"CreateEmptyMovieFoldersHelpText": "Luo puuttuvat elokuvakansiot levyn tarkistuksen yhteydessä.",
"DeleteDownloadClient": "Poista lataustyökalu",
@@ -371,6 +372,7 @@
"PendingChangesMessage": "On tallentamattomia muutoksia. Haluatko varmasti poistua sivulta?",
"PendingChangesStayReview": "Älä poistu ja tarkista muutokset",
"NetCore": ".NET",
"No": "Ei",
"NoBackupsAreAvailable": "Varmuuskopioita ei ole saatavilla",
"NoChange": "Ei muutosta",
"NoHistory": "Ei historiaa.",
@@ -383,7 +385,7 @@
"Ok": "Ok",
"OrganizeAndRename": "Järjestä ja nimeä uudelleen",
"OrganizeModalAllPathsRelative": "Kaikki polut ovat suhteessa:",
"OrganizeModalDisabled": "Uudelleennimeäminen on poistettu käytöstä, eikä uudelleennimettävää ole",
"OrganizeModalDisabled": "Nimeäminen uudelleen on poistettu käytöstä, mitään ei voi nimetä uudelleen",
"Events": "Tapahtumat",
"IncludeCustomFormatWhenRenamingHelpText": "Mahdollista tämän muodon käyttö {Custom Formats} -nimeämissäännön kanssa.",
"Overview": "Yleiskatsaus",
@@ -419,7 +421,7 @@
"RecycleBinCleanupDaysHelpTextWarning": "Tässä määritettyä aikaa vanhemmat tiedostot poistetaan roskakorista pysyvästi automaattisesti.",
"RecycleBinHelpText": "Pysyvän poiston sijaan elokuvatiedostot siirretään tähän kansioon.",
"RefreshAndScan": "Päivitä ja tarkista",
"RequiredHelpText": "Ehdon '{0}' on vastattava mukautettua muotoa sen soveltamiseksi. Muutoin yksi '{1}' vastaavuus on riittävä.",
"RequiredHelpText": "Tämän {0} ehdon on vastattava muokattua muotoa. Muuten yksi {1} ottelu riittää.",
"RequiredRestrictionPlaceHolder": "Lisää rajoitus",
"AppDataLocationHealthCheckMessage": "Päivitystä ei sallita, jotta AppData-kansion poisto päivityksen yhteydessä voidaan estää.",
"RestartRequiredHelpTextWarning": "Käyttöönotto vaatii uudelleenkäynnistyksen.",
@@ -482,7 +484,7 @@
"ConsideredAvailable": "Tulkitaan olevan saatavilla",
"CopyUsingHardlinksHelpText": "Käytä hardlink-kytköksiä, kun kopioit tiedostoja torrenteista, joita jaetaan vielä.",
"Local": "Paikalliset",
"CouldNotFindResults": "Haku '{0}' ei tuottanut tuloksia.",
"CouldNotFindResults": "Haku '{0}' ei tuottanut yhtään tuloksia.",
"CreateEmptyMovieFolders": "Luo tyhjät kansiot",
"CreateGroup": "Luo ryhmä",
"Crew": "Ryhmä",
@@ -493,12 +495,12 @@
"CustomFormatHelpText": "Radarr pisteyttää jokaisen julkaisun käyttäen pisteiden summaa täsmääville mukautetuille muodoille. Jos uusi julkaisu parantaisi pisteitä samalla tai paremmalla laadulla, Radarr sieppaa sen.",
"CustomFormatJSON": "Mukautettu muoto JSON",
"CustomFormats": "Mukautetut muodot",
"CustomFormatScore": "Mukautetun muodon pisteytys",
"CustomFormatScore": "Mukautetun muodon pisteet",
"CustomFormatsSettings": "Mukautettujen muotojen asetukset",
"CustomFormatsSettingsSummary": "Mukautetut muodot ja niiden asetukset.",
"CustomFormatUnknownConditionOption": "Tuntematon valinta '{0}' ehdolle '{1}'",
"CustomFormatUnknownConditionOption": "Tuntematon vaihtoehto '{0}' ehdolle '{1}'",
"Cutoff": "Katkaisu",
"CutoffFormatScoreHelpText": "Kun tämä mukautetun muodon pisteytys saavutetaan, ei elokuvia enää ladata.",
"CutoffFormatScoreHelpText": "Kun tämä mukautetun muodon pisteytys saavutetaan, Radarr ei enää lataa elokuvia.",
"CutoffUnmet": "Katkaisutasoa ei saavutettu",
"Days": "Päivää",
"Debug": "Virheenkorjaus",
@@ -560,7 +562,7 @@
"Downloading": "Ladataan",
"DownloadPropersAndRepacks": "Proper- ja repack-julkaisut",
"DownloadPropersAndRepacksHelpText1": "Määrittää päivitetäänkö tiedostot automaattisesti proper- ja repack-julkaisuihin (kunnollinen/uudelleenpaketoitu).",
"DownloadPropersAndRepacksHelpTextWarning": "Käytä mukautettuja muotoja automaattisiin Proper/Repack-päivityksiin",
"DownloadPropersAndRepacksHelpTextWarning": "Käytä mukautettuja muotoja automaattisiin päivityksiin potkureille / uudelleenpakkauksille",
"DownloadWarning": "Latausvaroitus: {0}",
"DownloadWarningCheckDownloadClientForMoreDetails": "Latausvaroitus: Katso tarkempia tietoja lataustyökalusta",
"Edition": "Painos",
@@ -598,7 +600,7 @@
"FailedLoadingSearchResults": "Hakutulosten lataus epäonnistui. Yritä uudelleen.",
"FailedToLoadMovieFromAPI": "Elokuvan lataus API:n kautta epäonnistui",
"FeatureRequests": "Kehitysehdotukset",
"FileDateHelpText": "Muuta tiedoston päiväys tuonnin ja uudelleentarkistuksen yhteydessä.",
"FileDateHelpText": "Tiedoston päiväyksen muutos tuonnin ja uudellentarkistuksen yhteydessä.",
"FileManagement": "Tiedostojen hallinta",
"Filename": "Tiedostonimi",
"FileNames": "Tiedostonimet",
@@ -629,6 +631,7 @@
"Group": "Ryhmä",
"Health": "Kunto",
"HealthNoIssues": "Kokoonpanossasi ei ole ongelmia.",
"HelpText": "Aikaväli minuutteina. Poista käytöstä asettamalla arvoksi '0' (tämä lopettaa julkaisujen automaattisen sieppauksen).",
"HiddenClickToShow": "Piilotettu, näytä painalla",
"History": "Historia",
"Host": "Osoite",
@@ -783,8 +786,8 @@
"RemoveSelected": "Poista valitut",
"RemovingTag": "Tunniste poistetaan",
"Renamed": "Nimetty uudelleen",
"RenameFiles": "Uudelleennimeä tiedostot",
"RenameMovies": "Uudelleennimeä elokuvat",
"RenameFiles": "Nimeä uudelleen",
"RenameMovies": "Nimeä elokuvat uudelleen",
"RenameMoviesHelpText": "Jos uudelleennimeäminen ei ole käytössä, käytetään olemassa olevaa tiedostonimeä.",
"Reorder": "Järjestä uudelleen",
"Replace": "Korvata",
@@ -793,8 +796,8 @@
"ReplaceWithSpaceDashSpace": "Korvus: välilyönti-väliviiva-välilyönti",
"Required": "Vaaditaan",
"RequiredRestrictionHelpText": "Julkaisun tulee sisältää ainakin yksi näistä termeistä (kirjainkokoa ei huomioida).",
"RescanAfterRefreshHelpText": "Tutki elokuvakansio uudelleen elokuvan päivityksen jälkeen.",
"RescanAfterRefreshHelpTextWarning": "Tiedostomuutoksia ei tunnisteta automaattisesti, jollei asetuksena ole 'Aina'.",
"RescanAfterRefreshHelpText": "Tarkista elokuvakansion sisältö uudelleen elokuvan päivityksen jälkeen.",
"RescanAfterRefreshHelpTextWarning": "Radarr ei tunnista tiedostomuutoksia automaattisesti, jollei asetuksena ole 'Aina'.",
"RescanMovieFolderAfterRefresh": "Elokuvakansion uudelleentarkistus",
"ResetAPIKey": "Uudista API-avain",
"Restart": "Käynnistä uudelleen",
@@ -826,7 +829,7 @@
"SearchMissing": "Haku puuttuu",
"SearchMovie": "Etsi elokuvaa",
"SearchOnAdd": "Etsi lisättäessä",
"SearchOnAddHelpText": "Etsi tuostilistan elokuvia, kun ne lisätään kirjastoon.",
"SearchOnAddHelpText": "Elokuvia etsitään tältä tuostilistalta, kun ne lisätään Radarriin.",
"SearchSelected": "Haku valittu",
"Seconds": "Sekuntia",
"Security": "Suojaus",
@@ -853,7 +856,7 @@
"SettingsTimeFormat": "Kellonajan esitystapa",
"SettingsWeekColumnHeader": "Viikkosarakkeen otsikko",
"SettingsWeekColumnHeaderHelpText": "Näkyy jokaisen sarakkeen yläpuolella käytettäessä viikkonäkymää.",
"ShouldMonitorHelpText": "Lisää listan elokuvat valvottuina.",
"ShouldMonitorHelpText": "Tältä tuontilistalta lisätyt elokuvat lisätään ja niitä valvotaan.",
"ShowAdvanced": "Näytä edistyneet",
"ShowAsAllDayEvents": "Näytä koko päivän tapahtumina",
"ShowCutoffUnmetIconHelpText": "Näytä kuvake elokuville, joiden tiedostot eivät vastaa vielä määritettyä katkaisutasoa.",
@@ -878,7 +881,7 @@
"Shutdown": "Sammuta",
"SizeOnDisk": "Koko levyllä",
"SkipFreeSpaceCheck": "Ohita vapaan levytilan tarkistus",
"SkipFreeSpaceCheckWhenImportingHelpText": "Käytä, kun vapaata tallennustilaa ei tunnisteta elokuvien juurikansiosta.",
"SkipFreeSpaceCheckWhenImportingHelpText": "Käytä, kun vaapaata tilaa ei tunnisteta elokuviesi pääkansiosta",
"Small": "Pieni",
"Socks4": "Sukat 4",
"Socks5": "Sukat5 (tuki TOR)",
@@ -945,7 +948,7 @@
"UnableToAddANewRemotePathMappingPleaseTryAgain": "Etäsijainnin kartoituksen lisäys epäonnistui. Yritä uudelleen.",
"UnableToImportCheckLogs": "Ladattu - Tuonti epäonnistui: tarkasta lokitiedot",
"UnableToLoadBackups": "Varmuuskopioiden lataus epäonnistui.",
"UnableToLoadCustomFormats": "Muokattuja muotoja ei voitu ladata.",
"UnableToLoadCustomFormats": "Muokattujen muotojen lataus epäonnistui.",
"UnableToLoadDelayProfiles": "Viiveprofiilien lataus epäonnistui.",
"Unlimited": "Rajoittamaton",
"UnableToLoadDownloadClientOptions": "Lataustyökalun asetuksien lataus epäonnistui.",
@@ -953,7 +956,7 @@
"UnableToLoadGeneralSettings": "Yleisten asetusten lataus epäonnistui.",
"UnableToLoadHistory": "Historian lataus epäonnistui.",
"UnableToLoadIndexerOptions": "Tietolähteiden asetuksien lataus epäonnistui.",
"UnableToLoadIndexers": "Tietolähteiden lataus epäonnistui",
"UnableToLoadIndexers": "Tietolähteiden lataus epäonnistui.",
"UnableToLoadLanguages": "Kielien lataus epäonnistui.",
"UnableToLoadListExclusions": "Tuontilistojen poikkeussääntöjen lataus epäonnistui.",
"UnableToLoadListOptions": "Tuontilistojen asetuksien lataus epäonnistui.",
@@ -986,7 +989,7 @@
"UpdateAutomaticallyHelpText": "Lataa ja asenna päivitykset automaattisesti. Voit edelleen asentaa ne myös lähteestä System:Updates.",
"UpdateCheckStartupTranslocationMessage": "Päivitystä ei voi asentaa, koska käynnistyskansio '{0}' sijaitsee 'App Translocation' -kansiossa.",
"UpdateMechanismHelpText": "Käytä Radarrin sisäänrakennettua päivitystoimintoa tai omaa komentosarjaasi.",
"UpdateSelected": "Päivitä valitut",
"UpdateSelected": "Päivitä valittu",
"UpgradeUntilCustomFormatScore": "Päivitä mukautetun muodon pistetytykseen saakka",
"UpgradeUntilQuality": "Päivitä laatuun asti",
"UpgradeUntilThisQualityIsMetOrExceeded": "Päivitä, kunnes tämä laatu saavutetaan tai ylitetään",
@@ -1013,6 +1016,7 @@
"Wiki": "Wiki",
"WouldYouLikeToRestoreBackup": "Haluatko palauttaa varmuuskopion {0}?",
"Year": "Vuosi",
"Yes": "Kyllä",
"YesCancel": "Kyllä, peruuta",
"YesMoveFiles": "Kyllä, siirrä tiedostot",
"Yesterday": "Eilen",
@@ -1070,7 +1074,7 @@
"RemotePathMappingCheckFileRemoved": "Tiedosto '{0}' poistettiin kesken käsittelyn.",
"RemotePathMappingCheckFilesLocalWrongOSPath": "Paikallinen lataustyökalu '{0}' ilmoitti tiedostosijainniksi '{1}', mutta se ei ole kelvollinen '{2}' -sijainti. Tarkista lataustyökalusi asetukset.",
"RemotePathMappingCheckFolderPermissions": "Radarr näkee, muttei voi käyttää latauskansiota '{0}'. Todennäköinen syy on sijainnin käyttöoikeusvirhe.",
"RemotePathMappingCheckGenericPermissions": "Lataustyökalu '{0}' sijoittaa lataukset kansioon '{1}', mutta Radarr ei näe sitä. Saatat joutua muokkaamaan kansion käyttöoikeuksia.",
"RemotePathMappingCheckGenericPermissions": "Lataustyökalu '{0}' sijoittaa lataukset kansioon '{1}', mutta Radarr ei näe sitä. Saata joutua muokkaamaan kansion käyttöoikeuksia.",
"RemotePathMappingCheckDockerFolderMissing": "Käytät Dockeria ja lataustyökalu '{0}' sijoittaa lataukset kohteeseen '{1}', mutta kansiota ei näytä olevan olemassa containerissa. Tarkista etäsijaintiesi kartoitukset ja containerin tallennusmedia-asetukset.",
"RemotePathMappingCheckFilesBadDockerPath": "Käytät Dockeria ja lataustyökalu '{0}' ilmoitti latauskohteeksi '{1}', mutta se ei ole kelvollinen '{2}' -sijainti. Tarkista etäsijaintiesi kartoitukset ja lataustyökalun asetukset.",
"RemotePathMappingCheckRemoteDownloadClient": "Etälataustyökalu '{0}' ilmoitti tiedostosijainniksi '{1}', mutta kansiota ei näytä olevan olemassa. Todennäköinen syy on puuttuva tai virheellinen etäsijainnin kartoitus.",
@@ -1111,28 +1115,5 @@
"Waiting": "Odottaa",
"OriginalTitle": "Alkuperäinen nimi",
"OriginalLanguage": "Alkuperäinen kieli",
"Database": "Tietokanta",
"RefreshMonitoredIntervalHelpText": "Miten usein valvottujen latausten tiedot päivitetään lataustyökaluilta (vähimmäisaika on 1 minuutti).",
"RssSyncHelpText": "Aikaväli minuutteina. Arvo nolla kytkee toiminnon pois käytöstä ja lopettaen samalla automaattisen julkaisujen kaappauksen täysin.",
"InstanceName": "Instanssin nimi",
"InstanceNameHelpText": "Instanssin nimi välilehdellä ja sovelluksen Syslog-nimeksi",
"AllCollectionsHiddenDueToFilter": "Käytössä oleva suodatin on piilottanut kaikki kokoelmat.",
"Collections": "Kokoelmat",
"MonitorMovies": "Valvo elokuvia",
"NoCollections": "Kokoelmia ei löytynyt. Aloita lisäämällä uusi elokuva tai tuo joitakin olemassa olevia.",
"EditCollection": "Muokkaa kokoelmaa",
"SearchOnAddCollectionHelpText": "Etsi kokoelman elokuvia, kun ne lisätään kirjastoon.",
"ChooseImportMode": "Valitse tuontitila",
"CollectionsSelectedInterp": "{0} kokoelmaa valittu",
"MonitorCollection": "Valvo kokoelmaa",
"MonitoredCollectionHelpText": "Valvonta lisää kokoelman elokuvat automaattisesti kirjastoon.",
"MovieAndCollection": "Elokuva ja kokoelma",
"MovieCollectionMissingRoot": "Elokuvakokoelman juurikansio puuttuu: {0}",
"MovieCollectionMultipleMissingRoots": "Useita elokuvakokoelmien juurikansioita puuttuu: {0}",
"MovieOnly": "Vain elokuva",
"RefreshCollections": "Päivitä kokoelmat",
"ScrollMovies": "Vieritä elokuvia",
"ShowCollectionDetails": "Näytä kokoelman tila",
"ShowOverview": "Näytä yleiskatsaus",
"UnableToLoadCollections": "Kokoelmia ei voitu ladata"
"Database": "Tietokanta"
}

View File

@@ -1,6 +1,6 @@
{
"IndexerStatusCheckAllClientMessage": "Tous les indexeurs sont indisponibles en raison d'échecs",
"IndexerSearchCheckNoInteractiveMessage": "Aucun indexeur disponible avec la recherche interactive activée, Radarr ne fournira aucun résultat de recherche interactive",
"IndexerSearchCheckNoInteractiveMessage": "Aucun indexeur disponible avec la recherche interactive activée, Radarr ne fournira aucun résultat de recherche interactif",
"IndexerSearchCheckNoAvailableIndexersMessage": "Tous les indexeurs compatibles avec la recherche sont temporairement indisponibles en raison d'erreurs d'indexation récentes",
"IndexerSearchCheckNoAutomaticMessage": "Aucun indexeur disponible avec la recherche automatique activée, Radarr ne fournira aucun résultat de recherche automatique",
"Indexers": "Indexeurs",
@@ -26,7 +26,7 @@
"Edit": "Éditer",
"Downloaded": "Téléchargé",
"DownloadClientStatusCheckAllClientMessage": "Aucun client de téléchargement n'est disponible en raison d'échecs",
"DownloadClients": "Clients de téléchargement",
"DownloadClients": "Clients Télécharg.",
"DownloadClientCheckNoneAvailableMessage": "Aucun client de téléchargement n'est disponible",
"Dates": "Dates",
"Date": "Date",
@@ -36,7 +36,7 @@
"Delete": "Supprimer",
"DelayProfiles": "Profils de retard",
"Day": "Jour",
"CustomFormats": "Formats personnalisés",
"CustomFormats": "Formats Persos",
"CustomFilters": "Filtres personnalisés",
"Crew": "Équipe",
"Connections": "Connexions",
@@ -48,7 +48,7 @@
"Calendar": "Calendrier",
"BackupNow": "Sauvegarder maintenant",
"Backup": "Sauvegarde",
"AppDataLocationHealthCheckMessage": "Mettre à jour ne sera pas possible afin d'éviter de supprimer le dossier AppData lors de la mise à jour",
"AppDataLocationHealthCheckMessage": "Mettre à jour ne sera pas possible pour éviter la suppression AppData lors de la mise à jour",
"Analytics": "Analytique",
"All": "Tout",
"AddNewTmdbIdMessage": "Vous pouvez également effectuer une recherche à l'aide de l'identifiant TMDb d'un film. exemple. tmdb:71663",
@@ -59,7 +59,7 @@
"Activity": "Activité",
"About": "À propos",
"CustomFormatsSettingsSummary": "Paramètres et Formats personnalisés",
"IndexerStatusCheckSingleClientMessage": "Indexeurs indisponibles en raison d'échecs : {0}",
"IndexerStatusCheckSingleClientMessage": "Indexeurs indisponibles en raison d'échecs: {0}",
"DownloadClientStatusCheckSingleClientMessage": "Clients de Téléchargement indisponibles en raison d'échecs: {0}",
"SetTags": "Définir Tags",
"ReleaseTitle": "Titre de la version",
@@ -292,7 +292,7 @@
"RecentFolders": "Dossiers récents",
"QuickImport": "Déplacer automatiquement",
"PosterSize": "Taille des posters",
"Posters": "Affiches",
"Posters": "Posters",
"PosterOptions": "Options des posters",
"PendingChangesStayReview": "Rester et vérifier les changements",
"PendingChangesMessage": "Vous avez effectué des changements non sauvegardés, souhaitez vous quitter cette page?",
@@ -322,7 +322,7 @@
"CertificateValidation": "Validation du certificat",
"BypassProxyForLocalAddresses": "Contourner le proxy pour les adresses locales",
"Branch": "Branche",
"BindAddressHelpText": "Adresse IPv4 valide ou '*' pour toutes les interfaces",
"BindAddressHelpText": "Adresse IP4 valide ou '*' pour toutes les interfaces",
"BindAddress": "Adresse d'attache",
"Backups": "Sauvegardes",
"BackupRetentionHelpText": "Les sauvegardes automatiques plus anciennes que la période de conservation seront automatiquement effacées",
@@ -347,6 +347,7 @@
"AllowHardcodedSubsHelpText": "Les sous-titres incrustés détectés seront automatiquement téléchargés",
"AllowHardcodedSubs": "Autoriser les sous-titres incrustés",
"AgeWhenGrabbed": "Age (au moment du téléchargement)",
"AddMoviesMonitored": "Ajouter des films en mode surveillé",
"AddListExclusion": "Ajouter une exclusion de liste",
"IgnoreDeletedMovies": "Annuler la surveillance des films supprimés",
"IgnoredAddresses": "Adresses ignorées",
@@ -354,6 +355,7 @@
"ICalHttpUrlHelpText": "Copiez cette URL dans votre client ou cliquez pour souscrire si votre navigateur est compatible avec webcal",
"ICalFeed": "Flux iCal",
"Hostname": "Nom d'hôte",
"HelpText": "Intervalle en minutes. Mettre à zéro pour désactiver (cela arrêtera tous les téléchargements automatiques)",
"Group": "Groupe",
"GrabRelease": "Télécharger la version",
"GrabID": "ID du grab",
@@ -383,7 +385,7 @@
"Enable": "Activer",
"EditPerson": "Éditer la personne",
"EditMovie": "Éditer le film",
"Edition": "Édition",
"Edition": "Edition",
"DownloadWarningCheckDownloadClientForMoreDetails": "Avertissement téléchargement : voir le client de téléchargement pour plus de détails",
"DownloadFailedCheckDownloadClientForMoreDetails": "Téléchargement échoué : voir le client de téléchargement pour plus de détails",
"DownloadClientSettings": "Réglages Clients de téléchargement",
@@ -453,7 +455,7 @@
"CopyToClipboard": "Copier dans le presse-papier",
"GoToInterp": "Aller à {0}",
"ForMoreInformationOnTheIndividualImportListsClinkOnTheInfoButtons": "Pour plus d'informations sur les listes d'importation individuelles, cliquez sur les boutons d'information.",
"ForMoreInformationOnTheIndividualDownloadClients": "Pour plus d'informations sur chaque client de téléchargement, cliquez sur les boutons plus d'information.",
"ForMoreInformationOnTheIndividualDownloadClients": "Pour plus d'informations sur les clients de téléchargement individuels, cliquez sur les boutons d'information.",
"FilterPlaceHolder": "Chercher les films",
"FailedLoadingSearchResults": "Échec du chargement des résultats de la recherche, veuillez réessayer.",
"Excluded": "Exclu",
@@ -571,7 +573,7 @@
"ProxyBypassFilterHelpText": "Utiliser ',' comme séparateur et '*.' comme caractère générique pour les sous-domaines",
"OnGrabHelpText": "À la Récupération",
"NegateHelpText": "Si coché, le format personnalisé ne s'appliquera pas si cette condition {0} correspond.",
"LastDuration": "Dernière durée",
"LastDuration": "dernière Durée",
"IncludeCustomFormatWhenRenamingHelpText": "Inclus dans {Custom Formats} renommer le format",
"GrabReleaseMessageText": "Radarr n'a pas été en mesure de déterminer à quel film cette version était destinée. Radarr peut être incapable d'importer automatiquement cette version. Voulez-vous récupérer '{0}' ?",
"ExtraFileExtensionsHelpTexts1": "Liste séparée par des virgules des fichiers supplémentaires à importer (.nfo sera importé en tant que .nfo-orig)",
@@ -584,7 +586,7 @@
"UpgradeUntilThisQualityIsMetOrExceeded": "Mettre à niveau jusqu'à ce que cette qualité soit atteinte ou dépassée",
"UpgradeAllowedHelpText": "Ne sera pas mis à jour si la qualité est désactivée",
"UpdateScriptPathHelpText": "Chemin vers un script personnalisé qui prend un package de mise à jour extraite et gère le reste du processus de mise à jour",
"UpdateMechanismHelpText": "Utiliser le programme de mise à jour intégré de Radarr ou un script",
"UpdateMechanismHelpText": "Utiliser le programme de mise à jour intégré dans Radarr ou un script",
"UpdateAutomaticallyHelpText": "Télécharger et installer automatiquement les mises à jour. Vous pourrez toujours installer à partir de System : Updates",
"Unreleased": "Indisponible",
"UnmonitoredHelpText": "Inclure les films non surveillés dans le flux iCal",
@@ -826,7 +828,7 @@
"EditQualityProfile": "Modifier les profils",
"ErrorRestoringBackup": "Erreur lors de la restauration de la sauvegarde",
"ExternalUpdater": "Radarr est configuré pour utiliser un système de mise à jour ad-hoc",
"FileWasDeletedByViaUI": "Le fichier a été supprimé via l'interface",
"FileWasDeletedByViaUI": "Le fichier à été supprimé via l'interface",
"Announced": "Annoncé",
"ChmodFolder": "chmod Dossier",
"ChmodFolderHelpText": "Nombre, appliqué durant l'import/renommage vers les dossiers et fichiers multimédias (sans exécuter les bits)",
@@ -846,7 +848,7 @@
"AllResultsHiddenFilter": "Tous les résultats ont été dissimulés par le filtre actuellement appliqué",
"Always": "Toujours",
"AptUpdater": "Utiliser apt pour installer la mise à jour",
"AreYouSureYouWantToRemoveSelectedItemsFromQueue": "Êtes-vous sûr de vouloir supprimer {0} objet(s) de la file d'attente ?",
"AreYouSureYouWantToRemoveSelectedItemsFromQueue": "Êtes-vous sûr de vouloir désinstaller {0} objet{1} de la file d'attente ?",
"AuthBasic": "Authentification de base (popup)",
"AuthForm": "Authentification par formulaire (page de connexion)",
"AreYouSureYouWantToDeleteFormat": "Êtes-vous sûr de vouloir supprimer le tag {0} ?",
@@ -892,7 +894,7 @@
"HomePage": "Page d'accueil",
"HttpHttps": "HTTP(S)",
"ImportLibrary": "Import bibliothèque",
"MissingFromDisk": "Radarr n'a pas pu trouver le fichier sur le disque, il a donc été supprimé dans la base de donnée",
"MissingFromDisk": "Radarr n'a pas pu trouver le fichier sur le disque, il a donc été supprimé",
"MovieIsRecommend": "Le film est recommandé en fonction de l'ajout récent",
"NoAltTitle": "Pas de titres alternatifs.",
"NoLinks": "Aucun liens",
@@ -910,7 +912,7 @@
"InteractiveImportErrQuality": "La qualité doit être choisie pour chaque fichier sélectionné",
"LowerCase": "Minuscules",
"ManualImportSelectMovie": "Importation manuelle - Sélectionnez un film",
"MappedDrivesRunningAsService": "Les lecteurs réseau mappés ne sont pas disponibles en fonctionnement en tant que service Windows. Veuillez consulter la FAQ pour plus d'informations",
"MappedDrivesRunningAsService": "Les lecteurs réseau mappés ne sont pas disponibles lorsqu'ils sont exécutés en tant que service Windows. Veuillez consulter la FAQ pour plus d'informations",
"RequiredRestrictionHelpText": "La version doit contenir au moins un de ces termes (insensible à la casse)",
"InvalidFormat": "Format invalide",
"LastExecution": "Dernière exécution",
@@ -942,6 +944,7 @@
"ImportNotForDownloads": "Ne pas utiliser pour importer des téléchargements à partir de votre client de téléchargement, cela concerne uniquement les bibliothèques organisées existantes, pas les fichiers non triés.",
"PreferUsenet": "Préférez Usenet",
"ReplaceWithDash": "Remplacer par Dash",
"No": "Non",
"InCinemasDate": "Dans les cinémas Date",
"InstallLatest": "Installer le dernier",
"KeepAndUnmonitorMovie": "Conserver et annuler la surveillance du film",
@@ -991,7 +994,7 @@
"SearchCutoffUnmet": "Limite de recherche non satisfaite",
"SearchMissing": "Recherche manquante",
"Seconds": "Secondes",
"SelectDotDot": "Sélectionner...",
"SelectDotDot": "'Sélectionner...",
"SelectLanguage": "Choisir la langue",
"SelectMovie": "Sélectionnez un film",
"SelectQuality": "Sélectionnez la qualité",
@@ -1002,7 +1005,7 @@
"Sunday": "dimanche",
"TagDetails": "Détails du tag - {0}",
"TheLogLevelDefault": "Le niveau de journalisation est par défaut «Info» et peut être modifié dans",
"ThisCannotBeCancelled": "Cela ne peut pas être annulé une fois démarré sans désactiver tous vos indexeurs.",
"ThisCannotBeCancelled": "Cela ne peut pas être annulé une fois démarré sans redémarrer Radarr.",
"TorrentDelayTime": "Retard du torrent : {0}",
"TorrentsDisabled": "Torrents désactivés",
"Trace": "Trace",
@@ -1024,6 +1027,7 @@
"Weeks": "Semaines",
"Wiki": "Wiki",
"WouldYouLikeToRestoreBackup": "Souhaitez-vous restaurer la sauvegarde {0} ?",
"Yes": "Oui",
"YesMoveFiles": "Oui, déplacez les fichiers",
"MoveFolders2": "Souhaitez-vous déplacer les fichiers vidéo de «{0}» vers «{1}» ?",
"SqliteVersionCheckUpgradeRequiredMessage": "La version {0} de SQLite actuellement installée n'est plus prise en charge. Veuillez mettre à niveau SQLite vers au moins la version {1}.",
@@ -1044,7 +1048,7 @@
"DownloadClientCheckDownloadingToRoot": "Le client de téléchargement {0} place les téléchargements dans le dossier racine {1}. Vous ne devez pas télécharger dans un dossier racine.",
"DeleteFileLabel": "Supprimer {0} fichiers",
"NotificationTriggersHelpText": "Sélectionnez les événements qui doivent déclencher cette notification",
"From": "de",
"From": "De",
"UpdateAvailable": "Une nouvelle mise à jour est disponible",
"RemotePathMappingCheckImportFailed": "Radarr a échoué en important un Film. Vérifier vos logs pour plus de détails.",
"RemotePathMappingCheckDownloadPermissions": "Radarr peut voir mais ne peut accéder au film téléchargé {0}. Il s'agit probablement d'une erreur de permissions.",
@@ -1070,22 +1074,22 @@
"RemotePathMappingCheckFilesGenericPermissions": "Le client de téléchargement {0} met les téléchargements dans {1} mais Radarr ne peut voir ce répertoire. Il est possible que vous ayez besoin d'ajuster les permissions de ce dossier.",
"RemotePathMappingCheckFilesLocalWrongOSPath": "Le client de téléchargement {0} met les téléchargements dans {1} mais il ne s'agit pas d'un chemin {2} valide. Vérifiez les paramètres de votre client de téléchargement.",
"BypassDelayIfHighestQualityHelpText": "Outrepasser le délai quand la version a la plus haute qualité activée dans le profil de qualité avec le protocole préféré",
"ClickToChangeReleaseGroup": "Cliquer pour changer le groupe de publication",
"ClickToChangeReleaseGroup": "Cliquez pour changer de release group",
"AnnouncedMsg": "Le film est annoncé",
"Filters": "Filtres",
"IndexerDownloadClientHelpText": "Spécifiez quel client de téléchargement est utilisé pour cet indexeur",
"IndexerDownloadClientHelpText": "Précisez quel client de téléchargement est utilisé pour cet indexer",
"TmdbRating": "Note TMDb",
"IndexerTagHelpText": "Utiliser seulement cet indexeur pour les films avec au moins un tag correspondant. Laissez vide pour l'utiliser avec tous les films.",
"IndexerJackettAll": "Indexeurs utilisant le endpoint non supporté 'all' de Jackett : {0}",
"IndexerJackettAll": "Les indexeurs utilisant le endpoint 'all' de Jackett: {0}",
"ManualImportSetReleaseGroup": "Import manuel - Spécifier le groupe de Release",
"TmdbVotes": "Votes TMDb",
"ImdbRating": "Note IMDb",
"ImdbVotes": "Votes IMDb",
"LocalPath": "Chemin local",
"DiscordUrlInSlackNotification": "Vous avez une configuration de notification Discord en tant que notification Slack. Configurez cela comme une notification Discord pour un meilleur fonctionnement. Les notifications affectées sont : {0}",
"RemotePathMappingCheckDockerFolderMissing": "Vous utilisez docker; {0} enregistre les téléchargements dans {1} mais ce dossier n'est pas présent dans ce conteneur. Vérifiez vos paramètres de dossier distant et les paramètres de votre conteneur docker.",
"DiscordUrlInSlackNotification": "Vous avez une configuration de notification Discord en tant que notification Slack. Configurez cela comme une notification Discord pour une meilleure fonctionnalité. Les notifications affectées sont: {0}",
"RemotePathMappingCheckDockerFolderMissing": "Vous utilisez docker; {0} enregistre les téléchargements dans {1} mais ce dossier n'est pas présent dans ce conteneur. Vérifiez vos paramètres de dossier distant et les paramètres de votre conteneur docker.",
"RemotePathMappingCheckRemoteDownloadClient": "Le client de téléchargement distant {0} met les téléchargements dans {1} mais ce chemin ne semble pas exister. Vérifiez vos paramètres de chemins distants.",
"RemotePathMappingCheckBadDockerPath": "Vous utilisez docker ; le client de téléchargement {0} enregistre les téléchargements dans {1} mais ce n'est pas un chemin valide. Vérifiez vos paramètres de dossier distant et les paramètres de votre client de téléchargement.",
"RemotePathMappingCheckBadDockerPath": "Vous utilisez docker; {0} enregistre les téléchargements dans {1} mais ce n'est pas un dossier valide. Vérifiez vos paramètres de dossier distant et les paramètres de votre client de téléchargement.",
"RemotePathMappingCheckFilesWrongOSPath": "Le client de téléchargement distant {0} met les téléchargements dans {1} mais il ne s'agit pas d'un chemin {2} valide. Vérifiez les paramètres de votre client de téléchargement.",
"RemotePathMappingCheckLocalFolderMissing": "Le client de téléchargement distant {0} met les téléchargements dans {1} mais ce chemin ne semble pas exister. Vérifiez vos paramètres de chemins distants.",
"OnApplicationUpdate": "Lors de la mise à jour de l'app",
@@ -1098,26 +1102,9 @@
"OriginalLanguage": "Langue d'origine",
"Rating": "Note",
"RemotePath": "Dossier distant",
"RemotePathMappingCheckFilesBadDockerPath": "Vous utilisez docker; {0} signifie les téléchargement dans {1} mais ce n'est pas un dossier valide. Vérifiez vos paramètres de dossier distant et les paramètres de votre client de téléchargement.",
"RemotePathMappingCheckFilesBadDockerPath": "Vous utilisez docker; {0} signifie les téléchargement dans {1} mais ce n'est pas un dossier valide. Vérifiez vos paramètres de dossier distant et les paramètres de votre client de téléchargement.",
"RemotePathMappingCheckWrongOSPath": "Le client de téléchargement distant {0} met les téléchargements dans {1} mais ce chemin {2} est invalide. Vérifiez vos paramètres de chemins distants et les paramètres de votre client de téléchargement.",
"RemoveCompleted": "Supprimer les complétés",
"Database": "Base de données",
"SelectLanguages": "Choisir la/les langue(s)",
"RemoveDownloadsAlert": "Les paramètres de suppression ont été déplacés dans les réglages de chaque client de téléchargement dans le tableau ci-dessus.",
"SizeLimit": "Limite de taille",
"Started": "Démarré",
"Waiting": "En attente",
"RemoveFailed": "Echec de la suppression",
"RemoveSelectedItem": "Supprimer l'élément sélectionné",
"RemoveSelectedItems": "Supprimer les éléments sélectionnés",
"SelectReleaseGroup": "Sélectionner le groupe de publication",
"SetReleaseGroup": "Régler le groupe de publication",
"RefreshMonitoredIntervalHelpText": "Intervalle en minutes entre chaque vérification des téléchargements, minimum 1 minute",
"AllCollectionsHiddenDueToFilter": "Tous les films sont masqués en raison du filtre appliqué.",
"Collections": "Collection",
"MonitorMovies": "Surveiller le film",
"NoCollections": "Aucun film trouvé, pour commencer, vous voudrez ajouter un nouveau film ou importer des films existants.",
"RssSyncHelpText": "Intervalle en minutes. Mettre à zéro pour désactiver (cela arrêtera tous les téléchargements automatiques)",
"CollectionsSelectedInterp": "{0} Collections(s) Sélectionnée(s)",
"ChooseImportMode": "Mode d'importation"
"SelectLanguages": "Choisir la langue"
}

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