UI Tuneup!

This commit is contained in:
Max 2023-05-26 21:54:12 +02:00
parent 8af1497695
commit 863aa4777e
11 changed files with 216 additions and 184 deletions

View File

@ -5,7 +5,6 @@ using System.Threading.Tasks;
using CodeHollow.FeedReader;
using Serilog;
using SharpRss.Models;
using ToolQit.Extensions;
namespace SharpRss.Services
{

View File

@ -3,13 +3,27 @@
<MudThemeProvider IsDarkMode="true"/>
<MudDialogProvider/>
<MudSnackbarProvider/>
<style>
.blur_transparency {
backdrop-filter: blur(16px) saturate(180%);
background: rgba(0,0,0,0.3);
}
.layout_image{
background-image: url('http://s1.picswalls.com/wallpapers/2016/06/10/best-4k-wallpaper_065236736_309.jpg');
height: 100%;
background-position: center;
background-repeat: no-repeat;
background-size: cover;
background-attachment: fixed;
}
</style>
<MudLayout style="background-image: url('http://s1.picswalls.com/wallpapers/2016/06/10/best-4k-wallpaper_065236736_309.jpg'); height: 100%; background-position: center; background-repeat: no-repeat; background-size: cover; background-attachment: fixed;">
<!-- Glassmorphism(backdrop-filter: blur(16px) saturate(180%);) added -->
<MudAppBar Color="Color.Transparent" Style="backdrop-filter: blur(16px) saturate(180%);">
<MudIconButton Icon="@Icons.Material.Filled.Menu" Color="Color.Inherit" Edge="Edge.Start" OnClick="@((e) => DrawerToggle())" />
<MudLayout>
<MudAppBar Class="blur_transparency">
<MudIconButton Icon="@Icons.Material.Filled.Menu" Color="Color.Inherit" Edge="Edge.Start" OnClick="@((e) => DrawerToggle())"/>
<MudText Typo="Typo.h6">SharpRSS</MudText>
<MudSpacer/>
<MudIconButton Icon="@Icons.Custom.Brands.GitHub" Href="https://github.com/hmaxnl/SharpRSS" Target="_blank"></MudIconButton>
</MudAppBar>
<MudDrawer @bind-Open="@_drawerOpen" ClipMode="DrawerClipMode.Always">
<SideGuide/>

View File

@ -8,18 +8,17 @@ namespace WebSharpRSS.Models
{
public FeedItemData()
{
if (Link == null) return;
//FaviconUrl = new Uri(Link).AbsoluteUri;
//FaviconUrl = string.Format(Caretaker.Settings["Paths"].GetString("FaviconResolveUrl"), Link.Remove(Link.IndexOf("http", StringComparison.Ordinal), Link.IndexOf("://", StringComparison.Ordinal) + 3));
}
public static FeedItemData? FromModel(FeedItemModel model) => Utilities.ConvertFrom<FeedItemData, FeedItemModel>(model);
private string? _faviconUrl;
public string? FaviconUrl
{
get
{
if (Link == null) return null;
Uri uri = new Uri(Link);
return string.Format(Caretaker.Settings["Paths"].GetString("FaviconResolveUrl"), uri.Host);
if (Link == null || _faviconUrl != null) return _faviconUrl;
_faviconUrl = string.Format(Caretaker.Settings["Paths"].GetString("FaviconResolveUrl"), new Uri(Link).Host);
return _faviconUrl;
}
}

View File

@ -19,14 +19,15 @@ namespace WebSharpRSS.Models
public TreeItemData(FeedModel feedModel)
{
FeedModel = feedModel;
Title = feedModel.Title;
FaviconUrl = string.Format(Caretaker.Settings["Paths"].GetString("FaviconResolveUrl"), feedModel.Url.Remove(feedModel.Url.IndexOf("http", StringComparison.Ordinal), feedModel.Url.IndexOf("://", StringComparison.Ordinal) + 3));
Title = feedModel.Title ?? string.Empty;
if (FeedModel.Url == null) return;
FaviconUrl = string.Format(Caretaker.Settings["Paths"].GetString("FaviconResolveUrl"), new Uri(FeedModel.Url).Host);
}
public readonly GroupModel? GroupModel;
public readonly FeedModel? FeedModel;
public HashSet<TreeItemData>? Children { get; set; }
public string Title { get; set; } = string.Empty;
public string Title { get; set; }
public bool IsSelected { get; set; }
public string? Icon { get; set; }
public string? FaviconUrl { get; set; }

View File

@ -1,68 +1,14 @@
@page "/"
@using CodeHollow.FeedReader;
@using SharpRss.Models;
@page "/dashboard"
@using WebSharpRSS.Models;
@using SharpRss.Services
@inject FeedStateContainer _stateContainer;
<MudStack Spacing="2" Class="ml-2 mr-2">
@*@foreach (var feedItemData in _itemDatas)
{
<MudItem>
<MudCard>
<MudCardContent>
<div style="justify-self: start;" class="d-flex align-center">
@if (feedItemData.Icon != null)
{
<MudIcon Icon="@feedItemData.Icon" Style="@($"color:{feedItemData.CategoryColorHex}")" />
}
@if (feedItemData.FaviconUrl != null)
{
<MudImage Src="@feedItemData.FaviconUrl" ObjectFit="ObjectFit.Contain" />
}
<MudText Class="d-inline pa-2 align-center">@feedItemData.FeedItem.Title</MudText>
</div>
<MudText Typo="Typo.body2">@feedItemData.FeedItem.Description</MudText>
<MudText Typo="Typo.overline">@feedItemData.FeedItem.PublishingDate.ToString()</MudText>
</MudCardContent>
</MudCard>
</MudItem>
}*@
</MudStack>
<MudText>Dashboard!</MudText>
<MudGrid Spacing="2" Class="ml-2 mr-2">
</MudGrid>
@code {
protected override void OnInitialized()
{
UpdateFeeds();
//_stateContainer.StateChanged += FeedsChanged;
}
private void FeedsChanged()
{
UpdateFeeds();
InvokeAsync(StateHasChanged);
}
//private HashSet<FeedItemData> _itemDatas = new HashSet<FeedItemData>();
//private TreeItemData? _treeItemData;
private void UpdateFeeds()
{
/*if (_stateContainer.TreeItem == null) return;
_treeItemData = _stateContainer.TreeItem;
if (_treeItemData.Feed != null)
{
Feed feed = _treeItemData.Feed;
_itemDatas = feed.Items.Select(x => new FeedItemData(x) { Icon = _treeItemData.Icon, FaviconUrl = _treeItemData.FaviconUrl, CategoryColorHex = _treeItemData.CategoryModel?.HexColor }).ToHashSet();
}
else if (_treeItemData.Feeds != null)
{
HashSet<FeedItemData> items = new HashSet<FeedItemData>();
foreach (var treeItem in _treeItemData.Feeds)
{
if (treeItem.Feed == null) continue;
items.UnionWith(treeItem.Feed.Items.Select(x => new FeedItemData(x) { Icon = treeItem.Icon, FaviconUrl = treeItem.FaviconUrl, CategoryColorHex = _treeItemData.CategoryModel?.HexColor }));
_itemDatas = items.OrderBy(x => x.FeedItem.PublishingDate).Reverse().ToHashSet();
}
}*/
}
}

View File

@ -0,0 +1,72 @@
@page "/list"
@using WebSharpRSS.Models
@using SharpRss.Services
@inject IDialogService _dialogService;
@inject RssService _rssService;
<div>
@if (_isLoading)
{
<div class="justify-self: center">
<MudProgressCircular Color="Color.Primary" Indeterminate="true" />
<MudText>Loading...</MudText>
</div>
}
else
{
<FeedItemList Items="items"/>
}
</div>
@code {
[Parameter]
[SupplyParameterFromQuery(Name = "fid")]
public string? Fid
{
get => _fid;
set
{
_fid = value;
LoadItems();
}
}
private string? _fid;
[Parameter]
[SupplyParameterFromQuery(Name = "gid")]
public string? Gid
{
get => _gid;
set
{
_gid = value;
LoadItems();
}
}
private string? _gid;
HashSet<FeedItemData> items = new HashSet<FeedItemData>();
bool _isLoading = true;
private async void LoadItems()
{
_isLoading = true;
if (Fid != null)
{
var fItems = await _rssService.GetFeedItemsAsync(Fid);
items = fItems.Select(x => FeedItemData.FromModel(x)).OrderBy(x => x.PublishingDate).Reverse().ToHashSet();
_isLoading = false;
}
else if (Gid != null)
{
var feeds = await _rssService.GetFeedsAsync(Gid);
var feedids = feeds.Select(x => x.Id);
var feedItems = await _rssService.GetFeedItemsFromFeedsAsync(feedids.ToArray());
items = feedItems.Select(x => FeedItemData.FromModel(x)).OrderBy(x => x.PublishingDate).Reverse().ToHashSet();
}
_isLoading = false;
StateHasChanged();
}
protected override void OnInitialized()
{
LoadItems();
}
}

View File

@ -1,107 +1,9 @@
@page "/read"
@using WebSharpRSS.Models;
@using ToolQit.Extensions
@using Serilog
@using SharpRss.Models
@using SharpRss.Services
@inject RssService _rssService;
<MudStack Spacing="2" Class="ml-2 mr-2">
@if (isLoading)
{
<div class="justify-self: center">
<MudProgressCircular Color="Color.Primary" Indeterminate="true" />
<MudText>Loading...</MudText>
</div>
}
else if (faulted)
{
<MudAlert Severity="Severity.Error" Variant="Variant.Filled">Could not load feeds!</MudAlert>
}
else
{
foreach (var feedItemData in items)
{
<MudItem Style="backdrop-filter: blur(16px) saturate(180%);">
<MudCard Style=" background: rgba(0,0,0,0.5);">
<MudCardContent>
<div style="justify-self: start;" class="d-flex align-center">
@if (feedItemData.FaviconUrl != null)
{
<MudImage Src="@feedItemData.FaviconUrl" ObjectFit="ObjectFit.Contain" />
}
<div class="d-inline pa-2 align-center" style="font-size: 16px;">
@((MarkupString)feedItemData.Title)
</div>
@*<MudText Class="d-inline pa-2 align-center">@feedItemData.Title</MudText>*@
</div>
<div>
@((MarkupString)feedItemData.Description)
</div>
@*<MudText Typo="Typo.body2">@feedItemData.Description</MudText>*@
<MudText Typo="Typo.overline">@feedItemData.PublishingDate.ToString()</MudText>
</MudCardContent>
</MudCard>
</MudItem>
}
}
</MudStack>
<MudText Typo="Typo.h1">Nothing here yet!</MudText>
@code {
[Parameter]
[SupplyParameterFromQuery(Name = "fid")]
public string? Fid
{
get => _fid;
set
{
_fid = value;
LoadItems();
}
}
private string? _fid;
[Parameter]
[SupplyParameterFromQuery(Name = "gid")]
public string? Gid
{
get => _gid;
set
{
_gid = value;
LoadItems();
}
}
private string? _gid;
HashSet<FeedItemData> items = new HashSet<FeedItemData>();
bool isLoading = true;
bool faulted = false;
private async void LoadItems()
{
faulted = false;
isLoading = true;
if (Fid != null)
{
var fItems = await _rssService.GetFeedItemsAsync(Fid);
items = fItems.Select(x => FeedItemData.FromModel(x)).OrderBy(x => x.PublishingDate).Reverse().ToHashSet();
isLoading = false;
}
else if (Gid != null)
{
var feeds = await _rssService.GetFeedsAsync(Gid);
var feedids = feeds.Select(x => x.Id);
var feedItems = await _rssService.GetFeedItemsFromFeedsAsync(feedids.ToArray());
items = feedItems.Select(x => FeedItemData.FromModel(x)).OrderBy(x => x.PublishingDate).Reverse().ToHashSet();
}
else
{
faulted = true;
}
isLoading = false;
StateHasChanged();
}
protected override void OnInitialized()
{
LoadItems();
}
}

View File

@ -0,0 +1,60 @@
@using WebSharpRSS.Models
@using Serilog
@using ToolQit.Extensions
@inject IDialogService _dialogService
<MudStack Spacing="2" Class="ma-2">
@if (Items != null)
{
foreach (var feedItemData in Items)
{
<MudItem @onclick="@(() => Callback(feedItemData))">
<MudPaper Height="250" Width="300" Class="px-2">
<div style="justify-self: start;" class="d-flex align-center">
@if (feedItemData.FaviconUrl != null)
{
<MudImage Src="@feedItemData.FaviconUrl" ObjectFit="ObjectFit.Contain"/>
}
<div class="d-inline pa-2 align-center" style="font-size: 16px;">
@if (feedItemData.Title != null)
{
@((MarkupString)feedItemData.Title)
}
</div>
</div>
<div>
@if (feedItemData.Description != null && !feedItemData.Description.IsNullEmptyWhiteSpace())
{
@((MarkupString)feedItemData.Description)
}
else
{
<MudText Color="Color.Dark" Typo="Typo.body2">No description found!</MudText>
}
</div>
<MudText Typo="Typo.overline">@feedItemData.PublishingDate.ToString()</MudText>
</MudPaper>
</MudItem>
}
}
else
{
<MudAlert Severity="Severity.Info" Variant="Variant.Filled">No items to load!</MudAlert>
}
</MudStack>
@code {
[Parameter]
public HashSet<FeedItemData>? Items { get; set; }
DialogOptions _dialogOptions = new DialogOptions() { FullWidth = true, MaxWidth = MaxWidth.ExtraLarge, NoHeader = true, CloseButton = true, CloseOnEscapeKey = true };
private void Callback(FeedItemData feedItem)
{
var parameters = new DialogParameters();
parameters.Add("Data", feedItem);
_dialogService.Show<ReadDialog>("", parameters, _dialogOptions);
Log.Verbose("Item: {ItemId} clicked", feedItem.Id);
}
}

View File

@ -0,0 +1,29 @@
@using WebSharpRSS.Models
@using ToolQit.Extensions
@if (FeedItem != null)
{
<div style="justify-self: start;" class="d-flex align-center">
@if (FeedItem.FaviconUrl != null)
{
<MudImage Src="@FeedItem.FaviconUrl" ObjectFit="ObjectFit.Contain"/>
}
<div class="d-inline px-3 align-center" style="font-size: 30px;">
@((MarkupString)(FeedItem?.Title ?? "This item doesn't contains a title!"))
</div>
</div>
<MudDivider DividerType="DividerType.FullWidth" Light="false" Class="my-2"/>
<div>
@((MarkupString)((FeedItem?.Content == null || FeedItem.Content.IsNullEmptyWhiteSpace() ? FeedItem?.Description : FeedItem.Content) ?? "This item doesn't contain any content!"))
</div>
}
else
{
<MudAlert Severity="Severity.Error" Variant="Variant.Filled">Could not load data!</MudAlert>
}
@code {
[Parameter]
public FeedItemData? FeedItem { get; set; }
}

View File

@ -0,0 +1,13 @@
@using WebSharpRSS.Models
<MudDialog>
<DialogContent>
<ItemView FeedItem="Data"/>
</DialogContent>
</MudDialog>
@code {
[Parameter]
public FeedItemData? Data { get; set; }
}

View File

@ -7,10 +7,10 @@
@using ToolQit.Extensions;
@inject RssService _rssService
@inject NavigationManager Navigation
@inject NavigationManager _navigation
<MudStack Spacing="2">
<MudTreeView Items="_guideItems" @bind-SelectedValue="SelectedItem" Hover="true">
<MudTreeView Color="Color.Success" Items="_guideItems" @bind-SelectedValue="SelectedItem" Hover="true">
<ItemTemplate>
<MudTreeViewItem @bind-Expanded="@context.IsExpanded" Value="@context" Items="@context.Children" CanExpand="@context.HasChild" @onclick="ItemClicked">
<Content>
@ -19,7 +19,7 @@
<MudTreeViewItemToggleButton ExpandedChanged="@(() => ExpandedChanged(context))" Loading="@context.Loading" Visible="@context.HasChild" LoadingIconColor="Color.Info" />
@if (context.FaviconUrl == null && context.Icon != null)
{
<MudIcon Icon="@context.Icon" Style="@($"color:{context.GroupModel?.HexColor ?? Theme.Palette.Primary.Value}")"/>
<MudIcon Icon="@context.Icon" Style="@($"color:{context.GroupModel?.HexColor ?? _theme.Palette.Primary.Value}")"/>
}
else
{
@ -27,9 +27,6 @@
}
<MudText Class="ml-2">@context.Title</MudText>
</div>
<div style="justify-self: end;">
@*<MudText Color="Color.Dark" Style="justify-self: end;" Typo="Typo.caption">@context.FeeditemCount</MudText>*@
</div>
</div>
</Content>
</MudTreeViewItem>
@ -38,7 +35,7 @@
</MudStack>
@code {
private MudTheme Theme = new MudTheme();
private MudTheme _theme = new MudTheme();
private readonly HashSet<TreeItemData> _guideItems = new HashSet<TreeItemData>();
private TreeItemData? _selectedItem;
private TreeItemData? SelectedItem
@ -55,11 +52,11 @@
if (_selectedItem == null) return;
if (_selectedItem.FeedModel != null)
{
Navigation.NavigateTo($"/read?fid={_selectedItem.FeedModel.Id}");
_navigation.NavigateTo($"/list?fid={_selectedItem.FeedModel.Id}");
}
else if (_selectedItem.GroupModel != null)
{
Navigation.NavigateTo($"/read?gid={_selectedItem.GroupModel.Id}");
_navigation.NavigateTo($"/list?gid={_selectedItem.GroupModel.Id}");
}
}
private async void ExpandedChanged(TreeItemData treeItemData)