Start adding server support

This commit is contained in:
2025-09-24 21:08:59 -04:00
parent 9e2e7aabe8
commit 4e721efa55
47 changed files with 1652 additions and 266 deletions

View File

@@ -4,7 +4,7 @@ namespace FeedCenter.Options;
public partial class AboutOptionsPanel
{
public AboutOptionsPanel(Window parentWindow) : base(parentWindow)
public AboutOptionsPanel(Window parentWindow, FeedCenterEntities entities) : base(parentWindow, entities)
{
InitializeComponent();
}

View File

@@ -0,0 +1,24 @@
using System.Collections.Generic;
namespace FeedCenter.Options
{
public class AccountTypeItem
{
public AccountType AccountType { get; set; }
public string Name { get; set; }
public static List<AccountTypeItem> AccountTypes =>
[
new()
{
Name = Properties.Resources.AccountTypeFever,
AccountType = AccountType.Fever
},
//new()
//{
// Name = Properties.Resources.AccountTypeGoogleReader,
// AccountType = AccountType.GoogleReader
//}
];
}
}

View File

@@ -0,0 +1,22 @@
using System;
using System.Globalization;
using System.Linq;
using System.Windows.Data;
namespace FeedCenter.Options;
public class AccountTypeToNameConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is AccountType accountType)
return AccountTypeItem.AccountTypes.First(at => at.AccountType == accountType).Name;
return value;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}

View File

