fixed indexer setting load/reload.

pull/2/head
Keivan Beigi 11 years ago
parent 1465fbf499
commit 2eb3ead230

@ -108,7 +108,6 @@
<Compile Include="Eventing\IHandle.cs" /> <Compile Include="Eventing\IHandle.cs" />
<Compile Include="HostController.cs" /> <Compile Include="HostController.cs" />
<Compile Include="Instrumentation\VersionLayoutRenderer.cs" /> <Compile Include="Instrumentation\VersionLayoutRenderer.cs" />
<Compile Include="ReflectionExtentions.cs" />
<Compile Include="StringExtention.cs" /> <Compile Include="StringExtention.cs" />
<Compile Include="HttpProvider.cs" /> <Compile Include="HttpProvider.cs" />
<Compile Include="ConfigFileProvider.cs" /> <Compile Include="ConfigFileProvider.cs" />

@ -1,25 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
namespace NzbDrone.Common
{
public static class ReflectionExtensions
{
public static IEnumerable<Type> GetInterfaces(this Assembly assembly)
{
return assembly.GetTypes().Where(c => c.IsInterface);
}
public static IEnumerable<Type> GetImplementations(this Assembly assembly, Type contractType)
{
return assembly.GetTypes()
.Where(implementation =>
contractType.IsAssignableFrom(implementation) &&
!implementation.IsInterface &&
!implementation.IsAbstract
);
}
}
}

@ -101,14 +101,13 @@ namespace NzbDrone.Core.Datastore.Migration
Create.TableForModel("IndexerDefinitions") Create.TableForModel("IndexerDefinitions")
.WithColumn("Enable").AsBoolean() .WithColumn("Enable").AsBoolean()
.WithColumn("Name").AsString().Unique() .WithColumn("Name").AsString().Unique()
.WithColumn("Settings").AsString(); .WithColumn("Settings").AsString().Nullable();
Create.TableForModel("NewznabDefinitions") Create.TableForModel("NewznabDefinitions")
.WithColumn("Enable").AsBoolean() .WithColumn("Enable").AsBoolean()
.WithColumn("Name").AsString().Unique() .WithColumn("Name").AsString().Unique()
.WithColumn("Url").AsString() .WithColumn("Url").AsString()
.WithColumn("ApiKey").AsString().Nullable() .WithColumn("ApiKey").AsString().Nullable();
.WithColumn("BuiltIn").AsBoolean();
Create.TableForModel("QualityProfiles") Create.TableForModel("QualityProfiles")
.WithColumn("Name").AsString().Unique() .WithColumn("Name").AsString().Unique()

