mirror of
https://github.com/Radarr/Radarr.git
synced 2024-09-11 03:52:33 +02:00
value injector should map lazy loaded values properly.
This commit is contained in:
parent
c34ae218e8
commit
e5cc0c1a93
@ -1,14 +1,11 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Data.Common;
|
||||
|
||||
namespace Marr.Data
|
||||
{
|
||||
public interface ILazyLoaded : ICloneable
|
||||
{
|
||||
void Prepare(Func<IDataMapper> dbCreator, object parent);
|
||||
bool IsLoaded { get; }
|
||||
void Prepare(Func<IDataMapper> dataMapperFactory, object parent);
|
||||
void LazyLoad();
|
||||
}
|
||||
|
||||
@ -18,8 +15,7 @@ public interface ILazyLoaded : ICloneable
|
||||
/// <typeparam name="TChild"></typeparam>
|
||||
public class LazyLoaded<TChild> : ILazyLoaded
|
||||
{
|
||||
protected TChild _child;
|
||||
protected bool _isLoaded;
|
||||
protected TChild _value;
|
||||
|
||||
public LazyLoaded()
|
||||
{
|
||||
@ -27,8 +23,8 @@ public LazyLoaded()
|
||||
|
||||
public LazyLoaded(TChild val)
|
||||
{
|
||||
_child = val;
|
||||
_isLoaded = true;
|
||||
_value = val;
|
||||
IsLoaded = true;
|
||||
}
|
||||
|
||||
public TChild Value
|
||||
@ -36,11 +32,13 @@ public TChild Value
|
||||
get
|
||||
{
|
||||
LazyLoad();
|
||||
return _child;
|
||||
return _value;
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void Prepare(Func<IDataMapper> dbCreator, object parent)
|
||||
public bool IsLoaded { get; protected set; }
|
||||
|
||||
public virtual void Prepare(Func<IDataMapper> dataMapperFactory, object parent)
|
||||
{ }
|
||||
|
||||
public virtual void LazyLoad()
|
||||
@ -50,7 +48,7 @@ public static implicit operator LazyLoaded<TChild>(TChild val)
|
||||
{
|
||||
return new LazyLoaded<TChild>(val);
|
||||
}
|
||||
|
||||
|
||||
public static implicit operator TChild(LazyLoaded<TChild> lazy)
|
||||
{
|
||||
return lazy.Value;
|
||||
@ -58,7 +56,7 @@ public static implicit operator TChild(LazyLoaded<TChild> lazy)
|
||||
|
||||
public object Clone()
|
||||
{
|
||||
return this.MemberwiseClone();
|
||||
return MemberwiseClone();
|
||||
}
|
||||
}
|
||||
|
||||
@ -70,7 +68,7 @@ public object Clone()
|
||||
internal class LazyLoaded<TParent, TChild> : LazyLoaded<TChild>
|
||||
{
|
||||
private TParent _parent;
|
||||
private Func<IDataMapper> _dbCreator;
|
||||
private Func<IDataMapper> _dbMapperFactory;
|
||||
|
||||
private readonly Func<IDataMapper, TParent, TChild> _query;
|
||||
private readonly Func<TParent, bool> _condition;
|
||||
@ -81,46 +79,41 @@ internal LazyLoaded(Func<IDataMapper, TParent, TChild> query, Func<TParent, bool
|
||||
_condition = condition;
|
||||
}
|
||||
|
||||
public LazyLoaded(TChild val)
|
||||
public LazyLoaded(TChild val)
|
||||
: base(val)
|
||||
{
|
||||
_child = val;
|
||||
_isLoaded = true;
|
||||
_value = val;
|
||||
IsLoaded = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The second part of the initialization happens when the entity is being built.
|
||||
/// </summary>
|
||||
/// <param name="dbCreator">Knows how to instantiate a new IDataMapper.</param>
|
||||
/// <param name="dataMapperFactory">Knows how to instantiate a new IDataMapper.</param>
|
||||
/// <param name="parent">The parent entity.</param>
|
||||
public override void Prepare(Func<IDataMapper> dbCreator, object parent)
|
||||
public override void Prepare(Func<IDataMapper> dataMapperFactory, object parent)
|
||||
{
|
||||
_dbCreator = dbCreator;
|
||||
_dbMapperFactory = dataMapperFactory;
|
||||
_parent = (TParent)parent;
|
||||
}
|
||||
|
||||
public bool IsLoaded
|
||||
{
|
||||
get { return _isLoaded; }
|
||||
}
|
||||
|
||||
public override void LazyLoad()
|
||||
{
|
||||
if (!_isLoaded)
|
||||
if (!IsLoaded)
|
||||
{
|
||||
if (_condition != null && _condition(_parent))
|
||||
{
|
||||
using (IDataMapper db = _dbCreator())
|
||||
using (IDataMapper db = _dbMapperFactory())
|
||||
{
|
||||
_child = _query(db, _parent);
|
||||
_value = _query(db, _parent);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_child = default(TChild);
|
||||
_value = default(TChild);
|
||||
}
|
||||
|
||||
_isLoaded = true;
|
||||
IsLoaded = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,6 @@
|
||||
using System;
|
||||
using FluentAssertions;
|
||||
using Marr.Data;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Api.Config;
|
||||
using NzbDrone.Api.Episodes;
|
||||
@ -40,5 +42,58 @@ public void matching_fields(Type modelType, Type resourceType)
|
||||
MappingValidation.ValidateMapping(modelType, resourceType);
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public void should_map_lay_loaded_values_should_not_be_inject_if_not_loaded()
|
||||
{
|
||||
var modelWithLazy = new ModelWithLazy()
|
||||
{
|
||||
Guid = new TestLazyLoaded<Guid>()
|
||||
};
|
||||
|
||||
modelWithLazy.InjectTo<ModelWithNoLazy>().Guid.Should().BeEmpty();
|
||||
|
||||
modelWithLazy.Guid.IsLoaded.Should().BeFalse();
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public void should_map_lay_loaded_values_should_be_inject_if_loaded()
|
||||
{
|
||||
|
||||
var guid = Guid.NewGuid();
|
||||
|
||||
var modelWithLazy = new ModelWithLazy()
|
||||
{
|
||||
Guid = new LazyLoaded<Guid>(guid)
|
||||
};
|
||||
|
||||
modelWithLazy.InjectTo<ModelWithNoLazy>().Guid.Should().Be(guid);
|
||||
|
||||
modelWithLazy.Guid.IsLoaded.Should().BeTrue();
|
||||
}
|
||||
}
|
||||
|
||||
public class ModelWithLazy
|
||||
{
|
||||
public LazyLoaded<Guid> Guid { get; set; }
|
||||
}
|
||||
|
||||
public class ModelWithNoLazy
|
||||
{
|
||||
public Guid Guid { get; set; }
|
||||
}
|
||||
|
||||
public class TestLazyLoaded<T> : LazyLoaded<T>
|
||||
{
|
||||
public TestLazyLoaded()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public override void Prepare(Func<IDataMapper> dataMapperFactory, object parent)
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
}
|
||||
}
|
@ -73,11 +73,14 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="ClientSchemaTests\SchemaBuilderFixture.cs" />
|
||||
<Compile Include="MappingTests\ReflectionExtensionFixture.cs" />
|
||||
<Compile Include="MappingTests\ResourceMappingFixture.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Marr.Data\Marr.Data.csproj">
|
||||
<Project>{F6FC6BE7-0847-4817-A1ED-223DC647C3D7}</Project>
|
||||
<Name>Marr.Data</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\NzbDrone.Api\NzbDrone.Api.csproj">
|
||||
<Project>{FD286DF8-2D3A-4394-8AD5-443FADE55FB2}</Project>
|
||||
<Name>NzbDrone.Api</Name>
|
||||
|
@ -2,6 +2,7 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Marr.Data;
|
||||
using Omu.ValueInjecter;
|
||||
|
||||
namespace NzbDrone.Api.Mapping
|
||||
@ -41,22 +42,16 @@ protected override object SetValue(ConventionInfo conventionInfo)
|
||||
|
||||
if (conventionInfo.SourceProp.Type.IsGenericType)
|
||||
{
|
||||
var genericInterfaces = conventionInfo.SourceProp.Type.GetGenericTypeDefinition().GetInterfaces();
|
||||
//handle IEnumerable<> also ICollection<> IList<> List<>
|
||||
if (conventionInfo.SourceProp.Type.GetGenericTypeDefinition().GetInterfaces().Any(d => d == typeof(IEnumerable)))
|
||||
if (genericInterfaces.Any(d => d == typeof(IEnumerable)))
|
||||
{
|
||||
var t = conventionInfo.SourceProp.Type.GetGenericArguments()[0];
|
||||
if (t.IsValueType || t == typeof(string)) return conventionInfo.SourceProp.Value;
|
||||
return MapLists(conventionInfo);
|
||||
}
|
||||
|
||||
var tlist = typeof(List<>).MakeGenericType(t);
|
||||
var list = Activator.CreateInstance(tlist);
|
||||
|
||||
var addMethod = tlist.GetMethod("Add");
|
||||
foreach (var o in (IEnumerable)conventionInfo.SourceProp.Value)
|
||||
{
|
||||
var e = Activator.CreateInstance(t).InjectFrom<CloneInjection>(o);
|
||||
addMethod.Invoke(list, new[] { e }); // in 4.0 you can use dynamic and just do list.Add(e);
|
||||
}
|
||||
return list;
|
||||
if (genericInterfaces.Any(i => i == typeof(ILazyLoaded)))
|
||||
{
|
||||
return MapLazy(conventionInfo);
|
||||
}
|
||||
|
||||
//unhandled generic type, you could also return null or throw
|
||||
@ -67,5 +62,38 @@ protected override object SetValue(ConventionInfo conventionInfo)
|
||||
return Activator.CreateInstance(conventionInfo.SourceProp.Type)
|
||||
.InjectFrom<CloneInjection>(conventionInfo.SourceProp.Value);
|
||||
}
|
||||
|
||||
private static object MapLazy(ConventionInfo conventionInfo)
|
||||
{
|
||||
|
||||
var genericArgument = conventionInfo.SourceProp.Type.GetGenericArguments()[0];
|
||||
|
||||
dynamic lazy = conventionInfo.SourceProp.Value;
|
||||
|
||||
if (lazy.IsLoaded && conventionInfo.TargetProp.Type.IsAssignableFrom(genericArgument))
|
||||
{
|
||||
return lazy.Value;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static object MapLists(ConventionInfo conventionInfo)
|
||||
{
|
||||
var t = conventionInfo.SourceProp.Type.GetGenericArguments()[0];
|
||||
if (t.IsValueType || t == typeof(string)) return conventionInfo.SourceProp.Value;
|
||||
|
||||
var tlist = typeof(List<>).MakeGenericType(t);
|
||||
var list = Activator.CreateInstance(tlist);
|
||||
|
||||
var addMethod = tlist.GetMethod("Add");
|
||||
foreach (var o in (IEnumerable)conventionInfo.SourceProp.Value)
|
||||
{
|
||||
var e = Activator.CreateInstance(t).InjectFrom<CloneInjection>(o);
|
||||
addMethod.Invoke(list, new[] { e }); // in 4.0 you can use dynamic and just do list.Add(e);
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
}
|
||||
}
|
@ -160,6 +160,10 @@
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Marr.Data\Marr.Data.csproj">
|
||||
<Project>{F6FC6BE7-0847-4817-A1ED-223DC647C3D7}</Project>
|
||||
<Name>Marr.Data</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\NzbDrone.Common\NzbDrone.Common.csproj">
|
||||
<Project>{f2be0fdf-6e47-4827-a420-dd4ef82407f8}</Project>
|
||||
<Name>NzbDrone.Common</Name>
|
||||
|
@ -89,6 +89,7 @@
|
||||
<Compile Include="DiskProviderFixture.cs" />
|
||||
<Compile Include="EnviromentProviderTest.cs" />
|
||||
<Compile Include="ProcessProviderTests.cs" />
|
||||
<Compile Include="ReflectionTests\ReflectionExtensionFixture.cs" />
|
||||
<Compile Include="ServiceFactoryFixture.cs" />
|
||||
<Compile Include="ServiceProviderTests.cs" />
|
||||
<Compile Include="WebClientTests.cs" />
|
||||
|
@ -1,31 +1,31 @@
|
||||
using System.Reflection;
|
||||
using FluentAssertions;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Common.Reflection;
|
||||
using NzbDrone.Core.Datastore;
|
||||
using NzbDrone.Test.Common;
|
||||
|
||||
namespace NzbDrone.Api.Test.MappingTests
|
||||
{
|
||||
public class ReflectionExtensionFixture : TestBase
|
||||
{
|
||||
[Test]
|
||||
public void should_get_properties_from_models()
|
||||
{
|
||||
var models = Assembly.Load("NzbDrone.Core").ImplementationsOf<ModelBase>();
|
||||
|
||||
foreach (var model in models)
|
||||
{
|
||||
model.GetSimpleProperties().Should().NotBeEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_be_able_to_get_implementations()
|
||||
{
|
||||
var models = Assembly.Load("NzbDrone.Core").ImplementationsOf<ModelBase>();
|
||||
|
||||
models.Should().NotBeEmpty();
|
||||
}
|
||||
}
|
||||
using System.Reflection;
|
||||
using FluentAssertions;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Common.Reflection;
|
||||
using NzbDrone.Core.Datastore;
|
||||
using NzbDrone.Test.Common;
|
||||
|
||||
namespace NzbDrone.Common.Test.ReflectionTests
|
||||
{
|
||||
public class ReflectionExtensionFixture : TestBase
|
||||
{
|
||||
[Test]
|
||||
public void should_get_properties_from_models()
|
||||
{
|
||||
var models = Assembly.Load("NzbDrone.Core").ImplementationsOf<ModelBase>();
|
||||
|
||||
foreach (var model in models)
|
||||
{
|
||||
model.GetSimpleProperties().Should().NotBeEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_be_able_to_get_implementations()
|
||||
{
|
||||
var models = Assembly.Load("NzbDrone.Core").ImplementationsOf<ModelBase>();
|
||||
|
||||
models.Should().NotBeEmpty();
|
||||
}
|
||||
}
|
||||
}
|
@ -404,12 +404,6 @@
|
||||
<Compile Include="Providers\BackupProvider.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Providers\Converting\AtomicParsleyProvider.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Providers\Converting\HandbrakeProvider.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Configuration\ConfigService.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
|
@ -1,75 +0,0 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using NLog;
|
||||
using NzbDrone.Core.Configuration;
|
||||
using NzbDrone.Core.Tv;
|
||||
using NzbDrone.Core.Model;
|
||||
|
||||
|
||||
namespace NzbDrone.Core.Providers.Converting
|
||||
{
|
||||
public class AtomicParsleyProvider
|
||||
{
|
||||
private readonly IConfigService _configService;
|
||||
|
||||
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
|
||||
|
||||
public AtomicParsleyProvider(IConfigService configService)
|
||||
{
|
||||
_configService = configService;
|
||||
}
|
||||
|
||||
public AtomicParsleyProvider()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public virtual bool RunAtomicParsley(Episode episode, string outputFile)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
|
||||
var atomicParsleyLocation = _configService.GetValue("AtomicParsleyLocation", "");
|
||||
var atomicParsleyTitleType = (AtomicParsleyTitleType) Convert.ToInt32(_configService.GetValue("AtomicParsley", 0));
|
||||
|
||||
var atomicParsleyCommand = String.Format("\"{0}\" --overWrite --title \"{1}\" --genre \"TV Shows\" --stik \"TV Show\" --TVShowName \"{2}\" --TVEpisodeNum \"{3}\" --TVSeason \"{4}\"",
|
||||
outputFile, episode.Title, episode.Series.Title, episode.EpisodeNumber, episode.SeasonNumber);
|
||||
|
||||
//If Episode Number + Name should be in Episode Title (Number - Title)
|
||||
if (atomicParsleyTitleType == AtomicParsleyTitleType.EpisodeNumber)
|
||||
{
|
||||
atomicParsleyCommand = String.Format("\"{0}\" --overWrite --title \"{3} - {1}\" --genre \"TV Shows\" --stik \"TV Show\" --TVShowName \"{2}\" --TVEpisodeNum \"{3}\" --TVSeason \"{4}\"",
|
||||
outputFile, episode.Title, episode.Series.Title, episode.EpisodeNumber, episode.SeasonNumber);
|
||||
}
|
||||
|
||||
//If Season/Episode Number + Name should be in Episode Title (SeasonNumber'x'EpisodeNumber - Title)
|
||||
else if (atomicParsleyTitleType == AtomicParsleyTitleType.Both)
|
||||
{
|
||||
atomicParsleyCommand = String.Format("\"{0}\" --overWrite --title \"{4}x{3:00} - {1}\" --genre \"TV Shows\" --stik \"TV Show\" --TVShowName \"{2}\" --TVEpisodeNum \"{3}\" --TVSeason \"{4}\"",
|
||||
outputFile, episode.Title, episode.Series.Title, episode.EpisodeNumber, episode.SeasonNumber);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var process = new Process();
|
||||
process.StartInfo.FileName = Path.Combine(atomicParsleyLocation, "AtomicParsley.exe");
|
||||
process.StartInfo.Arguments = atomicParsleyCommand;
|
||||
process.StartInfo.UseShellExecute = false;
|
||||
process.StartInfo.CreateNoWindow = true;
|
||||
process.StartInfo.RedirectStandardOutput = true;
|
||||
//process.OutputDataReceived += new DataReceivedEventHandler(HandBrakeOutputDataReceived);
|
||||
process.Start();
|
||||
//process.BeginOutputReadLine();
|
||||
process.WaitForExit();
|
||||
}
|
||||
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.DebugException(ex.Message, ex);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,106 +0,0 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Text.RegularExpressions;
|
||||
using NLog;
|
||||
using NzbDrone.Core.Configuration;
|
||||
using NzbDrone.Core.Tv;
|
||||
using NzbDrone.Core.Model.Notification;
|
||||
|
||||
|
||||
namespace NzbDrone.Core.Providers.Converting
|
||||
{
|
||||
public class HandbrakeProvider
|
||||
{
|
||||
//Interacts with Handbrake
|
||||
private readonly IConfigService _configService;
|
||||
private ProgressNotification _notification;
|
||||
private Episode _currentEpisode;
|
||||
|
||||
private Regex _processingRegex =
|
||||
new Regex(@"^(?:Encoding).+?(?:\,\s(?<percent>\d{1,3}\.\d{2})\s\%)(?:.+?ETA\s(?<hours>\d{2})h(?<minutes>\d{2})m(?<seconds>\d{2})s)?",
|
||||
RegexOptions.IgnoreCase | RegexOptions.Compiled);
|
||||
|
||||
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
|
||||
|
||||
public HandbrakeProvider(IConfigService configService)
|
||||
{
|
||||
_configService = configService;
|
||||
}
|
||||
|
||||
public HandbrakeProvider()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public virtual string ConvertFile(Episode episode, ProgressNotification notification)
|
||||
{
|
||||
_notification = notification;
|
||||
_currentEpisode = episode;
|
||||
|
||||
var outputFile = _configService.GetValue("iPodConvertDir", "");
|
||||
|
||||
var handBrakePreset = _configService.GetValue("HandBrakePreset", "iPhone & iPod Touch");
|
||||
var handBrakeCommand = String.Format("-i \"{0}\" -o \"{1}\" --preset=\"{2}\"", episode.EpisodeFile.Value.Path, outputFile, handBrakePreset);
|
||||
var handBrakeFile = @"C:\Program Files (x86)\Handbrake\HandBrakeCLI.exe";
|
||||
|
||||
try
|
||||
{
|
||||
var process = new Process();
|
||||
process.StartInfo.FileName = handBrakeFile;
|
||||
process.StartInfo.Arguments = handBrakeCommand;
|
||||
process.StartInfo.UseShellExecute = false;
|
||||
process.StartInfo.CreateNoWindow = true;
|
||||
process.StartInfo.RedirectStandardOutput = true;
|
||||
process.OutputDataReceived += new DataReceivedEventHandler(HandBrakeOutputDataReceived);
|
||||
process.Start();
|
||||
process.BeginOutputReadLine();
|
||||
process.WaitForExit();
|
||||
}
|
||||
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.DebugException(ex.Message, ex);
|
||||
return String.Empty;
|
||||
}
|
||||
|
||||
return outputFile;
|
||||
}
|
||||
|
||||
private void HandBrakeOutputDataReceived(object obj, DataReceivedEventArgs args)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
|
||||
//args.Data contains the line writen
|
||||
|
||||
var match = _processingRegex.Matches(args.Data);
|
||||
|
||||
if (match.Count != 1)
|
||||
return;
|
||||
|
||||
var episodeString = String.Format("{0} - {1}x{2:00}",
|
||||
_currentEpisode.Series.Title,
|
||||
_currentEpisode.SeasonNumber,
|
||||
_currentEpisode.EpisodeNumber);
|
||||
|
||||
var percent = Convert.ToDecimal(match[0].Groups["percent"].Value);
|
||||
int hours;
|
||||
int minutes;
|
||||
int seconds;
|
||||
|
||||
Int32.TryParse(match[0].Groups["hours"].Value, out hours);
|
||||
Int32.TryParse(match[0].Groups["minutes"].Value, out minutes);
|
||||
Int32.TryParse(match[0].Groups["seconds"].Value, out seconds);
|
||||
|
||||
if (seconds > 0 || minutes > 0 || hours > 0)
|
||||
{
|
||||
var eta = DateTime.Now.Add(new TimeSpan(0, hours, minutes, seconds));
|
||||
_notification.CurrentMessage = String.Format("Converting: {0}, {1}%. ETA: {2}", episodeString, percent, eta);
|
||||
}
|
||||
|
||||
else
|
||||
_notification.CurrentMessage = String.Format("Converting: {0}, {1}%.", episodeString, percent);
|
||||
|
||||
Console.WriteLine(args.Data);
|
||||
}
|
||||
}
|
||||
}
|
@ -50,8 +50,7 @@ public virtual List<MisnamedEpisodeModel> MisnamedFiles(int pageNumber, int page
|
||||
CurrentName = currentName,
|
||||
EpisodeFileId = firstEpisode.EpisodeFileId,
|
||||
ProperName = properName,
|
||||
SeriesId = firstEpisode.SeriesId,
|
||||
SeriesTitle = firstEpisode.Series.Title
|
||||
SeriesTitle = firstEpisode.Series.Value.Title
|
||||
});
|
||||
}
|
||||
});
|
||||
|
@ -30,15 +30,15 @@ public bool HasFile
|
||||
|
||||
public String SeriesTitle { get; private set; }
|
||||
|
||||
public Series Series { get; set; }
|
||||
public LazyLoaded<Series> Series { get; set; }
|
||||
|
||||
public LazyLoaded<EpisodeFile> EpisodeFile { get; set; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
string seriesTitle = Series == null ? "[NULL]" : Series.Title;
|
||||
string seriesTitle = Series == null ? "[NULL]" : Series.Value.Title;
|
||||
|
||||
if (Series != null && Series.SeriesType == SeriesTypes.Daily && AirDate.HasValue)
|
||||
if (Series != null && Series.Value.SeriesType == SeriesTypes.Daily && AirDate.HasValue)
|
||||
return string.Format("{0} - {1:yyyy-MM-dd}", seriesTitle, AirDate.Value);
|
||||
|
||||
return string.Format("{0} - S{1:00}E{2:00}", seriesTitle, SeasonNumber, EpisodeNumber);
|
||||
|
@ -208,7 +208,7 @@ public void RefreshEpisodeInfo(Series series)
|
||||
int episodeCount = 0;
|
||||
foreach (var episode in group.OrderBy(e => e.SeasonNumber).ThenBy(e => e.EpisodeNumber))
|
||||
{
|
||||
episode.AirDate = episode.AirDate.Value.AddMinutes(episode.Series.Runtime * episodeCount);
|
||||
episode.AirDate = episode.AirDate.Value.AddMinutes(episode.Series.Value.Runtime * episodeCount);
|
||||
episodeCount++;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user