@@ -0,0 +1,139 @@
<Window x:Class="FeedCenter.Options.AccountWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:properties="clr-namespace:FeedCenter.Properties"
xmlns:feedCenter="clr-namespace:FeedCenter"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
d:DataContext="{d:DesignInstance Type=feedCenter:Account}"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:mah="http://metro.mahapps.com/winfx/xaml/controls"
xmlns:options="clr-namespace:FeedCenter.Options"
mc:Ignorable="d"
Title="AccountWindow"
Height="350"
Width="450"
WindowStartupLocation="CenterOwner"
Icon="/FeedCenter;component/Resources/Application.ico"
FocusManager.FocusedElement="{Binding ElementName=NameTextBox}">
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Controls.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Fonts.xaml" />
<ResourceDictionary
Source="pack://application:,,,/MahApps.Metro;component/Styles/Controls.FlatButton.xaml" />
<ResourceDictionary
Source="pack://application:,,,/MahApps.Metro;component/Styles/Themes/light.cobalt.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
<Grid Margin="6">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TabControl Name="OptionsTabControl"
Grid.Row="0"
Grid.Column="0"
mah:HeaderedControlHelper.HeaderFontSize="16"
mah:TabControlHelper.Underlined="SelectedTabItem">
<TabItem Header="{x:Static properties:Resources.generalTab}">
<StackPanel Margin="0,4"
options:Spacing.Vertical="8">
<ComboBox Name="AccountTypeComboBox"
mah:TextBoxHelper.UseFloatingWatermark="True"
mah:TextBoxHelper.Watermark="{x:Static properties:Resources.accountTypeLabel}"
DisplayMemberPath="Name"
ItemsSource="{Binding Source={x:Static options:AccountTypeItem.AccountTypes}}"
SelectedValuePath="AccountType"
SelectedValue="{Binding Path=Type, UpdateSourceTrigger=Explicit, ValidatesOnExceptions=true}" />
<TextBox Name="NameTextBox"
mah:TextBoxHelper.UseFloatingWatermark="True"
mah:TextBoxHelper.Watermark="{x:Static properties:Resources.accountNameLabel}"
mah:TextBoxHelper.SelectAllOnFocus="True"
Text="{Binding Path=Name, UpdateSourceTrigger=Explicit, ValidatesOnExceptions=True}" />
<TextBox Name="UrlTextBox"
mah:TextBoxHelper.UseFloatingWatermark="True"
mah:TextBoxHelper.Watermark="{x:Static properties:Resources.accountUrlLabel}"
mah:TextBoxHelper.SelectAllOnFocus="True"
Text="{Binding Path=Url, UpdateSourceTrigger=Explicit, ValidatesOnExceptions=True}" />
<CheckBox Name="ReadIntervalCheckBox"
VerticalContentAlignment="Center"
IsChecked="{Binding Path=Enabled, UpdateSourceTrigger=Explicit, ValidatesOnExceptions=True}">
<StackPanel Orientation="Horizontal">
<Label Content="{x:Static properties:Resources.accountReadIntervalPrefix}"
HorizontalAlignment="Left"
Margin="0,0,5,0"
VerticalAlignment="Center"
Padding="0" />
<mah:NumericUpDown Width="100"
Maximum="10080"
Minimum="1"
IsEnabled="{Binding ElementName=ReadIntervalCheckBox, Path=IsChecked}"
Value="{Binding CheckInterval, UpdateSourceTrigger=Explicit, ValidatesOnExceptions=True}" />
<Label Content="{x:Static properties:Resources.accountReadIntervalSuffix}"
HorizontalAlignment="Left"
Margin="5,0,0,0"
VerticalAlignment="Center"
Padding="0" />
</StackPanel>
</CheckBox>
</StackPanel>
</TabItem>
<TabItem Header="{x:Static properties:Resources.authenticationTab}">
<StackPanel Margin="0,4">
<CheckBox Content="{x:Static properties:Resources.accountRequiresAuthenticationCheckBox}"
Margin="0,0,0,4"
Name="RequiresAuthenticationCheckBox"
IsChecked="{Binding Path=Authenticate, UpdateSourceTrigger=Explicit, ValidatesOnExceptions=True}" />
<TextBox Name="AuthenticationUserNameTextBox"
Margin="25,0,0,4"
IsEnabled="{Binding ElementName=RequiresAuthenticationCheckBox, Path=IsChecked}"
mah:TextBoxHelper.UseFloatingWatermark="True"
mah:TextBoxHelper.Watermark="{x:Static properties:Resources.authenticationUserNameLabel}"
Text="{Binding Path=Username, UpdateSourceTrigger=Explicit, ValidatesOnExceptions=True}" />
<PasswordBox Name="AuthenticationPasswordTextBox"
Margin="25,0,0,8"
Style="{StaticResource MahApps.Styles.PasswordBox.Button.Revealed}"
mah:PasswordBoxBindingBehavior.Password="{Binding Password, UpdateSourceTrigger=Explicit, ValidatesOnDataErrors=True}"
mah:TextBoxHelper.UseFloatingWatermark="True"
mah:TextBoxHelper.Watermark="{x:Static properties:Resources.authenticationPasswordLabel}"
IsEnabled="{Binding ElementName=RequiresAuthenticationCheckBox, Path=IsChecked}" />
</StackPanel>
</TabItem>
</TabControl>
<Grid Name="AccountReadProgress"
Grid.Row="1"
Height="20"
Visibility="Collapsed">
<ProgressBar Name="AccountReadProgressBar" />
<TextBlock Text="Loading account..."
HorizontalAlignment="Center"
VerticalAlignment="Center" />
</Grid>
<StackPanel
Name="ButtonPanel"
Grid.Column="0"
Grid.Row="1"
Orientation="Horizontal"
Visibility="Visible"
Margin="0,5,0,0"
HorizontalAlignment="Right">
<Button Content="{x:Static properties:Resources.OkayButton}"
HorizontalAlignment="Right"
VerticalAlignment="Bottom"
Width="75"
Margin="0,0,5,0"
IsDefault="True"
Click="HandleOkayButtonClick" />
<Button Content="{x:Static properties:Resources.CancelButton}"
HorizontalAlignment="Right"
VerticalAlignment="Bottom"
Width="75"
IsCancel="True" />
</StackPanel>
</Grid>
</Window>

View File

