Working out treeview.

This commit is contained in:
Max 2023-05-15 20:42:42 +02:00
parent 88ce202de4
commit cd9233c162
7 changed files with 27 additions and 242 deletions

View File

@ -1,4 +1,5 @@
using CodeHollow.FeedReader;
using System.Threading.Tasks;
using CodeHollow.FeedReader;
namespace SharpRss.Models
{
@ -9,14 +10,9 @@ namespace SharpRss.Models
_rssUrl = rssUrl;
_fetchTask = FetchAsync();
}
private Task _fetchTask;
private readonly Task _fetchTask;
private async Task FetchAsync()
{
IsReady = false;
_feed = await FeedCache.GetFeed(_rssUrl);
IsReady = true;
}
public async Task FetchAsync() => _feed = await FeedCache.GetFeed(_rssUrl);
private Feed? _feed;
public Feed Base {
@ -25,16 +21,14 @@ namespace SharpRss.Models
if (_feed == null)
{
if (_fetchTask.IsFaulted)
{ IsFaulted = _fetchTask.IsFaulted; return new Feed(); }
if (!(_fetchTask.Status == TaskStatus.Running || _fetchTask.Status == TaskStatus.WaitingForActivation))
{ return new Feed(); }
if (_fetchTask.Status is not (TaskStatus.Running or 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;
}
}

View File

@ -27,7 +27,6 @@ namespace SharpRss
private static HashSet<FeedModel> feedSet2 = new HashSet<FeedModel>()
{
new FeedModel("https://journals.plos.org/plosone/feed/atom"),
new FeedModel("https://cyberciti.biz/feed"),
new FeedModel("https://itsfoss.com/feed")
};

View File

@ -1,3 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using CodeHollow.FeedReader;
using MudBlazor;
using SharpRss.Models;
@ -5,25 +8,23 @@ using ToolQit;
namespace WebSharpRSS.Models
{
public class GuideItemModel
public class TreeItemData
{
public GuideItemModel(CategoryModel catModel)
public TreeItemData(CategoryModel catModel)
{
CategoryModel = catModel;
Feeds = CategoryModel.Feeds.Where(x => !x.IsFaulted && x.Base != null).Select(x => new GuideItemModel(x)).ToHashSet();
Feeds = CategoryModel.Feeds.Where(x => x.Base != null).Select(x => new TreeItemData(x)).ToHashSet();
Title = CategoryModel.Name;
Icon = Icons.Material.Filled.RssFeed;
}
public GuideItemModel(FeedModel feedModel)
public TreeItemData(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);
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);
}
public readonly CategoryModel? CategoryModel;
@ -36,7 +37,7 @@ namespace WebSharpRSS.Models
// Category
public bool IsExpanded { get; set; }
public HashSet<GuideItemModel>? Feeds { get; set; }
public HashSet<TreeItemData>? Feeds { get; set; }
// Feed
public Feed? Feed { get; set; }
}

View File

@ -1,6 +1,6 @@
{
"Paths": {
"FaviconResolveUrl": "https://icons.duckduckgo.com/ip3/{0}.ico",
"FaviconResolveUrl": "http://www.google.com/s2/favicons?domain={0}",
"LogPath": "/home/max/GitHub/SharpRSS/WebSharpRSS/logs/log_.json"
},
"SQL": {

View File

@ -1,149 +0,0 @@
@using CodeHollow.FeedReader
@using SharpRss.Models
@using ToolQit
@using ToolQit.Containers
@using ToolQit.Extensions
@using WebSharpRSS.Models;
<style>
.cat-item {
background: var(--background-color);
width: 100%;
display: flex;
position: relative;
box-sizing: border-box;
text-align: start;
align-items: center;
padding-top: 8px;
padding-bottom: 8px;
padding-left: 12px;
justify-content: flex-start;
text-decoration: none;
}
.cat-item:hover {
background: var(--hover-bg-color);
}
.cat-item-text {
flex: 1 1 auto;
min-width: 0;
}
.cat-item-icon {
display: inline-flex;
min-width: 56px;
flex-shrink: 0;
}
.feed-item {
background: var(--background-color);
width: 100%;
display: flex;
position: relative;
box-sizing: border-box;
text-align: start;
align-items: center;
padding-top: 8px;
padding-bottom: 8px;
padding-left: 30px;
justify-content: flex-start;
text-decoration: none;
}
.feed-item:hover {
background: var(--hover-bg-color);
}
.feed-item-text {
flex: 1 1 auto;
min-width: 0;
}
.feed-item-icon {
display: inline-flex;
min-width: 56px;
flex-shrink: 0;
}
</style>
<div>
<MudText>@HeaderText</MudText>
@foreach (GuideItemModel guideModel in GuideItems)
{
<GuideItem Model="@guideModel" ItemClicked="ItemClicked"/>
#if false
<div>
<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">
@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">@guideItem.Title</MudText>
</div>
</div>
@* Feeds *@
@if (guideItem.IsExpanded && guideItem.Feeds != null)
{
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")">
<div class="feed-item-icon">
@*@if (!guideFeed.FaviconUrl.IsNullEmptyWhiteSpace())
{
<MudImage ObjectFit="ObjectFit.ScaleDown" Src="@guideFeed.FaviconUrl"/>
}
else
{
<MudIcon Icon="@Icons.Material.Filled.RssFeed" Size="Size.Medium"/>
}*@
<MudIcon Icon="@Icons.Material.Filled.RssFeed" Size="Size.Medium"/>
</div>
<div class="feed-item-text">
<MudText Class="pointer-events-none">@feed.Base.Title</MudText>
</div>
</div>
}
}
</div>
#endif
}
</div>
@code {
[Parameter]
public string HeaderText { get; set; } = string.Empty;
[Parameter]
public HashSet<GuideItemModel> GuideItems { get; set; } = new HashSet<GuideItemModel>();
[Parameter]
public Action<CategoryModel>? CatItemClicked { get; set; }
[Parameter]
public Action<FeedModel>? FeedItemClicked { get; set; }
GuideItemModel? _selectedItem;
void ItemClicked(GuideItemModel model)
{
model.IsExpanded = !model.IsExpanded;
if (_selectedItem != model)
{
if (_selectedItem != null)
_selectedItem.IsSelected = false;
_selectedItem = model;
_selectedItem.IsSelected = true;
}
if (model.Feeds != null && model.Feeds.Count >= 1)
{
if (model.CategoryModel != null)
CatItemClicked?.Invoke(model.CategoryModel);
}
else
{
if (model.FeedModel != null)
FeedItemClicked?.Invoke(model.FeedModel);
}
}
}

View File

@ -1,45 +0,0 @@
@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);
}
}

