mirror of
https://github.com/hmaxnl/SharpRSS.git
synced 2025-01-18 21:04:21 +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
|
namespace SharpRss.Models
|
||||||
{
|
{
|
||||||
|
@ -9,14 +10,9 @@ namespace SharpRss.Models
|
||||||
_rssUrl = rssUrl;
|
_rssUrl = rssUrl;
|
||||||
_fetchTask = FetchAsync();
|
_fetchTask = FetchAsync();
|
||||||
}
|
}
|
||||||
private Task _fetchTask;
|
private readonly Task _fetchTask;
|
||||||
|
|
||||||
private async Task FetchAsync()
|
public async Task FetchAsync() => _feed = await FeedCache.GetFeed(_rssUrl);
|
||||||
{
|
|
||||||
IsReady = false;
|
|
||||||
_feed = await FeedCache.GetFeed(_rssUrl);
|
|
||||||
IsReady = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Feed? _feed;
|
private Feed? _feed;
|
||||||
public Feed Base {
|
public Feed Base {
|
||||||
|
@ -25,16 +21,14 @@ namespace SharpRss.Models
|
||||||
if (_feed == null)
|
if (_feed == null)
|
||||||
{
|
{
|
||||||
if (_fetchTask.IsFaulted)
|
if (_fetchTask.IsFaulted)
|
||||||
{ IsFaulted = _fetchTask.IsFaulted; return new Feed(); }
|
{ return new Feed(); }
|
||||||
if (!(_fetchTask.Status == TaskStatus.Running || _fetchTask.Status == TaskStatus.WaitingForActivation))
|
if (_fetchTask.Status is not (TaskStatus.Running or TaskStatus.WaitingForActivation))
|
||||||
_fetchTask.Start();
|
_fetchTask.Start();
|
||||||
_fetchTask.Wait();
|
_fetchTask.Wait();
|
||||||
}
|
}
|
||||||
return _feed ?? new Feed();
|
return _feed ?? new Feed();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public bool IsFaulted { get; private set; }
|
|
||||||
public bool IsReady { get; private set; }
|
|
||||||
private readonly string _rssUrl;
|
private readonly string _rssUrl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,6 @@ namespace SharpRss
|
||||||
private static HashSet<FeedModel> feedSet2 = new HashSet<FeedModel>()
|
private static HashSet<FeedModel> feedSet2 = new HashSet<FeedModel>()
|
||||||
{
|
{
|
||||||
new FeedModel("https://journals.plos.org/plosone/feed/atom"),
|
new FeedModel("https://journals.plos.org/plosone/feed/atom"),
|
||||||
new FeedModel("https://cyberciti.biz/feed"),
|
|
||||||
new FeedModel("https://itsfoss.com/feed")
|
new FeedModel("https://itsfoss.com/feed")
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using CodeHollow.FeedReader;
|
using CodeHollow.FeedReader;
|
||||||
using MudBlazor;
|
using MudBlazor;
|
||||||
using SharpRss.Models;
|
using SharpRss.Models;
|
||||||
|
@ -5,25 +8,23 @@ using ToolQit;
|
||||||
|
|
||||||
namespace WebSharpRSS.Models
|
namespace WebSharpRSS.Models
|
||||||
{
|
{
|
||||||
public class GuideItemModel
|
public class TreeItemData
|
||||||
{
|
{
|
||||||
public GuideItemModel(CategoryModel catModel)
|
public TreeItemData(CategoryModel catModel)
|
||||||
{
|
{
|
||||||
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;
|
Title = CategoryModel.Name;
|
||||||
Icon = Icons.Material.Filled.RssFeed;
|
Icon = Icons.Material.Filled.RssFeed;
|
||||||
}
|
}
|
||||||
|
|
||||||
public GuideItemModel(FeedModel feedModel)
|
public TreeItemData(FeedModel feedModel)
|
||||||
{
|
{
|
||||||
if (feedModel.IsFaulted)
|
|
||||||
return;
|
|
||||||
FeedModel = feedModel;
|
FeedModel = feedModel;
|
||||||
Feed = FeedModel.Base;
|
Feed = FeedModel.Base;
|
||||||
Title = Feed.Title;
|
Title = Feed.Title;
|
||||||
string faviconAdress = Feed.Link.Remove(Feed.Link.IndexOf("http"), Feed.Link.IndexOf("://") + 3);
|
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"), faviconAdress);
|
FaviconUrl = string.Format(Caretaker.Settings["Paths"].GetString("FaviconResolveUrl"), faviconAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
public readonly CategoryModel? CategoryModel;
|
public readonly CategoryModel? CategoryModel;
|
||||||
|
@ -36,7 +37,7 @@ namespace WebSharpRSS.Models
|
||||||
|
|
||||||
// Category
|
// Category
|
||||||
public bool IsExpanded { get; set; }
|
public bool IsExpanded { get; set; }
|
||||||
public HashSet<GuideItemModel>? Feeds { get; set; }
|
public HashSet<TreeItemData>? Feeds { get; set; }
|
||||||
// Feed
|
// Feed
|
||||||
public Feed? Feed { get; set; }
|
public Feed? Feed { get; set; }
|
||||||
}
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"Paths": {
|
"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"
|
"LogPath": "/home/max/GitHub/SharpRSS/WebSharpRSS/logs/log_.json"
|
||||||
},
|
},
|
||||||
"SQL": {
|
"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>
|
<MudNavMenu>
|
||||||
<MudNavLink Href="/" Icon="@Icons.Material.Filled.Home">Home</MudNavLink>
|
<MudNavLink Href="/" Icon="@Icons.Material.Filled.Home">Home</MudNavLink>
|
||||||
</MudNavMenu>
|
</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>
|
</MudStack>
|
||||||
|
|
||||||
@code {
|
@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()
|
protected override async void OnInitialized()
|
||||||
{
|
{
|
||||||
Log.Verbose("Setting up test data");
|
Log.Verbose("Loading guide data...");
|
||||||
//Categories = _rssService.GetCategories().Result;
|
|
||||||
HashSet<CategoryModel> cats = await _rssService.GetCategories();
|
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