@@ -0,0 +1,78 @@
using ChrisKaczor.Wpf.Validation;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Threading;
namespace FeedCenter.Options;
public partial class AccountWindow
{
private Account _account;
private bool _isNew;
private readonly FeedCenterEntities _entities;
public AccountWindow(FeedCenterEntities entities)
{
_entities = entities;
InitializeComponent();
}
public bool? Display(Account account, Window owner, bool isNew)
{
_account = account;
_isNew = isNew;
DataContext = account;
Title = isNew ? Properties.Resources.AccountWindowAdd : Properties.Resources.AccountWindowEdit;
Owner = owner;
return ShowDialog();
}
private void HandleOkayButtonClick(object sender, RoutedEventArgs e)
{
var transaction = _entities.BeginTransaction();
if (!this.IsValid(OptionsTabControl))
{
transaction.Rollback();
return;
}
if (_isNew)
{
_entities.Accounts.Add(_account);
}
transaction.Commit();
var accountId = _account.Id;
AccountReadProgressBar.Value = 0;
AccountReadProgressBar.Maximum = _account.GetProgressSteps(_entities) + 1;
AccountReadProgress.Visibility = Visibility.Visible;
ButtonPanel.Visibility = Visibility.Collapsed;
var dispatcher = Dispatcher.CurrentDispatcher;
Task.Run(() =>
{
var entities = new FeedCenterEntities();
var account = entities.Accounts.First(a => a.Id == accountId);
var accountReadInput = new AccountReadInput(entities, null, true, () => dispatcher.Invoke(() => AccountReadProgressBar.Value++));
account.Read(accountReadInput);
dispatcher.Invoke(() =>
{
DialogResult = true;
Close();
});
});
}
}

View File

@@ -0,0 +1,98 @@
<options:OptionsPanelBase x:Class="FeedCenter.Options.AccountsOptionsPanel"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:options="clr-namespace:FeedCenter.Options"
xmlns:properties="clr-namespace:FeedCenter.Properties"
xmlns:controls="clr-namespace:ChrisKaczor.Wpf.Controls;assembly=ChrisKaczor.Wpf.Controls.Link"
xmlns:feedCenter="clr-namespace:FeedCenter"
mc:Ignorable="d"
d:DesignHeight="311"
d:DesignWidth="425">
<options:OptionsPanelBase.Resources>
<ResourceDictionary>
<options:AccountTypeToNameConverter x:Key="AccountTypeToNameConverter" />
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Controls.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Fonts.xaml" />
<ResourceDictionary
Source="pack://application:,,,/MahApps.Metro;component/Styles/Controls.FlatButton.xaml" />
<ResourceDictionary
Source="pack://application:,,,/MahApps.Metro;component/Styles/Themes/light.cobalt.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</options:OptionsPanelBase.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<DataGrid Name="AccountDataGrid"
SelectionChanged="HandleAccountDataGridSelectionChanged"
Grid.Row="0"
SelectionMode="Single"
SelectionUnit="FullRow"
Grid.Column="0"
AutoGenerateColumns="False"
GridLinesVisibility="None"
CanUserResizeRows="False"
IsReadOnly="True"
HeadersVisibility="Column"
BorderThickness="1,1,1,1"
BorderBrush="{DynamicResource {x:Static SystemColors.ActiveBorderBrushKey}}"
AllowDrop="True"
Background="{x:Null}"
d:DataContext="{d:DesignInstance feedCenter:Account }">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Name}"
Header="{x:Static properties:Resources.AccountNameColumnHeader}"
SortDirection="Ascending"
Width="*" />
<DataGridTextColumn Binding="{Binding Type, Converter={StaticResource AccountTypeToNameConverter}}"
Header="{x:Static properties:Resources.AccountTypeColumnHeader}"
Width="*" />
</DataGrid.Columns>
<DataGrid.RowStyle>
<Style TargetType="DataGridRow"
BasedOn="{StaticResource MahApps.Styles.DataGridRow}">
<EventSetter Event="MouseDoubleClick"
Handler="HandleAccountDataGridRowMouseDoubleClick" />
</Style>
</DataGrid.RowStyle>
</DataGrid>
<Border Grid.Column="0"
Grid.Row="1"
BorderThickness="1,0,1,1"
BorderBrush="{DynamicResource {x:Static SystemColors.ActiveBorderBrushKey}}" />
<Border Grid.Row="1"
Grid.Column="0"
BorderThickness="1,0,1,1"
BorderBrush="{DynamicResource {x:Static SystemColors.ActiveBorderBrushKey}}">
<StackPanel Orientation="Horizontal"
Background="{DynamicResource {x:Static SystemColors.ControlBrushKey}}">
<controls:Link Name="AddAccountButton"
Margin="2"
Click="HandleAddAccountButtonClick"
Text="{x:Static properties:Resources.AddLink}"
ToolTip="{x:Static properties:Resources.AddAccountButton}">
</controls:Link>
<controls:Link Name="EditAccountButton"
Margin="2"
Click="HandleEditAccountButtonClick"
Text="{x:Static properties:Resources.EditLink}"
ToolTip="{x:Static properties:Resources.EditAccountButton}">
</controls:Link>
<controls:Link Name="DeleteAccountButton"
Margin="2"
Click="HandleDeleteAccountButtonClick"
Text="{x:Static properties:Resources.DeleteLink}"
ToolTip="{x:Static properties:Resources.DeleteAccountButton}">
</controls:Link>
</StackPanel>
</Border>
</Grid>
</options:OptionsPanelBase>