View File

@ -10,36 +10,21 @@
<MudNavMenu>
<MudNavLink Href="/" Icon="@Icons.Material.Filled.Home">Home</MudNavLink>
</MudNavMenu>
<CategoryGuide GuideItems="Categories" CatItemClicked="CategoryClicked" FeedItemClicked="FeedClicked"/>
<MudTreeView Items="Categories" @bind-SelectedValue="SelectedItem" @bind-ActivatedItem="ActivatedItem" Hover="true">
<ItemTemplate>
<MudTreeViewItem Items="@context.Feeds" Icon="@context.Icon" Text="@context.Title"/>
</ItemTemplate>
</MudTreeView>
</MudStack>
@code {
public HashSet<GuideItemModel> Categories = new HashSet<GuideItemModel>();
public HashSet<TreeItemData> Categories = new HashSet<TreeItemData>();
private TreeItemData ActivatedItem { get; set; }
private TreeItemData SelectedItem { get; set; }
protected override async void OnInitialized()
{
Log.Verbose("Setting up test data");
//Categories = _rssService.GetCategories().Result;
Log.Verbose("Loading guide data...");
HashSet<CategoryModel> cats = await _rssService.GetCategories();
await Task.Run(() => Categories = cats.Select(x => new GuideItemModel(x)).ToHashSet());
await Task.Run(() => Categories = cats.Select(x => new TreeItemData(x)).ToHashSet());
}
private void Callback(MudListItem obj)
{
switch (obj.Value)
{
case CategoryModel catModel:
break;
case FeedModel feedModel:
break;
}
}
private void CategoryClicked(CategoryModel cat)
{
}
private void FeedClicked(FeedModel guideFeedItem)
{
}
}