@ -3,27 +3,23 @@ using System.Collections.Generic;
namespace NzbDrone.Core.Indexers.FileSharingTalk namespace NzbDrone.Core.Indexers.FileSharingTalk
{ {
public class FileSharingTalk : BaseIndexer public class FileSharingTalk : IndexerWithSetting<FileSharingTalkSetting>
{ {
private readonly FileSharingTalkSetting _settings;
public FileSharingTalk(IProviderIndexerSetting settingProvider) public FileSharingTalk(IProviderIndexerSetting settingProvider)
: base(settingProvider)
{ {
_settings = settingProvider.Get<FileSharingTalkSetting>(this);
} }
public override IEnumerable<string> RecentFeed public override IEnumerable<string> RecentFeed
{ {
get get
{ {
yield return yield return string.Format(
string.Format(
"http://filesharingtalk.com/ng_rss.php?uid={0}&ps={1}&category=tv&subcategory=x264sd,x264720,xvid,webdl720,x2641080", "http://filesharingtalk.com/ng_rss.php?uid={0}&ps={1}&category=tv&subcategory=x264sd,x264720,xvid,webdl720,x2641080",
_settings.Uid, _settings.Secret); Settings.Uid, Settings.Secret);
} }
} }
public override IParseFeed Parser public override IParseFeed Parser
{ {
get get
@ -32,11 +28,6 @@ namespace NzbDrone.Core.Indexers.FileSharingTalk
} }
} }
public override IIndexerSetting Settings
{
get { return _settings; }
}
public override string Name public override string Name
{ {
get { return "FileSharingTalk"; } get { return "FileSharingTalk"; }

@ -0,0 +1,22 @@
using System;
using System.Collections.Generic;
namespace NzbDrone.Core.Indexers
{
public interface IIndexerBase
{
string Name { get; }
bool EnabledByDefault { get; }
IEnumerable<string> RecentFeed { get; }
IParseFeed Parser { get; }
bool IsConfigured { get; }
IEnumerable<string> GetEpisodeSearchUrls(string seriesTitle, int seasonNumber, int episodeNumber);
IEnumerable<string> GetDailyEpisodeSearchUrls(string seriesTitle, DateTime date);
IEnumerable<string> GetSeasonSearchUrls(string seriesTitle, int seasonNumber);
IEnumerable<string> GetPartialSeasonSearchUrls(string seriesTitle, int seasonNumber, int episodeWildcard);
}
}

@ -3,26 +3,12 @@ using System.Collections.Generic;
namespace NzbDrone.Core.Indexers namespace NzbDrone.Core.Indexers
{ {
public interface IIndexerBase public abstract class Indexer : IIndexerBase
{ {
string Name { get; }
bool EnabledByDefault { get; }
IEnumerable<string> RecentFeed { get; } public abstract string Name { get; }
IParseFeed Parser { get; }
IIndexerSetting Settings { get; }
IEnumerable<string> GetEpisodeSearchUrls(string seriesTitle, int seasonNumber, int episodeNumber);
IEnumerable<string> GetDailyEpisodeSearchUrls(string seriesTitle, DateTime date);
IEnumerable<string> GetSeasonSearchUrls(string seriesTitle, int seasonNumber);
IEnumerable<string> GetPartialSeasonSearchUrls(string seriesTitle, int seasonNumber, int episodeWildcard);
}
public abstract class BaseIndexer : IIndexerBase
{
public abstract string Name { get; }
public virtual bool EnabledByDefault public virtual bool EnabledByDefault
{ {
@ -40,14 +26,13 @@ namespace NzbDrone.Core.Indexers
} }
} }
public virtual IIndexerSetting Settings public virtual bool IsConfigured
{ {
get get { return true; }
{
return new NullSetting();
}
} }
public abstract IEnumerable<string> RecentFeed { get; } public abstract IEnumerable<string> RecentFeed { get; }
public abstract IEnumerable<string> GetEpisodeSearchUrls(string seriesTitle, int seasonNumber, int episodeNumber); public abstract IEnumerable<string> GetEpisodeSearchUrls(string seriesTitle, int seasonNumber, int episodeNumber);

@ -1,4 +1,5 @@
using System.Linq; using System;
using System.Linq;
using NzbDrone.Core.Datastore; using NzbDrone.Core.Datastore;
namespace NzbDrone.Core.Indexers namespace NzbDrone.Core.Indexers
@ -6,6 +7,7 @@ namespace NzbDrone.Core.Indexers
public interface IIndexerRepository : IBasicRepository<IndexerDefinition> public interface IIndexerRepository : IBasicRepository<IndexerDefinition>
{ {
IndexerDefinition Get(string name); IndexerDefinition Get(string name);
IndexerDefinition Find(string name);
} }
public class IndexerRepository : BasicRepository<IndexerDefinition>, IIndexerRepository public class IndexerRepository : BasicRepository<IndexerDefinition>, IIndexerRepository
@ -17,7 +19,13 @@ namespace NzbDrone.Core.Indexers
public IndexerDefinition Get(string name) public IndexerDefinition Get(string name)
{ {
return Query.Single(i => i.Name.ToLower() == name.ToLower()); return Query.Single(i => i.Name.Equals(name, StringComparison.InvariantCultureIgnoreCase));
} }
public IndexerDefinition Find(string name)
{
return Query.SingleOrDefault(i => i.Name.Equals(name, StringComparison.InvariantCultureIgnoreCase));
}
} }
} }

@ -38,7 +38,7 @@ namespace NzbDrone.Core.Indexers
public List<IIndexerBase> GetAvailableIndexers() public List<IIndexerBase> GetAvailableIndexers()
{ {
var enabled = All().Where(c => c.Enable).Select(c => c.Name); var enabled = All().Where(c => c.Enable).Select(c => c.Name);
var configureIndexers = _indexers.Where(c => c.Settings.IsValid); var configureIndexers = _indexers.Where(c => c.IsConfigured);
return configureIndexers.Where(c => enabled.Contains(c.Name)).ToList(); return configureIndexers.Where(c => enabled.Contains(c.Name)).ToList();
} }

@ -18,8 +18,14 @@ namespace NzbDrone.Core.Indexers
public TSetting Get<TSetting>(IIndexerBase indexer) where TSetting : IIndexerSetting, new() public TSetting Get<TSetting>(IIndexerBase indexer) where TSetting : IIndexerSetting, new()
{ {
var json = _indexerRepository.Get(indexer.Name).Settings; var indexerDef = _indexerRepository.Find(indexer.Name);
return JsonConvert.DeserializeObject<TSetting>(json);
if (indexerDef == null || string.IsNullOrWhiteSpace(indexerDef.Settings))
{
return new TSetting();
}
return JsonConvert.DeserializeObject<TSetting>(indexerDef.Settings);
} }
} }
} }