View File

@@ -0,0 +1,129 @@
using System.ComponentModel;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Input;
namespace FeedCenter.Options;
public partial class AccountsOptionsPanel
{
private readonly FeedCenterEntities _entities;
public AccountsOptionsPanel(Window parentWindow, FeedCenterEntities entities) : base(parentWindow, entities)
{
_entities = entities;
InitializeComponent();
}
public override string CategoryName => Properties.Resources.optionCategoryAccounts;
public override void LoadPanel()
{
base.LoadPanel();
var collectionViewSource = new CollectionViewSource { Source = _entities.Accounts };
collectionViewSource.SortDescriptions.Add(new SortDescription("Name", ListSortDirection.Ascending));
collectionViewSource.IsLiveSortingRequested = true;
collectionViewSource.View.Filter = item =>
{
if (item is not Account account)
return false;
// Filter out local accounts
return account.Type != AccountType.Local;
};
AccountDataGrid.ItemsSource = collectionViewSource.View;
AccountDataGrid.SelectedIndex = 0;
SetAccountButtonStates();
}
private void SetAccountButtonStates()
{
AddAccountButton.IsEnabled = true;
EditAccountButton.IsEnabled = AccountDataGrid.SelectedItem != null;
DeleteAccountButton.IsEnabled = AccountDataGrid.SelectedItem != null;
}
private void AddAccount()
{
var account = new Account(AccountType.Fever);
var accountWindow = new AccountWindow(_entities);
var result = accountWindow.Display(account, Window.GetWindow(this), true);
if (!result.HasValue || !result.Value)
return;
AccountDataGrid.SelectedItem = account;
SetAccountButtonStates();
}
private void EditSelectedAccount()
{
if (AccountDataGrid.SelectedItem == null)
return;
var account = (Account) AccountDataGrid.SelectedItem;
var accountWindow = new AccountWindow(_entities);
accountWindow.Display(account, Window.GetWindow(this), false);
}
private void DeleteSelectedAccount()
{
var account = (Account) AccountDataGrid.SelectedItem;
if (MessageBox.Show(ParentWindow, string.Format(Properties.Resources.ConfirmDeleteAccount, account.Name),
Properties.Resources.ConfirmDeleteTitle, MessageBoxButton.YesNo, MessageBoxImage.Question,
MessageBoxResult.No) == MessageBoxResult.No)
return;
var index = AccountDataGrid.SelectedIndex;
if (index == AccountDataGrid.Items.Count - 1)
AccountDataGrid.SelectedIndex = index - 1;
else
AccountDataGrid.SelectedIndex = index + 1;
_entities.SaveChanges(() => _entities.Accounts.Remove(account));
SetAccountButtonStates();
}
private void HandleAddAccountButtonClick(object sender, RoutedEventArgs e)
{
AddAccount();
}
private void HandleEditAccountButtonClick(object sender, RoutedEventArgs e)
{
EditSelectedAccount();
}
private void HandleDeleteAccountButtonClick(object sender, RoutedEventArgs e)
{
DeleteSelectedAccount();
}
private void HandleAccountDataGridSelectionChanged(object sender, SelectionChangedEventArgs e)
{
SetAccountButtonStates();
}
private void HandleAccountDataGridRowMouseDoubleClick(object sender, MouseButtonEventArgs e)
{
if (!EditAccountButton.IsEnabled)
return;
EditSelectedAccount();
}
}

