mirror of
https://github.com/hmaxnl/SharpRSS.git
synced 2025-01-18 12:54:20 +01:00
Working out treeview.
This commit is contained in:
parent
88ce202de4
commit
cd9233c162
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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")
|
||||
};
|
||||
|
||||
|
|
|
@ -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; }
|
||||
}
|
|
@ -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": {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
{
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user