mirror of
https://github.com/hmaxnl/SharpRSS.git
synced 2025-01-18 21:04:21 +01:00
Implemented db backend base, added UI features
This commit is contained in:
parent
66acd6a1c2
commit
24d62d79dc
|
@ -13,7 +13,6 @@ namespace SharpRss
|
||||||
public static class FeedCache
|
public static class FeedCache
|
||||||
{
|
{
|
||||||
private static readonly Dictionary<string, Feed> CachedFeeds = new Dictionary<string, Feed>();
|
private static readonly Dictionary<string, Feed> CachedFeeds = new Dictionary<string, Feed>();
|
||||||
|
|
||||||
public static async Task<Feed> GetFeed(string urlKey)
|
public static async Task<Feed> GetFeed(string urlKey)
|
||||||
{
|
{
|
||||||
Log.Verbose("Fetching feed: {UrlKey}", urlKey);
|
Log.Verbose("Fetching feed: {UrlKey}", urlKey);
|
||||||
|
@ -33,9 +32,11 @@ namespace SharpRss
|
||||||
feedUrl = urls.First().Url;
|
feedUrl = urls.First().Url;
|
||||||
|
|
||||||
Feed feed = await FeedReader.ReadAsync(feedUrl);
|
Feed feed = await FeedReader.ReadAsync(feedUrl);
|
||||||
if (feed == null)
|
if (feed != null)
|
||||||
|
{
|
||||||
Log.Warning("Could not get feed: {FeedUrl}", feedUrl);
|
Log.Warning("Could not get feed: {FeedUrl}", feedUrl);
|
||||||
CachedFeeds.Add(urlKey, feed);
|
CachedFeeds[feedUrl] = feed;
|
||||||
|
}
|
||||||
return feed;
|
return feed;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
using System;
|
using System;
|
||||||
using ToolQit.Extensions;
|
|
||||||
|
|
||||||
namespace SharpRss.Models
|
namespace SharpRss.Models
|
||||||
{
|
{
|
||||||
|
@ -28,6 +27,7 @@ namespace SharpRss.Models
|
||||||
|
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
public string HexColor { get; set; }
|
public string HexColor { get; set; }
|
||||||
|
public string PathIcon { get; set; }
|
||||||
public string CategoryId { get; private set; }
|
public string CategoryId { get; private set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,13 +9,15 @@ namespace SharpRss.Models
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
public FeedModel(Feed feed)
|
public FeedModel(string rssFeedUrl, CategoryModel? category = null)
|
||||||
{
|
{
|
||||||
|
if (category != null)
|
||||||
|
CategoryId = category.CategoryId;
|
||||||
FeedId = Guid.NewGuid().ToString();
|
FeedId = Guid.NewGuid().ToString();
|
||||||
Url = feed.Link;
|
FeedUrl = rssFeedUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Url { get; set; }
|
public string FeedUrl { get; set; }
|
||||||
public string FeedId { get; private set; }
|
public string FeedId { get; private set; }
|
||||||
public string CategoryId { get; set; } = "";
|
public string CategoryId { get; set; } = "";
|
||||||
|
|
||||||
|
@ -23,29 +25,11 @@ namespace SharpRss.Models
|
||||||
{
|
{
|
||||||
FeedModel feedModel = new FeedModel()
|
FeedModel feedModel = new FeedModel()
|
||||||
{
|
{
|
||||||
Url = url,
|
FeedUrl = url,
|
||||||
FeedId = feedId,
|
FeedId = feedId,
|
||||||
CategoryId = categoryId
|
CategoryId = categoryId
|
||||||
};
|
};
|
||||||
return feedModel;
|
return feedModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
//private readonly Task _fetchTask;
|
|
||||||
//public async Task FetchAsync() => _feed = await FeedCache.GetFeed(Url);
|
|
||||||
/*private Feed? _feed;
|
|
||||||
public Feed Base {
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (_feed == null)
|
|
||||||
{
|
|
||||||
if (_fetchTask.IsFaulted)
|
|
||||||
{ return new Feed(); }
|
|
||||||
if (_fetchTask.Status is not (TaskStatus.Running or TaskStatus.WaitingForActivation))
|
|
||||||
_fetchTask.Start();
|
|
||||||
_fetchTask.Wait();
|
|
||||||
}
|
|
||||||
return _feed ?? new Feed();
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ using SharpRss.Models;
|
||||||
|
|
||||||
namespace SharpRss.Services
|
namespace SharpRss.Services
|
||||||
{
|
{
|
||||||
public class DatabaseService : IDisposable
|
internal class DatabaseService : IDisposable
|
||||||
{
|
{
|
||||||
private string _connectionString => $"Data Source={Path.Combine(Environment.CurrentDirectory, "sharp_rss.db")};";
|
private string _connectionString => $"Data Source={Path.Combine(Environment.CurrentDirectory, "sharp_rss.db")};";
|
||||||
internal DatabaseService()
|
internal DatabaseService()
|
||||||
|
@ -24,22 +24,11 @@ namespace SharpRss.Services
|
||||||
{
|
{
|
||||||
bool result = true;
|
bool result = true;
|
||||||
_sqlConn.Open();
|
_sqlConn.Open();
|
||||||
/*var queryResult = await _sqlConn.QueryAsync("SELECT * FROM category_data WHERE name=@catName", new { catName = category.Name });
|
|
||||||
var enumerable = queryResult.ToList();
|
|
||||||
if (queryResult != null && enumerable.Any()) // Category already exists!
|
|
||||||
result = false;*/
|
|
||||||
foreach (var categoryModel in categories)
|
foreach (var categoryModel in categories)
|
||||||
{
|
{
|
||||||
await _sqlConn.QueryAsync("INSERT OR IGNORE INTO category_data (name, hex_color, category_id) VALUES(@catName, @hexColor, @categoryId)",
|
await _sqlConn.QueryAsync("INSERT INTO category_data (name, hex_color, path_icon, category_id) VALUES(@catName, @hexColor, @pathIcon, @categoryId) ON CONFLICT(name) DO UPDATE SET hex_color=@hexColor, path_icon=@pathIcon",
|
||||||
new { catName = categoryModel.Name, hexColor = categoryModel.HexColor, categoryId = categoryModel.CategoryId });
|
new { catName = categoryModel.Name, hexColor = categoryModel.HexColor, pathIcon = categoryModel.PathIcon, categoryId = categoryModel.CategoryId });
|
||||||
}
|
}
|
||||||
/*if (result)
|
|
||||||
{
|
|
||||||
|
|
||||||
|
|
||||||
if (createResult.Any()) // Did not create the category
|
|
||||||
result = false;
|
|
||||||
}*/
|
|
||||||
_sqlConn.Close();
|
_sqlConn.Close();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -50,7 +39,7 @@ namespace SharpRss.Services
|
||||||
_sqlConn.Open();
|
_sqlConn.Open();
|
||||||
foreach (var feedModel in feeds)
|
foreach (var feedModel in feeds)
|
||||||
{
|
{
|
||||||
await _sqlConn.QueryAsync("INSERT OR IGNORE INTO feed_data(url, feed_id, category_id) VALUES(@url, @feedId, @categoryId)", new { url = feedModel.Url, feedId = feedModel.FeedId, categoryId = feedModel.CategoryId });
|
await _sqlConn.QueryAsync("INSERT OR REPLACE INTO feed_data(url, feed_id, category_id) VALUES(@url, @feedId, @categoryId) ON CONFLICT(url) DO UPDATE SET category_id=@categoryId", new { url = feedModel.FeedUrl, feedId = feedModel.FeedId, categoryId = feedModel.CategoryId });
|
||||||
}
|
}
|
||||||
_sqlConn.Close();
|
_sqlConn.Close();
|
||||||
return result;
|
return result;
|
||||||
|
@ -90,14 +79,14 @@ namespace SharpRss.Services
|
||||||
{
|
{
|
||||||
Log.Verbose("Checking database...");
|
Log.Verbose("Checking database...");
|
||||||
_sqlConn.Open();
|
_sqlConn.Open();
|
||||||
var queryResponse = await _sqlConn.QueryAsync("CREATE TABLE IF NOT EXISTS category_data (name STRING NOT NULL, hex_color STRING NOT NULL, category_id STRING PRIMARY KEY)");
|
var queryResponse = await _sqlConn.QueryAsync("CREATE TABLE IF NOT EXISTS category_data (name STRING NOT NULL, hex_color STRING NOT NULL, path_icon STRING, category_id STRING PRIMARY KEY, CONSTRAINT name UNIQUE (name))");
|
||||||
if (queryResponse.Any())
|
if (queryResponse.Any())
|
||||||
{
|
{
|
||||||
_sqlConn.Close();
|
_sqlConn.Close();
|
||||||
_sqlConn.Dispose();
|
_sqlConn.Dispose();
|
||||||
throw new SqliteException("Error initializing database!", 0);
|
throw new SqliteException("Error initializing database!", 0);
|
||||||
}
|
}
|
||||||
queryResponse = await _sqlConn.QueryAsync("CREATE TABLE IF NOT EXISTS feed_data (url STRING NOT NULL, feed_id STRING PRIMARY KEY, category_id STRING DEFAULT '')");
|
queryResponse = await _sqlConn.QueryAsync("CREATE TABLE IF NOT EXISTS feed_data (url STRING NOT NULL, feed_id STRING PRIMARY KEY, category_id STRING NOT NULL DEFAULT '', CONSTRAINT url, UNIQUE (url))");
|
||||||
if (queryResponse.Any())
|
if (queryResponse.Any())
|
||||||
{
|
{
|
||||||
_sqlConn.Close();
|
_sqlConn.Close();
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using CodeHollow.FeedReader;
|
||||||
using SharpRss.Models;
|
using SharpRss.Models;
|
||||||
|
using ToolQit.Extensions;
|
||||||
|
|
||||||
namespace SharpRss.Services
|
namespace SharpRss.Services
|
||||||
{
|
{
|
||||||
|
@ -11,64 +14,76 @@ namespace SharpRss.Services
|
||||||
{
|
{
|
||||||
public RssService()
|
public RssService()
|
||||||
{
|
{
|
||||||
_dbService = new DatabaseService();
|
//SetupTestCategoriesAndFeedsAsync();
|
||||||
Initialize();
|
|
||||||
}
|
}
|
||||||
private readonly DatabaseService _dbService;
|
private readonly DatabaseService _dbService = new DatabaseService();
|
||||||
|
|
||||||
private async void Initialize()
|
private async void SetupTestCategoriesAndFeedsAsync()
|
||||||
{
|
{
|
||||||
//HashSet<CategoryModel> categoryModels = await _dbService.GetCategoriesAsync();
|
await _dbService.AddCategoriesAsync(new HashSet<CategoryModel>()
|
||||||
|
{
|
||||||
|
new CategoryModel() { Name = "All" },
|
||||||
|
new CategoryModel() { Name = "RSS" },
|
||||||
|
new CategoryModel() { Name = "Tech" },
|
||||||
|
new CategoryModel() { Name = "News" }
|
||||||
|
});
|
||||||
|
await _dbService.AddFeedsAsync(new HashSet<FeedModel>()
|
||||||
|
{
|
||||||
|
new FeedModel("http://fedoramagazine.org/feed/"),
|
||||||
|
new FeedModel("https://www.nasa.gov/rss/dyn/breaking_news.rss"),
|
||||||
|
new FeedModel("https://journals.plos.org/plosone/feed/atom"),
|
||||||
|
new FeedModel("https://itsfoss.com/feed")
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<HashSet<object>> GetAllAsync()
|
public async Task<Feed> GetFeedAsync(string rssUrl)
|
||||||
|
{
|
||||||
|
return await FeedCache.GetFeed(rssUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<HashSet<object>> GetAllUnsortedAsync()
|
||||||
{
|
{
|
||||||
HashSet<object> items = new HashSet<object>();
|
HashSet<object> items = new HashSet<object>();
|
||||||
|
var categories = await _dbService.GetCategoriesAsync();
|
||||||
|
var feeds = await _dbService.GetFeedsAsync(string.Empty);
|
||||||
|
items.UnionWith(categories);
|
||||||
|
items.UnionWith(feeds);
|
||||||
return items;
|
return items;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<HashSet<CategoryModel>> GetCategoriesAsync()
|
public async Task<HashSet<CategoryModel>> GetCategoriesAsync()
|
||||||
{
|
{
|
||||||
return new HashSet<CategoryModel>();
|
var result = await _dbService.GetCategoriesAsync();
|
||||||
|
return result.OrderBy(x => x.Name).ToHashSet();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<HashSet<FeedModel>> GetFeedsAsync(CategoryModel? categoryModel = null)
|
public async Task<HashSet<FeedModel>> GetFeedsAsync(CategoryModel? categoryModel = null)
|
||||||
{
|
{
|
||||||
HashSet<FeedModel> feeds = new HashSet<FeedModel>();
|
HashSet<FeedModel> feeds;
|
||||||
if (categoryModel != null)
|
if (categoryModel != null)
|
||||||
{
|
feeds = await _dbService.GetFeedsAsync(categoryModel.CategoryId);
|
||||||
// Get feeds from the category.
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
feeds = await _dbService.GetFeedsAsync();
|
||||||
// Get all the feeds.
|
|
||||||
}
|
|
||||||
return feeds;
|
return feeds;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async void AddCategoryAsync(string name)
|
public async void AddCategoryAsync(string name, string? icon, string hexColor)
|
||||||
{
|
{
|
||||||
|
CategoryModel categoryModel = new CategoryModel()
|
||||||
|
{
|
||||||
|
Name = name
|
||||||
|
};
|
||||||
|
if (icon != null)
|
||||||
|
categoryModel.PathIcon = icon;
|
||||||
|
if (!hexColor.IsNullEmptyWhiteSpace())
|
||||||
|
categoryModel.HexColor = hexColor;
|
||||||
|
await _dbService.AddCategoriesAsync(new HashSet<CategoryModel>() { categoryModel });
|
||||||
}
|
}
|
||||||
|
|
||||||
public async void AddFeedAsync(string rssUrl)
|
public async void AddFeedAsync(string rssUrl, CategoryModel? category = null)
|
||||||
{
|
{
|
||||||
|
FeedModel feedModel = new FeedModel(rssUrl, category);
|
||||||
|
await _dbService.AddFeedsAsync(new HashSet<FeedModel>() { feedModel });
|
||||||
}
|
}
|
||||||
|
|
||||||
/*private static HashSet<FeedModel> feedSet = new HashSet<FeedModel>()
|
|
||||||
{
|
|
||||||
new FeedModel("http://fedoramagazine.org/feed/"),
|
|
||||||
new FeedModel("https://www.nasa.gov/rss/dyn/breaking_news.rss"),
|
|
||||||
};
|
|
||||||
private static HashSet<FeedModel> feedSet2 = new HashSet<FeedModel>()
|
|
||||||
{
|
|
||||||
new FeedModel("https://journals.plos.org/plosone/feed/atom"),
|
|
||||||
new FeedModel("https://itsfoss.com/feed")
|
|
||||||
};*/
|
|
||||||
|
|
||||||
/*HashSet<CategoryModel> set = new HashSet<CategoryModel>()
|
|
||||||
{
|
|
||||||
new CategoryModel("RSS", feedSet),
|
|
||||||
new CategoryModel("Tech", feedSet2)
|
|
||||||
};*/
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,16 +1,14 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using SharpRss.Models;
|
|
||||||
|
|
||||||
namespace WebSharpRSS.Models
|
namespace WebSharpRSS.Models
|
||||||
{
|
{
|
||||||
public class FeedStateContainer
|
public class FeedStateContainer
|
||||||
{
|
{
|
||||||
public HashSet<FeedModel> Feeds { get; set; }
|
public TreeItemData? TreeItem { get; set; }
|
||||||
public event Action StateChanged;
|
public event Action? StateChanged;
|
||||||
public void SetValue(HashSet<FeedModel> feedSet)
|
public void SetValue(TreeItemData treeItemSet)
|
||||||
{
|
{
|
||||||
Feeds = feedSet;
|
TreeItem = treeItemSet;
|
||||||
Invoke();
|
Invoke();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,32 +3,33 @@ using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using CodeHollow.FeedReader;
|
using CodeHollow.FeedReader;
|
||||||
using MudBlazor;
|
using MudBlazor;
|
||||||
|
using Serilog;
|
||||||
using SharpRss.Models;
|
using SharpRss.Models;
|
||||||
|
using SharpRss.Services;
|
||||||
using ToolQit;
|
using ToolQit;
|
||||||
|
|
||||||
namespace WebSharpRSS.Models
|
namespace WebSharpRSS.Models
|
||||||
{
|
{
|
||||||
public class TreeItemData
|
public class TreeItemData
|
||||||
{
|
{
|
||||||
public TreeItemData(CategoryModel catModel)
|
public TreeItemData(CategoryModel catModel, RssService rssService)
|
||||||
{
|
{
|
||||||
|
_service = rssService;
|
||||||
CategoryModel = catModel;
|
CategoryModel = catModel;
|
||||||
//Feeds = CategoryModel.Feeds.Where(x => x.Base != null).Select(x => new TreeItemData(x)).ToHashSet();
|
Initialize();
|
||||||
Title = CategoryModel.Name;
|
|
||||||
Icon = Icons.Material.Filled.RssFeed;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public TreeItemData(FeedModel feedModel)
|
public TreeItemData(FeedModel feedModel, RssService rssService)
|
||||||
{
|
{
|
||||||
|
_service = rssService;
|
||||||
FeedModel = feedModel;
|
FeedModel = feedModel;
|
||||||
//Feed = FeedModel.Base;
|
Initialize();
|
||||||
Title = Feed.Title;
|
|
||||||
string faviconAddress = Feed.Link.Remove(Feed.Link.IndexOf("http", StringComparison.Ordinal), Feed.Link.IndexOf("://", StringComparison.Ordinal) + 3);
|
|
||||||
FaviconUrl = string.Format(Caretaker.Settings["Paths"].GetString("FaviconResolveUrl"), faviconAddress);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private readonly RssService _service;
|
||||||
public readonly CategoryModel? CategoryModel;
|
public readonly CategoryModel? CategoryModel;
|
||||||
public readonly FeedModel? FeedModel;
|
public readonly FeedModel? FeedModel;
|
||||||
|
private HashSet<FeedModel> _feedModels;
|
||||||
|
|
||||||
public string Title { get; set; } = string.Empty;
|
public string Title { get; set; } = string.Empty;
|
||||||
public bool IsSelected { get; set; }
|
public bool IsSelected { get; set; }
|
||||||
|
@ -36,11 +37,11 @@ namespace WebSharpRSS.Models
|
||||||
public string? FaviconUrl { get; set; }
|
public string? FaviconUrl { get; set; }
|
||||||
|
|
||||||
// Category
|
// Category
|
||||||
public bool HasChild => Feeds != null;
|
public bool HasChild => _feedModels != null && _feedModels.Any();
|
||||||
public bool IsExpanded { get; set; }
|
public bool IsExpanded { get; set; }
|
||||||
public HashSet<TreeItemData>? Feeds { get; set; }
|
public HashSet<TreeItemData>? Feeds { get; set; }
|
||||||
// Feed
|
// Feed
|
||||||
public Feed? Feed { get; set; }
|
public Feed? Feed { get; private set; }
|
||||||
public int FeeditemCount
|
public int FeeditemCount
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
|
@ -60,5 +61,35 @@ namespace WebSharpRSS.Models
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async void Initialize()
|
||||||
|
{
|
||||||
|
if (CategoryModel != null)
|
||||||
|
{
|
||||||
|
Title = CategoryModel.Name;
|
||||||
|
Icon = Icons.Material.Filled.Category;
|
||||||
|
_feedModels = await _service.GetFeedsAsync(CategoryModel);
|
||||||
|
if (_feedModels.Any())
|
||||||
|
Feeds = _feedModels.Select(x => new TreeItemData(x, _service)).OrderBy(x => x.Title).ToHashSet();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FeedModel != null)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Feed = await _service.GetFeedAsync(FeedModel.FeedUrl);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Log.Error(e, "Error fetching feed: {FeedUrl}", FeedModel.FeedUrl);
|
||||||
|
Feed = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Icon = Icons.Material.Filled.RssFeed;
|
||||||
|
Title = Feed.Title;
|
||||||
|
string faviconAddress = Feed.Link.Remove(Feed.Link.IndexOf("http", StringComparison.Ordinal), Feed.Link.IndexOf("://", StringComparison.Ordinal) + 3);
|
||||||
|
FaviconUrl = string.Format(Caretaker.Settings["Paths"].GetString("FaviconResolveUrl"), faviconAddress);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -4,33 +4,28 @@
|
||||||
@using WebSharpRSS.Models;
|
@using WebSharpRSS.Models;
|
||||||
@using SharpRss.Services
|
@using SharpRss.Services
|
||||||
|
|
||||||
@inject RssService _rssService;
|
@*@inject RssService _rssService;*@
|
||||||
@inject FeedStateContainer _stateContainer;
|
@inject FeedStateContainer _stateContainer;
|
||||||
|
|
||||||
<MudGrid Spacing="3" Justify="Justify.FlexStart">
|
<MudGrid Spacing="3" Justify="Justify.FlexStart">
|
||||||
@if (Feeds != null)
|
@foreach (var feedItem in _items)
|
||||||
{
|
{
|
||||||
foreach (var feedItem in _items)
|
<MudItem xs="6">
|
||||||
{
|
<MudCard>
|
||||||
<MudItem xs="6">
|
<MudCardContent>
|
||||||
<MudCard>
|
<MudText>@feedItem.Title</MudText>
|
||||||
<MudCardContent>
|
<MudText Typo="Typo.body2">@feedItem.Description</MudText>
|
||||||
<MudText>@feedItem.Title</MudText>
|
<MudText Typo="Typo.overline">@feedItem.PublishingDate.ToString()</MudText>
|
||||||
<MudText Typo="Typo.body2">@feedItem.Description</MudText>
|
</MudCardContent>
|
||||||
<MudText Typo="Typo.overline">@feedItem.PublishingDate.ToString()</MudText>
|
</MudCard>
|
||||||
</MudCardContent>
|
</MudItem>
|
||||||
</MudCard>
|
|
||||||
</MudItem>
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
</MudGrid>
|
</MudGrid>
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
[Parameter]
|
|
||||||
public HashSet<FeedModel>? Feeds { get; set; }
|
|
||||||
|
|
||||||
private HashSet<FeedItem> _items = new HashSet<FeedItem>();
|
private HashSet<FeedItem> _items = new HashSet<FeedItem>();
|
||||||
protected override async void OnInitialized()
|
protected override void OnInitialized()
|
||||||
{
|
{
|
||||||
UpdateFeeds();
|
UpdateFeeds();
|
||||||
_stateContainer.StateChanged += FeedsChanged;
|
_stateContainer.StateChanged += FeedsChanged;
|
||||||
|
@ -43,11 +38,17 @@
|
||||||
|
|
||||||
private void UpdateFeeds()
|
private void UpdateFeeds()
|
||||||
{
|
{
|
||||||
Feeds = _stateContainer.Feeds;
|
if (_stateContainer.TreeItem == null) return;
|
||||||
if (Feeds == null) return;
|
if (_stateContainer.TreeItem.Feed != null)
|
||||||
foreach (var feedmodel in Feeds)
|
_items = _stateContainer.TreeItem.Feed.Items.ToHashSet();
|
||||||
|
if (_stateContainer.TreeItem.Feeds != null)
|
||||||
{
|
{
|
||||||
//_items = feedmodel.Base.Items.OrderBy(x => x.PublishingDate).Reverse().ToHashSet();
|
_items = new HashSet<FeedItem>();
|
||||||
|
foreach (var itemData in _stateContainer.TreeItem.Feeds)
|
||||||
|
{
|
||||||
|
if (itemData.Feed == null) continue;
|
||||||
|
_items.UnionWith(itemData.Feed.Items);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -4,8 +4,6 @@ using Microsoft.Extensions.Hosting;
|
||||||
using MudBlazor;
|
using MudBlazor;
|
||||||
using MudBlazor.Services;
|
using MudBlazor.Services;
|
||||||
using Serilog;
|
using Serilog;
|
||||||
using SharpRss;
|
|
||||||
using SharpRss.Models;
|
|
||||||
using SharpRss.Services;
|
using SharpRss.Services;
|
||||||
using ToolQit;
|
using ToolQit;
|
||||||
using WebSharpRSS;
|
using WebSharpRSS;
|
||||||
|
@ -13,12 +11,12 @@ using WebSharpRSS.Models;
|
||||||
|
|
||||||
Caretaker.Settings.SetAppDefaultSettings();
|
Caretaker.Settings.SetAppDefaultSettings();
|
||||||
Bootstrapper.SetupLogging();
|
Bootstrapper.SetupLogging();
|
||||||
Log.Information("Starting application....");
|
Log.Information("Starting...");
|
||||||
|
|
||||||
var builder = WebApplication.CreateBuilder(args);
|
var builder = WebApplication.CreateBuilder(args);
|
||||||
builder.Services.AddRazorPages();
|
builder.Services.AddRazorPages();
|
||||||
builder.Services.AddServerSideBlazor();
|
builder.Services.AddServerSideBlazor();
|
||||||
builder.Services.AddTransient<RssService>();
|
builder.Services.AddSingleton<RssService>();
|
||||||
builder.Services.AddSingleton<FeedStateContainer>();
|
builder.Services.AddSingleton<FeedStateContainer>();
|
||||||
builder.Services.AddMudServices(config =>
|
builder.Services.AddMudServices(config =>
|
||||||
{
|
{
|
||||||
|
|
|
@ -11,16 +11,16 @@
|
||||||
@inject RssService _rssService
|
@inject RssService _rssService
|
||||||
|
|
||||||
<MudStack Spacing="2">
|
<MudStack Spacing="2">
|
||||||
<MudTreeView Items="GuideItems" @bind-SelectedValue="SelectedItem" Hover="true">
|
<MudTreeView Items="_guideItems" @bind-SelectedValue="SelectedItem" Hover="true">
|
||||||
<ItemTemplate>
|
<ItemTemplate>
|
||||||
<MudTreeViewItem @bind-Expanded="@context.IsExpanded" Items="@context.Feeds" Value="@context">
|
<MudTreeViewItem @bind-Expanded="@context.IsExpanded" Items="@context.Feeds" Value="@context" CanExpand="@context.HasChild" @onclick="ItemClicked">
|
||||||
<Content>
|
<Content>
|
||||||
<div style="display: grid; grid-template-columns: 1fr auto; align-items: center; width: 100%">
|
<div style="display: grid; grid-template-columns: 1fr auto; align-items: center; width: 100%">
|
||||||
<div style="justify-self: start;" class="d-flex align-center">
|
<div style="justify-self: start;" class="d-flex align-center">
|
||||||
<MudTreeViewItemToggleButton @bind-Expanded="@context.IsExpanded" Visible="@context.HasChild" />
|
<MudTreeViewItemToggleButton @bind-Expanded="@context.IsExpanded" Visible="@context.HasChild" LoadingIconColor="Color.Info"/>
|
||||||
@if (context.FaviconUrl.IsNullEmptyWhiteSpace() && context.Icon != null)
|
@if (context.FaviconUrl.IsNullEmptyWhiteSpace() && context.Icon != null)
|
||||||
{
|
{
|
||||||
<MudIcon Icon="@context.Icon"/>
|
<MudIcon Icon="@context.Icon" Style="@($"color:{context.CategoryModel?.HexColor ?? Theme.Palette.Primary.Value}")"/>
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -39,36 +39,30 @@
|
||||||
</MudStack>
|
</MudStack>
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
public HashSet<TreeItemData> GuideItems = new HashSet<TreeItemData>();
|
private MudTheme Theme = new MudTheme();
|
||||||
private TreeItemData? _selecteditem;
|
private readonly HashSet<TreeItemData> _guideItems = new HashSet<TreeItemData>();
|
||||||
|
private TreeItemData? _selectedItem;
|
||||||
private TreeItemData? SelectedItem
|
private TreeItemData? SelectedItem
|
||||||
{
|
{
|
||||||
get => _selecteditem;
|
get => _selectedItem;
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
_selecteditem = value;
|
_selectedItem = value;
|
||||||
ItemClicked();
|
ItemClicked();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private void ItemClicked()
|
private void ItemClicked()
|
||||||
{
|
{
|
||||||
if (SelectedItem == null) return;
|
if (SelectedItem == null) return;
|
||||||
if (SelectedItem.FeedModel != null)
|
_stateContainer.SetValue(SelectedItem);
|
||||||
_stateContainer.SetValue(new HashSet<FeedModel>() { SelectedItem.FeedModel });
|
|
||||||
if (SelectedItem.Feeds != null)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
protected override async void OnInitialized()
|
protected override async void OnInitialized()
|
||||||
{
|
{
|
||||||
Log.Verbose("Loading guide data...");
|
Log.Verbose("Loading guide data...");
|
||||||
|
HashSet<object> items = await _rssService.GetAllUnsortedAsync();
|
||||||
/*HashSet<CategoryModel> cats = await _rssService.GetAllAsync();
|
_guideItems.UnionWith(items.Select(x => x is CategoryModel model ? new TreeItemData(model, _rssService) : x is FeedModel feedModel ? new TreeItemData(feedModel, _rssService) : throw new ArgumentException("Arg x is invalid!")));
|
||||||
await Task.Run(() => Categories.UnionWith(cats.Select(x => new TreeItemData(x)).ToHashSet()));*/
|
|
||||||
|
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
Log.Verbose(" Guide initialized!");
|
Log.Verbose(" Guide initialized!");
|
||||||
//await Task.Run(() => Categories = cats.Select(x => new TreeItemData(x)).ToHashSet());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
Binary file not shown.
Loading…
Reference in New Issue
Block a user