mirror of
https://github.com/hmaxnl/SharpRSS.git
synced 2025-01-18 12:54:20 +01:00
Custom guideitem, cleaned models. Added favicon resolving.
This commit is contained in:
parent
ff1185729b
commit
88ce202de4
12
SharpRSS.sln
12
SharpRSS.sln
|
@ -1,10 +1,13 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebSharpRSS", "WebSharpRSS\WebSharpRSS.csproj", "{749FE445-8D46-4631-BB57-FC648E22ADB6}"
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.5.33627.172
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WebSharpRSS", "WebSharpRSS\WebSharpRSS.csproj", "{749FE445-8D46-4631-BB57-FC648E22ADB6}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpRss", "SharpRss\SharpRss.csproj", "{DB3777BA-A383-4B83-AF65-DE51907CE75A}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SharpRss", "SharpRss\SharpRss.csproj", "{DB3777BA-A383-4B83-AF65-DE51907CE75A}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ToolQit", "ToolQit\ToolQit\ToolQit.csproj", "{BD905344-9DBF-4986-B853-E70B22848876}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ToolQit", "ToolQit\ToolQit\ToolQit.csproj", "{BD905344-9DBF-4986-B853-E70B22848876}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
|
@ -25,4 +28,7 @@ Global
|
|||
{BD905344-9DBF-4986-B853-E70B22848876}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{BD905344-9DBF-4986-B853-E70B22848876}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
|
|
@ -16,7 +16,7 @@ namespace SharpRss
|
|||
|
||||
public static async Task<Feed> GetFeed(string urlKey)
|
||||
{
|
||||
Log.Verbose("Request for: {UrlKey}", urlKey);
|
||||
Log.Verbose("Fetching feed: {UrlKey}", urlKey);
|
||||
if (urlKey.IsNullEmptyWhiteSpace())
|
||||
{
|
||||
Log.Error("RSS Url is empty!");
|
||||
|
|
|
@ -5,7 +5,7 @@ namespace SharpRss.Models
|
|||
/// <summary>
|
||||
/// To store and load data from file/database
|
||||
/// </summary>
|
||||
public class CategoryModel : IGuideItem
|
||||
public class CategoryModel
|
||||
{
|
||||
public CategoryModel(CategoryModel model)
|
||||
{
|
||||
|
@ -20,7 +20,5 @@ namespace SharpRss.Models
|
|||
|
||||
public string Name { get; set; }
|
||||
public HashSet<FeedModel> Feeds { get; set; }
|
||||
public bool IsSelected { get; set; }
|
||||
public bool IsExpanded { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,43 +1,40 @@
|
|||
using System.Dynamic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using CodeHollow.FeedReader;
|
||||
using Serilog;
|
||||
using ToolQit.Extensions;
|
||||
using CodeHollow.FeedReader;
|
||||
|
||||
namespace SharpRss.Models
|
||||
{
|
||||
public class FeedModel : IGuideItem
|
||||
public class FeedModel
|
||||
{
|
||||
public FeedModel(string rssUrl)
|
||||
{
|
||||
_rssUrl = rssUrl;
|
||||
Task.Run(async () => Base = await FeedCache.GetFeed(_rssUrl));
|
||||
_fetchTask = FetchAsync();
|
||||
}
|
||||
private Task _fetchTask;
|
||||
|
||||
private async Task FetchAsync()
|
||||
{
|
||||
IsReady = false;
|
||||
_feed = await FeedCache.GetFeed(_rssUrl);
|
||||
IsReady = true;
|
||||
}
|
||||
|
||||
public Feed Base { get; private set; }
|
||||
public bool IsSelected { get; set; }
|
||||
public bool IsExpanded { get; set; }
|
||||
private Feed? _feed;
|
||||
public Feed Base {
|
||||
get
|
||||
{
|
||||
if (_feed == null)
|
||||
{
|
||||
if (_fetchTask.IsFaulted)
|
||||
{ IsFaulted = _fetchTask.IsFaulted; return new Feed(); }
|
||||
if (!(_fetchTask.Status == TaskStatus.Running || _fetchTask.Status == TaskStatus.WaitingForActivation))
|
||||
_fetchTask.Start();
|
||||
_fetchTask.Wait();
|
||||
}
|
||||
return _feed ?? new Feed();
|
||||
}
|
||||
}
|
||||
public bool IsFaulted { get; private set; }
|
||||
public bool IsReady { get; private set; }
|
||||
private readonly string _rssUrl;
|
||||
/*public async void Load(bool reload = false)
|
||||
{
|
||||
if (Base != null && !reload || !IsReady) return;
|
||||
if (_rssUrl.IsNullEmptyWhiteSpace())
|
||||
{
|
||||
Log.Error("RSS Url is empty!");
|
||||
return;
|
||||
}
|
||||
IsReady = false;
|
||||
string feedUrl;
|
||||
var urls = await FeedReader.GetFeedUrlsFromUrlAsync(_rssUrl);
|
||||
if (!urls.Any())
|
||||
feedUrl = _rssUrl;
|
||||
else
|
||||
feedUrl = urls.First().Url;
|
||||
Log.Verbose("Creating feed: {FeedUrl}", feedUrl);
|
||||
Base = await FeedReader.ReadAsync(feedUrl);
|
||||
IsReady = true;
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
namespace SharpRss.Models
|
||||
{
|
||||
public interface IGuideItem
|
||||
{
|
||||
public bool IsSelected { get; set; }
|
||||
public bool IsExpanded { get; set; }
|
||||
}
|
||||
}
|
|
@ -22,7 +22,7 @@ namespace SharpRss
|
|||
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")
|
||||
new FeedModel("https://www.nasa.gov/rss/dyn/breaking_news.rss"),
|
||||
};
|
||||
private static HashSet<FeedModel> feedSet2 = new HashSet<FeedModel>()
|
||||
{
|
||||
|
|
|
@ -12,7 +12,8 @@ namespace WebSharpRSS
|
|||
public static void SetAppDefaultSettings(this DataContainer dataCon)
|
||||
{
|
||||
var paths = dataCon["Paths"];
|
||||
paths.Set("FaviconResolveUrl", "https://icons.duckduckgo.com/ip3/{0}.ico", false);
|
||||
//paths.Set("FaviconResolveUrl", "https://icons.duckduckgo.com/ip3/{0}.ico", false);
|
||||
paths.Set("FaviconResolveUrl", "http://www.google.com/s2/favicons?domain={0}", false);
|
||||
paths.Set("LogPath", Path.Combine(Environment.CurrentDirectory, "logs", "log_.json"), false);
|
||||
|
||||
var dbSql = dataCon["SQL"];
|
||||
|
|
|
@ -1,40 +0,0 @@
|
|||
using System.Collections.Generic;
|
||||
using CodeHollow.FeedReader;
|
||||
using SharpRss.Models;
|
||||
|
||||
namespace WebSharpRSS.Models
|
||||
{
|
||||
public class GuideItem
|
||||
{
|
||||
public GuideItem(CategoryModel catModel)
|
||||
{
|
||||
_categoryModel = catModel;
|
||||
Feeds = _categoryModel.Feeds;
|
||||
}
|
||||
|
||||
public GuideItem(FeedModel feedModel)
|
||||
{
|
||||
_feedModel = feedModel;
|
||||
Feed = _feedModel.Base;
|
||||
}
|
||||
|
||||
private readonly CategoryModel? _categoryModel;
|
||||
private readonly FeedModel? _feedModel;
|
||||
|
||||
public string Title { get; set; }
|
||||
public bool IsSelected { get; set; }
|
||||
public string Icon { get; set; }
|
||||
|
||||
// Category
|
||||
public bool IsExpanded { get; set; }
|
||||
public HashSet<FeedModel>? Feeds { get; set; }
|
||||
// Feed
|
||||
public Feed? Feed { get; set; }
|
||||
|
||||
// Functions
|
||||
public async void ItemClick()
|
||||
{
|
||||
IsExpanded = !IsExpanded;
|
||||
}
|
||||
}
|
||||
}
|
43
WebSharpRSS/Models/GuideItemModel.cs
Normal file
43
WebSharpRSS/Models/GuideItemModel.cs
Normal file
|
@ -0,0 +1,43 @@
|
|||
using CodeHollow.FeedReader;
|
||||
using MudBlazor;
|
||||
using SharpRss.Models;
|
||||
using ToolQit;
|
||||
|
||||
namespace WebSharpRSS.Models
|
||||
{
|
||||
public class GuideItemModel
|
||||
{
|
||||
public GuideItemModel(CategoryModel catModel)
|
||||
{
|
||||
CategoryModel = catModel;
|
||||
Feeds = CategoryModel.Feeds.Where(x => !x.IsFaulted && x.Base != null).Select(x => new GuideItemModel(x)).ToHashSet();
|
||||
Title = CategoryModel.Name;
|
||||
Icon = Icons.Material.Filled.RssFeed;
|
||||
}
|
||||
|
||||
public GuideItemModel(FeedModel feedModel)
|
||||
{
|
||||
if (feedModel.IsFaulted)
|
||||
return;
|
||||
FeedModel = feedModel;
|
||||
Feed = FeedModel.Base;
|
||||
Title = Feed.Title;
|
||||
string faviconAdress = Feed.Link.Remove(Feed.Link.IndexOf("http"), Feed.Link.IndexOf("://") + 3);
|
||||
FaviconUrl = string.Format(Caretaker.Settings["Paths"].GetString("FaviconResolveUrl"), faviconAdress);
|
||||
}
|
||||
|
||||
public readonly CategoryModel? CategoryModel;
|
||||
public readonly FeedModel? FeedModel;
|
||||
|
||||
public string Title { get; set; } = string.Empty;
|
||||
public bool IsSelected { get; set; }
|
||||
public string? Icon { get; set; }
|
||||
public string? FaviconUrl { get; set; }
|
||||
|
||||
// Category
|
||||
public bool IsExpanded { get; set; }
|
||||
public HashSet<GuideItemModel>? Feeds { get; set; }
|
||||
// Feed
|
||||
public Feed? Feed { get; set; }
|
||||
}
|
||||
}
|
|
@ -5,8 +5,10 @@ using MudBlazor;
|
|||
using MudBlazor.Services;
|
||||
using Serilog;
|
||||
using SharpRss;
|
||||
using SharpRss.Models;
|
||||
using ToolQit;
|
||||
using WebSharpRSS;
|
||||
using WebSharpRSS.Models;
|
||||
|
||||
Caretaker.Settings.SetAppDefaultSettings();
|
||||
Bootstrapper.SetupLogging();
|
||||
|
|
|
@ -3,10 +3,10 @@
|
|||
@using ToolQit
|
||||
@using ToolQit.Containers
|
||||
@using ToolQit.Extensions
|
||||
@using WebSharpRSS.Models;
|
||||
<style>
|
||||
.cat-item {
|
||||
background: var(--background-color);
|
||||
tab-index: 0;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
position: relative;
|
||||
|
@ -34,7 +34,6 @@
|
|||
|
||||
.feed-item {
|
||||
background: var(--background-color);
|
||||
tab-index: 0;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
position: relative;
|
||||
|
@ -64,21 +63,31 @@
|
|||
|
||||
<div>
|
||||
<MudText>@HeaderText</MudText>
|
||||
@foreach (CategoryModel guideCategory in Categories)
|
||||
@foreach (GuideItemModel guideModel in GuideItems)
|
||||
{
|
||||
<GuideItem Model="@guideModel" ItemClicked="ItemClicked"/>
|
||||
#if false
|
||||
<div>
|
||||
<div @onclick="@(() => ItemClicked(guideCategory))" class="cat-item mud-ripple" style="--hover-bg-color: @Colors.Blue.Accent1; --background-color: @(guideCategory.IsSelected ? Colors.Blue.Accent2 : "transparent")">
|
||||
<div @onclick="@(() => guideItem.ItemClick())" class="cat-item mud-ripple" style="--hover-bg-color: @Colors.Blue.Accent1; --background-color: @(guideItem.IsSelected ? Colors.Blue.Accent2 : "transparent")">
|
||||
<div class="cat-item-icon">
|
||||
<MudIcon Class="pointer-events-none" Icon="@Icons.Material.Filled.RssFeed" Size="Size.Medium"/>
|
||||
@if (guideItem.FaviconUrl != null)
|
||||
{
|
||||
<MudImage ObjectFit="ObjectFit.ScaleDown" Src="@guideItem.FaviconUrl" />
|
||||
}
|
||||
else
|
||||
{
|
||||
<MudIcon Class="pointer-events-none" Icon="@guideItem.Icon" Size="Size.Medium" />
|
||||
}
|
||||
|
||||
</div>
|
||||
<div class="cat-item-text">
|
||||
<MudText Class="pointer-events-none" Typo="Typo.subtitle1">@guideCategory.Name</MudText>
|
||||
<MudText Class="pointer-events-none" Typo="Typo.subtitle1">@guideItem.Title</MudText>
|
||||
</div>
|
||||
</div>
|
||||
@* Feeds *@
|
||||
@if (guideCategory.IsExpanded && guideCategory.Feeds != null)
|
||||
@if (guideItem.IsExpanded && guideItem.Feeds != null)
|
||||
{
|
||||
foreach (FeedModel feed in guideCategory.Feeds)
|
||||
foreach (FeedModel feed in guideItem.Feeds)
|
||||
{
|
||||
if (feed == null || feed.Base == null) continue;
|
||||
<div @onclick="() => ItemClicked(feed)" class="feed-item mud-ripple" style="--hover-bg-color: @Colors.Blue.Accent1; --background-color: @(feed.IsSelected ? Colors.Blue.Accent2 : "transparent")">
|
||||
|
@ -100,40 +109,41 @@
|
|||
}
|
||||
}
|
||||
</div>
|
||||
#endif
|
||||
}
|
||||
</div>
|
||||
|
||||
@code {
|
||||
[Parameter]
|
||||
public string HeaderText { get; set; }
|
||||
public string HeaderText { get; set; } = string.Empty;
|
||||
[Parameter]
|
||||
public HashSet<CategoryModel> Categories { get; set; } = new HashSet<CategoryModel>();
|
||||
public HashSet<GuideItemModel> GuideItems { get; set; } = new HashSet<GuideItemModel>();
|
||||
[Parameter]
|
||||
public Action<CategoryModel>? CatItemClicked { get; set; }
|
||||
[Parameter]
|
||||
public Action<FeedModel>? FeedItemClicked { get; set; }
|
||||
|
||||
IGuideItem? _selectedItem;
|
||||
GuideItemModel? _selectedItem;
|
||||
|
||||
void ItemClicked(IGuideItem categoryItem)
|
||||
void ItemClicked(GuideItemModel model)
|
||||
{
|
||||
categoryItem.IsExpanded = !categoryItem.IsExpanded;
|
||||
|
||||
if (_selectedItem != categoryItem)
|
||||
model.IsExpanded = !model.IsExpanded;
|
||||
if (_selectedItem != model)
|
||||
{
|
||||
if (_selectedItem != null)
|
||||
_selectedItem.IsSelected = false;
|
||||
_selectedItem = categoryItem;
|
||||
_selectedItem = model;
|
||||
_selectedItem.IsSelected = true;
|
||||
}
|
||||
switch (categoryItem)
|
||||
if (model.Feeds != null && model.Feeds.Count >= 1)
|
||||
{
|
||||
case CategoryModel catGuideItem:
|
||||
CatItemClicked?.Invoke(catGuideItem);
|
||||
break;
|
||||
case FeedModel feedGuideItem:
|
||||
FeedItemClicked?.Invoke(feedGuideItem);
|
||||
break;
|
||||
if (model.CategoryModel != null)
|
||||
CatItemClicked?.Invoke(model.CategoryModel);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (model.FeedModel != null)
|
||||
FeedItemClicked?.Invoke(model.FeedModel);
|
||||
}
|
||||
}
|
||||
}
|
45
WebSharpRSS/Shared/GuideItem.razor
Normal file
45
WebSharpRSS/Shared/GuideItem.razor
Normal file
|
@ -0,0 +1,45 @@
|
|||
@using WebSharpRSS.Models;
|
||||
|
||||
|
||||
<div>
|
||||
<div @onclick="@(() => ItemClickedVoid())" class="cat-item mud-ripple" style="--hover-bg-color: @Colors.Blue.Accent1; --background-color: @(Model.IsSelected ? Colors.Blue.Accent2 : "transparent")">
|
||||
<div class="cat-item-icon">
|
||||
@if (Model.FaviconUrl != null)
|
||||
{
|
||||
<MudImage ObjectFit="ObjectFit.ScaleDown" Src="@Model.FaviconUrl" />
|
||||
}
|
||||
else
|
||||
{
|
||||
<MudIcon Class="pointer-events-none" Icon="@Model.Icon" Size="Size.Medium" />
|
||||
}
|
||||
|
||||
</div>
|
||||
<div class="cat-item-text">
|
||||
<MudText Class="pointer-events-none" Typo="Typo.subtitle1">@Model.Title</MudText>
|
||||
</div>
|
||||
</div>
|
||||
@if (IsExpanded && Model.Feeds != null && !(Model.Feeds.Count <= 0))
|
||||
{
|
||||
foreach (GuideItemModel item in Model.Feeds)
|
||||
{
|
||||
<div style="margin-left: 20px">
|
||||
<GuideItem Model="@item" />
|
||||
</div>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
|
||||
@code {
|
||||
[Parameter]
|
||||
public GuideItemModel Model { get; set; }
|
||||
[Parameter]
|
||||
public EventCallback<GuideItemModel> ItemClicked { get; set; }
|
||||
|
||||
public bool IsExpanded { get; set; }
|
||||
|
||||
private void ItemClickedVoid()
|
||||
{
|
||||
IsExpanded = !IsExpanded;
|
||||
ItemClicked.InvokeAsync(Model);
|
||||
}
|
||||
}
|
|
@ -2,6 +2,7 @@
|
|||
@using MudBlazor.Utilities
|
||||
@using CodeHollow.FeedReader
|
||||
@using Serilog
|
||||
@using WebSharpRSS.Models;
|
||||
|
||||
@inject RssService _rssService
|
||||
|
||||
|
@ -9,20 +10,17 @@
|
|||
<MudNavMenu>
|
||||
<MudNavLink Href="/" Icon="@Icons.Material.Filled.Home">Home</MudNavLink>
|
||||
</MudNavMenu>
|
||||
<CategoryGuide Categories="Categories" CatItemClicked="CategoryClicked" FeedItemClicked="FeedClicked"/>
|
||||
<CategoryGuide GuideItems="Categories" CatItemClicked="CategoryClicked" FeedItemClicked="FeedClicked"/>
|
||||
</MudStack>
|
||||
|
||||
@code {
|
||||
public HashSet<CategoryModel> Categories = new HashSet<CategoryModel>();
|
||||
protected override void OnInitialized()
|
||||
public HashSet<GuideItemModel> Categories = new HashSet<GuideItemModel>();
|
||||
protected override async void OnInitialized()
|
||||
{
|
||||
Log.Verbose("Setting up test data");
|
||||
Categories = _rssService.GetCategories().Result;
|
||||
/*Cats = _rssService.GetCategories().Result.Select(x => new GuideModel(x)).ToHashSet();*/
|
||||
/*Categories.Add(new CategoryGuideItem() { CategoryTitle = "Social", CategoryIcon = Icons.Material.Filled.People });
|
||||
Categories.Add(new CategoryGuideItem() { CategoryTitle = "Blogs", CategoryIcon = Icons.Material.Filled.RssFeed, CategoryHexColor = Colors.Green.Accent1 });
|
||||
Categories.Add(new CategoryGuideItem() { CategoryTitle = "Tech", CategoryIcon = Icons.Material.Filled.Computer, CategoryHexColor = Colors.Brown.Lighten1 });
|
||||
Categories.Add(new CategoryGuideItem() { CategoryTitle = "News", CategoryIcon = Icons.Material.Filled.Newspaper, CategoryHexColor = Colors.Red.Accent1 });*/
|
||||
//Categories = _rssService.GetCategories().Result;
|
||||
HashSet<CategoryModel> cats = await _rssService.GetCategories();
|
||||
await Task.Run(() => Categories = cats.Select(x => new GuideItemModel(x)).ToHashSet());
|
||||
}
|
||||
|
||||
private void Callback(MudListItem obj)
|
||||
|
|
Loading…
Reference in New Issue
Block a user