@ -0,0 +1,16 @@
using NzbDrone.Common.Eventing;
namespace NzbDrone.Core.Indexers
{
public class IndexerSettingUpdatedEvent : IEvent
{
public string IndexerName { get; private set; }
public IIndexerSetting IndexerSetting { get; private set; }
public IndexerSettingUpdatedEvent(string indexerName, IIndexerSetting indexerSetting)
{
IndexerName = indexerName;
IndexerSetting = indexerSetting;
}
}
}

@ -0,0 +1,30 @@
using System;
using NzbDrone.Common.Eventing;
namespace NzbDrone.Core.Indexers
{
public abstract class IndexerWithSetting<TSetting> :
Indexer,
IHandle<IndexerSettingUpdatedEvent> where TSetting : IIndexerSetting, new()
{
protected IndexerWithSetting(IProviderIndexerSetting settingProvider)
{
Settings = settingProvider.Get<TSetting>(this);
}
public override bool IsConfigured
{
get { return Settings.IsValid; }
}
protected TSetting Settings { get; private set; }
public void Handle(IndexerSettingUpdatedEvent message)
{
if (message.IndexerName.Equals(Name, StringComparison.InvariantCultureIgnoreCase))
{
Settings = (TSetting)message.IndexerSetting;
}
}
}
}

