mirror of
https://github.com/Artemis-RGB/Artemis
synced 2026-02-04 02:43:32 +00:00
Show multiple recent releases per entry if available
This commit is contained in:
parent
562049681f
commit
559434630d
@ -175,7 +175,7 @@ public class WindowsUpdateNotificationProvider : IUpdateNotificationProvider
|
|||||||
else if (action == "disable-workshop-notifications")
|
else if (action == "disable-workshop-notifications")
|
||||||
_workshopUpdateService.DisableNotifications();
|
_workshopUpdateService.DisableNotifications();
|
||||||
else if (action == "view-library")
|
else if (action == "view-library")
|
||||||
NavigateToRoute("workshop/library");
|
NavigateToRoute("workshop/library/recently-updated");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void NavigateToRoute(string route)
|
private void NavigateToRoute(string route)
|
||||||
|
|||||||
@ -39,7 +39,7 @@ public partial class EntryInfoViewModel : ActivatableViewModelBase
|
|||||||
.DisposeWith(d);
|
.DisposeWith(d);
|
||||||
});
|
});
|
||||||
|
|
||||||
IsAdministrator = authenticationService.GetRoles().Contains("Administrator");
|
IsAdministrator = authenticationService.Roles.Contains("Administrator");
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsAdministrator { get; }
|
public bool IsAdministrator { get; }
|
||||||
|
|||||||
@ -69,7 +69,7 @@ public partial class EntrySpecificationsViewModel : ValidatableViewModelBase
|
|||||||
_categoriesValid = categoriesRule.ValidationChanged.Select(c => c.IsValid).ToProperty(this, vm => vm.CategoriesValid);
|
_categoriesValid = categoriesRule.ValidationChanged.Select(c => c.IsValid).ToProperty(this, vm => vm.CategoriesValid);
|
||||||
_descriptionValid = descriptionRule.ValidationChanged.Select(c => c.IsValid).ToProperty(this, vm => vm.DescriptionValid);
|
_descriptionValid = descriptionRule.ValidationChanged.Select(c => c.IsValid).ToProperty(this, vm => vm.DescriptionValid);
|
||||||
|
|
||||||
IsAdministrator = authenticationService.GetRoles().Contains("Administrator");
|
IsAdministrator = authenticationService.Roles.Contains("Administrator");
|
||||||
this.WhenActivatedAsync(async _ => await PopulateCategories());
|
this.WhenActivatedAsync(async _ => await PopulateCategories());
|
||||||
this.WhenAnyValue(vm => vm.Fit).Subscribe(_ => UpdateIcon());
|
this.WhenAnyValue(vm => vm.Fit).Subscribe(_ => UpdateIcon());
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,6 +8,7 @@
|
|||||||
xmlns:converters="clr-namespace:Artemis.UI.Converters"
|
xmlns:converters="clr-namespace:Artemis.UI.Converters"
|
||||||
xmlns:mdxaml="https://github.com/whistyun/Markdown.Avalonia.Tight"
|
xmlns:mdxaml="https://github.com/whistyun/Markdown.Avalonia.Tight"
|
||||||
xmlns:ui="clr-namespace:Artemis.UI"
|
xmlns:ui="clr-namespace:Artemis.UI"
|
||||||
|
xmlns:workshop="clr-namespace:Artemis.WebClient.Workshop;assembly=Artemis.WebClient.Workshop"
|
||||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||||
x:Class="Artemis.UI.Screens.Workshop.Library.Tabs.RecentlyUpdatedItemView"
|
x:Class="Artemis.UI.Screens.Workshop.Library.Tabs.RecentlyUpdatedItemView"
|
||||||
x:DataType="tabs:RecentlyUpdatedItemViewModel">
|
x:DataType="tabs:RecentlyUpdatedItemViewModel">
|
||||||
@ -16,27 +17,43 @@
|
|||||||
<converters:DateTimeConverter x:Key="DateTimeConverter" />
|
<converters:DateTimeConverter x:Key="DateTimeConverter" />
|
||||||
<ui:ArtemisLinkCommand x:Key="ArtemisLinkCommand" />
|
<ui:ArtemisLinkCommand x:Key="ArtemisLinkCommand" />
|
||||||
</UserControl.Resources>
|
</UserControl.Resources>
|
||||||
<Border MinHeight="110"
|
<UserControl.Styles>
|
||||||
MaxHeight="140"
|
<Style Selector="Border.badge">
|
||||||
Padding="12"
|
<Setter Property="Background" Value="{DynamicResource ControlSolidFillColorDefaultBrush}" />
|
||||||
|
<Setter Property="CornerRadius" Value="12" />
|
||||||
|
<Setter Property="Padding" Value="6 1"></Setter>
|
||||||
|
<Setter Property="TextBlock.FontSize" Value="12" />
|
||||||
|
</Style>
|
||||||
|
<Style Selector="StackPanel.entry-clickable:pointerover TextBlock">
|
||||||
|
<Setter Property="TextDecorations" Value="Underline" />
|
||||||
|
</Style>
|
||||||
|
<Style Selector="TextBlock.version-clickable:pointerover">
|
||||||
|
<Setter Property="TextDecorations" Value="Underline" />
|
||||||
|
</Style>
|
||||||
|
</UserControl.Styles>
|
||||||
|
<Border Padding="12"
|
||||||
HorizontalAlignment="Stretch"
|
HorizontalAlignment="Stretch"
|
||||||
Classes="card">
|
Classes="card">
|
||||||
<Grid ColumnDefinitions="Auto,*" RowDefinitions="Auto, Auto">
|
<Grid ColumnDefinitions="Auto,*" RowDefinitions="Auto, Auto">
|
||||||
|
<StackPanel Grid.Column="0"
|
||||||
<StackPanel Grid.Column="0" Grid.Row="0" Orientation="Horizontal">
|
Grid.Row="0"
|
||||||
|
Classes="entry-clickable"
|
||||||
|
Orientation="Horizontal"
|
||||||
|
Cursor="Hand"
|
||||||
|
Background="Transparent"
|
||||||
|
PointerPressed="Entry_OnPointerPressed">
|
||||||
<!-- Icon -->
|
<!-- Icon -->
|
||||||
<Border CornerRadius="6"
|
<Border CornerRadius="6"
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
Margin="0 0 2 0"
|
Width="18"
|
||||||
Width="20"
|
Height="18"
|
||||||
Height="20"
|
|
||||||
ClipToBounds="True">
|
ClipToBounds="True">
|
||||||
<Image Stretch="UniformToFill" il:ImageLoader.Source="{CompiledBinding Entry.Id, Converter={StaticResource EntryIconUriConverter}, Mode=OneWay}" />
|
<Image Stretch="UniformToFill" il:ImageLoader.Source="{CompiledBinding Entry.Id, Converter={StaticResource EntryIconUriConverter}, Mode=OneWay}" />
|
||||||
</Border>
|
</Border>
|
||||||
|
|
||||||
<!-- Title -->
|
<!-- Title -->
|
||||||
<TextBlock Margin="0 0 0 5" TextTrimming="CharacterEllipsis">
|
<TextBlock Margin="2 0" TextTrimming="CharacterEllipsis">
|
||||||
<Run Classes="h5" Text="{CompiledBinding Entry.Name, FallbackValue=Title}" />
|
<Run Text="{CompiledBinding Entry.Name, FallbackValue=Title}" />
|
||||||
<Run Classes="subtitle">by</Run>
|
<Run Classes="subtitle">by</Run>
|
||||||
<Run Classes="subtitle" Text="{CompiledBinding Entry.Author, FallbackValue=Author}" />
|
<Run Classes="subtitle" Text="{CompiledBinding Entry.Author, FallbackValue=Author}" />
|
||||||
</TextBlock>
|
</TextBlock>
|
||||||
@ -44,46 +61,54 @@
|
|||||||
IsVisible="{CompiledBinding Entry.IsOfficial}"
|
IsVisible="{CompiledBinding Entry.IsOfficial}"
|
||||||
Kind="ShieldStar"
|
Kind="ShieldStar"
|
||||||
Foreground="{DynamicResource SystemAccentColorLight1}"
|
Foreground="{DynamicResource SystemAccentColorLight1}"
|
||||||
Margin="2 -2 0 0"
|
Margin="0 -2 0 0"
|
||||||
Width="18"
|
Width="18"
|
||||||
Height="18"
|
Height="18"
|
||||||
HorizontalAlignment="Left"
|
HorizontalAlignment="Left"
|
||||||
ToolTip.Tip="Official entry by the Artemis team" />
|
ToolTip.Tip="Official entry by the Artemis team" />
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|
||||||
<StackPanel Grid.Column="1" Grid.Row="0">
|
|
||||||
<!-- Info -->
|
|
||||||
<StackPanel Margin="0 0 4 0" HorizontalAlignment="Right">
|
|
||||||
<TextBlock TextAlignment="Right">
|
|
||||||
<avalonia:MaterialIcon Kind="Harddisk" />
|
|
||||||
<Run Text="{CompiledBinding Release.Version}" />
|
|
||||||
</TextBlock>
|
|
||||||
</StackPanel>
|
|
||||||
|
|
||||||
<!-- Install state -->
|
<StackPanel Grid.Column="1" Grid.Row="0" Orientation="Horizontal" HorizontalAlignment="Right" Spacing="10">
|
||||||
<StackPanel Margin="0 0 4 0" HorizontalAlignment="Right" VerticalAlignment="Bottom">
|
<Border Classes="badge" VerticalAlignment="Top">
|
||||||
<TextBlock TextAlignment="Right" IsVisible="{CompiledBinding NotYetInstalled}">
|
<TextBlock Text="{CompiledBinding Entry.EntryType}"></TextBlock>
|
||||||
<avalonia:MaterialIcon Kind="Update" Foreground="{DynamicResource SystemAccentColorLight1}" Width="20" Height="20" />
|
</Border>
|
||||||
<Run>not yet installed</Run>
|
|
||||||
</TextBlock>
|
|
||||||
</StackPanel>
|
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|
||||||
<Panel Grid.Column="0" Grid.Row="1" Grid.ColumnSpan="2">
|
<ItemsControl Grid.Column="0" Grid.Row="1" Grid.ColumnSpan="2" ItemsSource="{CompiledBinding Releases}">
|
||||||
<TextBlock Classes="subtitle" IsVisible="{CompiledBinding Release.Changelog, Converter={x:Static StringConverters.IsNullOrEmpty}}">
|
<ItemsControl.ItemTemplate>
|
||||||
There are no release notes for this release.
|
<DataTemplate DataType="workshop:IGetRecentUpdates_Entries_Releases_Release">
|
||||||
</TextBlock>
|
<StackPanel Orientation="Vertical">
|
||||||
<mdxaml:MarkdownScrollViewer Markdown="{CompiledBinding Release.Changelog}"
|
<Border Classes="card-separator" />
|
||||||
MarkdownStyleName="FluentAvalonia"
|
<Grid ColumnDefinitions="*,Auto" HorizontalAlignment="Stretch">
|
||||||
IsVisible="{CompiledBinding Release.Changelog, Converter={x:Static StringConverters.IsNotNullOrEmpty}}">
|
<TextBlock Grid.Column="0"
|
||||||
<mdxaml:MarkdownScrollViewer.Engine>
|
Text="{CompiledBinding Version}"
|
||||||
<mdxaml:Markdown HyperlinkCommand="{StaticResource ArtemisLinkCommand}" />
|
Classes="version-clickable"
|
||||||
</mdxaml:MarkdownScrollViewer.Engine>
|
Cursor="Hand"
|
||||||
<mdxaml:MarkdownScrollViewer.Styles>
|
Background="Transparent"
|
||||||
<StyleInclude Source="/Styles/Markdown.axaml" />
|
PointerPressed="Release_OnPointerPressed" />
|
||||||
</mdxaml:MarkdownScrollViewer.Styles>
|
<TextBlock Grid.Column="1"
|
||||||
</mdxaml:MarkdownScrollViewer>
|
Text="{CompiledBinding CreatedAt, Converter={StaticResource DateTimeConverter}, ConverterParameter='humanize'}"
|
||||||
</Panel>
|
Classes="subtitle"
|
||||||
|
HorizontalAlignment="Right" />
|
||||||
|
</Grid>
|
||||||
|
<TextBlock Classes="subtitle" IsVisible="{CompiledBinding Changelog, Converter={x:Static StringConverters.IsNullOrEmpty}}">
|
||||||
|
There are no release notes for this release.
|
||||||
|
</TextBlock>
|
||||||
|
<mdxaml:MarkdownScrollViewer Markdown="{CompiledBinding Changelog}"
|
||||||
|
MarkdownStyleName="FluentAvalonia"
|
||||||
|
IsVisible="{CompiledBinding Changelog, Converter={x:Static StringConverters.IsNotNullOrEmpty}}">
|
||||||
|
<mdxaml:MarkdownScrollViewer.Engine>
|
||||||
|
<mdxaml:Markdown HyperlinkCommand="{StaticResource ArtemisLinkCommand}" />
|
||||||
|
</mdxaml:MarkdownScrollViewer.Engine>
|
||||||
|
<mdxaml:MarkdownScrollViewer.Styles>
|
||||||
|
<StyleInclude Source="/Styles/Markdown.axaml" />
|
||||||
|
</mdxaml:MarkdownScrollViewer.Styles>
|
||||||
|
</mdxaml:MarkdownScrollViewer>
|
||||||
|
</StackPanel>
|
||||||
|
</DataTemplate>
|
||||||
|
</ItemsControl.ItemTemplate>
|
||||||
|
</ItemsControl>
|
||||||
|
|
||||||
</Grid>
|
</Grid>
|
||||||
</Border>
|
</Border>
|
||||||
</UserControl>
|
</UserControl>
|
||||||
@ -1,4 +1,8 @@
|
|||||||
using ReactiveUI.Avalonia;
|
using System.Threading.Tasks;
|
||||||
|
using Artemis.WebClient.Workshop;
|
||||||
|
using Avalonia.Controls;
|
||||||
|
using Avalonia.Input;
|
||||||
|
using ReactiveUI.Avalonia;
|
||||||
|
|
||||||
namespace Artemis.UI.Screens.Workshop.Library.Tabs;
|
namespace Artemis.UI.Screens.Workshop.Library.Tabs;
|
||||||
|
|
||||||
@ -8,4 +12,15 @@ public partial class RecentlyUpdatedItemView : ReactiveUserControl<RecentlyUpdat
|
|||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void Entry_OnPointerPressed(object? sender, PointerPressedEventArgs e)
|
||||||
|
{
|
||||||
|
ViewModel?.NavigateToEntry();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Release_OnPointerPressed(object? sender, PointerPressedEventArgs e)
|
||||||
|
{
|
||||||
|
object? dataContext = (sender as TextBlock)?.DataContext;
|
||||||
|
ViewModel?.NavigateToRelease(dataContext as IGetRecentUpdates_Entries_Releases);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -1,23 +1,49 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using Artemis.UI.Shared;
|
using Artemis.UI.Shared;
|
||||||
|
using Artemis.UI.Shared.Routing;
|
||||||
using Artemis.WebClient.Workshop;
|
using Artemis.WebClient.Workshop;
|
||||||
using Artemis.WebClient.Workshop.Models;
|
using Artemis.WebClient.Workshop.Models;
|
||||||
using Artemis.WebClient.Workshop.Services;
|
using Artemis.WebClient.Workshop.Services;
|
||||||
|
using PropertyChanged.SourceGenerator;
|
||||||
|
|
||||||
namespace Artemis.UI.Screens.Workshop.Library.Tabs;
|
namespace Artemis.UI.Screens.Workshop.Library.Tabs;
|
||||||
|
|
||||||
public partial class RecentlyUpdatedItemViewModel : ActivatableViewModelBase
|
public partial class RecentlyUpdatedItemViewModel : ActivatableViewModelBase
|
||||||
{
|
{
|
||||||
public IGetRecentUpdates_Entries Entry { get; }
|
private readonly IWorkshopService _workshopService;
|
||||||
public IGetRecentUpdates_Entries_LatestRelease Release { get; }
|
private readonly IRouter _router;
|
||||||
public InstalledEntry InstalledEntry { get; }
|
[Notify] private bool _notYetInstalled;
|
||||||
|
|
||||||
public RecentlyUpdatedItemViewModel(IGetRecentUpdates_Entries entry, IWorkshopService workshopService)
|
public RecentlyUpdatedItemViewModel(IGetRecentUpdates_Entries entry, IWorkshopService workshopService, IRouter router)
|
||||||
{
|
{
|
||||||
|
_workshopService = workshopService;
|
||||||
|
_router = router;
|
||||||
|
Releases = entry.Releases;
|
||||||
Entry = entry;
|
Entry = entry;
|
||||||
Release = entry.LatestRelease ?? throw new InvalidOperationException("Entry does not have a latest release");
|
|
||||||
InstalledEntry = workshopService.GetInstalledEntry(entry.Id) ?? throw new InvalidOperationException("Entry is not installed");
|
InstalledEntry = workshopService.GetInstalledEntry(entry.Id) ?? throw new InvalidOperationException("Entry is not installed");
|
||||||
|
LatestRelease = Releases.First(r => r.Id == entry.LatestReleaseId);
|
||||||
|
NotYetInstalled = InstalledEntry.ReleaseId != Releases.Max(r => r.Id);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool NotYetInstalled => InstalledEntry.ReleaseId < Release.Id;
|
|
||||||
|
public InstalledEntry InstalledEntry { get; }
|
||||||
|
public IGetRecentUpdates_Entries Entry { get; }
|
||||||
|
public IReadOnlyList<IGetRecentUpdates_Entries_Releases> Releases { get; set; }
|
||||||
|
public IGetRecentUpdates_Entries_Releases LatestRelease { get; }
|
||||||
|
|
||||||
|
public async Task NavigateToEntry()
|
||||||
|
{
|
||||||
|
await _workshopService.NavigateToEntry(Entry.Id, Entry.EntryType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task NavigateToRelease(IGetRecentUpdates_Entries_Releases? release)
|
||||||
|
{
|
||||||
|
if (release == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
await _router.Navigate($"workshop/entries/{Entry.EntryType.ToString()}s/details/{Entry.Id}/releases/{release.Id}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -15,8 +15,8 @@
|
|||||||
</Styles>
|
</Styles>
|
||||||
</UserControl.Styles>
|
</UserControl.Styles>
|
||||||
|
|
||||||
<Grid RowDefinitions="Auto,*">
|
<Grid RowDefinitions="Auto,*" MaxWidth="1000">
|
||||||
<Grid Grid.Row="0" Grid.Column="0" MaxWidth="1000" Margin="0 22 0 10">
|
<Grid Grid.Row="0" Grid.Column="0" Margin="0 22 0 10">
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition MinWidth="165" MaxWidth="400" />
|
<ColumnDefinition MinWidth="165" MaxWidth="400" />
|
||||||
<ColumnDefinition Width="*" />
|
<ColumnDefinition Width="*" />
|
||||||
@ -34,7 +34,7 @@
|
|||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|
||||||
<ScrollViewer Grid.Row="1" Grid.Column="0" HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto" VerticalAlignment="Top">
|
<ScrollViewer Grid.Row="1" Grid.Column="0" HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto" VerticalAlignment="Top">
|
||||||
<ItemsControl ItemsSource="{CompiledBinding Entries}" Margin="0 0 20 0" MaxWidth="1000">
|
<ItemsControl ItemsSource="{CompiledBinding Entries}" Margin="0 0 20 0">
|
||||||
<ItemsControl.ItemsPanel>
|
<ItemsControl.ItemsPanel>
|
||||||
<ItemsPanelTemplate>
|
<ItemsPanelTemplate>
|
||||||
<VirtualizingStackPanel />
|
<VirtualizingStackPanel />
|
||||||
|
|||||||
@ -51,7 +51,7 @@ public partial class RecentlyUpdatedViewModel : RoutableScreen
|
|||||||
.Transform(getRecentlyUpdatedItemViewModel)
|
.Transform(getRecentlyUpdatedItemViewModel)
|
||||||
.SortAndBind(
|
.SortAndBind(
|
||||||
out ReadOnlyObservableCollection<RecentlyUpdatedItemViewModel> entries,
|
out ReadOnlyObservableCollection<RecentlyUpdatedItemViewModel> entries,
|
||||||
SortExpressionComparer<RecentlyUpdatedItemViewModel>.Descending(p => p.Release.CreatedAt)
|
SortExpressionComparer<RecentlyUpdatedItemViewModel>.Descending(p => p.LatestRelease.CreatedAt)
|
||||||
)
|
)
|
||||||
.Subscribe();
|
.Subscribe();
|
||||||
|
|
||||||
|
|||||||
@ -44,28 +44,4 @@ query GetDefaultPlugins {
|
|||||||
pluginGuid
|
pluginGuid
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
query GetRecentUpdates($entryIds: [Long!]!, $cutoff: DateTime!) {
|
|
||||||
entries(
|
|
||||||
includeDefaults: true
|
|
||||||
where: {
|
|
||||||
and: [
|
|
||||||
{ id: { in: $entryIds } }
|
|
||||||
{ latestRelease: { createdAt: { gte: $cutoff } } }
|
|
||||||
]
|
|
||||||
}
|
|
||||||
) {
|
|
||||||
id
|
|
||||||
author
|
|
||||||
isOfficial
|
|
||||||
name
|
|
||||||
summary
|
|
||||||
entryType
|
|
||||||
createdAt
|
|
||||||
latestRelease {
|
|
||||||
...release
|
|
||||||
changelog
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@ -0,0 +1,27 @@
|
|||||||
|
query GetRecentUpdates($entryIds: [Long!]!, $cutoff: DateTime!) {
|
||||||
|
entries(
|
||||||
|
includeDefaults: true
|
||||||
|
order: [{ latestRelease: { createdAt: DESC } }]
|
||||||
|
where: {
|
||||||
|
and: [
|
||||||
|
{ id: { in: $entryIds } }
|
||||||
|
{ releases: { some: { createdAt: { gte: $cutoff } } } }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
id
|
||||||
|
author
|
||||||
|
isOfficial
|
||||||
|
name
|
||||||
|
summary
|
||||||
|
entryType
|
||||||
|
latestReleaseId
|
||||||
|
releases(
|
||||||
|
order: [{ createdAt: DESC }]
|
||||||
|
where: { createdAt: { gte: $cutoff } }
|
||||||
|
) {
|
||||||
|
...release
|
||||||
|
changelog
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -23,7 +23,8 @@ internal class AuthenticationService : CorePropertyChanged, IAuthenticationServi
|
|||||||
private readonly IAuthenticationRepository _authenticationRepository;
|
private readonly IAuthenticationRepository _authenticationRepository;
|
||||||
private readonly SemaphoreSlim _authLock = new(1, 1);
|
private readonly SemaphoreSlim _authLock = new(1, 1);
|
||||||
private readonly SourceList<Claim> _claims;
|
private readonly SourceList<Claim> _claims;
|
||||||
|
private readonly SourceList<string> _roles;
|
||||||
|
|
||||||
private readonly IDiscoveryCache _discoveryCache;
|
private readonly IDiscoveryCache _discoveryCache;
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger _logger;
|
||||||
private readonly IHttpClientFactory _httpClientFactory;
|
private readonly IHttpClientFactory _httpClientFactory;
|
||||||
@ -41,7 +42,10 @@ internal class AuthenticationService : CorePropertyChanged, IAuthenticationServi
|
|||||||
|
|
||||||
_claims = new SourceList<Claim>();
|
_claims = new SourceList<Claim>();
|
||||||
_claims.Connect().Bind(out ReadOnlyObservableCollection<Claim> claims).Subscribe();
|
_claims.Connect().Bind(out ReadOnlyObservableCollection<Claim> claims).Subscribe();
|
||||||
|
_roles = new SourceList<string>();
|
||||||
|
_roles.Connect().Bind(out ReadOnlyObservableCollection<string> roles).Subscribe();
|
||||||
Claims = claims;
|
Claims = claims;
|
||||||
|
Roles = roles;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<DiscoveryDocumentResponse> GetDiscovery()
|
private async Task<DiscoveryDocumentResponse> GetDiscovery()
|
||||||
@ -68,6 +72,11 @@ internal class AuthenticationService : CorePropertyChanged, IAuthenticationServi
|
|||||||
c.Clear();
|
c.Clear();
|
||||||
c.AddRange(token.Claims);
|
c.AddRange(token.Claims);
|
||||||
});
|
});
|
||||||
|
_roles.Edit(r =>
|
||||||
|
{
|
||||||
|
r.Clear();
|
||||||
|
r.AddRange(_claims.Items.Where(c => c.Type == JwtClaimTypes.Role).Select(c => c.Value));
|
||||||
|
});
|
||||||
|
|
||||||
_isLoggedInSubject.OnNext(true);
|
_isLoggedInSubject.OnNext(true);
|
||||||
}
|
}
|
||||||
@ -118,7 +127,10 @@ internal class AuthenticationService : CorePropertyChanged, IAuthenticationServi
|
|||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public ReadOnlyObservableCollection<Claim> Claims { get; }
|
public ReadOnlyObservableCollection<Claim> Claims { get; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public ReadOnlyObservableCollection<string> Roles { get; }
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public IObservable<Claim?> GetClaim(string type)
|
public IObservable<Claim?> GetClaim(string type)
|
||||||
{
|
{
|
||||||
@ -278,6 +290,7 @@ internal class AuthenticationService : CorePropertyChanged, IAuthenticationServi
|
|||||||
|
|
||||||
_token = null;
|
_token = null;
|
||||||
_claims.Clear();
|
_claims.Clear();
|
||||||
|
_roles.Clear();
|
||||||
SetStoredRefreshToken(null);
|
SetStoredRefreshToken(null);
|
||||||
_isLoggedInSubject.OnNext(false);
|
_isLoggedInSubject.OnNext(false);
|
||||||
}
|
}
|
||||||
@ -289,12 +302,6 @@ internal class AuthenticationService : CorePropertyChanged, IAuthenticationServi
|
|||||||
return emailVerified?.Value.ToLower() == "true";
|
return emailVerified?.Value.ToLower() == "true";
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public List<string> GetRoles()
|
|
||||||
{
|
|
||||||
return Claims.Where(c => c.Type == JwtClaimTypes.Role).Select(c => c.Value).ToList();
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task<bool> InternalAutoLogin(bool force = false)
|
private async Task<bool> InternalAutoLogin(bool force = false)
|
||||||
{
|
{
|
||||||
if (!force && _isLoggedInSubject.Value)
|
if (!force && _isLoggedInSubject.Value)
|
||||||
|
|||||||
@ -8,6 +8,7 @@ public interface IAuthenticationService : IProtectedArtemisService
|
|||||||
{
|
{
|
||||||
IObservable<bool> IsLoggedIn { get; }
|
IObservable<bool> IsLoggedIn { get; }
|
||||||
ReadOnlyObservableCollection<Claim> Claims { get; }
|
ReadOnlyObservableCollection<Claim> Claims { get; }
|
||||||
|
ReadOnlyObservableCollection<string> Roles { get; }
|
||||||
|
|
||||||
IObservable<Claim?> GetClaim(string type);
|
IObservable<Claim?> GetClaim(string type);
|
||||||
Task<string?> GetBearer();
|
Task<string?> GetBearer();
|
||||||
@ -15,5 +16,4 @@ public interface IAuthenticationService : IProtectedArtemisService
|
|||||||
Task Login(CancellationToken cancellationToken);
|
Task Login(CancellationToken cancellationToken);
|
||||||
Task Logout();
|
Task Logout();
|
||||||
bool GetIsEmailVerified();
|
bool GetIsEmailVerified();
|
||||||
List<string> GetRoles();
|
|
||||||
}
|
}
|
||||||
@ -65,7 +65,10 @@ type Entry {
|
|||||||
categories: [Category!]!
|
categories: [Category!]!
|
||||||
tags: [Tag!]!
|
tags: [Tag!]!
|
||||||
images: [Image!]!
|
images: [Image!]!
|
||||||
releases: [Release!]!
|
releases(
|
||||||
|
order: [ReleaseSortInput!] @cost(weight: "10")
|
||||||
|
where: ReleaseFilterInput @cost(weight: "10")
|
||||||
|
): [Release!]!
|
||||||
dependantReleases: [Release!]!
|
dependantReleases: [Release!]!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user