mirror of
https://github.com/hmaxnl/SharpRSS.git
synced 2025-01-18 21:04:21 +01:00
UI Tuneup!
This commit is contained in:
parent
8af1497695
commit
863aa4777e
|
@ -5,7 +5,6 @@ using System.Threading.Tasks;
|
|||
using CodeHollow.FeedReader;
|
||||
using Serilog;
|
||||
using SharpRss.Models;
|
||||
using ToolQit.Extensions;
|
||||
|
||||
namespace SharpRss.Services
|
||||
{
|
||||
|
|
|
@ -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/>
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}*/
|
||||
}
|
||||
}
|
72
WebSharpRSS/Pages/List.razor
Normal file
72
WebSharpRSS/Pages/List.razor
Normal 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();
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
60
WebSharpRSS/Shared/FeedItemList.razor
Normal file
60
WebSharpRSS/Shared/FeedItemList.razor
Normal 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);
|
||||
}
|
||||
|
||||
}
|
29
WebSharpRSS/Shared/ItemView.razor
Normal file
29
WebSharpRSS/Shared/ItemView.razor
Normal 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; }
|
||||
}
|
13
WebSharpRSS/Shared/ReadDialog.razor
Normal file
13
WebSharpRSS/Shared/ReadDialog.razor
Normal file
|
@ -0,0 +1,13 @@
|
|||
@using WebSharpRSS.Models
|
||||
|
||||
<MudDialog>
|
||||
<DialogContent>
|
||||
<ItemView FeedItem="Data"/>
|
||||
</DialogContent>
|
||||
</MudDialog>
|
||||
|
||||
@code {
|
||||
[Parameter]
|
||||
public FeedItemData? Data { get; set; }
|
||||
|
||||
}
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue
Block a user