@ -4,7 +4,7 @@ using System.Linq;
namespace NzbDrone.Core.Indexers.Newznab namespace NzbDrone.Core.Indexers.Newznab
{ {
public class Newznab : BaseIndexer public class Newznab : Indexer
{ {
private readonly INewznabService _newznabProvider; private readonly INewznabService _newznabProvider;

@ -1,16 +1,10 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using NzbDrone.Common;
using NzbDrone.Core.Configuration;
namespace NzbDrone.Core.Indexers.NzbClub namespace NzbDrone.Core.Indexers.NzbClub
{ {
public class NzbClub : BaseIndexer public class NzbClub : Indexer
{ {
public NzbClub(HttpProvider httpProvider, IConfigService configService)
{
}
public override IEnumerable<string> RecentFeed public override IEnumerable<string> RecentFeed
{ {
get get

@ -3,7 +3,7 @@ using System.Collections.Generic;
namespace NzbDrone.Core.Indexers.NzbIndex namespace NzbDrone.Core.Indexers.NzbIndex
{ {
public class NzbIndex : BaseIndexer public class NzbIndex : Indexer
{ {
public override IEnumerable<string> RecentFeed public override IEnumerable<string> RecentFeed
{ {
@ -76,7 +76,7 @@ namespace NzbDrone.Core.Indexers.NzbIndex
} }

@ -3,13 +3,13 @@ using System.Collections.Generic;
namespace NzbDrone.Core.Indexers.NzbsRUs namespace NzbDrone.Core.Indexers.NzbsRUs
{ {
public class Nzbsrus : BaseIndexer public class Nzbsrus : IndexerWithSetting<NzbsrusSetting>
{ {
private readonly NzbsrusSetting _setting; private readonly NzbsrusSetting _setting;
public Nzbsrus(IProviderIndexerSetting settingProvider) public Nzbsrus(IProviderIndexerSetting settingProvider):base(settingProvider)
{ {
_setting = settingProvider.Get<NzbsrusSetting>(this);
} }
public override IEnumerable<string> RecentFeed public override IEnumerable<string> RecentFeed
@ -23,12 +23,6 @@ namespace NzbDrone.Core.Indexers.NzbsRUs
} }
} }
public override IIndexerSetting Settings
{
get { return _setting; }
}
public override string Name public override string Name
{ {
get { return "NzbsRUs"; } get { return "NzbsRUs"; }

@ -3,7 +3,7 @@ using System.Collections.Generic;
namespace NzbDrone.Core.Indexers.Nzbx namespace NzbDrone.Core.Indexers.Nzbx
{ {
public class Nzbx : BaseIndexer public class Nzbx : Indexer
{ {
public override string Name public override string Name
{ {

@ -3,13 +3,11 @@ using System.Collections.Generic;
namespace NzbDrone.Core.Indexers.Omgwtfnzbs namespace NzbDrone.Core.Indexers.Omgwtfnzbs
{ {
public class Omgwtfnzbs : BaseIndexer public class Omgwtfnzbs : IndexerWithSetting<OmgwtfnzbsSetting>
{ {
private readonly OmgwtfnzbsSetting _settings;
public Omgwtfnzbs(IProviderIndexerSetting settingProvider) public Omgwtfnzbs(IProviderIndexerSetting settingProvider)
: base(settingProvider)
{ {
_settings = settingProvider.Get<OmgwtfnzbsSetting>(this);
} }
public override string Name public override string Name
@ -24,14 +22,10 @@ namespace NzbDrone.Core.Indexers.Omgwtfnzbs
yield return yield return
String.Format("http://rss.omgwtfnzbs.org/rss-search.php?catid=19,20&user={0}&api={1}&eng=1", String.Format("http://rss.omgwtfnzbs.org/rss-search.php?catid=19,20&user={0}&api={1}&eng=1",
_settings.Username, _settings.ApiKey); Settings.Username, Settings.ApiKey);
} }
} }
public override IIndexerSetting Settings
{
get { return _settings; }
}
public override IEnumerable<string> GetEpisodeSearchUrls(string seriesTitle, int seasonNumber, int episodeNumber) public override IEnumerable<string> GetEpisodeSearchUrls(string seriesTitle, int seasonNumber, int episodeNumber)
{ {

@ -3,17 +3,11 @@ using System.Collections.Generic;
namespace NzbDrone.Core.Indexers.Wombles namespace NzbDrone.Core.Indexers.Wombles
{ {
public class Wombles : BaseIndexer public class Wombles : Indexer
{ {
public override IEnumerable<string> RecentFeed public override IEnumerable<string> RecentFeed
{ {
get get { yield return string.Format("http://nzb.isasecret.com/rss"); }
{
return new[]
{
string.Format("http://nzb.isasecret.com/rss")
};
}
} }
public override string Name public override string Name
@ -21,8 +15,6 @@ namespace NzbDrone.Core.Indexers.Wombles
get { return "WomblesIndex"; } get { return "WomblesIndex"; }
} }
public override IEnumerable<string> GetEpisodeSearchUrls(string seriesTitle, int seasonNumber, int episodeNumber) public override IEnumerable<string> GetEpisodeSearchUrls(string seriesTitle, int seasonNumber, int episodeNumber)
{ {
return new List<string>(); return new List<string>();

@ -236,6 +236,9 @@
<Compile Include="Download\Clients\Sabnzbd\SabAutoConfigureService.cs" /> <Compile Include="Download\Clients\Sabnzbd\SabAutoConfigureService.cs" />
<Compile Include="Download\DownloadClientProvider.cs" /> <Compile Include="Download\DownloadClientProvider.cs" />
<Compile Include="Download\DownloadClientType.cs" /> <Compile Include="Download\DownloadClientType.cs" />
<Compile Include="Indexers\IIndexerBase.cs" />
<Compile Include="Indexers\IndexerSettingUpdatedEvent.cs" />
<Compile Include="Indexers\IndexerWithSetting.cs" />
<Compile Include="MediaFiles\Events\EpisodeDownloadedEvent.cs" /> <Compile Include="MediaFiles\Events\EpisodeDownloadedEvent.cs" />
<Compile Include="Download\EpisodeGrabbedEvent.cs" /> <Compile Include="Download\EpisodeGrabbedEvent.cs" />
<Compile Include="Download\SeriesRenamedEvent.cs" /> <Compile Include="Download\SeriesRenamedEvent.cs" />
@ -254,7 +257,7 @@
<Compile Include="Indexers\RssSyncService.cs" /> <Compile Include="Indexers\RssSyncService.cs" />
<Compile Include="Indexers\FileSharingTalk\FileSharingTalk.cs" /> <Compile Include="Indexers\FileSharingTalk\FileSharingTalk.cs" />
<Compile Include="Indexers\FileSharingTalk\FileSharingTalkParser.cs" /> <Compile Include="Indexers\FileSharingTalk\FileSharingTalkParser.cs" />
<Compile Include="Indexers\BaseIndexer.cs" /> <Compile Include="Indexers\Indexer.cs" />
<Compile Include="Indexers\IndexerDefinition.cs" /> <Compile Include="Indexers\IndexerDefinition.cs" />
<Compile Include="Indexers\IndexerRepository.cs" /> <Compile Include="Indexers\IndexerRepository.cs" />
<Compile Include="Indexers\IndexerSettingProvider.cs" /> <Compile Include="Indexers\IndexerSettingProvider.cs" />

@ -1,4 +1,5 @@
using System; using System;
using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
@ -11,9 +12,7 @@ using NzbDrone.Common.Eventing;
using NzbDrone.Core.Datastore; using NzbDrone.Core.Datastore;
using NzbDrone.Core.Datastore.Migration.Framework; using NzbDrone.Core.Datastore.Migration.Framework;
using NzbDrone.Core.ExternalNotification; using NzbDrone.Core.ExternalNotification;
using NzbDrone.Core.IndexerSearch; using NzbDrone.Core.Organizer;
using NzbDrone.Core.Indexers;
using NzbDrone.Core.Lifecycle;
using NzbDrone.Core.RootFolders; using NzbDrone.Core.RootFolders;
using TinyIoC; using TinyIoC;
@ -21,27 +20,31 @@ namespace NzbDrone
{ {
public static class ContainerBuilder public static class ContainerBuilder
{ {
private static readonly Logger logger = LogManager.GetLogger("ContainerBuilder"); private static readonly Logger Logger = LogManager.GetLogger("ContainerBuilder");
public static TinyIoCContainer Instance { get; private set; } public static TinyIoCContainer Instance { get; private set; }
private static readonly List<Type> NzbDroneTypes;
static ContainerBuilder() static ContainerBuilder()
{ {
var container = new TinyIoCContainer(); var container = new TinyIoCContainer();
container.AutoRegisterInterfaces("NzbDrone"); NzbDroneTypes = new List<Type>();
container.AutoRegisterInterfaces("NzbDrone.Common"); NzbDroneTypes.AddRange(Assembly.Load("NzbDrone").GetTypes());
container.AutoRegisterInterfaces("NzbDrone.Core"); NzbDroneTypes.AddRange(Assembly.Load("NzbDrone.Common").GetTypes());
container.AutoRegisterInterfaces("NzbDrone.Api"); NzbDroneTypes.AddRange(Assembly.Load("NzbDrone.Core").GetTypes());
NzbDroneTypes.AddRange(Assembly.Load("NzbDrone.Api").GetTypes());
container.AutoRegisterInterfaces();
container.AutoRegisterImplementations<IIndexerBase>();
container.AutoRegisterImplementations<ExternalNotificationBase>(); container.AutoRegisterImplementations<ExternalNotificationBase>();
container.Register<IEventAggregator, EventAggregator>().AsSingleton(); container.Register<IEventAggregator, EventAggregator>().AsSingleton();
container.Register<INancyBootstrapper, TinyNancyBootstrapper>().AsSingleton(); container.Register<INancyBootstrapper, TinyNancyBootstrapper>().AsSingleton();
container.Register<IAnnouncer, MigrationLogger>().AsSingleton(); container.Register<IAnnouncer, MigrationLogger>().AsSingleton();
container.Register<Router>().AsSingleton();
container.Register(typeof(IBasicRepository<RootFolder>), typeof(BasicRepository<RootFolder>)).AsMultiInstance(); container.Register(typeof(IBasicRepository<RootFolder>), typeof(BasicRepository<RootFolder>)).AsMultiInstance();
container.Register(typeof(IBasicRepository<NameSpecification>), typeof(BasicRepository<NameSpecification>)).AsMultiInstance();
container.InitDatabase(); container.InitDatabase();
@ -50,30 +53,23 @@ namespace NzbDrone
private static void InitDatabase(this TinyIoCContainer container) private static void InitDatabase(this TinyIoCContainer container)
{ {
logger.Info("Registering Database..."); Logger.Info("Registering Database...");
//TODO: move this to factory //TODO: move this to factory
var environmentProvider = new EnvironmentProvider(); var environmentProvider = new EnvironmentProvider();
var appDataPath = environmentProvider.GetAppDataPath(); var appDataPath = environmentProvider.GetAppDataPath();
if (!Directory.Exists(appDataPath)) Directory.CreateDirectory(appDataPath);
if (!Directory.Exists(appDataPath))
{
Directory.CreateDirectory(appDataPath);
}
container.Register( container.Register((c, p) => c.Resolve<IDbFactory>().Create(environmentProvider.GetNzbDroneDatabase()));
delegate(TinyIoCContainer c, NamedParameterOverloads p)
{
return c.Resolve<IDbFactory>().Create(environmentProvider.GetNzbDroneDatabase());
});
} }
private static void AutoRegisterInterfaces(this TinyIoCContainer container, string assemblyName) private static void AutoRegisterInterfaces(this TinyIoCContainer container)
{ {
var assembly = Assembly.Load(assemblyName); var interfaces = NzbDroneTypes.Where(t => t.IsInterface);
if (assembly == null)
{
throw new ApplicationException("Couldn't load assembly " + assemblyName);
}
var interfaces = assembly.GetInterfaces().Where(c => !c.FullName.StartsWith("Nancy."));
foreach (var contract in interfaces) foreach (var contract in interfaces)
{ {
@ -81,6 +77,7 @@ namespace NzbDrone
} }
} }
private static void AutoRegisterImplementations<TContract>(this TinyIoCContainer container) private static void AutoRegisterImplementations<TContract>(this TinyIoCContainer container)
{ {
container.AutoRegisterImplementations(typeof(TContract)); container.AutoRegisterImplementations(typeof(TContract));
@ -88,24 +85,30 @@ namespace NzbDrone
private static void AutoRegisterImplementations(this TinyIoCContainer container, Type contractType) private static void AutoRegisterImplementations(this TinyIoCContainer container, Type contractType)
{ {
var implementations = contractType.Assembly.GetImplementations(contractType).ToList(); var implementations = GetImplementations(contractType).ToList();
foreach(var implementation in implementations) if (implementations.Count == 0)
{ {
logger.Trace("Registering {0} as {1}", implementation.Name, contractType.Name); return;
container.Register(contractType, implementation).AsMultiInstance(); }
if (implementations.Count == 1)
{
container.Register(contractType, implementations.Single()).AsMultiInstance();
}
else
{
container.RegisterMultiple(contractType, implementations).AsMultiInstance();
} }
} }
private static void AutoRegisterMultipleImplementations<TContract>(this TinyIoCContainer container) private static IEnumerable<Type> GetImplementations(Type contractType)
{
container.AutoRegisterMultipleImplementations(typeof(TContract));
}
private static void AutoRegisterMultipleImplementations(this TinyIoCContainer container, Type contractType)
{ {
var implementations = contractType.Assembly.GetImplementations(contractType); return NzbDroneTypes
container.RegisterMultiple(contractType, implementations).AsMultiInstance(); .Where(implementation =>
contractType.IsAssignableFrom(implementation) &&
!implementation.IsInterface &&
!implementation.IsAbstract
);
} }
} }
} }

@ -117,7 +117,7 @@
<Compile Include="ApplicationServer.cs"> <Compile Include="ApplicationServer.cs">
<SubType>Component</SubType> <SubType>Component</SubType>
</Compile> </Compile>
<Compile Include="CommonContainerExtentions.cs" /> <Compile Include="ContainerBuilder.cs" />
<Compile Include="NzbDroneBootstrapper.cs" /> <Compile Include="NzbDroneBootstrapper.cs" />
<Compile Include="ApplicationMode.cs" /> <Compile Include="ApplicationMode.cs" />
<Compile Include="AppMain.cs" /> <Compile Include="AppMain.cs" />

Loading…
Cancel
Save