Rework database loading/migration

This commit is contained in:
2023-04-06 17:20:38 -04:00
parent b5f570688d
commit 6514f23329
21 changed files with 561 additions and 569 deletions

View File

@@ -44,9 +44,11 @@ namespace FeedCenter
using (isolationHandle) using (isolationHandle)
{ {
// Set the path // Set the path
LegacyDatabase.DatabasePath = SystemConfiguration.DataDirectory;
LegacyDatabase.DatabaseFile = Path.Combine(SystemConfiguration.DataDirectory, Settings.Default.DatabaseFile_Legacy);
Database.DatabasePath = SystemConfiguration.DataDirectory; Database.DatabasePath = SystemConfiguration.DataDirectory;
Database.DatabaseFile = Path.Combine(SystemConfiguration.DataDirectory, Settings.Default.DatabaseFile); Database.DatabaseFile = Path.Combine(SystemConfiguration.DataDirectory, Settings.Default.DatabaseFile);
Database.Load();
// Get the generic provider // Get the generic provider
var genericProvider = (GenericSettingsProvider) Settings.Default.Providers[nameof(GenericSettingsProvider)]; var genericProvider = (GenericSettingsProvider) Settings.Default.Providers[nameof(GenericSettingsProvider)];

View File

@@ -1,218 +1,25 @@
using FeedCenter.Properties; using System.IO;
using Serilog;
using System;
using System.Collections.Generic;
using System.Data.SqlServerCe;
using System.IO;
using System.Linq;
namespace FeedCenter.Data namespace FeedCenter.Data
{ {
public static class Database public static class Database
{ {
#region Static database settings public static string DatabaseFile { get; set; }
public static string DatabasePath { get; set; }
public static string DatabaseFile; public static FeedCenterEntities Entities { get; set; }
public static string DatabasePath;
#endregion public static bool Exists => File.Exists(DatabaseFile);
#region File version public static bool Loaded { get; set; }
public static FeedCenterEntities Entities;
private enum SqlServerCeFileVersion
{
Unknown,
Version20,
Version30,
Version35,
Version40,
}
public static void Load() public static void Load()
{ {
if (Loaded) return;
Entities = new FeedCenterEntities(); Entities = new FeedCenterEntities();
}
private static SqlServerCeFileVersion GetFileVersion(string databasePath) Loaded = true;
{
// Create a mapping of version numbers to the version enumeration
var versionMapping = new Dictionary<int, SqlServerCeFileVersion>
{
{ 0x73616261, SqlServerCeFileVersion.Version20 },
{ 0x002dd714, SqlServerCeFileVersion.Version30 },
{ 0x00357b9d, SqlServerCeFileVersion.Version35 },
{ 0x003d0900, SqlServerCeFileVersion.Version40 }
};
int signature;
try
{
// Open the database file
using var stream = new FileStream(databasePath, FileMode.Open, FileAccess.Read);
// Read the file using the binary reader
var reader = new BinaryReader(stream);
// Seek to the version signature
stream.Seek(16, SeekOrigin.Begin);
// Read the version signature
signature = reader.ReadInt32();
}
catch (Exception exception)
{
Log.Logger.Error(exception, "Exception");
throw;
}
// If we know about the version number then return the right enumeration - otherwise unknown
return versionMapping.ContainsKey(signature) ? versionMapping[signature] : SqlServerCeFileVersion.Unknown;
}
#endregion
public static bool DatabaseExists => File.Exists(DatabaseFile);
public static void CreateDatabase()
{
Log.Logger.Information("Creating database engine");
// Create the database engine
using var engine = new SqlCeEngine($"Data Source={DatabaseFile}");
Log.Logger.Information("Creating database");
// Create the database itself
engine.CreateDatabase();
Log.Logger.Information("Running database script");
// Run the creation script
ExecuteScript(Resources.CreateDatabase);
}
private static int GetVersion(SqlCeConnection connection)
{
string versionString;
try
{
// Check the database version table
using var command = new SqlCeCommand("SELECT Value FROM DatabaseVersion", connection);
versionString = command.ExecuteScalar().ToString();
}
catch (SqlCeException)
{
// Check the setting table for the version
using var command = new SqlCeCommand("SELECT Value FROM Setting WHERE Name = 'DatabaseVersion'", connection);
versionString = command.ExecuteScalar().ToString();
}
if (string.IsNullOrEmpty(versionString))
versionString = "0";
Log.Logger.Information("Database version: {0}", versionString);
return int.Parse(versionString);
}
public static void UpdateDatabase()
{
Log.Logger.Information("Getting database file version");
// Get the database file version
var fileVersion = GetFileVersion(DatabaseFile);
Log.Logger.Information("Database file version: {0}", fileVersion);
// See if we need to upgrade the database file version
if (fileVersion != SqlServerCeFileVersion.Version40)
{
Log.Logger.Information("Creating database engine");
// Create the database engine
using var engine = new SqlCeEngine($"Data Source={DatabaseFile}");
Log.Logger.Information("Upgrading database");
// Upgrade the database (if needed)
engine.Upgrade();
}
Log.Logger.Information("Getting database version");
// Create a database connection
using var connection = new SqlCeConnection($"Data Source={DatabaseFile}");
// Open the connection
connection.Open();
// Get the database version
var databaseVersion = GetVersion(connection);
// Create a dictionary of database upgrade scripts and their version numbers
var scriptList = new Dictionary<int, string>();
// Loop over the properties of the resource object looking for update scripts
foreach (var property in typeof(Resources).GetProperties().Where(property => property.Name.StartsWith("DatabaseUpdate")))
{
// Get the name of the property
var propertyName = property.Name;
// Extract the version from the name
var version = int.Parse(propertyName.Substring(propertyName.IndexOf("_", StringComparison.Ordinal) + 1));
// Add to the script list
scriptList[version] = propertyName;
}
// Loop over the scripts ordered by version
foreach (var pair in scriptList.OrderBy(pair => pair.Key))
{
// If the database version is less than or equal to the script version the script needs to run
if (databaseVersion <= pair.Key)
{
// Get the script text
var scriptText = Resources.ResourceManager.GetString(pair.Value);
// Run the script
ExecuteScript(scriptText);
}
}
}
public static void MaintainDatabase()
{
Log.Logger.Information("Creating database engine");
// Create the database engine
using var engine = new SqlCeEngine($"Data Source={DatabaseFile}");
Log.Logger.Information("Shrinking database");
// Compact the database
engine.Shrink();
}
private static void ExecuteScript(string scriptText)
{
// Create a database connection
using var connection = new SqlCeConnection($"Data Source={DatabaseFile}");
// Open the connection
connection.Open();
// Setup the delimiters
var delimiters = new[] { "\r\nGO\r\n" };
// Split the script at the delimiters
var statements = scriptText.Split(delimiters, StringSplitOptions.RemoveEmptyEntries);
// Loop over each statement in the script
foreach (var statement in statements)
{
// Execute the statement
using var command = new SqlCeCommand(statement, connection);
command.ExecuteNonQuery();
}
} }
} }
} }

View File

@@ -1,13 +0,0 @@
using System.Data.SqlTypes;
namespace FeedCenter.Data
{
public static class Extensions
{
#region SqlDateTime
public static SqlDateTime SqlDateTimeZero = new SqlDateTime(0, 0);
#endregion
}
}

View File

@@ -0,0 +1,234 @@
using Dapper;
using FeedCenter.Options;
using FeedCenter.Properties;
using Realms;
using Serilog;
using System;
using System.Collections.Generic;
using System.Data.SqlServerCe;
using System.IO;
using System.Linq;
namespace FeedCenter.Data;
public static class LegacyDatabase
{
public static string DatabaseFile { get; set; }
public static string DatabasePath { get; set; }
private enum SqlServerCeFileVersion
{
Unknown,
Version20,
Version30,
Version35,
Version40,
}
private static SqlServerCeFileVersion GetFileVersion(string databasePath)
{
// Create a mapping of version numbers to the version enumeration
var versionMapping = new Dictionary<int, SqlServerCeFileVersion>
{
{ 0x73616261, SqlServerCeFileVersion.Version20 },
{ 0x002dd714, SqlServerCeFileVersion.Version30 },
{ 0x00357b9d, SqlServerCeFileVersion.Version35 },
{ 0x003d0900, SqlServerCeFileVersion.Version40 }
};
int signature;
try
{
// Open the database file
using var stream = new FileStream(databasePath, FileMode.Open, FileAccess.Read);
// Read the file using the binary reader
var reader = new BinaryReader(stream);
// Seek to the version signature
stream.Seek(16, SeekOrigin.Begin);
// Read the version signature
signature = reader.ReadInt32();
}
catch (Exception exception)
{
Log.Logger.Error(exception, "Exception");
throw;
}
// If we know about the version number then return the right enumeration - otherwise unknown
return versionMapping.TryGetValue(signature, out var value) ? value : SqlServerCeFileVersion.Unknown;
}
public static bool Exists => File.Exists(DatabaseFile);
private static int GetVersion(SqlCeConnection connection)
{
string versionString;
try
{
// Check the database version table
using var command = new SqlCeCommand("SELECT Value FROM DatabaseVersion", connection);
versionString = command.ExecuteScalar().ToString();
}
catch (SqlCeException)
{
// Check the setting table for the version
using var command = new SqlCeCommand("SELECT Value FROM Setting WHERE Name = 'DatabaseVersion'", connection);
versionString = command.ExecuteScalar().ToString();
}
if (string.IsNullOrEmpty(versionString))
versionString = "0";
Log.Logger.Information("Database version: {0}", versionString);
return int.Parse(versionString);
}
public static void UpdateDatabase()
{
Log.Logger.Information("Getting database file version");
// Get the database file version
var fileVersion = GetFileVersion(DatabaseFile);
Log.Logger.Information("Database file version: {0}", fileVersion);
// See if we need to upgrade the database file version
if (fileVersion != SqlServerCeFileVersion.Version40)
{
Log.Logger.Information("Creating database engine");
// Create the database engine
using var engine = new SqlCeEngine($"Data Source={DatabaseFile}");
Log.Logger.Information("Upgrading database");
// Upgrade the database (if needed)
engine.Upgrade();
}
Log.Logger.Information("Getting database version");
// Create a database connection
using var connection = new SqlCeConnection($"Data Source={DatabaseFile}");
// Open the connection
connection.Open();
// Get the database version
var databaseVersion = GetVersion(connection);
// Create a dictionary of database upgrade scripts and their version numbers
var scriptList = new Dictionary<int, string>();
// Loop over the properties of the resource object looking for update scripts
foreach (var property in typeof(Resources).GetProperties().Where(property => property.Name.StartsWith("DatabaseUpdate")))
{
// Get the name of the property
var propertyName = property.Name;
// Extract the version from the name
var version = int.Parse(propertyName[(propertyName.IndexOf("_", StringComparison.Ordinal) + 1)..]);
// Add to the script list
scriptList[version] = propertyName;
}
// Loop over the scripts ordered by version
foreach (var pair in scriptList.OrderBy(pair => pair.Key))
{
// If the database version is beyond this script then we can skip it
if (databaseVersion > pair.Key) continue;
// Get the script text
var scriptText = Resources.ResourceManager.GetString(pair.Value);
// Run the script
ExecuteScript(scriptText);
}
}
public static void MaintainDatabase()
{
Log.Logger.Information("Creating database engine");
// Create the database engine
using var engine = new SqlCeEngine($"Data Source={DatabaseFile}");
Log.Logger.Information("Shrinking database");
// Compact the database
engine.Shrink();
}
public static void MigrateDatabase()
{
var realmConfiguration = new RealmConfiguration($"{Database.DatabaseFile}");
var realm = Realm.GetInstance(realmConfiguration);
if (!File.Exists(DatabaseFile))
return;
using var connection = new SqlCeConnection($"Data Source={DatabaseFile}");
connection.Open();
var settings = connection.Query<Setting>("SELECT * FROM Setting").OrderBy(s => s.Version).ToList();
var categories = connection.Query<Category>("SELECT * FROM Category").ToList();
var feeds = connection.Query<Feed>("SELECT * FROM Feed").ToList();
var feedItems = connection.Query<FeedItem>("SELECT * FROM FeedItem").ToList();
realm.Write(() =>
{
foreach (var category in categories)
{
category.Feeds = feeds.Where(f => f.CategoryId == category.Id).ToList();
}
foreach (var feed in feeds)
{
feed.Category = categories.FirstOrDefault(c => c.Id == feed.CategoryId);
}
foreach (var feedItem in feedItems)
{
var feed = feeds.First(f => f.Id == feedItem.FeedId);
feed.Items.Add(feedItem);
}
realm.Add(feeds);
realm.Add(categories);
realm.Add(settings, true);
});
connection.Close();
File.Move(DatabaseFile, DatabaseFile + "_bak");
}
private static void ExecuteScript(string scriptText)
{
// Create a database connection
using var connection = new SqlCeConnection($"Data Source={DatabaseFile}");
// Open the connection
connection.Open();
// Setup the delimiters
var delimiters = new[] { "\r\nGO\r\n" };
// Split the script at the delimiters
var statements = scriptText.Split(delimiters, StringSplitOptions.RemoveEmptyEntries);
// Loop over each statement in the script
foreach (var statement in statements)
{
// Execute the statement
using var command = new SqlCeCommand(statement, connection);
command.ExecuteNonQuery();
}
}
}

View File

@@ -1,10 +1,7 @@
using Dapper; using FeedCenter.Data;
using FeedCenter.Data;
using FeedCenter.Options; using FeedCenter.Options;
using Realms; using Realms;
using System; using System;
using System.Data.SqlServerCe;
using System.IO;
using System.Linq; using System.Linq;
namespace FeedCenter namespace FeedCenter
@@ -19,60 +16,10 @@ namespace FeedCenter
public FeedCenterEntities() public FeedCenterEntities()
{ {
Load(); var realmConfiguration = new RealmConfiguration($"{Database.DatabaseFile}");
}
public void Refresh()
{
Realm.Refresh();
}
public void Load()
{
var realmConfiguration = new RealmConfiguration($"{Database.DatabasePath}/FeedCenter.realm");
Realm = Realm.GetInstance(realmConfiguration); Realm = Realm.GetInstance(realmConfiguration);
if (File.Exists(Database.DatabaseFile))
{
using var connection = new SqlCeConnection($"Data Source={Database.DatabaseFile}");
connection.Open();
var settings = connection.Query<Setting>("SELECT * FROM Setting").OrderBy(s => s.Version).ToList();
var categories = connection.Query<Category>("SELECT * FROM Category").ToList();
var feeds = connection.Query<Feed>("SELECT * FROM Feed").ToList();
var feedItems = connection.Query<FeedItem>("SELECT * FROM FeedItem").ToList();
Realm.Write(() =>
{
foreach (var category in categories)
{
category.Feeds = feeds.Where(f => f.CategoryId == category.Id).ToList();
}
foreach (var feed in feeds)
{
feed.Category = categories.FirstOrDefault(c => c.Id == feed.CategoryId);
}
foreach (var feedItem in feedItems)
{
var feed = feeds.First(f => f.Id == feedItem.FeedId);
feed.Items.Add(feedItem);
}
Realm.Add(feeds);
Realm.Add(categories);
Realm.Add(settings, true);
});
connection.Close();
File.Move(Database.DatabaseFile, Database.DatabaseFile + "_bak");
}
Settings = new RealmObservableCollection<Setting>(Realm); Settings = new RealmObservableCollection<Setting>(Realm);
Feeds = new RealmObservableCollection<Feed>(Realm); Feeds = new RealmObservableCollection<Feed>(Realm);
Categories = new RealmObservableCollection<Category>(Realm); Categories = new RealmObservableCollection<Category>(Realm);
@@ -83,6 +30,11 @@ namespace FeedCenter
} }
} }
public void Refresh()
{
Realm.Refresh();
}
public void SaveChanges(Action action) public void SaveChanges(Action action)
{ {
Realm.Write(action); Realm.Write(action);

View File

@@ -157,12 +157,23 @@
<Compile Remove="SqlSettingsProvider.cs" /> <Compile Remove="SqlSettingsProvider.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Update="Properties\Resources.Designer.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<Compile Update="Properties\Settings.Designer.cs"> <Compile Update="Properties\Settings.Designer.cs">
<DesignTimeSharedInput>True</DesignTimeSharedInput> <DesignTimeSharedInput>True</DesignTimeSharedInput>
<AutoGen>True</AutoGen> <AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon> <DependentUpon>Settings.settings</DependentUpon>
</Compile> </Compile>
</ItemGroup> </ItemGroup>
<ItemGroup>
<EmbeddedResource Update="Properties\Resources.resx">
<Generator>PublicResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
</ItemGroup>
<ItemGroup> <ItemGroup>
<None Update="Properties\Settings.settings"> <None Update="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator> <Generator>SettingsSingleFileGenerator</Generator>

View File

@@ -108,13 +108,14 @@ namespace FeedCenter
Close(); Close();
} }
private async void HandleRefreshCurrentButtonClick(object sender, RoutedEventArgs e) private void HandleRefreshCurrentButtonClick(object sender, RoutedEventArgs e)
{ {
IsEnabled = false; IsEnabled = false;
Mouse.OverrideCursor = Cursors.Wait; Mouse.OverrideCursor = Cursors.Wait;
var feed = (Feed) FeedDataGrid.SelectedItem; var feed = (Feed) FeedDataGrid.SelectedItem;
await feed.ReadAsync(_database, true);
_database.SaveChanges(() => feed.Read(_database, true));
var selectedIndex = FeedDataGrid.SelectedIndex; var selectedIndex = FeedDataGrid.SelectedIndex;

View File

@@ -72,8 +72,8 @@ namespace FeedCenter
public string Link { get; set; } public string Link { get; set; }
public string Description { get; set; } public string Description { get; set; }
public DateTimeOffset LastChecked { get; set; } public DateTimeOffset LastChecked { get; set; }
public int CheckInterval { get; set; } public int CheckInterval { get; set; } = 60;
public bool Enabled { get; set; } public bool Enabled { get; set; } = true;
public bool Authenticate { get; set; } public bool Authenticate { get; set; }
public string Username { get; set; } public string Username { get; set; }
public string Password { get; set; } public string Password { get; set; }
@@ -164,7 +164,7 @@ namespace FeedCenter
} }
// If the feed was successfully read and we have no last update timestamp - set the last update timestamp to now // If the feed was successfully read and we have no last update timestamp - set the last update timestamp to now
if (result == FeedReadResult.Success && LastUpdated == Extensions.SqlDateTimeZero.Value) if (result == FeedReadResult.Success && LastUpdated == default)
LastUpdated = DateTimeOffset.Now; LastUpdated = DateTimeOffset.Now;
Log.Logger.Information("Done reading feed: {0}", result); Log.Logger.Information("Done reading feed: {0}", result);
@@ -172,11 +172,6 @@ namespace FeedCenter
return result; return result;
} }
public async Task<FeedReadResult> ReadAsync(FeedCenterEntities database, bool forceRead = false)
{
return await Task.Run(() => Read(database, forceRead));
}
public Tuple<FeedType, string> DetectFeedType() public Tuple<FeedType, string> DetectFeedType()
{ {
var retrieveResult = RetrieveFeed(); var retrieveResult = RetrieveFeed();

View File

@@ -23,7 +23,6 @@ namespace FeedCenter
var feed = Feed.Create(_database); var feed = Feed.Create(_database);
feed.Source = feedUrl; feed.Source = feedUrl;
feed.Category = _database.DefaultCategory; feed.Category = _database.DefaultCategory;
feed.Enabled = true;
// Try to detect the feed type // Try to detect the feed type
var feedTypeResult = feed.DetectFeedType(); var feedTypeResult = feed.DetectFeedType();

View File

@@ -15,8 +15,23 @@ namespace FeedCenter
private class FeedReadWorkerInput private class FeedReadWorkerInput
{ {
public bool ForceRead; public bool ForceRead { get; }
public Feed Feed; public Guid? FeedId { get; }
public FeedReadWorkerInput()
{
}
public FeedReadWorkerInput(bool forceRead)
{
ForceRead = forceRead;
}
public FeedReadWorkerInput(bool forceRead, Guid? feedId)
{
ForceRead = forceRead;
FeedId = feedId;
}
} }
private void SetProgressMode(bool value, int feedCount) private void SetProgressMode(bool value, int feedCount)
@@ -48,7 +63,7 @@ namespace FeedCenter
SetProgressMode(true, 1); SetProgressMode(true, 1);
// Create the input class // Create the input class
var workerInput = new FeedReadWorkerInput { ForceRead = forceRead, Feed = _currentFeed }; var workerInput = new FeedReadWorkerInput(forceRead, _currentFeed.Id);
// Start the worker // Start the worker
_feedReadWorker.RunWorkerAsync(workerInput); _feedReadWorker.RunWorkerAsync(workerInput);
@@ -68,7 +83,7 @@ namespace FeedCenter
SetProgressMode(true, _database.Feeds.Count); SetProgressMode(true, _database.Feeds.Count);
// Create the input class // Create the input class
var workerInput = new FeedReadWorkerInput { ForceRead = forceRead, Feed = null }; var workerInput = new FeedReadWorkerInput(forceRead);
// Start the worker // Start the worker
_feedReadWorker.RunWorkerAsync(workerInput); _feedReadWorker.RunWorkerAsync(workerInput);
@@ -126,7 +141,7 @@ namespace FeedCenter
var worker = (BackgroundWorker) sender; var worker = (BackgroundWorker) sender;
// Get the input information // Get the input information
var workerInput = (FeedReadWorkerInput) e.Argument ?? new FeedReadWorkerInput { Feed = null, ForceRead = false }; var workerInput = (FeedReadWorkerInput) e.Argument ?? new FeedReadWorkerInput();
// Setup for progress // Setup for progress
var currentProgress = 0; var currentProgress = 0;
@@ -135,8 +150,8 @@ namespace FeedCenter
var feedsToRead = new List<Feed>(); var feedsToRead = new List<Feed>();
// If we have a single feed then add it to the list - otherwise add them all // If we have a single feed then add it to the list - otherwise add them all
if (workerInput.Feed != null) if (workerInput.FeedId != null)
feedsToRead.Add(database.Feeds.First(feed => feed.Id == workerInput.Feed.Id)); feedsToRead.Add(database.Feeds.First(feed => feed.Id == workerInput.FeedId));
else else
feedsToRead.AddRange(database.Feeds); feedsToRead.AddRange(database.Feeds);

View File

@@ -29,7 +29,7 @@ namespace FeedCenter.Options
private void HandleOkayButtonClick(object sender, RoutedEventArgs e) private void HandleOkayButtonClick(object sender, RoutedEventArgs e)
{ {
if (!this.Validate()) if (!this.IsValid())
return; return;
// Dialog is good // Dialog is good

View File

@@ -54,8 +54,6 @@ namespace FeedCenter.Options
var expressions = this.GetBindingExpressions(new[] { UpdateSourceTrigger.Explicit }); var expressions = this.GetBindingExpressions(new[] { UpdateSourceTrigger.Explicit });
this.UpdateAllSources(expressions); this.UpdateAllSources(expressions);
this.Validate();
} }
public override string CategoryName => Properties.Resources.optionCategoryGeneral; public override string CategoryName => Properties.Resources.optionCategoryGeneral;
@@ -106,22 +104,22 @@ namespace FeedCenter.Options
{ {
var userAgents = new List<UserAgentItem> var userAgents = new List<UserAgentItem>
{ {
new UserAgentItem new()
{ {
Caption = Properties.Resources.DefaultUserAgentCaption, Caption = Properties.Resources.DefaultUserAgentCaption,
UserAgent = string.Empty UserAgent = string.Empty
}, },
new UserAgentItem new()
{ {
Caption = "Windows RSS Platform 2.0", Caption = "Windows RSS Platform 2.0",
UserAgent = "Windows-RSS-Platform/2.0 (MSIE 9.0; Windows NT 6.1)" UserAgent = "Windows-RSS-Platform/2.0 (MSIE 9.0; Windows NT 6.1)"
}, },
new UserAgentItem new()
{ {
Caption = "Feedly 1.0", Caption = "Feedly 1.0",
UserAgent = "Feedly/1.0" UserAgent = "Feedly/1.0"
}, },
new UserAgentItem new()
{ {
Caption = "curl", Caption = "curl",
UserAgent = "curl/7.47.0" UserAgent = "curl/7.47.0"

View File

@@ -9,7 +9,7 @@ namespace FeedCenter.Options
{ {
#region Member variables #region Member variables
private readonly List<OptionsPanelBase> _optionPanels = new List<OptionsPanelBase>(); private readonly List<OptionsPanelBase> _optionPanels = new();
private readonly FeedCenterEntities _database = Database.Entities; private readonly FeedCenterEntities _database = Database.Entities;

View File

@@ -1,10 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
This file is automatically generated by Visual Studio .Net. It is
used to store generic object data source configuration information.
Renaming the file extension or editing the content of this file may
cause the file to be unrecognizable by the program.
-->
<GenericObjectDataSource DisplayName="FeedCenterEntities" Identifier="FeedCenter.FeedCenterEntities" ProviderType="Microsoft.VisualStudio.DataDesign.DataSourceProviders.EntityDataModel.EdmDataSourceProvider" Version="1.0" xmlns="urn:schemas-microsoft-com:xml-msdatasource">
<TypeInfo>FeedCenter.FeedCenterEntities, Model.Designer.cs, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null</TypeInfo>
</GenericObjectDataSource>

View File

@@ -1298,11 +1298,11 @@ namespace FeedCenter.Properties {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Checking database existence.... /// Looks up a localized string similar to Checking for legacy database....
/// </summary> /// </summary>
public static string SplashCheckingForDatabase { public static string SplashCheckingForLegacyDatabase {
get { get {
return ResourceManager.GetString("SplashCheckingForDatabase", resourceCulture); return ResourceManager.GetString("SplashCheckingForLegacyDatabase", resourceCulture);
} }
} }
@@ -1343,11 +1343,29 @@ namespace FeedCenter.Properties {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Maintaining database.... /// Looks up a localized string similar to Loading database....
/// </summary> /// </summary>
public static string SplashMaintainingDatabase { public static string SplashLoadingDatabase {
get { get {
return ResourceManager.GetString("SplashMaintainingDatabase", resourceCulture); return ResourceManager.GetString("SplashLoadingDatabase", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Maintaining legacy database....
/// </summary>
public static string SplashMaintainingLegacyDatabase {
get {
return ResourceManager.GetString("SplashMaintainingLegacyDatabase", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Migrating legacy database....
/// </summary>
public static string SplashMigratingLegacyDatabase {
get {
return ResourceManager.GetString("SplashMigratingLegacyDatabase", resourceCulture);
} }
} }
@@ -1370,11 +1388,11 @@ namespace FeedCenter.Properties {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Updating database.... /// Looks up a localized string similar to Updating legacy database....
/// </summary> /// </summary>
public static string SplashUpdatingDatabase { public static string SplashUpdatingLegacyDatabase {
get { get {
return ResourceManager.GetString("SplashUpdatingDatabase", resourceCulture); return ResourceManager.GetString("SplashUpdatingLegacyDatabase", resourceCulture);
} }
} }

View File

@@ -154,8 +154,8 @@
<data name="SplashCheckingForUpdate" xml:space="preserve"> <data name="SplashCheckingForUpdate" xml:space="preserve">
<value>Checking for update...</value> <value>Checking for update...</value>
</data> </data>
<data name="SplashCheckingForDatabase" xml:space="preserve"> <data name="SplashCheckingForLegacyDatabase" xml:space="preserve">
<value>Checking database existence...</value> <value>Checking for legacy database...</value>
</data> </data>
<data name="SplashCreatingDatabase" xml:space="preserve"> <data name="SplashCreatingDatabase" xml:space="preserve">
<value>Creating database...</value> <value>Creating database...</value>
@@ -169,11 +169,11 @@
<data name="SplashDownloadingUpdate" xml:space="preserve"> <data name="SplashDownloadingUpdate" xml:space="preserve">
<value>Downloading update...</value> <value>Downloading update...</value>
</data> </data>
<data name="SplashMaintainingDatabase" xml:space="preserve"> <data name="SplashMaintainingLegacyDatabase" xml:space="preserve">
<value>Maintaining database...</value> <value>Maintaining legacy database...</value>
</data> </data>
<data name="SplashUpdatingDatabase" xml:space="preserve"> <data name="SplashUpdatingLegacyDatabase" xml:space="preserve">
<value>Updating database...</value> <value>Updating legacy database...</value>
</data> </data>
<data name="SplashStarting" xml:space="preserve"> <data name="SplashStarting" xml:space="preserve">
<value>Starting...</value> <value>Starting...</value>
@@ -529,4 +529,10 @@
<data name="defaultUserAgentLabel" xml:space="preserve"> <data name="defaultUserAgentLabel" xml:space="preserve">
<value>Default _user agent:</value> <value>Default _user agent:</value>
</data> </data>
<data name="SplashLoadingDatabase" xml:space="preserve">
<value>Loading database...</value>
</data>
<data name="SplashMigratingLegacyDatabase" xml:space="preserve">
<value>Migrating legacy database...</value>
</data>
</root> </root>

View File

@@ -74,9 +74,9 @@ namespace FeedCenter.Properties {
[global::System.Configuration.ApplicationScopedSettingAttribute()] [global::System.Configuration.ApplicationScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("FeedCenter.sdf")] [global::System.Configuration.DefaultSettingValueAttribute("FeedCenter.sdf")]
public string DatabaseFile { public string DatabaseFile_Legacy {
get { get {
return ((string)(this["DatabaseFile"])); return ((string)(this["DatabaseFile_Legacy"]));
} }
} }
@@ -293,5 +293,14 @@ namespace FeedCenter.Properties {
this["DefaultUserAgent"] = value; this["DefaultUserAgent"] = value;
} }
} }
[global::System.Configuration.ApplicationScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("FeedCenter.realm")]
public string DatabaseFile {
get {
return ((string)(this["DatabaseFile"]));
}
}
} }
} }

View File

@@ -2,19 +2,19 @@
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)" GeneratedClassNamespace="FeedCenter.Properties" GeneratedClassName="Settings"> <SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)" GeneratedClassNamespace="FeedCenter.Properties" GeneratedClassName="Settings">
<Profiles /> <Profiles />
<Settings> <Settings>
<Setting Name="WindowLocked" Provider="Common.Settings.GenericSettingsProvider" Type="System.Boolean" Scope="User"> <Setting Name="WindowLocked" Provider="CKaczor.GenericSettingsProvider.GenericSettingsProvider" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">False</Value> <Value Profile="(Default)">False</Value>
</Setting> </Setting>
<Setting Name="WindowSize" Provider="Common.Settings.GenericSettingsProvider" Type="System.Windows.Size" Scope="User"> <Setting Name="WindowSize" Provider="CKaczor.GenericSettingsProvider.GenericSettingsProvider" Type="System.Windows.Size" Scope="User">
<Value Profile="(Default)">0,0</Value> <Value Profile="(Default)">0,0</Value>
</Setting> </Setting>
<Setting Name="WindowLocation" Provider="Common.Settings.GenericSettingsProvider" Type="System.Windows.Point" Scope="User"> <Setting Name="WindowLocation" Provider="CKaczor.GenericSettingsProvider.GenericSettingsProvider" Type="System.Windows.Point" Scope="User">
<Value Profile="(Default)">0,0</Value> <Value Profile="(Default)">0,0</Value>
</Setting> </Setting>
<Setting Name="LogDatabase" Type="System.Boolean" Scope="Application"> <Setting Name="LogDatabase" Type="System.Boolean" Scope="Application">
<Value Profile="(Default)">True</Value> <Value Profile="(Default)">True</Value>
</Setting> </Setting>
<Setting Name="DatabaseFile" Type="System.String" Scope="Application"> <Setting Name="DatabaseFile_Legacy" Type="System.String" Scope="Application">
<Value Profile="(Default)">FeedCenter.sdf</Value> <Value Profile="(Default)">FeedCenter.sdf</Value>
</Setting> </Setting>
<Setting Name="ProgressSleepInterval" Type="System.Int32" Scope="Application"> <Setting Name="ProgressSleepInterval" Type="System.Int32" Scope="Application">
@@ -26,40 +26,40 @@
<Setting Name="BalloonTipTimeout" Type="System.Int32" Scope="Application"> <Setting Name="BalloonTipTimeout" Type="System.Int32" Scope="Application">
<Value Profile="(Default)">5000</Value> <Value Profile="(Default)">5000</Value>
</Setting> </Setting>
<Setting Name="FeedScrollInterval" Provider="Common.Settings.GenericSettingsProvider" Type="System.TimeSpan" Scope="User"> <Setting Name="FeedScrollInterval" Provider="CKaczor.GenericSettingsProvider.GenericSettingsProvider" Type="System.TimeSpan" Scope="User">
<Value Profile="(Default)">00:01:00</Value> <Value Profile="(Default)">00:01:00</Value>
</Setting> </Setting>
<Setting Name="FeedCheckInterval" Provider="Common.Settings.GenericSettingsProvider" Type="System.TimeSpan" Scope="User"> <Setting Name="FeedCheckInterval" Provider="CKaczor.GenericSettingsProvider.GenericSettingsProvider" Type="System.TimeSpan" Scope="User">
<Value Profile="(Default)">00:30:00</Value> <Value Profile="(Default)">00:30:00</Value>
</Setting> </Setting>
<Setting Name="DisplayEmptyFeeds" Provider="Common.Settings.GenericSettingsProvider" Type="System.Boolean" Scope="User"> <Setting Name="DisplayEmptyFeeds" Provider="CKaczor.GenericSettingsProvider.GenericSettingsProvider" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">True</Value> <Value Profile="(Default)">True</Value>
</Setting> </Setting>
<Setting Name="LastVersionCheck" Provider="Common.Settings.GenericSettingsProvider" Type="System.DateTime" Scope="User"> <Setting Name="LastVersionCheck" Provider="CKaczor.GenericSettingsProvider.GenericSettingsProvider" Type="System.DateTime" Scope="User">
<Value Profile="(Default)" /> <Value Profile="(Default)" />
</Setting> </Setting>
<Setting Name="VersionCheckInterval" Type="System.TimeSpan" Scope="Application"> <Setting Name="VersionCheckInterval" Type="System.TimeSpan" Scope="Application">
<Value Profile="(Default)">01:00:00</Value> <Value Profile="(Default)">01:00:00</Value>
</Setting> </Setting>
<Setting Name="StartWithWindows" Provider="Common.Settings.GenericSettingsProvider" Type="System.Boolean" Scope="User"> <Setting Name="StartWithWindows" Provider="CKaczor.GenericSettingsProvider.GenericSettingsProvider" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">False</Value> <Value Profile="(Default)">False</Value>
</Setting> </Setting>
<Setting Name="FirstRun" Type="System.Boolean" Scope="User"> <Setting Name="FirstRun" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">True</Value> <Value Profile="(Default)">True</Value>
</Setting> </Setting>
<Setting Name="ToolbarLocation" Provider="Common.Settings.GenericSettingsProvider" Type="System.Windows.Controls.Dock" Scope="User"> <Setting Name="ToolbarLocation" Provider="CKaczor.GenericSettingsProvider.GenericSettingsProvider" Type="System.Windows.Controls.Dock" Scope="User">
<Value Profile="(Default)">Bottom</Value> <Value Profile="(Default)">Bottom</Value>
</Setting> </Setting>
<Setting Name="OpenAllSleepInterval" Provider="Common.Settings.GenericSettingsProvider" Type="System.Int32" Scope="User"> <Setting Name="OpenAllSleepInterval" Provider="CKaczor.GenericSettingsProvider.GenericSettingsProvider" Type="System.Int32" Scope="User">
<Value Profile="(Default)">500</Value> <Value Profile="(Default)">500</Value>
</Setting> </Setting>
<Setting Name="Browser" Provider="Common.Settings.GenericSettingsProvider" Type="System.String" Scope="User"> <Setting Name="Browser" Provider="CKaczor.GenericSettingsProvider.GenericSettingsProvider" Type="System.String" Scope="User">
<Value Profile="(Default)" /> <Value Profile="(Default)" />
</Setting> </Setting>
<Setting Name="OpenAllSleepIntervalFirst" Provider="Common.Settings.GenericSettingsProvider" Type="System.Int32" Scope="User"> <Setting Name="OpenAllSleepIntervalFirst" Provider="CKaczor.GenericSettingsProvider.GenericSettingsProvider" Type="System.Int32" Scope="User">
<Value Profile="(Default)">1500</Value> <Value Profile="(Default)">1500</Value>
</Setting> </Setting>
<Setting Name="MultipleLineDisplay" Provider="Common.Settings.GenericSettingsProvider" Type="FeedCenter.Options.MultipleLineDisplay" Scope="User"> <Setting Name="MultipleLineDisplay" Provider="CKaczor.GenericSettingsProvider.GenericSettingsProvider" Type="FeedCenter.Options.MultipleLineDisplay" Scope="User">
<Value Profile="(Default)">Normal</Value> <Value Profile="(Default)">Normal</Value>
</Setting> </Setting>
<Setting Name="VersionLocation" Type="System.String" Scope="Application"> <Setting Name="VersionLocation" Type="System.String" Scope="Application">
@@ -68,8 +68,11 @@
<Setting Name="LastCategoryID" Type="System.String" Scope="User"> <Setting Name="LastCategoryID" Type="System.String" Scope="User">
<Value Profile="(Default)" /> <Value Profile="(Default)" />
</Setting> </Setting>
<Setting Name="DefaultUserAgent" Provider="Common.Settings.GenericSettingsProvider" Type="System.String" Scope="User"> <Setting Name="DefaultUserAgent" Provider="CKaczor.GenericSettingsProvider.GenericSettingsProvider" Type="System.String" Scope="User">
<Value Profile="(Default)" /> <Value Profile="(Default)" />
</Setting> </Setting>
<Setting Name="DatabaseFile" Type="System.String" Scope="Application">
<Value Profile="(Default)">FeedCenter.realm</Value>
</Setting>
</Settings> </Settings>
</SettingsFile> </SettingsFile>

View File

@@ -10,6 +10,11 @@ namespace FeedCenter
{ {
public static object OpenDataStore() public static object OpenDataStore()
{ {
if (!Database.Exists)
return null;
Database.Load();
return Database.Entities; return Database.Entities;
} }

View File

@@ -7,12 +7,10 @@ using System.ComponentModel;
using System.Threading; using System.Threading;
using System.Windows.Threading; using System.Windows.Threading;
namespace FeedCenter namespace FeedCenter;
{
public partial class SplashWindow : IDisposable
{
#region Progress step
public partial class SplashWindow : IDisposable
{
private class ProgressStep private class ProgressStep
{ {
public delegate bool ProgressCallback(); public delegate bool ProgressCallback();
@@ -29,18 +27,10 @@ namespace FeedCenter
} }
} }
#endregion
#region Member variables
private readonly List<ProgressStep> _progressSteps = new(); private readonly List<ProgressStep> _progressSteps = new();
private readonly Dispatcher _dispatcher; private readonly Dispatcher _dispatcher;
private readonly BackgroundWorker _backgroundWorker; private readonly BackgroundWorker _backgroundWorker;
#endregion
#region Constructor
public SplashWindow() public SplashWindow()
{ {
InitializeComponent(); InitializeComponent();
@@ -48,46 +38,28 @@ namespace FeedCenter
// Store the dispatcher - the background worker has trouble getting the right thread when called from Main // Store the dispatcher - the background worker has trouble getting the right thread when called from Main
_dispatcher = Dispatcher.CurrentDispatcher; _dispatcher = Dispatcher.CurrentDispatcher;
// Get the version to display VersionLabel.Content = string.Format(Properties.Resources.Version, UpdateCheck.LocalVersion.ToString());
var version = UpdateCheck.LocalVersion.ToString();
// Show the version
VersionLabel.Content = string.Format(Properties.Resources.Version, version);
// Set the starting caption
StatusLabel.Content = Properties.Resources.SplashStarting; StatusLabel.Content = Properties.Resources.SplashStarting;
// Build the progress steps
LoadProgressSteps(); LoadProgressSteps();
// Set the progress bar to the number of steps
ProgressBar.Maximum = _progressSteps.Count; ProgressBar.Maximum = _progressSteps.Count;
// Create the worker with progress and cancel
_backgroundWorker = new BackgroundWorker { WorkerReportsProgress = true, WorkerSupportsCancellation = true }; _backgroundWorker = new BackgroundWorker { WorkerReportsProgress = true, WorkerSupportsCancellation = true };
// Setup the events
_backgroundWorker.DoWork += HandleBackgroundWorkerDoWork; _backgroundWorker.DoWork += HandleBackgroundWorkerDoWork;
_backgroundWorker.ProgressChanged += HandleBackgroundWorkerProgressChanged; _backgroundWorker.ProgressChanged += HandleBackgroundWorkerProgressChanged;
_backgroundWorker.RunWorkerCompleted += HandleBackgroundWorkerCompleted; _backgroundWorker.RunWorkerCompleted += HandleBackgroundWorkerCompleted;
} }
#endregion
#region Form overrides
protected override void OnContentRendered(EventArgs e) protected override void OnContentRendered(EventArgs e)
{ {
base.OnContentRendered(e); base.OnContentRendered(e);
// Start the worker
_backgroundWorker.RunWorkerAsync(); _backgroundWorker.RunWorkerAsync();
} }
#endregion
#region Background worker
private void HandleBackgroundWorkerProgressChanged(object sender, ProgressChangedEventArgs e) private void HandleBackgroundWorkerProgressChanged(object sender, ProgressChangedEventArgs e)
{ {
if (!_dispatcher.CheckAccess()) if (!_dispatcher.CheckAccess())
@@ -96,7 +68,6 @@ namespace FeedCenter
return; return;
} }
// Update the progress bar
ProgressBar.Value += e.ProgressPercentage; ProgressBar.Value += e.ProgressPercentage;
// Get the message // Get the message
@@ -132,7 +103,7 @@ namespace FeedCenter
var result = progressStep.Callback(); var result = progressStep.Callback();
// If the step indicated a skip then set the skip key, otherwise clear it // If the step indicated a skip then set the skip key, otherwise clear it
skipKey = (result ? string.Empty : progressStep.Key); skipKey = result ? string.Empty : progressStep.Key;
} }
// Stop if cancelled // Stop if cancelled
@@ -162,67 +133,65 @@ namespace FeedCenter
// Move the progress bar to the max just in case // Move the progress bar to the max just in case
ProgressBar.Value = ProgressBar.Maximum; ProgressBar.Value = ProgressBar.Maximum;
// Close the window
Close(); Close();
} }
#endregion
#region Progress steps
private static class ProgressKey private static class ProgressKey
{ {
public const string DatabaseCreate = "CreateDatabase"; public const string ManageLegacyDatabase = "ManageLegacyDatabase";
public const string DatabaseUpdate = "UpdateDatabase"; public const string ManageDatabase = "ManageDatabase";
public const string DatabaseMaintenance = "MaintainDatabase";
} }
private void LoadProgressSteps() private void LoadProgressSteps()
{ {
// Load the progress steps _progressSteps.Add(new ProgressStep(ProgressKey.ManageLegacyDatabase, Properties.Resources.SplashCheckingForLegacyDatabase, CheckDatabase));
_progressSteps.Add(new ProgressStep(ProgressKey.DatabaseCreate, Properties.Resources.SplashCheckingForDatabase, CheckDatabase)); _progressSteps.Add(new ProgressStep(ProgressKey.ManageLegacyDatabase, Properties.Resources.SplashUpdatingLegacyDatabase, UpdateDatabase));
_progressSteps.Add(new ProgressStep(ProgressKey.DatabaseCreate, Properties.Resources.SplashCreatingDatabase, CreateDatabase)); _progressSteps.Add(new ProgressStep(ProgressKey.ManageLegacyDatabase, Properties.Resources.SplashMaintainingLegacyDatabase, MaintainDatabase));
_progressSteps.Add(new ProgressStep(ProgressKey.ManageLegacyDatabase, Properties.Resources.SplashMigratingLegacyDatabase, MigrateDatabase));
_progressSteps.Add(new ProgressStep(ProgressKey.DatabaseUpdate, Properties.Resources.SplashUpdatingDatabase, UpdateDatabase)); _progressSteps.Add(new ProgressStep(ProgressKey.ManageDatabase, Properties.Resources.SplashLoadingDatabase, LoadDatabase));
_progressSteps.Add(new ProgressStep(ProgressKey.DatabaseMaintenance, Properties.Resources.SplashMaintainingDatabase, MaintainDatabase));
} }
private static bool CheckDatabase() private static bool CheckDatabase()
{ {
// If the database exists then we're done return LegacyDatabase.Exists;
return !Database.DatabaseExists;
}
private static bool CreateDatabase()
{
// Create the database
//Database.CreateDatabase();
return true;
} }
private static bool UpdateDatabase() private static bool UpdateDatabase()
{ {
// Update the database LegacyDatabase.UpdateDatabase();
// Database.UpdateDatabase();
return true; return true;
} }
private static bool MaintainDatabase() private static bool MaintainDatabase()
{ {
// Maintain the database LegacyDatabase.MaintainDatabase();
//Database.MaintainDatabase();
return true; return true;
} }
#endregion private static bool MigrateDatabase()
{
LegacyDatabase.MigrateDatabase();
return true;
}
private bool LoadDatabase()
{
_dispatcher.Invoke(() =>
{
Database.Load();
Settings.Default.Reload();
});
return true;
}
public void Dispose() public void Dispose()
{ {
_backgroundWorker?.Dispose(); _backgroundWorker?.Dispose();
} }
}
} }

View File

@@ -13,12 +13,6 @@
<setting name="WindowLocked" serializeAs="String"> <setting name="WindowLocked" serializeAs="String">
<value>False</value> <value>False</value>
</setting> </setting>
<setting name="WindowSize" serializeAs="String">
<value>0,0</value>
</setting>
<setting name="WindowLocation" serializeAs="String">
<value>0,0</value>
</setting>
<setting name="CheckVersionAtStartup" serializeAs="String"> <setting name="CheckVersionAtStartup" serializeAs="String">
<value>True</value> <value>True</value>
</setting> </setting>
@@ -32,7 +26,7 @@
<value>True</value> <value>True</value>
</setting> </setting>
<setting name="LastVersionCheck" serializeAs="String"> <setting name="LastVersionCheck" serializeAs="String">
<value/> <value />
</setting> </setting>
<setting name="StartWithWindows" serializeAs="String"> <setting name="StartWithWindows" serializeAs="String">
<value>False</value> <value>False</value>
@@ -40,26 +34,20 @@
<setting name="FirstRun" serializeAs="String"> <setting name="FirstRun" serializeAs="String">
<value>True</value> <value>True</value>
</setting> </setting>
<setting name="ToolbarLocation" serializeAs="String">
<value>Bottom</value>
</setting>
<setting name="OpenAllSleepInterval" serializeAs="String"> <setting name="OpenAllSleepInterval" serializeAs="String">
<value>500</value> <value>500</value>
</setting> </setting>
<setting name="Browser" serializeAs="String"> <setting name="Browser" serializeAs="String">
<value/> <value />
</setting> </setting>
<setting name="OpenAllSleepIntervalFirst" serializeAs="String"> <setting name="OpenAllSleepIntervalFirst" serializeAs="String">
<value>1500</value> <value>1500</value>
</setting> </setting>
<setting name="MultipleLineDisplay" serializeAs="String">
<value>Normal</value>
</setting>
<setting name="LastCategoryID" serializeAs="String"> <setting name="LastCategoryID" serializeAs="String">
<value/> <value />
</setting> </setting>
<setting name="DefaultUserAgent" serializeAs="String"> <setting name="DefaultUserAgent" serializeAs="String">
<value/> <value />
</setting> </setting>
</FeedCenter.Properties.Settings> </FeedCenter.Properties.Settings>
</userSettings> </userSettings>
@@ -68,7 +56,7 @@
<setting name="LogDatabase" serializeAs="String"> <setting name="LogDatabase" serializeAs="String">
<value>True</value> <value>True</value>
</setting> </setting>
<setting name="DatabaseFile" serializeAs="String"> <setting name="DatabaseFile_Legacy" serializeAs="String">
<value>FeedCenter.sdf</value> <value>FeedCenter.sdf</value>
</setting> </setting>
<setting name="ProgressSleepInterval" serializeAs="String"> <setting name="ProgressSleepInterval" serializeAs="String">
@@ -83,6 +71,9 @@
<setting name="VersionLocation" serializeAs="String"> <setting name="VersionLocation" serializeAs="String">
<value>https://api.github.com/repos/ckaczor/FeedCenter/releases/latest</value> <value>https://api.github.com/repos/ckaczor/FeedCenter/releases/latest</value>
</setting> </setting>
<setting name="DatabaseFile" serializeAs="String">
<value>FeedCenter.realm</value>
</setting>
</FeedCenter.Properties.Settings> </FeedCenter.Properties.Settings>
</applicationSettings> </applicationSettings>
</configuration> </configuration>