diff --git a/src/Monbsoft.Feeader.Avalonia/Models/FeedContext.cs b/src/Monbsoft.Feeader.Avalonia/Models/FeedContext.cs new file mode 100644 index 0000000..701068e --- /dev/null +++ b/src/Monbsoft.Feeader.Avalonia/Models/FeedContext.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Monbsoft.Feeader.Avalonia.Models +{ + public class FeedContext + { + public FeedContext(IEnumerable feeds) + { + Feeds = feeds.ToList(); + } + + public List Feeds { get; } + } +} diff --git a/src/Monbsoft.Feeader.Avalonia/Monbsoft.Feeader.Avalonia.csproj b/src/Monbsoft.Feeader.Avalonia/Monbsoft.Feeader.Avalonia.csproj index 6c25e31..2c71bc2 100644 --- a/src/Monbsoft.Feeader.Avalonia/Monbsoft.Feeader.Avalonia.csproj +++ b/src/Monbsoft.Feeader.Avalonia/Monbsoft.Feeader.Avalonia.csproj @@ -29,4 +29,9 @@ + + + ChangeFeedView.axaml + + diff --git a/src/Monbsoft.Feeader.Avalonia/ViewModels/AddFeedViewModel.cs b/src/Monbsoft.Feeader.Avalonia/ViewModels/AddFeedViewModel.cs deleted file mode 100644 index 679b7bd..0000000 --- a/src/Monbsoft.Feeader.Avalonia/ViewModels/AddFeedViewModel.cs +++ /dev/null @@ -1,61 +0,0 @@ -using Monbsoft.Feeader.Avalonia.Models; -using Monbsoft.Feeader.Avalonia.Services; -using NLog.Fluent; -using ReactiveUI; -using System; -using System.Linq; -using System.Reactive; -using System.Reactive.Linq; - -namespace Monbsoft.Feeader.Avalonia.ViewModels -{ - public class AddFeedViewModel : ViewModelBase - { - private string? _name; - private string? _url; - - public AddFeedViewModel() - { - this.WhenAnyValue(x => x.Url) - .Where(x => !string.IsNullOrWhiteSpace(x)) - .Throttle(TimeSpan.FromMilliseconds(400)) - .ObserveOn(RxApp.MainThreadScheduler) - .Subscribe(DoSearch); - - AddCommand = ReactiveCommand.Create(() => - { - - return new Feed(Name, Url); - }); - - } - - - public ReactiveCommand AddCommand { get; } - - public string? Name - { - get => _name; - set => this.RaiseAndSetIfChanged(ref _name, value); - } - - public string? Url - { - get => _url; - set => this.RaiseAndSetIfChanged(ref _url, value); - } - - private async void DoSearch(string url) - { - try - { - var feed = await FeedService.GetFeedDataAsync(url); - Name = feed.Name; - } - catch(Exception ex) - { - Log.Error(ex.Message); - } - } - } -} \ No newline at end of file diff --git a/src/Monbsoft.Feeader.Avalonia/ViewModels/ArticleViewModel.cs b/src/Monbsoft.Feeader.Avalonia/ViewModels/ArticleViewModel.cs index b5864f0..3a053df 100644 --- a/src/Monbsoft.Feeader.Avalonia/ViewModels/ArticleViewModel.cs +++ b/src/Monbsoft.Feeader.Avalonia/ViewModels/ArticleViewModel.cs @@ -11,8 +11,9 @@ namespace Monbsoft.Feeader.Avalonia.ViewModels { public class ArticleViewModel : ViewModelBase { - private Uri? _pictureUri; private Bitmap? _picture; + private Uri? _pictureUri; + private Feed? _selectedFeed; public ArticleViewModel(Article article) { @@ -54,7 +55,7 @@ public async Task LoadPictureAsync(CancellationToken cancellationToken) if (_pictureUri != null) { Picture = await PictureService.LoadPictureBitmapAsync(_pictureUri, cancellationToken); - } + } } } } diff --git a/src/Monbsoft.Feeader.Avalonia/ViewModels/ChangeFeedViewModel.cs b/src/Monbsoft.Feeader.Avalonia/ViewModels/ChangeFeedViewModel.cs new file mode 100644 index 0000000..fd282da --- /dev/null +++ b/src/Monbsoft.Feeader.Avalonia/ViewModels/ChangeFeedViewModel.cs @@ -0,0 +1,110 @@ +using Monbsoft.Feeader.Avalonia.Models; +using Monbsoft.Feeader.Avalonia.Services; +using NLog.Fluent; +using ReactiveUI; +using System; +using System.Collections.ObjectModel; +using System.Linq; +using System.Reactive; +using System.Reactive.Linq; + +namespace Monbsoft.Feeader.Avalonia.ViewModels +{ + public class ChangeFeedViewModel : ViewModelBase + { + private FeedContext _context; + private string _name; + private string _url; + private Feed? _selectedFeed; + private FeedState _state; + + public ChangeFeedViewModel(FeedContext context) + { + this.WhenAnyValue(x => x.Url) + .Where(x => !string.IsNullOrWhiteSpace(x)) + .Throttle(TimeSpan.FromMilliseconds(400)) + .ObserveOn(RxApp.MainThreadScheduler) + .Subscribe(DoSearch); + + this.WhenAnyValue(x => x.SelectedFeed) + .ObserveOn(RxApp.MainThreadScheduler) + .Subscribe(f => + { + Name = f?.Name; + Url = f?.Link; + _state = f != null ? FeedState.Change : FeedState.Add; + }); + + Feeds = new ObservableCollection(context.Feeds); + _state = FeedState.Add; + _context = context; + + AddCommand = ReactiveCommand.Create(() => + { + if(_state == FeedState.Change && _selectedFeed != null) + { + _context.Feeds.Remove(_selectedFeed); + } + _context.Feeds.Add(new Feed(Name!, Url!)); + return _context; + }); + + } + + /// + /// A + /// + public ReactiveCommand AddCommand { get; } + /// + /// Gets the feeds + /// + public ObservableCollection Feeds { get; } + /// + /// Gets the name of the feed + /// + public string? Name + { + get => _name; + set => this.RaiseAndSetIfChanged(ref _name, value); + } + /// + /// Gets or sets the selected feed + /// + public Feed? SelectedFeed + { + get => _selectedFeed; + set => this.RaiseAndSetIfChanged(ref _selectedFeed, value); + } + /// + /// Gets the url of the feed + /// + public string? Url + { + get => _url; + set => this.RaiseAndSetIfChanged(ref _url, value); + } + + private async void DoSearch(string? url) + { + try + { + if (!string.IsNullOrEmpty(url)) + { + var feed = await FeedService.GetFeedDataAsync(url); + Name = feed.Name; + } + } + catch(Exception ex) + { + Log.Error(ex.Message); + } + } + + enum FeedState + { + Add = 0, + Change = 1 + } + + } +} \ No newline at end of file diff --git a/src/Monbsoft.Feeader.Avalonia/ViewModels/MainWindowViewModel.cs b/src/Monbsoft.Feeader.Avalonia/ViewModels/MainWindowViewModel.cs index 0801a9f..29bdfa6 100644 --- a/src/Monbsoft.Feeader.Avalonia/ViewModels/MainWindowViewModel.cs +++ b/src/Monbsoft.Feeader.Avalonia/ViewModels/MainWindowViewModel.cs @@ -2,14 +2,12 @@ using Monbsoft.Feeader.Avalonia.Services; using ReactiveUI; using System; -using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; using System.Linq; using System.Reactive.Concurrency; using System.Reactive.Linq; using System.Threading; -using System.Threading.Tasks; using System.Windows.Input; namespace Monbsoft.Feeader.Avalonia.ViewModels; @@ -23,13 +21,12 @@ public class MainWindowViewModel : ViewModelBase public MainWindowViewModel() { - ShowDialog = new Interaction(); + ShowDialog = new Interaction(); - AddFeedCommand = ReactiveCommand.CreateFromTask(async () => + ShowSettingsCommand = ReactiveCommand.CreateFromTask(async () => { - var store = new AddFeedViewModel(); + var store = new SettingsWindowViewModel(new FeedContext(Feeds)); var feed = await ShowDialog.Handle(store); - AddFeed(feed); }); this.WhenAnyValue(x => x.SelectedFeed) @@ -39,7 +36,7 @@ public MainWindowViewModel() RxApp.MainThreadScheduler.Schedule(LoadFeedsAsync); } - public ICommand AddFeedCommand { get; } + public ICommand ShowSettingsCommand { get; } public ObservableCollection Articles { get; } = new (); public ObservableCollection Feeds { get; } = new(); public Feed? SelectedFeed @@ -52,8 +49,8 @@ public ArticleViewModel? SelectedArticle get => _selectedArticle; set => this.RaiseAndSetIfChanged(ref _selectedArticle, value); } - public Interaction ShowDialog { get; } - + public Interaction ShowDialog { get; } + public async void LoadFeedsAsync() { FeedService.InitializeCache(); @@ -72,6 +69,7 @@ private async void AddFeed(Feed? feed) return; Feeds.Add(feed); await FeedService.SaveAsync(Feeds.ToList()); + Debug.WriteLine($"Feed {feed?.Name} added"); } private async void LoadArticles(Feed feed) { diff --git a/src/Monbsoft.Feeader.Avalonia/ViewModels/SettingsWindowViewModel.cs b/src/Monbsoft.Feeader.Avalonia/ViewModels/SettingsWindowViewModel.cs new file mode 100644 index 0000000..6ab4fd8 --- /dev/null +++ b/src/Monbsoft.Feeader.Avalonia/ViewModels/SettingsWindowViewModel.cs @@ -0,0 +1,22 @@ +using Monbsoft.Feeader.Avalonia.Models; +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Monbsoft.Feeader.Avalonia.ViewModels +{ + public class SettingsWindowViewModel : ViewModelBase + { + private readonly FeedContext _feedContext; + + public SettingsWindowViewModel(FeedContext context) + { + ChangeFeedViewModel = new ChangeFeedViewModel(context); + } + + public ChangeFeedViewModel ChangeFeedViewModel { get; } + } +} diff --git a/src/Monbsoft.Feeader.Avalonia/Views/AddFeedWindow.axaml b/src/Monbsoft.Feeader.Avalonia/Views/AddFeedWindow.axaml deleted file mode 100644 index 2f27393..0000000 --- a/src/Monbsoft.Feeader.Avalonia/Views/AddFeedWindow.axaml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - diff --git a/src/Monbsoft.Feeader.Avalonia/Views/ArticleView.axaml b/src/Monbsoft.Feeader.Avalonia/Views/ArticleView.axaml index 88ab9f0..3f624fa 100644 --- a/src/Monbsoft.Feeader.Avalonia/Views/ArticleView.axaml +++ b/src/Monbsoft.Feeader.Avalonia/Views/ArticleView.axaml @@ -4,27 +4,20 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" x:Class="Monbsoft.Feeader.Avalonia.Views.ArticleView"> - - - - - + - - - - - + HorizontalAlignment="Stretch" + MaxHeight="300"/> + + + \ No newline at end of file diff --git a/src/Monbsoft.Feeader.Avalonia/Views/ChangeFeedView.axaml b/src/Monbsoft.Feeader.Avalonia/Views/ChangeFeedView.axaml new file mode 100644 index 0000000..8f9e7d6 --- /dev/null +++ b/src/Monbsoft.Feeader.Avalonia/Views/ChangeFeedView.axaml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Monbsoft.Feeader.Avalonia/Views/NavMenuView.axaml.cs b/src/Monbsoft.Feeader.Avalonia/Views/ChangeFeedView.axaml.cs similarity index 78% rename from src/Monbsoft.Feeader.Avalonia/Views/NavMenuView.axaml.cs rename to src/Monbsoft.Feeader.Avalonia/Views/ChangeFeedView.axaml.cs index 0233294..d871e1e 100644 --- a/src/Monbsoft.Feeader.Avalonia/Views/NavMenuView.axaml.cs +++ b/src/Monbsoft.Feeader.Avalonia/Views/ChangeFeedView.axaml.cs @@ -4,9 +4,9 @@ namespace Monbsoft.Feeader.Avalonia.Views { - public partial class NavMenuView : UserControl + public partial class AddFeedView : UserControl { - public NavMenuView() + public AddFeedView() { InitializeComponent(); } diff --git a/src/Monbsoft.Feeader.Avalonia/Views/NavMenuView.axaml b/src/Monbsoft.Feeader.Avalonia/Views/FeedListView.axaml similarity index 84% rename from src/Monbsoft.Feeader.Avalonia/Views/NavMenuView.axaml rename to src/Monbsoft.Feeader.Avalonia/Views/FeedListView.axaml index 18cdc04..a1e2afc 100644 --- a/src/Monbsoft.Feeader.Avalonia/Views/NavMenuView.axaml +++ b/src/Monbsoft.Feeader.Avalonia/Views/FeedListView.axaml @@ -3,7 +3,7 @@ xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" - x:Class="Monbsoft.Feeader.Avalonia.Views.NavMenuView"> + x:Class="Monbsoft.Feeader.Avalonia.Views.FeedListView"> @@ -19,11 +19,11 @@ - + >Settings - \ No newline at end of file + diff --git a/src/Monbsoft.Feeader.Avalonia/Views/FeedListView.axaml.cs b/src/Monbsoft.Feeader.Avalonia/Views/FeedListView.axaml.cs new file mode 100644 index 0000000..1542095 --- /dev/null +++ b/src/Monbsoft.Feeader.Avalonia/Views/FeedListView.axaml.cs @@ -0,0 +1,19 @@ +using Avalonia; +using Avalonia.Controls; +using Avalonia.Markup.Xaml; + +namespace Monbsoft.Feeader.Avalonia.Views +{ + public partial class FeedListView : UserControl + { + public FeedListView() + { + InitializeComponent(); + } + + private void InitializeComponent() + { + AvaloniaXamlLoader.Load(this); + } + } +} diff --git a/src/Monbsoft.Feeader.Avalonia/Views/MainWindow.axaml b/src/Monbsoft.Feeader.Avalonia/Views/MainWindow.axaml index 4d07e69..d2e1a9b 100644 --- a/src/Monbsoft.Feeader.Avalonia/Views/MainWindow.axaml +++ b/src/Monbsoft.Feeader.Avalonia/Views/MainWindow.axaml @@ -17,9 +17,9 @@ - + - + diff --git a/src/Monbsoft.Feeader.Avalonia/Views/MainWindow.axaml.cs b/src/Monbsoft.Feeader.Avalonia/Views/MainWindow.axaml.cs index c7162b6..3d467ab 100644 --- a/src/Monbsoft.Feeader.Avalonia/Views/MainWindow.axaml.cs +++ b/src/Monbsoft.Feeader.Avalonia/Views/MainWindow.axaml.cs @@ -12,23 +12,22 @@ public partial class MainWindow : ReactiveWindow { public MainWindow() { - InitializeComponent(); - this.WhenActivated(d => d(ViewModel!.ShowDialog.RegisterHandler(DoShowDialogAsync))); + InitializeComponent(); + this.WhenActivated(d => d(ViewModel!.ShowDialog.RegisterHandler(DoSettingsAsync))); } - private async Task DoShowDialogAsync(InteractionContext interaction) + private async Task DoSettingsAsync(InteractionContext interaction) { - var dialog = new AddFeedWindow(); + var dialog = new SettingsWindow(); dialog.WindowStartupLocation = WindowStartupLocation.CenterOwner; dialog.DataContext = interaction.Input; - dialog.Height = 200; - dialog.Width = 355; + dialog.Height = 450; + dialog.Width = 850; - var result = await dialog.ShowDialog(this); + var result = await dialog.ShowDialog(this); interaction.SetOutput(result); - - } + } private void InitializeComponent() { AvaloniaXamlLoader.Load(this); diff --git a/src/Monbsoft.Feeader.Avalonia/Views/SettingsWindow.axaml b/src/Monbsoft.Feeader.Avalonia/Views/SettingsWindow.axaml new file mode 100644 index 0000000..74d8172 --- /dev/null +++ b/src/Monbsoft.Feeader.Avalonia/Views/SettingsWindow.axaml @@ -0,0 +1,12 @@ + + + + + diff --git a/src/Monbsoft.Feeader.Avalonia/Views/AddFeedWindow.axaml.cs b/src/Monbsoft.Feeader.Avalonia/Views/SettingsWindow.axaml.cs similarity index 54% rename from src/Monbsoft.Feeader.Avalonia/Views/AddFeedWindow.axaml.cs rename to src/Monbsoft.Feeader.Avalonia/Views/SettingsWindow.axaml.cs index 9cda3ba..7d4e687 100644 --- a/src/Monbsoft.Feeader.Avalonia/Views/AddFeedWindow.axaml.cs +++ b/src/Monbsoft.Feeader.Avalonia/Views/SettingsWindow.axaml.cs @@ -1,22 +1,17 @@ using Avalonia; using Avalonia.Controls; using Avalonia.Markup.Xaml; -using Avalonia.ReactiveUI; -using Monbsoft.Feeader.Avalonia.ViewModels; -using ReactiveUI; -using System; namespace Monbsoft.Feeader.Avalonia.Views { - public partial class AddFeedWindow : ReactiveWindow + public partial class SettingsWindow : Window { - public AddFeedWindow() + public SettingsWindow() { InitializeComponent(); #if DEBUG this.AttachDevTools(); #endif - this.WhenActivated(d => d(ViewModel!.AddCommand.Subscribe(Close))); } private void InitializeComponent()