View File

@@ -1,5 +1,4 @@
using FeedCenter.Data;
using System.Collections.Generic;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Windows;
@@ -12,9 +11,12 @@ public partial class BulkFeedWindow
{
private List<CheckedListItem<Feed>> _checkedListBoxItems;
private CollectionViewSource _collectionViewSource;
private readonly FeedCenterEntities _entities;
public BulkFeedWindow()
public BulkFeedWindow(FeedCenterEntities entities)
{
_entities = entities;
InitializeComponent();
}
@@ -22,7 +24,7 @@ public partial class BulkFeedWindow
{
_checkedListBoxItems = new List<CheckedListItem<Feed>>();
foreach (var feed in Database.Entities.Feeds)
foreach (var feed in _entities.Feeds)
_checkedListBoxItems.Add(new CheckedListItem<Feed> { Item = feed });
_collectionViewSource = new CollectionViewSource { Source = _checkedListBoxItems };
@@ -52,7 +54,7 @@ public partial class BulkFeedWindow
private void HandleOkButtonClick(object sender, RoutedEventArgs e)
{
Database.Entities.SaveChanges(() =>
_entities.SaveChanges(() =>
{
foreach (var item in _checkedListBoxItems.Where(i => i.IsChecked))
{

View File

@@ -24,14 +24,17 @@
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Controls.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Fonts.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Controls.FlatButton.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Themes/light.cobalt.xaml" />
<ResourceDictionary
Source="pack://application:,,,/MahApps.Metro;component/Styles/Controls.FlatButton.xaml" />
<ResourceDictionary
Source="pack://application:,,,/MahApps.Metro;component/Styles/Themes/light.cobalt.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
<StackPanel Margin="6"
options:Spacing.Vertical="5">
<TextBox mah:TextBoxHelper.UseFloatingWatermark="True"
<TextBox Name="NameTextBox"
mah:TextBoxHelper.UseFloatingWatermark="True"
mah:TextBoxHelper.Watermark="{x:Static properties:Resources.categoryNameLabel}"
mah:TextBoxHelper.SelectAllOnFocus="True"
Text="{Binding Path=Name, UpdateSourceTrigger=Explicit, ValidatesOnExceptions=True}" />

View File

@@ -1,13 +1,16 @@
using System.Windows;
using ChrisKaczor.Wpf.Validation;
using FeedCenter.Data;
using ChrisKaczor.Wpf.Validation;
using System.Windows;
namespace FeedCenter.Options;
public partial class CategoryWindow
{
public CategoryWindow()
private readonly FeedCenterEntities _entities;
public CategoryWindow(FeedCenterEntities entities)
{
_entities = entities;
InitializeComponent();
}
@@ -30,7 +33,7 @@ public partial class CategoryWindow
private void HandleOkayButtonClick(object sender, RoutedEventArgs e)
{
var transaction = Database.Entities.BeginTransaction();
var transaction = _entities.BeginTransaction();
if (!this.IsValid())
{
@@ -39,7 +42,6 @@ public partial class CategoryWindow
}
transaction.Commit();
Database.Entities.Refresh();
// Dialog is good
DialogResult = true;

View File

@@ -5,7 +5,7 @@ namespace FeedCenter.Options;
public partial class DisplayOptionsPanel
{
public DisplayOptionsPanel(Window parentWindow) : base(parentWindow)
public DisplayOptionsPanel(Window parentWindow, FeedCenterEntities entities) : base(parentWindow, entities)
{
InitializeComponent();
}

View File

@@ -1,19 +1,22 @@
using ChrisKaczor.Wpf.Validation;
using FeedCenter.Data;
using System.Windows;
namespace FeedCenter.Options;
public partial class FeedWindow
{
public FeedWindow()
private readonly FeedCenterEntities _entities;
public FeedWindow(FeedCenterEntities entities)
{
_entities = entities;
InitializeComponent();
}
public bool? Display(Feed feed, Window owner)
{
CategoryComboBox.ItemsSource = Database.Entities.Categories;
CategoryComboBox.ItemsSource = _entities.Categories;
DataContext = feed;
@@ -26,7 +29,7 @@ public partial class FeedWindow
private void HandleOkayButtonClick(object sender, RoutedEventArgs e)
{
var transaction = Database.Entities.BeginTransaction();
var transaction = _entities.BeginTransaction();
if (!this.IsValid(OptionsTabControl))
{
@@ -35,7 +38,6 @@ public partial class FeedWindow
}
transaction.Commit();
Database.Entities.Refresh();
DialogResult = true;

View File

@@ -1,5 +1,4 @@
using FeedCenter.Data;
using Microsoft.Win32;
using Microsoft.Win32;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
@@ -14,9 +13,12 @@ namespace FeedCenter.Options;
public partial class FeedsOptionsPanel
{
private CollectionViewSource _collectionViewSource;
private readonly FeedCenterEntities _entities;
public FeedsOptionsPanel(Window parentWindow) : base(parentWindow)
public FeedsOptionsPanel(Window parentWindow, FeedCenterEntities entities) : base(parentWindow, entities)
{
_entities = entities;
InitializeComponent();
}
@@ -26,7 +28,7 @@ public partial class FeedsOptionsPanel
{
base.LoadPanel();
var collectionViewSource = new CollectionViewSource { Source = Database.Entities.Categories };
var collectionViewSource = new CollectionViewSource { Source = _entities.Categories };
collectionViewSource.SortDescriptions.Add(new SortDescription("SortKey", ListSortDirection.Ascending));
collectionViewSource.SortDescriptions.Add(new SortDescription("Name", ListSortDirection.Ascending));
collectionViewSource.IsLiveSortingRequested = true;
@@ -44,20 +46,20 @@ public partial class FeedsOptionsPanel
private void AddFeed()
{
var feed = Feed.Create();
var feed = Feed.Create(_entities);
var category = (Category) CategoryDataGrid.SelectedItem;
feed.CategoryId = category.Id;
var feedWindow = new FeedWindow();
var feedWindow = new FeedWindow(_entities);
var result = feedWindow.Display(feed, Window.GetWindow(this));
if (!result.HasValue || !result.Value)
return;
Database.Entities.SaveChanges(() => Database.Entities.Feeds.Add(feed));
_entities.SaveChanges(() => _entities.Feeds.Add(feed));
FeedDataGrid.SelectedItem = feed;
@@ -71,7 +73,7 @@ public partial class FeedsOptionsPanel
var feed = (Feed) FeedDataGrid.SelectedItem;
var feedWindow = new FeedWindow();
var feedWindow = new FeedWindow(_entities);
feedWindow.Display(feed, Window.GetWindow(this));
}
@@ -86,7 +88,7 @@ public partial class FeedsOptionsPanel
FeedDataGrid.SelectedItems.CopyTo(selectedItems, 0);
foreach (var feed in selectedItems)
Database.Entities.SaveChanges(() => Database.Entities.Feeds.Remove(feed));
_entities.SaveChanges(() => _entities.Feeds.Remove(feed));
SetFeedButtonStates();
}
@@ -116,7 +118,7 @@ public partial class FeedsOptionsPanel
ExportFeeds();
}
private static void ExportFeeds()
private void ExportFeeds()
{
var saveFileDialog = new SaveFileDialog
{
@@ -143,7 +145,7 @@ public partial class FeedsOptionsPanel
xmlWriter.WriteStartElement("opml");
xmlWriter.WriteStartElement("body");
foreach (var feed in Database.Entities.Feeds.OrderBy(feed => feed.Name))
foreach (var feed in _entities.Feeds.OrderBy(feed => feed.Name))
{
xmlWriter.WriteStartElement("outline");
@@ -162,7 +164,7 @@ public partial class FeedsOptionsPanel
xmlWriter.Close();
}
private static void ImportFeeds()
private void ImportFeeds()
{
var openFileDialog = new OpenFileDialog
{
@@ -188,8 +190,7 @@ public partial class FeedsOptionsPanel
while (xmlReader.NodeType != XmlNodeType.EndElement)
{
var feed = Feed.Create();
feed.CategoryId = Database.Entities.Categories.First(c => c.IsDefault).Id;
var feed = Feed.Create(_entities);
while (xmlReader.MoveToNextAttribute())
{
@@ -218,7 +219,7 @@ public partial class FeedsOptionsPanel
if (string.IsNullOrEmpty(feed.Name))
feed.Name = feed.Title;
Database.Entities.Feeds.Add(feed);
_entities.SaveChanges(() => _entities.Feeds.Add(feed));
xmlReader.MoveToElement();
@@ -242,23 +243,23 @@ public partial class FeedsOptionsPanel
var selectedId = ((Category) CategoryDataGrid.SelectedItem).Id;
EditCategoryButton.IsEnabled = CategoryDataGrid.SelectedItem != null &&
selectedId != Database.Entities.DefaultCategory.Id;
selectedId != _entities.DefaultCategory.Id;
DeleteCategoryButton.IsEnabled = CategoryDataGrid.SelectedItem != null &&
selectedId != Database.Entities.DefaultCategory.Id;
selectedId != _entities.DefaultCategory.Id;
}
private void AddCategory()
{
var category = new Category();
var categoryWindow = new CategoryWindow();
var categoryWindow = new CategoryWindow(_entities);
var result = categoryWindow.Display(category, Window.GetWindow(this));
if (!result.HasValue || !result.Value)
return;
Database.Entities.SaveChanges(() => Database.Entities.Categories.Add(category));
_entities.SaveChanges(() => _entities.Categories.Add(category));
CategoryDataGrid.SelectedItem = category;
@@ -272,7 +273,7 @@ public partial class FeedsOptionsPanel
var category = (Category) CategoryDataGrid.SelectedItem;
var categoryWindow = new CategoryWindow();
var categoryWindow = new CategoryWindow(_entities);
categoryWindow.Display(category, Window.GetWindow(this));
}
@@ -284,10 +285,10 @@ public partial class FeedsOptionsPanel
if (MessageBox.Show(ParentWindow, string.Format(Properties.Resources.ConfirmDeleteCategory, category.Name), Properties.Resources.ConfirmDeleteTitle, MessageBoxButton.YesNo, MessageBoxImage.Question, MessageBoxResult.No) == MessageBoxResult.No)
return;
var defaultCategory = Database.Entities.DefaultCategory;
var defaultCategory = _entities.DefaultCategory;
foreach (var feed in Database.Entities.Feeds.Where(f => f.CategoryId == category.Id))
Database.Entities.SaveChanges(() => feed.CategoryId = defaultCategory.Id);
foreach (var feed in _entities.Feeds.Where(f => f.CategoryId == category.Id))
_entities.SaveChanges(() => feed.CategoryId = defaultCategory.Id);
var index = CategoryDataGrid.SelectedIndex;
@@ -296,7 +297,7 @@ public partial class FeedsOptionsPanel
else
CategoryDataGrid.SelectedIndex = index + 1;
Database.Entities.SaveChanges(() => Database.Entities.Categories.Remove(category));
_entities.SaveChanges(() => _entities.Categories.Remove(category));
SetCategoryButtonStates();
}
@@ -320,7 +321,7 @@ public partial class FeedsOptionsPanel
{
if (_collectionViewSource == null)
{
_collectionViewSource = new CollectionViewSource { Source = Database.Entities.Feeds };
_collectionViewSource = new CollectionViewSource { Source = _entities.Feeds };
_collectionViewSource.SortDescriptions.Add(new SortDescription("Name", ListSortDirection.Ascending));
_collectionViewSource.Filter += HandleCollectionViewSourceFilter;
@@ -342,7 +343,7 @@ public partial class FeedsOptionsPanel
var feed = (Feed) e.Item;
e.Accepted = feed.CategoryId == selectedCategory.Id;
e.Accepted = feed.CategoryId == selectedCategory.Id && feed.Account.Type == AccountType.Local;
}
private void HandleCategoryDataGridRowDrop(object sender, DragEventArgs e)
@@ -352,7 +353,7 @@ public partial class FeedsOptionsPanel
var category = (Category) ((DataGridRow) sender).Item;
foreach (var feed in feedList!)
Database.Entities.SaveChanges(() => feed.CategoryId = category.Id);
_entities.SaveChanges(() => feed.CategoryId = category.Id);
_collectionViewSource.View.Refresh();
@@ -382,7 +383,7 @@ public partial class FeedsOptionsPanel
private void HandleMultipleEditClick(object sender, RoutedEventArgs e)
{
var bulkFeedWindow = new BulkFeedWindow();
var bulkFeedWindow = new BulkFeedWindow(_entities);
bulkFeedWindow.Display(Window.GetWindow(this));
}

View File

@@ -6,7 +6,7 @@ namespace FeedCenter.Options;
public partial class GeneralOptionsPanel
{
public GeneralOptionsPanel(Window parentWindow) : base(parentWindow)
public GeneralOptionsPanel(Window parentWindow, FeedCenterEntities entities) : base(parentWindow, entities)
{
InitializeComponent();
}

View File

@@ -6,10 +6,12 @@ namespace FeedCenter.Options;
public class OptionsPanelBase : UserControl
{
protected readonly Window ParentWindow;
protected readonly FeedCenterEntities Entities;
protected OptionsPanelBase(Window parentWindow)
protected OptionsPanelBase(Window parentWindow, FeedCenterEntities entities)
{
ParentWindow = parentWindow;
Entities = entities;
}
public virtual string CategoryName => null;

View File

@@ -6,6 +6,7 @@ namespace FeedCenter.Options;
public partial class OptionsWindow
{
private readonly List<OptionsPanelBase> _optionPanels = new();
private readonly FeedCenterEntities _entities = new();
public OptionsWindow()
{
@@ -20,11 +21,12 @@ public partial class OptionsWindow
private void AddCategories()
{
_optionPanels.Add(new GeneralOptionsPanel(this));
_optionPanels.Add(new DisplayOptionsPanel(this));
_optionPanels.Add(new FeedsOptionsPanel(this));
_optionPanels.Add(new UpdateOptionsPanel(this));
_optionPanels.Add(new AboutOptionsPanel(this));
_optionPanels.Add(new GeneralOptionsPanel(this, _entities));
_optionPanels.Add(new DisplayOptionsPanel(this, _entities));
_optionPanels.Add(new FeedsOptionsPanel(this, _entities));
_optionPanels.Add(new AccountsOptionsPanel(this, _entities));
_optionPanels.Add(new UpdateOptionsPanel(this, _entities));
_optionPanels.Add(new AboutOptionsPanel(this, _entities));
}
private void LoadCategories()

View File

@@ -6,7 +6,7 @@ namespace FeedCenter.Options;
public partial class UpdateOptionsPanel
{
public UpdateOptionsPanel(Window parentWindow) : base(parentWindow)
public UpdateOptionsPanel(Window parentWindow, FeedCenterEntities entities) : base(parentWindow, entities)
{
InitializeComponent();
}