1
0
mirror of https://github.com/Artemis-RGB/Artemis synced 2025-12-12 13:28:33 +00:00

Compare commits

...

3 Commits

54 changed files with 406 additions and 595 deletions

View File

@ -3,18 +3,17 @@
xmlns:controls="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia">
<Design.PreviewWith>
<controls:HyperlinkButton Grid.Column="0" Classes="icon-button icon-button-small broken-state-button" Margin="50">
<HyperlinkButton Grid.Column="0" Classes="icon-button icon-button-small broken-state-button" Margin="50">
<avalonia:MaterialIcon Kind="AlertCircle" />
</controls:HyperlinkButton>
</HyperlinkButton>
</Design.PreviewWith>
<!-- Add Styles Here -->
<Style Selector="controls|HyperlinkButton.broken-state-button avalonia|MaterialIcon">
<Style Selector="HyperlinkButton.broken-state-button avalonia|MaterialIcon">
<Setter Property="Foreground" Value="#E74C4C" />
</Style>
<Style Selector="controls|HyperlinkButton.broken-state-button:pointerover avalonia|MaterialIcon">
<Style Selector="HyperlinkButton.broken-state-button:pointerover avalonia|MaterialIcon">
<Setter Property="Foreground" Value="#B93F3F" />
</Style>
</Styles>

View File

@ -25,14 +25,14 @@
</ToggleButton>
<TextBlock Margin="0 5 0 0">HyperlinkButton.icon-button</TextBlock>
<controls:HyperlinkButton Classes="icon-button">
<HyperlinkButton Classes="icon-button">
<avalonia:MaterialIcon Kind="Web" />
</controls:HyperlinkButton>
</HyperlinkButton>
<TextBlock Margin="0 5 0 0">HyperlinkButton.icon-button icon-button-small</TextBlock>
<controls:HyperlinkButton Classes="icon-button icon-button-small">
<HyperlinkButton Classes="icon-button icon-button-small">
<avalonia:MaterialIcon Kind="Web" />
</controls:HyperlinkButton>
</HyperlinkButton>
<TextBlock Margin="0 5 0 0">Button.window-button</TextBlock>
@ -93,7 +93,7 @@
<Setter Property="Height" Value="20" />
</Style>
<Style Selector="controls|HyperlinkButton.icon-button">
<Style Selector="HyperlinkButton.icon-button">
<Setter Property="Foreground" Value="{DynamicResource ButtonForeground}" />
</Style>
@ -113,24 +113,24 @@
<Setter Property="Background" Value="#D64848"></Setter>
</Style>
<Style Selector="Button.danger:pointerover">
<Style Selector="^ /template/ controls|FABorder#Root">
<Setter Property="Background" Value="#D65757"/>
<Setter Property="BorderBrush" Value="{DynamicResource ButtonBorderBrushPointerOver}" />
</Style>
</Style>
<Style Selector="Button.danger:pressed">
<Style Selector="^ /template/ controls|FABorder#Root">
<Setter Property="Background" Value="#D64848" />
<Setter Property="BorderBrush" Value="{DynamicResource ButtonBorderBrushPressed}" />
</Style>
</Style>
<Style Selector="Button.danger:disabled">
<Style Selector="^ /template/ controls|FABorder#Root">
<Setter Property="Background" Value="#D79D9C" />
<Setter Property="BorderBrush" Value="{DynamicResource ButtonBorderBrushDisabled}" />
</Style>
</Style>
<!-- <Style Selector="Button.danger:pointerover"> -->
<!-- <Style Selector="^ /template/ controls|FABorder#Root"> -->
<!-- <Setter Property="Background" Value="#D65757"/> -->
<!-- <Setter Property="BorderBrush" Value="{DynamicResource ButtonBorderBrushPointerOver}" /> -->
<!-- </Style> -->
<!-- </Style> -->
<!-- -->
<!-- <Style Selector="Button.danger:pressed"> -->
<!-- <Style Selector="^ /template/ controls|FABorder#Root"> -->
<!-- <Setter Property="Background" Value="#D64848" /> -->
<!-- <Setter Property="BorderBrush" Value="{DynamicResource ButtonBorderBrushPressed}" /> -->
<!-- </Style> -->
<!-- </Style> -->
<!-- -->
<!-- <Style Selector="Button.danger:disabled"> -->
<!-- <Style Selector="^ /template/ controls|FABorder#Root"> -->
<!-- <Setter Property="Background" Value="#D79D9C" /> -->
<!-- <Setter Property="BorderBrush" Value="{DynamicResource ButtonBorderBrushDisabled}" /> -->
<!-- </Style> -->
<!-- </Style> -->
</Styles>

View File

@ -51,7 +51,7 @@
RowDefinitions="*,*">
<TextBlock Grid.Column="0" Grid.Row="0" Classes="BodyStrongTextBlockStyle">Welcome to the data model picker</TextBlock>
<TextBlock Grid.Column="0" Grid.Row="1" Foreground="{DynamicResource TextFillColorSecondary}">Select a value from the data model below</TextBlock>
<controls:HyperlinkButton Grid.Column="1" Grid.Row="0" Grid.RowSpan="2">Learn more</controls:HyperlinkButton>
<HyperlinkButton Grid.Column="1" Grid.Row="0" Grid.RowSpan="2">Learn more</HyperlinkButton>
</Grid>
</Panel>
</Border>

View File

@ -17,7 +17,7 @@
<Label Grid.Column="0" Name="DescriptionEditorLabel" Target="DescriptionEditor" Margin="0 28 0 0" />
<StackPanel Grid.Column="1" Orientation="Horizontal" HorizontalAlignment="Right">
<CheckBox Name="SynchronizedScrolling" IsChecked="True" VerticalAlignment="Bottom">Synchronized scrolling</CheckBox>
<fa:HyperlinkButton
<HyperlinkButton
Margin="0 0 0 -20"
Content="Markdown supported"
NavigateUri="https://wiki.artemis-rgb.com/guides/user/markdown?mtm_campaign=artemis&amp;mtm_kwd=markdown-editor"

View File

@ -17,9 +17,9 @@
<TextBlock TextWrapping="Wrap" Classes="subtitle" Margin="0 10">
These performance stats are rather basic, for advanced performance profiling check out the wiki.
</TextBlock>
<controls:HyperlinkButton Grid.Column="1" NavigateUri="https://wiki.artemis-rgb.com/en/guides/user/plugins/profiling?mtm_campaign=artemis&amp;mtm_kwd=debugger">
<HyperlinkButton Grid.Column="1" NavigateUri="https://wiki.artemis-rgb.com/en/guides/user/plugins/profiling?mtm_campaign=artemis&amp;mtm_kwd=debugger">
JetBrains Profiling Guide
</controls:HyperlinkButton>
</HyperlinkButton>
</Grid>
</StackPanel>

View File

@ -104,7 +104,7 @@
</StackPanel>
</Grid>
</StackPanel>
<controls:HyperlinkButton
<HyperlinkButton
Grid.Row="1"
Content="Learn more about layouts on the wiki"
NavigateUri="https://wiki.artemis-rgb.com/en/guides/developer/layouts?mtm_campaign=artemis&amp;mtm_kwd=device-properties"

View File

@ -3,7 +3,6 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
xmlns:controls="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
xmlns:home="clr-namespace:Artemis.UI.Screens.Home"
mc:Ignorable="d" d:DesignWidth="1200" d:DesignHeight="900"
x:Class="Artemis.UI.Screens.Home.HomeView"
@ -42,17 +41,17 @@
Under Settings > Plugins you can find your currently installed plugins, these default plugins are created by Artemis developers. We're also keeping track of a list of third-party plugins on our wiki.
</TextBlock>
</StackPanel>
<controls:HyperlinkButton Grid.Row="1" Grid.ColumnSpan="2" Grid.Column="0" HorizontalAlignment="Right" Command="{CompiledBinding GetMorePlugins}">
<controls:HyperlinkButton.ContextMenu>
<HyperlinkButton Grid.Row="1" Grid.ColumnSpan="2" Grid.Column="0" HorizontalAlignment="Right" Command="{CompiledBinding GetMorePlugins}">
<HyperlinkButton.ContextMenu>
<ContextMenu>
<MenuItem Header="Test"></MenuItem>
</ContextMenu>
</controls:HyperlinkButton.ContextMenu>
</HyperlinkButton.ContextMenu>
<StackPanel Orientation="Horizontal">
<avalonia:MaterialIcon Kind="OpenInBrowser" />
<TextBlock Margin="8 0 0 0" VerticalAlignment="Center">Get more plugins</TextBlock>
</StackPanel>
</controls:HyperlinkButton>
</HyperlinkButton>
</Grid>
</Border>
@ -68,30 +67,30 @@
<DockPanel Grid.Row="1" Grid.ColumnSpan="2" Grid.Column="0">
<Grid Margin="8" RowDefinitions="*,*">
<controls:HyperlinkButton Grid.Row="0" NavigateUri="https://github.com/Artemis-RGB/Artemis">
<HyperlinkButton Grid.Row="0" NavigateUri="https://github.com/Artemis-RGB/Artemis">
<StackPanel Orientation="Horizontal">
<avalonia:MaterialIcon Kind="Github" />
<TextBlock Margin="8 0 0 0" VerticalAlignment="Center">GitHub</TextBlock>
</StackPanel>
</controls:HyperlinkButton>
<controls:HyperlinkButton Grid.Row="0" HorizontalAlignment="Right" NavigateUri="https://artemis-rgb.com?mtm_campaign=artemis&amp;mtm_kwd=home">
</HyperlinkButton>
<HyperlinkButton Grid.Row="0" HorizontalAlignment="Right" NavigateUri="https://artemis-rgb.com?mtm_campaign=artemis&amp;mtm_kwd=home">
<StackPanel Orientation="Horizontal">
<avalonia:MaterialIcon Kind="Web" />
<TextBlock Margin="8 0 0 0" VerticalAlignment="Center">Website</TextBlock>
</StackPanel>
</controls:HyperlinkButton>
<controls:HyperlinkButton Grid.Row="1" NavigateUri="https://discordapp.com/invite/S3MVaC9">
</HyperlinkButton>
<HyperlinkButton Grid.Row="1" NavigateUri="https://discordapp.com/invite/S3MVaC9">
<StackPanel Orientation="Horizontal">
<avalonia:MaterialIcon Kind="Chat" />
<TextBlock Margin="8 0 0 0" VerticalAlignment="Center">Discord</TextBlock>
</StackPanel>
</controls:HyperlinkButton>
<controls:HyperlinkButton Grid.Row="1" HorizontalAlignment="Right" NavigateUri="mailto:spoinky.nl@gmail.com">
</HyperlinkButton>
<HyperlinkButton Grid.Row="1" HorizontalAlignment="Right" NavigateUri="mailto:spoinky.nl@gmail.com">
<StackPanel Orientation="Horizontal">
<avalonia:MaterialIcon Kind="Email" />
<TextBlock Margin="8 0 0 0" VerticalAlignment="Center">E-mail</TextBlock>
</StackPanel>
</controls:HyperlinkButton>
</HyperlinkButton>
</Grid>
</DockPanel>
</Grid>
@ -106,7 +105,7 @@
</TextBlock>
</StackPanel>
<controls:HyperlinkButton Grid.Row="1"
<HyperlinkButton Grid.Row="1"
Grid.Column="0"
HorizontalAlignment="Center"
NavigateUri="https://wiki.artemis-rgb.com/en/donating?mtm_campaign=artemis&amp;mtm_kwd=home">
@ -114,7 +113,7 @@
<avalonia:MaterialIcon Kind="Gift" />
<TextBlock Margin="8 0 0 0" VerticalAlignment="Center">Donate</TextBlock>
</StackPanel>
</controls:HyperlinkButton>
</HyperlinkButton>
<TextBlock Grid.Row="1"
Grid.Column="1"
Classes="subtitle"

View File

@ -28,24 +28,24 @@
<TextBlock Grid.Row="0" Grid.Column="1" FontSize="28" VerticalAlignment="Bottom" Text="{CompiledBinding Plugin.Info.Name}" />
<StackPanel Grid.Row="0" Grid.Column="2" HorizontalAlignment="Right" VerticalAlignment="Bottom" Orientation="Horizontal">
<controls:HyperlinkButton Classes="icon-button"
<HyperlinkButton Classes="icon-button"
IsVisible="{CompiledBinding Plugin.Info.HelpPage, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"
NavigateUri="{CompiledBinding Plugin.Info.HelpPage}"
ToolTip.Tip="{CompiledBinding Plugin.Info.HelpPage}">
<avalonia:MaterialIcon Kind="Quiz" />
</controls:HyperlinkButton>
<controls:HyperlinkButton Classes="icon-button"
</HyperlinkButton>
<HyperlinkButton Classes="icon-button"
IsVisible="{CompiledBinding Plugin.Info.Website, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"
NavigateUri="{CompiledBinding Plugin.Info.Website}"
ToolTip.Tip="{CompiledBinding Plugin.Info.Website}">
<avalonia:MaterialIcon Kind="Web" />
</controls:HyperlinkButton>
<controls:HyperlinkButton Classes="icon-button"
</HyperlinkButton>
<HyperlinkButton Classes="icon-button"
IsVisible="{CompiledBinding Plugin.Info.Repository, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"
NavigateUri="{CompiledBinding Plugin.Info.Repository}"
ToolTip.Tip="{CompiledBinding Plugin.Info.Repository}">
<avalonia:MaterialIcon Kind="Git" />
</controls:HyperlinkButton>
</HyperlinkButton>
</StackPanel>
<TextBlock Grid.Row="1"
@ -54,7 +54,7 @@
Classes="subtitle"
Text="{CompiledBinding Plugin.Info.Version}" />
<controls:HyperlinkButton Grid.Row="1"
<HyperlinkButton Grid.Row="1"
Grid.Column="2"
IsVisible="{CompiledBinding Plugin.Info.License, Converter={x:Static ObjectConverters.IsNotNull}}"
VerticalAlignment="Top"

View File

@ -87,30 +87,30 @@
</DropDownButton.Flyout>
</DropDownButton>
<controls:HyperlinkButton Classes="icon-button icon-button-large"
<HyperlinkButton Classes="icon-button icon-button-large"
IsVisible="{CompiledBinding Plugin.ConfigurationDialog, Converter={x:Static ObjectConverters.IsNotNull}}"
Command="{CompiledBinding OpenSettings}"
ToolTip.Tip="Open settings">
<avalonia:MaterialIcon Kind="Cog" />
</controls:HyperlinkButton>
<controls:HyperlinkButton Classes="icon-button icon-button-large"
</HyperlinkButton>
<HyperlinkButton Classes="icon-button icon-button-large"
IsVisible="{CompiledBinding Plugin.Info.HelpPage, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"
NavigateUri="{CompiledBinding Plugin.Info.HelpPage}"
ToolTip.Tip="{CompiledBinding Plugin.Info.HelpPage}">
<avalonia:MaterialIcon Kind="Quiz" />
</controls:HyperlinkButton>
<controls:HyperlinkButton Classes="icon-button icon-button-large"
</HyperlinkButton>
<HyperlinkButton Classes="icon-button icon-button-large"
IsVisible="{CompiledBinding Plugin.Info.Website, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"
NavigateUri="{CompiledBinding Plugin.Info.Website}"
ToolTip.Tip="{CompiledBinding Plugin.Info.Website}">
<avalonia:MaterialIcon Kind="Web" />
</controls:HyperlinkButton>
<controls:HyperlinkButton Classes="icon-button icon-button-large"
</HyperlinkButton>
<HyperlinkButton Classes="icon-button icon-button-large"
IsVisible="{CompiledBinding Plugin.Info.Repository, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"
NavigateUri="{CompiledBinding Plugin.Info.Repository}"
ToolTip.Tip="{CompiledBinding Plugin.Info.Repository}">
<avalonia:MaterialIcon Kind="Git" />
</controls:HyperlinkButton>
</HyperlinkButton>
</StackPanel>
<CheckBox Name="EnabledToggle"

View File

@ -22,12 +22,12 @@
<TextBlock Classes="h4" Text="{CompiledBinding Layer.Name}" TextWrapping="Wrap" />
</StackPanel>
<controls:HyperlinkButton Grid.Row="0"
<HyperlinkButton Grid.Row="0"
Grid.Column="1"
VerticalAlignment="Top"
NavigateUri="https://wiki.artemis-rgb.com/guides/user/profiles/layers/adaption-hints?mtm_campaign=artemis&amp;mtm_kwd=profile-editor">
Learn more about adaption hints
</controls:HyperlinkButton>
</HyperlinkButton>
<TextBlock Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" Classes="subtitle" TextWrapping="Wrap">
Add hints below to help decide where to place this layer when the profile is imported.

View File

@ -9,14 +9,14 @@
x:Class="Artemis.UI.Screens.ProfileEditor.ProfileTree.FolderTreeItemView"
x:DataType="profileTree:FolderTreeItemViewModel">
<Grid ColumnDefinitions="Auto,Auto,*,Auto,Auto">
<controls:HyperlinkButton Grid.Column="0"
<HyperlinkButton Grid.Column="0"
Classes="icon-button icon-button-small broken-state-button"
Margin="0 0 5 0"
Command="{CompiledBinding ShowBrokenStateExceptions}"
IsVisible="{CompiledBinding ProfileElement.BrokenState, Converter={x:Static ObjectConverters.IsNotNull}}"
ToolTip.Tip="{CompiledBinding ProfileElement.BrokenState, FallbackValue=''}">
<avalonia:MaterialIcon Kind="AlertCircle" />
</controls:HyperlinkButton>
</HyperlinkButton>
<avalonia:MaterialIcon Grid.Column="1"
Kind="Folder"
Margin="0 0 5 0"

View File

@ -9,14 +9,14 @@
x:Class="Artemis.UI.Screens.ProfileEditor.ProfileTree.LayerTreeItemView"
x:DataType="profileTree:LayerTreeItemViewModel">
<Grid ColumnDefinitions="Auto,Auto,*,Auto,Auto">
<controls:HyperlinkButton Grid.Column="0"
<HyperlinkButton Grid.Column="0"
Classes="icon-button icon-button-small broken-state-button"
Margin="0 0 5 0"
Command="{CompiledBinding ShowBrokenStateExceptions}"
IsVisible="{CompiledBinding ProfileElement.BrokenState, Converter={x:Static ObjectConverters.IsNotNull}}"
ToolTip.Tip="{CompiledBinding ProfileElement.BrokenState, FallbackValue=''}">
<avalonia:MaterialIcon Kind="AlertCircle" />
</controls:HyperlinkButton>
</HyperlinkButton>
<avalonia:MaterialIcon Grid.Column="1" Kind="{CompiledBinding Layer.LayerBrush.Descriptor.Icon, FallbackValue=Layers}" Margin="0 0 5 0" />
<TextBlock Grid.Column="2" Text="{CompiledBinding Layer.Name}" VerticalAlignment="Center" />

View File

@ -42,11 +42,11 @@
<TextBlock TextWrapping="Wrap" HorizontalAlignment="Center" TextAlignment="Center" Foreground="{DynamicResource TextFillColorSecondary}">
When you enable data bindings you can no longer use keyframes or normal values for this property.
</TextBlock>
<controls:HyperlinkButton HorizontalAlignment="Center"
<HyperlinkButton HorizontalAlignment="Center"
NavigateUri="https://wiki.artemis-rgb.com/en/guides/user/profiles/data-bindings?mtm_campaign=artemis&amp;mtm_kwd=profile-editor"
Margin="0 10">
Learn more
</controls:HyperlinkButton>
</HyperlinkButton>
</StackPanel>
</Grid>
</UserControl>

View File

@ -25,15 +25,15 @@
</TextBlock>
<StackPanel Grid.Row="0" Grid.Column="2" HorizontalAlignment="Right" VerticalAlignment="Bottom" Orientation="Horizontal">
<controls:HyperlinkButton Classes="icon-button" ToolTip.Tip="View website" NavigateUri="https://artemis-rgb.com?mtm_campaign=artemis&amp;mtm_kwd=about">
<HyperlinkButton Classes="icon-button" ToolTip.Tip="View website" NavigateUri="https://artemis-rgb.com?mtm_campaign=artemis&amp;mtm_kwd=about">
<avalonia:MaterialIcon Kind="Web" />
</controls:HyperlinkButton>
<controls:HyperlinkButton Classes="icon-button" ToolTip.Tip="View GitHub repository" NavigateUri="https://github.com/Artemis-RGB/Artemis">
</HyperlinkButton>
<HyperlinkButton Classes="icon-button" ToolTip.Tip="View GitHub repository" NavigateUri="https://github.com/Artemis-RGB/Artemis">
<avalonia:MaterialIcon Kind="Github" />
</controls:HyperlinkButton>
<controls:HyperlinkButton Classes="icon-button" ToolTip.Tip="View Wiki" NavigateUri="https://wiki.artemis-rgb.com?mtm_campaign=artemis&amp;mtm_kwd=about">
</HyperlinkButton>
<HyperlinkButton Classes="icon-button" ToolTip.Tip="View Wiki" NavigateUri="https://wiki.artemis-rgb.com?mtm_campaign=artemis&amp;mtm_kwd=about">
<avalonia:MaterialIcon Kind="BookOpenOutline" />
</controls:HyperlinkButton>
</HyperlinkButton>
</StackPanel>
<SelectableTextBlock Grid.Row="1"
@ -42,12 +42,12 @@
Classes="subtitle"
Text="{CompiledBinding Version}" />
<controls:HyperlinkButton Grid.Row="1"
<HyperlinkButton Grid.Row="1"
Grid.Column="2"
VerticalAlignment="Top"
NavigateUri="https://github.com/Artemis-RGB/Artemis/blob/master/LICENSE">
PolyForm Noncommercial License 1.0.0
</controls:HyperlinkButton>
</HyperlinkButton>
</Grid>
<Border Classes="card" Margin="0 20 0 10">
@ -65,9 +65,9 @@
Project owner, main contributor
</TextBlock>
<StackPanel Grid.Column="1" Grid.Row="2" Orientation="Horizontal" Margin="-6">
<controls:HyperlinkButton Classes="icon-button" ToolTip.Tip="View GitHub profile" NavigateUri="https://github.com/RobertBeekman/">
<HyperlinkButton Classes="icon-button" ToolTip.Tip="View GitHub profile" NavigateUri="https://github.com/RobertBeekman/">
<avalonia:MaterialIcon Kind="Github" Width="20" Height="20" />
</controls:HyperlinkButton>
</HyperlinkButton>
</StackPanel>
</Grid>
@ -86,9 +86,9 @@
RGB.NET, main contributor
</TextBlock>
<StackPanel Grid.Column="1" Grid.Row="2" Orientation="Horizontal" Margin="-6">
<controls:HyperlinkButton Classes="icon-button" ToolTip.Tip="View GitHub profile" NavigateUri="https://github.com/DarthAffe/">
<HyperlinkButton Classes="icon-button" ToolTip.Tip="View GitHub profile" NavigateUri="https://github.com/DarthAffe/">
<avalonia:MaterialIcon Kind="Github" Width="20" Height="20" />
</controls:HyperlinkButton>
</HyperlinkButton>
</StackPanel>
</Grid>
@ -107,9 +107,9 @@
Main contributor
</TextBlock>
<StackPanel Grid.Column="1" Grid.Row="2" Orientation="Horizontal" Margin="-6">
<controls:HyperlinkButton Classes="icon-button" ToolTip.Tip="View GitHub profile" NavigateUri="https://github.com/diogotr7/">
<HyperlinkButton Classes="icon-button" ToolTip.Tip="View GitHub profile" NavigateUri="https://github.com/diogotr7/">
<avalonia:MaterialIcon Kind="Github" Width="20" Height="20" />
</controls:HyperlinkButton>
</HyperlinkButton>
</StackPanel>
</Grid>
@ -128,9 +128,9 @@
Graphics design
</TextBlock>
<StackPanel Grid.Column="1" Grid.Row="2" Orientation="Horizontal" Margin="-6">
<controls:HyperlinkButton Classes="icon-button" ToolTip.Tip="View website" NavigateUri="https://kwer.online/">
<HyperlinkButton Classes="icon-button" ToolTip.Tip="View website" NavigateUri="https://kwer.online/">
<avalonia:MaterialIcon Kind="Web" Width="20" Height="20" />
</controls:HyperlinkButton>
</HyperlinkButton>
</StackPanel>
</Grid>
</StackPanel>
@ -185,39 +185,39 @@
<TextBlock Classes="library-name">SQLite</TextBlock>
</StackPanel>
<StackPanel Grid.Column="1">
<controls:HyperlinkButton NavigateUri="https://avaloniaui.net/">
<HyperlinkButton NavigateUri="https://avaloniaui.net/">
https://avaloniaui.net/
</controls:HyperlinkButton>
<controls:HyperlinkButton NavigateUri="https://github.com/dadhi/DryIoc">
</HyperlinkButton>
<HyperlinkButton NavigateUri="https://github.com/dadhi/DryIoc">
https://github.com/dadhi/DryIoc
</controls:HyperlinkButton>
<controls:HyperlinkButton NavigateUri="https://learn.microsoft.com/en-us/ef/core/">
</HyperlinkButton>
<HyperlinkButton NavigateUri="https://learn.microsoft.com/en-us/ef/core/">
https://learn.microsoft.com/en-us/ef/core/
</controls:HyperlinkButton>
<controls:HyperlinkButton NavigateUri="https://github.com/amwx/FluentAvalonia">
</HyperlinkButton>
<HyperlinkButton NavigateUri="https://github.com/amwx/FluentAvalonia">
https://github.com/amwx/FluentAvalonia
</controls:HyperlinkButton>
<controls:HyperlinkButton NavigateUri="https://unosquare.github.io/embedio/">
</HyperlinkButton>
<HyperlinkButton NavigateUri="https://unosquare.github.io/embedio/">
https://unosquare.github.io/embedio/
</controls:HyperlinkButton>
<controls:HyperlinkButton NavigateUri="https://github.com/Humanizr/Humanizer">
</HyperlinkButton>
<HyperlinkButton NavigateUri="https://github.com/Humanizr/Humanizer">
https://github.com/Humanizr/Humanizer
</controls:HyperlinkButton>
<controls:HyperlinkButton NavigateUri="https://github.com/natemcmaster/DotNetCorePlugins">
</HyperlinkButton>
<HyperlinkButton NavigateUri="https://github.com/natemcmaster/DotNetCorePlugins">
https://github.com/natemcmaster/DotNetCorePlugins
</controls:HyperlinkButton>
<controls:HyperlinkButton NavigateUri="https://github.com/DarthAffe/RGB.NET">
</HyperlinkButton>
<HyperlinkButton NavigateUri="https://github.com/DarthAffe/RGB.NET">
https://github.com/DarthAffe/RGB.NET
</controls:HyperlinkButton>
<controls:HyperlinkButton NavigateUri="https://serilog.net/">
</HyperlinkButton>
<HyperlinkButton NavigateUri="https://serilog.net/">
https://serilog.net/
</controls:HyperlinkButton>
<controls:HyperlinkButton NavigateUri="https://github.com/mono/SkiaSharp">
</HyperlinkButton>
<HyperlinkButton NavigateUri="https://github.com/mono/SkiaSharp">
https://github.com/mono/SkiaSharp
</controls:HyperlinkButton>
<controls:HyperlinkButton NavigateUri="https://www.sqlite.org/">
</HyperlinkButton>
<HyperlinkButton NavigateUri="https://www.sqlite.org/">
https://www.sqlite.org/
</controls:HyperlinkButton>
</HyperlinkButton>
</StackPanel>
</Grid>
</StackPanel>

View File

@ -17,9 +17,9 @@
<TextBox Classes="clearButton" Text="{CompiledBinding SearchPluginInput}" Watermark="Search plugins" Margin="0 0 10 0" />
<StackPanel Spacing="5" Grid.Row="0" Grid.Column="1" HorizontalAlignment="Right" Orientation="Horizontal">
<controls:HyperlinkButton VerticalAlignment="Top" Command="{CompiledBinding GetMorePlugins}">
<HyperlinkButton VerticalAlignment="Top" Command="{CompiledBinding GetMorePlugins}">
Get more plugins
</controls:HyperlinkButton>
</HyperlinkButton>
<Button Classes="accent" Command="{CompiledBinding ImportPlugin}">Import plugin</Button>
</StackPanel>
</Grid>

View File

@ -29,10 +29,10 @@
TextWrapping="Wrap"
Text="{CompiledBinding Channel, StringFormat='Found no releases for the \'{0}\' channel.'}">
</TextBlock>
<controls:HyperlinkButton NavigateUri="https://wiki.artemis-rgb.com/en/channels?mtm_campaign=artemis&amp;mtm_kwd=releases"
<HyperlinkButton NavigateUri="https://wiki.artemis-rgb.com/en/channels?mtm_campaign=artemis&amp;mtm_kwd=releases"
HorizontalAlignment="Center">
Learn more about channels on the wiki
</controls:HyperlinkButton>
</HyperlinkButton>
</StackPanel>
<Grid ColumnDefinitions="300,*" Margin="10" IsVisible="{CompiledBinding ReleaseViewModels.Count}">

View File

@ -54,7 +54,7 @@
<!-- Bottom buttons -->
<Border Grid.Row="4" Margin="8" Height="1" Background="{DynamicResource ButtonBorderBrush}"></Border>
<WrapPanel Grid.Row="5" Orientation="Horizontal" HorizontalAlignment="Left" Margin="5 0 5 5">
<ui:HyperlinkButton Classes="icon-button"
<HyperlinkButton Classes="icon-button"
Width="44"
Height="44"
ToolTip.Tip="View website"
@ -62,8 +62,8 @@
ToolTip.VerticalOffset="-5"
NavigateUri="https://artemis-rgb.com?mtm_campaign=artemis&amp;mtm_kwd=sidebar">
<avalonia:MaterialIcon Kind="Web" Width="20" Height="20" />
</ui:HyperlinkButton>
<ui:HyperlinkButton Classes="icon-button"
</HyperlinkButton>
<HyperlinkButton Classes="icon-button"
Width="44"
Height="44"
ToolTip.Tip="View GitHub repository"
@ -71,8 +71,8 @@
ToolTip.VerticalOffset="-5"
NavigateUri="https://github.com/Artemis-RGB/Artemis">
<avalonia:MaterialIcon Kind="Github" Width="20" Height="20" />
</ui:HyperlinkButton>
<ui:HyperlinkButton Classes="icon-button"
</HyperlinkButton>
<HyperlinkButton Classes="icon-button"
Width="44"
Height="44"
ToolTip.Tip="View Wiki"
@ -80,8 +80,8 @@
ToolTip.VerticalOffset="-5"
NavigateUri="https://wiki.artemis-rgb.com?mtm_campaign=artemis&amp;mtm_kwd=sidebar">
<avalonia:MaterialIcon Kind="BookOpenOutline" Width="20" Height="20" />
</ui:HyperlinkButton>
<ui:HyperlinkButton Classes="icon-button"
</HyperlinkButton>
<HyperlinkButton Classes="icon-button"
Width="44"
Height="44"
ToolTip.Tip="Join our Discord"
@ -89,8 +89,8 @@
ToolTip.VerticalOffset="-5"
NavigateUri="https://discord.gg/S3MVaC9">
<avalonia:MaterialIcon Kind="Chat" Width="20" Height="20" />
</ui:HyperlinkButton>
<ui:HyperlinkButton Classes="icon-button"
</HyperlinkButton>
<HyperlinkButton Classes="icon-button"
Width="44"
Height="44"
ToolTip.Tip="View donation options"
@ -98,7 +98,7 @@
ToolTip.VerticalOffset="-5"
NavigateUri="https://wiki.artemis-rgb.com/en/donating?mtm_campaign=artemis&amp;mtm_kwd=sidebar">
<avalonia:MaterialIcon Kind="Gift" Width="20" Height="20" />
</ui:HyperlinkButton>
</HyperlinkButton>
</WrapPanel>
</Grid>
</UserControl>

View File

@ -33,18 +33,18 @@
<TextBlock Classes="link-name">Discord</TextBlock>
</StackPanel>
<StackPanel Grid.Column="1">
<controls:HyperlinkButton NavigateUri="https://wiki.artemis-rgb.com/?mtm_campaign=artemis&amp;mtm_kwd=wizard">
<HyperlinkButton NavigateUri="https://wiki.artemis-rgb.com/?mtm_campaign=artemis&amp;mtm_kwd=wizard">
https://wiki.artemis-rgb.com/
</controls:HyperlinkButton>
<controls:HyperlinkButton NavigateUri="https://wiki.artemis-rgb.com/en/guides/user/introduction?mtm_campaign=artemis&amp;mtm_kwd=wizard">
</HyperlinkButton>
<HyperlinkButton NavigateUri="https://wiki.artemis-rgb.com/en/guides/user/introduction?mtm_campaign=artemis&amp;mtm_kwd=wizard">
https://wiki.artemis-rgb.com/en/guides/user/introduction
</controls:HyperlinkButton>
<controls:HyperlinkButton NavigateUri="https://github.com/Artemis-RGB/Artemis">
</HyperlinkButton>
<HyperlinkButton NavigateUri="https://github.com/Artemis-RGB/Artemis">
https://github.com/Artemis-RGB/Artemis
</controls:HyperlinkButton>
<controls:HyperlinkButton NavigateUri="https://discord.gg/S3MVaC9">
</HyperlinkButton>
<HyperlinkButton NavigateUri="https://discord.gg/S3MVaC9">
https://discord.gg/S3MVaC9
</controls:HyperlinkButton>
</HyperlinkButton>
</StackPanel>
</Grid>
</StackPanel>

View File

@ -16,15 +16,15 @@
</TextBlock>
<StackPanel Grid.Row="0" Grid.Column="2" HorizontalAlignment="Right" VerticalAlignment="Bottom" Orientation="Horizontal">
<controls:HyperlinkButton Classes="icon-button" ToolTip.Tip="View website" NavigateUri="https://artemis-rgb.com?mtm_campaign=artemis&amp;mtm_kwd=wizard">
<HyperlinkButton Classes="icon-button" ToolTip.Tip="View website" NavigateUri="https://artemis-rgb.com?mtm_campaign=artemis&amp;mtm_kwd=wizard">
<avalonia:MaterialIcon Kind="Web" />
</controls:HyperlinkButton>
<controls:HyperlinkButton Classes="icon-button" ToolTip.Tip="View GitHub repository" NavigateUri="https://github.com/Artemis-RGB/Artemis">
</HyperlinkButton>
<HyperlinkButton Classes="icon-button" ToolTip.Tip="View GitHub repository" NavigateUri="https://github.com/Artemis-RGB/Artemis">
<avalonia:MaterialIcon Kind="Github" />
</controls:HyperlinkButton>
<controls:HyperlinkButton Classes="icon-button" ToolTip.Tip="View Wiki" NavigateUri="https://wiki.artemis-rgb.com?mtm_campaign=artemis&amp;mtm_kwd=wizard">
</HyperlinkButton>
<HyperlinkButton Classes="icon-button" ToolTip.Tip="View Wiki" NavigateUri="https://wiki.artemis-rgb.com?mtm_campaign=artemis&amp;mtm_kwd=wizard">
<avalonia:MaterialIcon Kind="BookOpenOutline" />
</controls:HyperlinkButton>
</HyperlinkButton>
</StackPanel>
<TextBlock Grid.Row="1"
@ -33,12 +33,12 @@
Classes="subtitle"
Text="{CompiledBinding Version}" />
<controls:HyperlinkButton Grid.Row="1"
<HyperlinkButton Grid.Row="1"
Grid.Column="2"
VerticalAlignment="Top"
NavigateUri="https://github.com/Artemis-RGB/Artemis/blob/master/LICENSE">
PolyForm Noncommercial License 1.0.0
</controls:HyperlinkButton>
</HyperlinkButton>
</Grid>
<Border Classes="card">

View File

@ -169,13 +169,13 @@
<TextBlock Classes="h4" Text="{CompiledBinding NodeScript.Name}" />
<TextBlock Classes="subtitle" Margin="10 0 0 13" Text="{CompiledBinding NodeScript.Description}" VerticalAlignment="Bottom" />
</StackPanel>
<controls:HyperlinkButton Grid.Row="1"
<HyperlinkButton Grid.Row="1"
Grid.Column="1"
VerticalAlignment="Top"
HorizontalAlignment="Right"
NavigateUri="https://wiki.artemis-rgb.com/en/guides/user/profiles/nodes?mtm_campaign=artemis&amp;mtm_kwd=script-editor">
Learn more about visual scripts
</controls:HyperlinkButton>
</HyperlinkButton>
<Border Classes="card-condensed" Grid.Row="2" Grid.ColumnSpan="2">
<ContentControl Content="{CompiledBinding NodeScriptViewModel}" />

View File

@ -39,18 +39,18 @@
Background="{DynamicResource ContentDialogBackground}">
<Border Background="{DynamicResource TaskDialogHeaderBackground}">
<Grid Classes="node-header" VerticalAlignment="Top" ColumnDefinitions="Auto,*,Auto,Auto">
<controls:HyperlinkButton Grid.Column="0"
<HyperlinkButton Grid.Column="0"
Classes="icon-button icon-button-small broken-state-button"
Margin="5 0 0 0"
Command="{CompiledBinding ShowBrokenState}"
IsVisible="{CompiledBinding Node.BrokenState, Converter={x:Static ObjectConverters.IsNotNull}}"
ToolTip.Tip="{CompiledBinding Node.BrokenState}">
<avalonia:MaterialIcon Kind="AlertCircle" />
</controls:HyperlinkButton>
</HyperlinkButton>
<TextBlock Grid.Column="1" VerticalAlignment="Center" Margin="10 0 0 0" Text="{CompiledBinding Node.Name}" ToolTip.Tip="{CompiledBinding Node.Description}" />
<controls:HyperlinkButton Grid.Column="2"
<HyperlinkButton Grid.Column="2"
IsVisible="{CompiledBinding Node.HelpUrl, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"
VerticalAlignment="Center"
Classes="icon-button icon-button-small"
@ -58,7 +58,7 @@
ToolTip.Tip="View node help"
NavigateUri="{CompiledBinding Node.HelpUrl}">
<avalonia:MaterialIcon Kind="Help" />
</controls:HyperlinkButton>
</HyperlinkButton>
<Button Grid.Column="3" VerticalAlignment="Center" Classes="icon-button icon-button-small" Margin="5" Command="{CompiledBinding DeleteNode}">
<avalonia:MaterialIcon Kind="Close"></avalonia:MaterialIcon>
</Button>

View File

@ -43,7 +43,7 @@
<TextBlock Grid.Column="1" Grid.Row="0" Text="{CompiledBinding Name}" Margin="0 4 0 0"></TextBlock>
<TextBlock Grid.Column="1" Grid.Row="1" Text="{CompiledBinding Email}"></TextBlock>
<controls:HyperlinkButton
<HyperlinkButton
IsVisible="{CompiledBinding AllowLogout}"
Grid.Column="1"
Grid.Row="3"
@ -51,8 +51,8 @@
Padding="6 4"
Click="Manage_OnClick">
Manage account
</controls:HyperlinkButton>
<controls:HyperlinkButton
</HyperlinkButton>
<HyperlinkButton
IsVisible="{CompiledBinding AllowLogout}"
Grid.Column="1"
Grid.Row="2"
@ -60,7 +60,7 @@
Padding="6 4"
Click="Signout_OnClick">
Sign out
</controls:HyperlinkButton>
</HyperlinkButton>
</Grid>
</Flyout>
</Ellipse.ContextFlyout>

View File

@ -1,65 +0,0 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:entries="clr-namespace:Artemis.UI.Screens.Workshop.Entries"
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="Artemis.UI.Screens.Workshop.Entries.EntryVoteView"
x:DataType="entries:EntryVoteViewModel">
<UserControl.Styles>
<Styles>
<Style Selector="Button.vote-button avalonia|MaterialIcon">
<Setter Property="Transitions">
<Transitions>
<BrushTransition Property="Foreground" Duration="0:0:0.2" Easing="CubicEaseOut" />
</Transitions>
</Setter>
</Style>
<Style Selector="Button.vote-button.upvote:pointerover avalonia|MaterialIcon">
<Setter Property="Foreground" Value="#F57634"></Setter>
</Style>
<Style Selector="Button.vote-button.downvote:pointerover avalonia|MaterialIcon">
<Setter Property="Foreground" Value="#7193FF"></Setter>
</Style>
<Style Selector="TextBlock.upvoted">
<Setter Property="Foreground" Value="#F57634"></Setter>
</Style>
<Style Selector="TextBlock.downvoted">
<Setter Property="Foreground" Value="#7193FF"></Setter>
</Style>
</Styles>
</UserControl.Styles>
<!-- Voting -->
<StackPanel Spacing="4" VerticalAlignment="Center">
<Button IsEnabled="{CompiledBinding IsLoggedIn^}"
HorizontalAlignment="Stretch"
Theme="{StaticResource TransparentButton}"
Classes="vote-button upvote"
Command="{CompiledBinding CastVote}"
CommandParameter="{x:True}">
<Panel>
<avalonia:MaterialIcon Kind="ArrowUp" IsVisible="{CompiledBinding !Upvoted}" />
<avalonia:MaterialIcon Kind="ArrowUpThick" IsVisible="{CompiledBinding Upvoted}" Foreground="#F57634" />
</Panel>
</Button>
<TextBlock Text="{CompiledBinding Score, FallbackValue=0}"
HorizontalAlignment="Stretch"
TextAlignment="Center"
Classes.upvoted="{CompiledBinding Upvoted}"
Classes.downvoted="{CompiledBinding Downvoted}" />
<Button IsEnabled="{CompiledBinding IsLoggedIn^}"
HorizontalAlignment="Stretch"
Theme="{StaticResource TransparentButton}"
Classes="vote-button downvote"
Command="{CompiledBinding CastVote}"
CommandParameter="{x:False}">
<Panel>
<avalonia:MaterialIcon Kind="ArrowDown" IsVisible="{CompiledBinding !Downvoted}" />
<avalonia:MaterialIcon Kind="ArrowDownThick" IsVisible="{CompiledBinding Downvoted}" Foreground="#7193FF" />
</Panel>
</Button>
</StackPanel>
</UserControl>

View File

@ -1,14 +0,0 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
using Avalonia.ReactiveUI;
namespace Artemis.UI.Screens.Workshop.Entries;
public partial class EntryVoteView : ReactiveUserControl<EntryVoteViewModel>
{
public EntryVoteView()
{
InitializeComponent();
}
}

View File

@ -1,91 +0,0 @@
using System;
using System.Reactive.Disposables;
using System.Threading.Tasks;
using Artemis.UI.Shared;
using Artemis.UI.Shared.Services;
using Artemis.UI.Shared.Services.Builders;
using Artemis.WebClient.Workshop;
using Artemis.WebClient.Workshop.Services;
using PropertyChanged.SourceGenerator;
using ReactiveUI;
namespace Artemis.UI.Screens.Workshop.Entries;
public partial class EntryVoteViewModel : ActivatableViewModelBase
{
private readonly IEntrySummary _entry;
private readonly INotificationService _notificationService;
private readonly IVoteClient _voteClient;
private bool _voting;
[Notify] private int _score;
[Notify] private bool _upvoted;
[Notify] private bool _downvoted;
public EntryVoteViewModel(IEntrySummary entry, IAuthenticationService authenticationService, INotificationService notificationService, IVoteClient voteClient)
{
_entry = entry;
_notificationService = notificationService;
_voteClient = voteClient;
IsLoggedIn = authenticationService.IsLoggedIn;
Score = entry.UpvoteCount - entry.DownvoteCount;
this.WhenActivated(d => IsLoggedIn.Subscribe(l => _ = GetVoteStatus(l)).DisposeWith(d));
}
public IObservable<bool> IsLoggedIn { get; }
public async Task CastVote(bool upvote)
{
// Could use a ReactiveCommand to achieve the same thing but that disables the button
// while executing which grays it out for a fraction of a second and looks bad
if (_voting)
return;
_voting = true;
try
{
IVoteCount? result;
// If the vote was removed, reset the upvote/downvote state
if ((Upvoted && upvote) || (Downvoted && !upvote))
{
result = await _voteClient.ClearVote(_entry.Id);
Upvoted = false;
Downvoted = false;
}
else
{
result = await _voteClient.CastVote(_entry.Id, upvote);
Upvoted = upvote;
Downvoted = !upvote;
}
if (result != null)
Score = result.UpvoteCount - result.DownvoteCount;
else
_notificationService.CreateNotification().WithTitle("Failed to cast vote").WithMessage("Please try again later.").WithSeverity(NotificationSeverity.Error).Show();
}
finally
{
_voting = false;
}
}
private async Task GetVoteStatus(bool isLoggedIn)
{
if (!isLoggedIn)
{
Upvoted = false;
Downvoted = false;
}
else
{
bool? vote = await _voteClient.GetVote(_entry.Id);
if (vote != null)
{
Upvoted = vote.Value;
Downvoted = !vote.Value;
}
}
}
}

View File

@ -21,7 +21,6 @@
<ComboBoxItem>Recently updated</ComboBoxItem>
<ComboBoxItem>Recently added</ComboBoxItem>
<ComboBoxItem>Download count</ComboBoxItem>
<ComboBoxItem>Score</ComboBoxItem>
</ComboBox>
</StackPanel>
<TextBlock Grid.Column="3" VerticalAlignment="Center" Margin="5 0 0 0" MinWidth="75" TextAlignment="Right">

View File

@ -0,0 +1,76 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:il="clr-namespace:AsyncImageLoader;assembly=AsyncImageLoader.Avalonia"
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
xmlns:list="clr-namespace:Artemis.UI.Screens.Workshop.Entries.List"
xmlns:converters="clr-namespace:Artemis.UI.Converters"
mc:Ignorable="d"
x:Class="Artemis.UI.Screens.Workshop.Entries.List.EntryListItemVerticalView"
x:DataType="list:EntryListItemViewModel">
<UserControl.Styles>
<StyleInclude Source="/Screens/Workshop/Search/SearchViewStyles.axaml" />
</UserControl.Styles>
<UserControl.Resources>
<converters:EntryIconUriConverter x:Key="EntryIconUriConverter" />
</UserControl.Resources>
<Button Command="{CompiledBinding NavigateToEntry}" Padding="12">
<Grid RowDefinitions="Auto,43,Auto,Auto,*" ColumnDefinitions="Auto,*" Width="150" Height="200">
<Border Grid.Row="0"
Grid.Column="0"
Grid.ColumnSpan="2"
CornerRadius="6"
Width="60"
Height="60"
Margin="0 5"
ClipToBounds="True"
HorizontalAlignment="Left">
<Image Stretch="UniformToFill" il:ImageLoader.Source="{CompiledBinding Entry.Id, Converter={StaticResource EntryIconUriConverter}, Mode=OneWay}" />
</Border>
<TextBlock Grid.Row="1"
Grid.Column="0"
Grid.ColumnSpan="2"
MaxLines="2"
TextWrapping="Wrap"
TextTrimming="CharacterEllipsis"
FontSize="16"
VerticalAlignment="Center"
Text="{CompiledBinding Entry.Name, FallbackValue=Title that is super long and should be wrapped}" />
<StackPanel Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="2" Orientation="Horizontal" Margin="0 1">
<TextBlock Classes="subtitle" MaxLines="1" TextTrimming="CharacterEllipsis" Text="{CompiledBinding Entry.Author, FallbackValue=Author}"/>
<avalonia:MaterialIcon IsVisible="{CompiledBinding Entry.IsOfficial}"
Kind="ShieldStar"
Foreground="{DynamicResource SystemAccentColorLight1}"
Margin="2 0 0 0"
Width="18"
Height="18"
HorizontalAlignment="Left"
ToolTip.Tip="Official entry by the Artemis team" />
</StackPanel>
<TextBlock Grid.Row="3"
Grid.Column="0"
Grid.ColumnSpan="2"
MaxLines="2"
TextWrapping="Wrap"
TextTrimming="CharacterEllipsis"
FontSize="12"
Opacity="0.8"
Text="{CompiledBinding Entry.Summary, FallbackValue=Summary that is super long and should be wrapped}" />
<Border Grid.Row="4" Grid.Column="0" Classes="badge" VerticalAlignment="Bottom" HorizontalAlignment="Left">
<TextBlock>
<Run Text="{CompiledBinding Entry.Downloads, FallbackValue=0}" />
<Run>downloads</Run>
</TextBlock>
</Border>
<Border Grid.Row="4" Grid.Column="1" Classes="badge" VerticalAlignment="Bottom" HorizontalAlignment="Right">
<TextBlock Text="{CompiledBinding Entry.EntryType, FallbackValue=Type}"></TextBlock>
</Border>
</Grid>
</Button>
</UserControl>

View File

@ -0,0 +1,14 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
using Avalonia.ReactiveUI;
namespace Artemis.UI.Screens.Workshop.Entries.List;
public partial class EntryListItemVerticalView : ReactiveUserControl<EntryListItemVerticalViewModel>
{
public EntryListItemVerticalView()
{
InitializeComponent();
}
}

View File

@ -0,0 +1,13 @@
using Artemis.UI.Shared.Routing;
using Artemis.WebClient.Workshop;
using Artemis.WebClient.Workshop.Services;
namespace Artemis.UI.Screens.Workshop.Entries.List;
public class EntryListItemVerticalViewModel : EntryListItemViewModel
{
/// <inheritdoc />
public EntryListItemVerticalViewModel(IEntrySummary entry, IRouter router, IWorkshopService workshopService) : base(entry, router, workshopService)
{
}
}

View File

@ -3,7 +3,6 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
xmlns:entries1="clr-namespace:Artemis.UI.Screens.Workshop.Entries"
xmlns:il="clr-namespace:AsyncImageLoader;assembly=AsyncImageLoader.Avalonia"
xmlns:converters="clr-namespace:Artemis.UI.Converters"
xmlns:list="clr-namespace:Artemis.UI.Screens.Workshop.Entries.List"
@ -21,12 +20,9 @@
HorizontalContentAlignment="Stretch"
Command="{CompiledBinding NavigateToEntry}"
IsVisible="{CompiledBinding Entry, Converter={x:Static ObjectConverters.IsNotNull}}">
<Grid ColumnDefinitions="Auto, Auto,*,Auto" RowDefinitions="*, Auto">
<!-- Score -->
<ContentControl Grid.Column="0" Grid.Row="0" Grid.RowSpan="2" Width="40" Margin="0 0 10 0" Content="{CompiledBinding VoteViewModel}"/>
<Grid ColumnDefinitions="Auto,*,Auto" RowDefinitions="*, Auto">
<!-- Icon -->
<Border Grid.Column="1"
<Border Grid.Column="0"
Grid.Row="0"
Grid.RowSpan="2"
CornerRadius="6"
@ -39,7 +35,7 @@
</Border>
<!-- Body -->
<Grid Grid.Column="2" Grid.Row="0" Grid.RowSpan="2" VerticalAlignment="Stretch" RowDefinitions="Auto,*,Auto">
<Grid Grid.Column="1" Grid.Row="0" Grid.RowSpan="2" VerticalAlignment="Stretch" RowDefinitions="Auto,*,Auto">
<StackPanel Grid.Row="0" Orientation="Horizontal">
<TextBlock Margin="0 0 0 5" TextTrimming="CharacterEllipsis">
<Run Classes="h5" Text="{CompiledBinding Entry.Name, FallbackValue=Title}" />
@ -82,7 +78,7 @@
</Grid>
<!-- Info -->
<StackPanel Grid.Column="3" Grid.Row="0" Margin="0 0 4 0" HorizontalAlignment="Right">
<StackPanel Grid.Column="2" Grid.Row="0" Margin="0 0 4 0" HorizontalAlignment="Right">
<TextBlock TextAlignment="Right" Text="{CompiledBinding Entry.CreatedAt, FallbackValue=01-01-1337, Converter={StaticResource DateTimeConverter}}" />
<TextBlock TextAlignment="Right">
<avalonia:MaterialIcon Kind="Downloads" />
@ -92,7 +88,7 @@
</StackPanel>
<!-- Install state -->
<StackPanel Grid.Column="3" Grid.Row="1" Margin="0 0 4 0" HorizontalAlignment="Right" VerticalAlignment="Bottom" IsVisible="{CompiledBinding IsInstalled}">
<StackPanel Grid.Column="2" Grid.Row="1" Margin="0 0 4 0" HorizontalAlignment="Right" VerticalAlignment="Bottom" IsVisible="{CompiledBinding IsInstalled}">
<TextBlock TextAlignment="Right" IsVisible="{CompiledBinding !UpdateAvailable}">
<avalonia:MaterialIcon Kind="CheckCircle" Foreground="{DynamicResource SystemAccentColorLight1}" Width="20" Height="20" />
<Run>installed</Run>

View File

@ -1,4 +1,5 @@
using System;
using System.Reactive;
using System.Reactive.Disposables;
using System.Threading.Tasks;
using Artemis.UI.Shared;
@ -17,12 +18,12 @@ public partial class EntryListItemViewModel : ActivatableViewModelBase
[Notify] private bool _isInstalled;
[Notify] private bool _updateAvailable;
public EntryListItemViewModel(IEntrySummary entry, IRouter router, IWorkshopService workshopService, Func<IEntrySummary, EntryVoteViewModel> getEntryVoteViewModel)
public EntryListItemViewModel(IEntrySummary entry, IRouter router, IWorkshopService workshopService)
{
_router = router;
Entry = entry;
VoteViewModel = getEntryVoteViewModel(entry);
NavigateToEntry = ReactiveCommand.CreateFromTask(ExecuteNavigateToEntry);
this.WhenActivated((CompositeDisposable _) =>
{
@ -33,9 +34,9 @@ public partial class EntryListItemViewModel : ActivatableViewModelBase
}
public IEntrySummary Entry { get; }
public EntryVoteViewModel VoteViewModel { get; }
public ReactiveCommand<Unit, Unit> NavigateToEntry { get; }
public async Task NavigateToEntry()
private async Task ExecuteNavigateToEntry()
{
switch (Entry.EntryType)
{

View File

@ -137,9 +137,6 @@ public partial class EntryListViewModel : RoutableScreen
if (InputViewModel.SortBy == 2)
return new[] {new EntrySortInput {Downloads = SortEnumType.Desc}};
// Sort by score
if (InputViewModel.SortBy == 3)
return new[] {new EntrySortInput {Score = SortEnumType.Desc}};
// Sort by latest release, then by created at
return new[]

View File

@ -10,7 +10,7 @@
<Border Classes="router-container">
<Grid RowDefinitions="200,*,*">
<ProgressBar ZIndex="999" IsIndeterminate="True" IsVisible="{CompiledBinding !WorkshopReachable}" Grid.Row="0" VerticalAlignment="Top"></ProgressBar>
<Image Grid.Row="0"
Grid.RowSpan="2"
VerticalAlignment="Top"
@ -38,7 +38,7 @@
<DropShadowEffect Color="Black" OffsetX="2" OffsetY="2" BlurRadius="5"></DropShadowEffect>
</TextBlock.Effect>
</TextBlock>
<StackPanel Margin="30 -75 30 0" Grid.Row="1">
<StackPanel Spacing="10" Orientation="Horizontal" VerticalAlignment="Top">
<Button Width="150" Height="180" Command="{CompiledBinding Navigate}" CommandParameter="workshop/entries/profiles" VerticalContentAlignment="Top">
@ -56,7 +56,7 @@
<TextBlock TextWrapping="Wrap" FontSize="12" Opacity="0.8">Layouts make your devices look great in the editor.</TextBlock>
</StackPanel>
</Button>
<Button Width="150" Height="180" Command="{CompiledBinding Navigate}" CommandParameter="workshop/entries/plugins" VerticalContentAlignment="Top">
<StackPanel>
<avalonia:MaterialIcon Kind="Connection" HorizontalAlignment="Left" Width="60" Height="60" Margin="0 5" />
@ -64,7 +64,7 @@
<TextBlock TextWrapping="Wrap" FontSize="12" Opacity="0.8">Plugins add new functionality to Artemis.</TextBlock>
</StackPanel>
</Button>
<Button Width="150" Height="180" Command="{CompiledBinding Navigate}" CommandParameter="workshop/library" VerticalContentAlignment="Top">
<StackPanel>
<avalonia:MaterialIcon Kind="Bookshelf" HorizontalAlignment="Left" Width="60" Height="60" Margin="0 5" />
@ -72,7 +72,7 @@
<TextBlock TextWrapping="Wrap" FontSize="12" Opacity="0.8">Manage your submissions and downloaded content.</TextBlock>
</StackPanel>
</Button>
<Button Width="150" Height="180" Command="{CompiledBinding AddSubmission}" VerticalContentAlignment="Top">
<StackPanel>
<avalonia:MaterialIcon Kind="CloudUpload" HorizontalAlignment="Left" Width="60" Height="60" Margin="0 5" />
@ -85,10 +85,26 @@
</StackPanel>
<TextBlock Classes="h4" Margin="0 15 0 5">Featured submissions</TextBlock>
<TextBlock>Not yet implemented, here we'll show submissions we think are worth some extra attention.</TextBlock>
<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Disabled" Padding="0 0 0 20">
<ItemsControl ItemsSource="{CompiledBinding PopularEntries}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" Spacing="10" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</ScrollViewer>
<TextBlock Classes="h4" Margin="0 15 0 5">Recently updated</TextBlock>
<TextBlock>Not yet implemented, here we'll a few of the most recent uploads/updates to the workshop.</TextBlock>
<TextBlock Classes="h4" Margin="0 15 0 5">Recently added</TextBlock>
<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Disabled" Padding="0 0 0 20">
<ItemsControl ItemsSource="{CompiledBinding LatestEntries}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" Spacing="10" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</ScrollViewer>
</StackPanel>
</Grid>
</Border>

View File

@ -1,33 +1,70 @@
using System;
using System.Collections.ObjectModel;
using System.Linq;
using System.Reactive;
using System.Threading;
using System.Threading.Tasks;
using Artemis.UI.Extensions;
using Artemis.UI.Screens.Workshop.Entries.List;
using Artemis.UI.Screens.Workshop.SubmissionWizard;
using Artemis.UI.Shared.Routing;
using Artemis.UI.Shared.Services;
using Artemis.WebClient.Workshop;
using Artemis.WebClient.Workshop.Services;
using DynamicData;
using PropertyChanged.SourceGenerator;
using ReactiveUI;
using StrawberryShake;
namespace Artemis.UI.Screens.Workshop.Home;
public partial class WorkshopHomeViewModel : RoutableScreen
{
private readonly IWindowService _windowService;
[Notify(Setter.Private)] private bool _workshopReachable;
public WorkshopHomeViewModel(IRouter router, IWindowService windowService, IWorkshopService workshopService)
public WorkshopHomeViewModel(IRouter router, IWindowService windowService, IWorkshopService workshopService, IWorkshopClient client,
Func<IEntrySummary, EntryListItemVerticalViewModel> getEntryListItemViewModel)
{
_windowService = windowService;
SourceList<IEntrySummary> latest = new();
SourceList<IEntrySummary> popular = new();
latest.Connect().Transform(getEntryListItemViewModel).Bind(out ReadOnlyObservableCollection<EntryListItemVerticalViewModel> latestEntries).Subscribe();
popular.Connect().Transform(getEntryListItemViewModel).Bind(out ReadOnlyObservableCollection<EntryListItemVerticalViewModel> popularEntries).Subscribe();
AddSubmission = ReactiveCommand.CreateFromTask(ExecuteAddSubmission, this.WhenAnyValue(vm => vm.WorkshopReachable));
Navigate = ReactiveCommand.CreateFromTask<string>(async r => await router.Navigate(r), this.WhenAnyValue(vm => vm.WorkshopReachable));
PopularEntries = popularEntries;
LatestEntries = latestEntries;
this.WhenActivatedAsync(async d => WorkshopReachable = await workshopService.ValidateWorkshopStatus(d.AsCancellationToken()));
this.WhenActivatedAsync(async d =>
{
WorkshopReachable = await workshopService.ValidateWorkshopStatus(d.AsCancellationToken());
IOperationResult<IGetPopularEntriesResult> popularResult = await client.GetPopularEntries.ExecuteAsync();
popular.Edit(p =>
{
p.Clear();
if (popularResult.Data?.PopularEntries != null)
p.AddRange(popularResult.Data.PopularEntries);
});
IOperationResult<IGetEntriesv2Result> latestResult = await client.GetEntriesv2.ExecuteAsync(null, null, [new EntrySortInput {CreatedAt = SortEnumType.Desc}], 25, null);
latest.Edit(l =>
{
l.Clear();
if (latestResult.Data?.EntriesV2?.Edges != null)
l.AddRange(latestResult.Data.EntriesV2.Edges.Select(e => e.Node));
});
});
}
public ReactiveCommand<Unit, Unit> AddSubmission { get; }
public ReactiveCommand<string, Unit> Navigate { get; }
public ReadOnlyObservableCollection<EntryListItemVerticalViewModel> PopularEntries { get; }
public ReadOnlyObservableCollection<EntryListItemVerticalViewModel> LatestEntries { get; }
private async Task ExecuteAddSubmission(CancellationToken arg)
{

View File

@ -70,9 +70,9 @@
</ListBox>
</StackPanel>
</Border>
<controls:HyperlinkButton Command="{CompiledBinding ViewWorkshopPage}" HorizontalAlignment="Center">
<HyperlinkButton Command="{CompiledBinding ViewWorkshopPage}" HorizontalAlignment="Center">
View workshop page
</controls:HyperlinkButton>
</HyperlinkButton>
</StackPanel>
<controls:Frame Grid.Column="1" Grid.Row="0" Name="RouterFrame" IsNavigationStackEnabled="False" CacheSize="0">

View File

@ -11,6 +11,7 @@
x:DataType="tabs:InstalledTabItemViewModel">
<UserControl.Resources>
<converters:EntryIconUriConverter x:Key="EntryIconUriConverter" />
<converters:DateTimeConverter x:Key="DateTimeConverter" />
</UserControl.Resources>
<Button MinHeight="110"
MaxHeight="140"
@ -18,12 +19,9 @@
HorizontalAlignment="Stretch"
HorizontalContentAlignment="Stretch"
Command="{CompiledBinding ViewWorkshopPage}">
<Grid ColumnDefinitions="Auto,Auto,*,Auto,Auto" RowDefinitions="*, Auto">
<!-- Score -->
<ContentControl Grid.Column="0" Grid.Row="0" Grid.RowSpan="2" Width="40" Margin="0 0 10 0" Content="{CompiledBinding VoteViewModel}"/>
<Grid ColumnDefinitions="Auto,*,Auto,Auto" RowDefinitions="*, Auto">
<!-- Icon -->
<Border Grid.Column="1"
<Border Grid.Column="0"
Grid.Row="0"
Grid.RowSpan="2"
CornerRadius="6"
@ -36,7 +34,7 @@
</Border>
<!-- Body -->
<Grid Grid.Column="2" Grid.Row="0" Grid.RowSpan="2" VerticalAlignment="Stretch" RowDefinitions="Auto,*,Auto">
<Grid Grid.Column="1" Grid.Row="0" Grid.RowSpan="2" VerticalAlignment="Stretch" RowDefinitions="Auto,*,Auto">
<StackPanel Grid.Row="0" Orientation="Horizontal">
<TextBlock Margin="0 0 0 5" TextTrimming="CharacterEllipsis">
<Run Classes="h5" Text="{CompiledBinding Entry.Name, FallbackValue=Title}" />
@ -78,7 +76,7 @@
</Grid>
<!-- Info -->
<StackPanel Grid.Column="3" Grid.Row="0" Margin="0 0 4 0" HorizontalAlignment="Right">
<StackPanel Grid.Column="2" Grid.Row="0" Margin="0 0 4 0" HorizontalAlignment="Right">
<TextBlock TextAlignment="Right">
<avalonia:MaterialIcon Kind="Harddisk" />
<Run Text="{CompiledBinding Entry.ReleaseVersion}" />
@ -86,7 +84,7 @@
</StackPanel>
<!-- Install state -->
<StackPanel Grid.Column="3" Grid.Row="1" Margin="0 0 4 0" HorizontalAlignment="Right" VerticalAlignment="Bottom">
<StackPanel Grid.Column="2" Grid.Row="1" Margin="0 0 4 0" HorizontalAlignment="Right" VerticalAlignment="Bottom">
<TextBlock TextAlignment="Right" IsVisible="{CompiledBinding UpdateAvailable}">
<avalonia:MaterialIcon Kind="Update" Foreground="{DynamicResource SystemAccentColorLight1}" Width="20" Height="20" />
<Run>update available</Run>
@ -94,7 +92,7 @@
</StackPanel>
<!-- Management -->
<Border Grid.Column="4" Grid.Row="0" Grid.RowSpan="2" BorderBrush="{DynamicResource ButtonBorderBrush}" BorderThickness="1 0 0 0" Margin="10 0 0 0" Padding="10 0 0 0">
<Border Grid.Column="3" Grid.Row="0" Grid.RowSpan="2" BorderBrush="{DynamicResource ButtonBorderBrush}" BorderThickness="1 0 0 0" Margin="10 0 0 0" Padding="10 0 0 0">
<StackPanel VerticalAlignment="Center">
<StackPanel Orientation="Horizontal" Spacing="5">
<Button Command="{CompiledBinding ViewLocal}" HorizontalAlignment="Stretch" >Open</Button>

View File

@ -10,7 +10,6 @@ using Artemis.Core.Services;
using Artemis.UI.DryIoc.Factories;
using Artemis.UI.Extensions;
using Artemis.UI.Screens.Plugins;
using Artemis.UI.Screens.Workshop.Entries;
using Artemis.UI.Services.Interfaces;
using Artemis.UI.Shared;
using Artemis.UI.Shared.Routing;
@ -36,7 +35,6 @@ public partial class InstalledTabItemViewModel : ActivatableViewModelBase
[Notify] private bool _updateAvailable;
[Notify] private bool _autoUpdate;
[Notify] private EntryVoteViewModel _voteViewModel;
public InstalledTabItemViewModel(InstalledEntry entry,
IWorkshopClient client,
@ -45,8 +43,7 @@ public partial class InstalledTabItemViewModel : ActivatableViewModelBase
IRouter router,
IWindowService windowService,
IPluginManagementService pluginManagementService,
ISettingsVmFactory settingsVmFactory,
Func<IEntrySummary, EntryVoteViewModel> getEntryVoteViewModel)
ISettingsVmFactory settingsVmFactory)
{
_client = client;
_workshopService = workshopService;
@ -56,9 +53,9 @@ public partial class InstalledTabItemViewModel : ActivatableViewModelBase
_pluginManagementService = pluginManagementService;
_settingsVmFactory = settingsVmFactory;
_autoUpdate = entry.AutoUpdate;
Entry = entry;
this.WhenActivatedAsync(async _ =>
{
// Grab the latest entry summary from the workshop
@ -68,7 +65,6 @@ public partial class InstalledTabItemViewModel : ActivatableViewModelBase
if (entrySummary.Data?.Entry != null)
{
Entry.ApplyEntrySummary(entrySummary.Data.Entry);
VoteViewModel = getEntryVoteViewModel(entrySummary.Data.Entry);
_workshopService.SaveInstalledEntry(Entry);
}
}
@ -77,7 +73,7 @@ public partial class InstalledTabItemViewModel : ActivatableViewModelBase
UpdateAvailable = Entry.ReleaseId != Entry.LatestReleaseId;
}
});
this.WhenAnyValue(vm => vm.AutoUpdate).Skip(1).Subscribe(_ => AutoUpdateToggled());
}
@ -126,10 +122,10 @@ public partial class InstalledTabItemViewModel : ActivatableViewModelBase
private void AutoUpdateToggled()
{
_workshopService.SetAutoUpdate(Entry, AutoUpdate);
if (!AutoUpdate)
return;
Task.Run(async () =>
{
await _workshopUpdateService.AutoUpdateEntry(Entry);

View File

@ -21,9 +21,9 @@
<TextBlock Grid.Row="0" Grid.Column="1" FontSize="36" VerticalAlignment="Bottom" Text="Not logged in" IsVisible="{CompiledBinding CurrentUserViewModel.IsAnonymous}"/>
<StackPanel Grid.Row="0" Grid.Column="2" HorizontalAlignment="Right" VerticalAlignment="Bottom" Orientation="Horizontal">
<controls:HyperlinkButton Classes="icon-button" ToolTip.Tip="View Wiki" NavigateUri="https://wiki.artemis-rgb.com?mtm_campaign=artemis&amp;mtm_kwd=workshop-wizard">
<HyperlinkButton Classes="icon-button" ToolTip.Tip="View Wiki" NavigateUri="https://wiki.artemis-rgb.com?mtm_campaign=artemis&amp;mtm_kwd=workshop-wizard">
<avalonia:MaterialIcon Kind="BookOpenOutline" />
</controls:HyperlinkButton>
</HyperlinkButton>
</StackPanel>
<TextBlock Grid.Row="1"

View File

@ -39,7 +39,7 @@
<shared:EnumComboBox Value="{CompiledBinding PhysicalLayout}"></shared:EnumComboBox>
</StackPanel>
<controls:HyperlinkButton Grid.Row="1"
<HyperlinkButton Grid.Row="1"
Grid.Column="0"
IsVisible="{CompiledBinding IsKeyboardLayout}"
Margin="0 10 0 0"
@ -47,7 +47,7 @@
HorizontalAlignment="Right"
NavigateUri="https://wiki.artemis-rgb.com/en/guides/developer/layouts/keyboard-layouts?mtm_campaign=artemis&amp;mtm_kwd=workshop-wizard">
Learn about physical layouts
</controls:HyperlinkButton>
</HyperlinkButton>
<ScrollViewer Grid.Row="2"
Grid.Column="0"

View File

@ -24,12 +24,12 @@
</TextBlock>
<controls:HyperlinkButton Grid.Row="0"
<HyperlinkButton Grid.Row="0"
Grid.Column="1"
VerticalAlignment="Top"
NavigateUri="https://wiki.artemis-rgb.com/guides/user/profiles/layers/adaption-hints?mtm_campaign=artemis&amp;mtm_kwd=workshop-wizard">
Learn more about adaption hints
</controls:HyperlinkButton>
</HyperlinkButton>
<ScrollViewer Grid.Row="2"
Grid.Column="0"

View File

@ -22,9 +22,9 @@
<TextBlock Grid.Row="0" Grid.Column="1" FontSize="36" VerticalAlignment="Bottom" Text="Not logged in" IsVisible="{CompiledBinding CurrentUserViewModel.IsAnonymous}" />
<StackPanel Grid.Row="0" Grid.Column="2" HorizontalAlignment="Right" VerticalAlignment="Bottom" Orientation="Horizontal">
<controls:HyperlinkButton Classes="icon-button" ToolTip.Tip="View Wiki" NavigateUri="https://wiki.artemis-rgb.com?mtm_campaign=artemis&amp;mtm_kwd=workshop-wizard">
<HyperlinkButton Classes="icon-button" ToolTip.Tip="View Wiki" NavigateUri="https://wiki.artemis-rgb.com?mtm_campaign=artemis&amp;mtm_kwd=workshop-wizard">
<avalonia:MaterialIcon Kind="BookOpenOutline" />
</controls:HyperlinkButton>
</HyperlinkButton>
</StackPanel>
<TextBlock Grid.Row="1"

View File

@ -27,7 +27,7 @@
<Setter Property="SelectionForeground" Value="{DynamicResource TextOnAccentFillColorSelectedTextBrush}" />
</Style>
<Style Selector="controls|ContentDialog.fullscreen controls|FABorder#BackgroundElement">
<Style Selector="controls|ContentDialog.fullscreen Border#BackgroundElement">
<Setter Property="MaxWidth" Value="99999"></Setter>
<Setter Property="MaxHeight" Value="99999"></Setter>
<Setter Property="Margin" Value="100"></Setter>

View File

@ -53,7 +53,6 @@ public static class ContainerExtensions
container.Register<IAuthenticationRepository, AuthenticationRepository>(Reuse.Singleton);
container.Register<IAuthenticationService, AuthenticationService>(Reuse.Singleton);
container.Register<IWorkshopService, WorkshopService>(Reuse.Singleton);
container.Register<IVoteClient, VoteClient>(Reuse.Singleton);
container.Register<ILayoutProvider, WorkshopLayoutProvider>(Reuse.Singleton);
container.Register<IUserManagementService, UserManagementService>();

View File

@ -1,16 +0,0 @@
mutation CastVote($input: CastVoteInput!) {
castVote(input: $input) {
...voteCount
}
}
mutation ClearVote($entryId: Long!) {
clearVote(entryId: $entryId) {
...voteCount
}
}
fragment voteCount on Entry {
upvoteCount
downvoteCount
}

View File

@ -2,4 +2,4 @@ mutation AddEntry ($input: CreateEntryInput!) {
addEntry(input: $input) {
id
}
}
}

View File

@ -36,8 +36,6 @@ fragment entrySummary on Entry {
summary
entryType
downloads
upvoteCount
downvoteCount
createdAt
latestReleaseId
categories {
@ -53,8 +51,6 @@ fragment entryDetails on Entry {
summary
entryType
downloads
upvoteCount
downvoteCount
createdAt
description
categories {

View File

@ -1,18 +1,9 @@
query GetEntries($search: String $filter: EntryFilterInput $skip: Int $take: Int $order: [EntrySortInput!]) {
entries(search: $search where: $filter skip: $skip take: $take, order: $order) {
totalCount
items {
...entrySummary
}
}
}
query GetEntriesv2($search: String $filter: EntryFilterInput $order: [EntrySortInput!] $first: Int $after: String) {
entriesV2(search: $search where: $filter order: $order first: $first after: $after) {
totalCount
pageInfo {
hasNextPage
endCursor
endCursor
}
edges {
cursor
@ -21,4 +12,10 @@ query GetEntriesv2($search: String $filter: EntryFilterInput $order: [EntrySortI
}
}
}
}
query GetPopularEntries {
popularEntries {
...entrySummary
}
}

View File

@ -1,6 +0,0 @@
query GetVotes {
votes {
entryId
upvote
}
}

View File

@ -1,105 +0,0 @@
using StrawberryShake;
namespace Artemis.WebClient.Workshop.Services;
public class VoteClient : IVoteClient
{
private readonly Dictionary<long, bool> _cache = new();
private readonly IWorkshopClient _client;
private readonly SemaphoreSlim _lock = new(1, 1);
private DateTime _cacheAge = DateTime.MinValue;
public VoteClient(IWorkshopClient client, IAuthenticationService authenticationService)
{
_client = client;
authenticationService.IsLoggedIn.Subscribe(_ => _cacheAge = DateTime.MinValue);
}
/// <inheritdoc/>
public async Task<bool?> GetVote(long entryId)
{
await _lock.WaitAsync();
try
{
if (_cacheAge < DateTime.UtcNow.AddMinutes(-15))
{
_cache.Clear();
IOperationResult<IGetVotesResult> result = await _client.GetVotes.ExecuteAsync();
if (result.Data?.Votes != null)
foreach (IGetVotes_Votes vote in result.Data.Votes)
_cache.Add(vote.EntryId, vote.Upvote);
_cacheAge = DateTime.UtcNow;
}
return _cache.TryGetValue(entryId, out bool upvote) ? upvote : null;
}
finally
{
_lock.Release();
}
}
/// <inheritdoc/>
public async Task<IVoteCount?> CastVote(long entryId, bool upvote)
{
await _lock.WaitAsync();
try
{
IOperationResult<ICastVoteResult> result = await _client.CastVote.ExecuteAsync(new CastVoteInput {EntryId = entryId, Upvote = upvote});
if (result.IsSuccessResult() && result.Data?.CastVote != null)
_cache[entryId] = upvote;
return result.Data?.CastVote;
}
finally
{
_lock.Release();
}
}
/// <inheritdoc/>
public async Task<IVoteCount?> ClearVote(long entryId)
{
await _lock.WaitAsync();
try
{
IOperationResult<IClearVoteResult> result = await _client.ClearVote.ExecuteAsync(entryId);
if (result.IsSuccessResult() && result.Data?.ClearVote != null)
_cache.Remove(entryId);
return result.Data?.ClearVote;
}
finally
{
_lock.Release();
}
}
}
public interface IVoteClient
{
/// <summary>
/// Gets the vote status for a specific entry.
/// </summary>
/// <param name="entryId">The ID of the entry</param>
/// <returns>A Task containing the vote status.</returns>
Task<bool?> GetVote(long entryId);
/// <summary>
/// Casts a vote for a specific entry.
/// </summary>
/// <param name="entryId">The ID of the entry.</param>
/// <param name="upvote">A boolean indicating whether the vote is an upvote.</param>
/// <returns>A Task containing the cast vote.</returns>
Task<IVoteCount?> CastVote(long entryId, bool upvote);
/// <summary>
/// Clears a vote for a specific entry.
/// </summary>
/// <param name="entryId">The ID of the entry</param>
/// <returns>A Task containing the vote status.</returns>
Task<IVoteCount?> ClearVote(long entryId);
}

View File

@ -2,10 +2,10 @@ namespace Artemis.WebClient.Workshop;
public static class WorkshopConstants
{
public const string AUTHORITY_URL = "https://localhost:5001";
public const string WORKSHOP_URL = "https://localhost:7281";
// public const string AUTHORITY_URL = "https://identity.artemis-rgb.com";
// public const string WORKSHOP_URL = "https://workshop.artemis-rgb.com";
// public const string AUTHORITY_URL = "https://localhost:5001";
// public const string WORKSHOP_URL = "https://localhost:7281";
public const string AUTHORITY_URL = "https://identity.artemis-rgb.com";
public const string WORKSHOP_URL = "https://workshop.artemis-rgb.com";
public const string IDENTITY_CLIENT_NAME = "IdentityApiClient";
public const string WORKSHOP_CLIENT_NAME = "WorkshopApiClient";
}

View File

@ -2,7 +2,7 @@ schema: schema.graphql
extensions:
endpoints:
Default GraphQL Endpoint:
url: https://localhost:7281/graphql/
url: https://workshop.artemis-rgb.com/graphql
headers:
user-agent: JS GraphQL
introspect: true

View File

@ -56,7 +56,6 @@ type Entry {
dependantReleases: [Release!]!
description: String!
downloads: Long!
downvoteCount: Int!
entryType: EntryType!
icon: Image
iconId: UUID
@ -69,11 +68,10 @@ type Entry {
layoutInfo: [LayoutInfo!]!
name: String!
pluginInfo: PluginInfo
popularityScore: Float!
releases: [Release!]!
score: Int!
summary: String!
tags: [Tag!]!
upvoteCount: Int!
}
type Image {
@ -103,8 +101,6 @@ type LayoutInfo {
type Mutation {
addEntry(input: CreateEntryInput!): Entry
addLayoutInfo(input: CreateLayoutInfoInput!): LayoutInfo
castVote(input: CastVoteInput!): Entry
clearVote(entryId: Long!): Entry
removeEntry(id: Long!): Entry
removeLayoutInfo(id: Long!): LayoutInfo!
removeRelease(id: Long!): Release!
@ -152,7 +148,7 @@ type PluginInfosCollectionSegment {
type Query {
categories(order: [CategorySortInput!], where: CategoryFilterInput): [Category!]!
entries(order: [EntrySortInput!], search: String, skip: Int, take: Int, where: EntryFilterInput): EntriesCollectionSegment
entries(order: [EntrySortInput!], popular: Boolean, search: String, skip: Int, take: Int, where: EntryFilterInput): EntriesCollectionSegment
entriesV2(
"Returns the elements in the list that come after the specified cursor."
after: String,
@ -163,18 +159,19 @@ type Query {
"Returns the last _n_ elements from the list."
last: Int,
order: [EntrySortInput!],
popular: Boolean,
search: String,
where: EntryFilterInput
): EntriesV2Connection
entry(id: Long!): Entry
pluginInfo(pluginGuid: UUID!): PluginInfo
pluginInfos(order: [PluginInfoSortInput!], skip: Int, take: Int, where: PluginInfoFilterInput): PluginInfosCollectionSegment
popularEntries(where: EntryFilterInput): [Entry!]!
release(id: Long!): Release
searchEntries(input: String!, order: [EntrySortInput!], type: EntryType, where: EntryFilterInput): [Entry!]!
searchKeyboardLayout(deviceProvider: UUID!, logicalLayout: String, model: String!, physicalLayout: KeyboardLayoutType!, vendor: String!): LayoutInfo
searchLayout(deviceProvider: UUID!, deviceType: RGBDeviceType!, model: String!, vendor: String!): LayoutInfo
submittedEntries(order: [EntrySortInput!], where: EntryFilterInput): [Entry!]!
votes(order: [VoteSortInput!], where: VoteFilterInput): [Vote!]!
}
type Release {
@ -195,15 +192,6 @@ type Tag {
name: String!
}
type Vote {
entry: Entry!
entryId: Long!
id: Long!
upvote: Boolean!
userId: UUID!
votedAt: DateTime!
}
enum ApplyPolicy {
AFTER_RESOLVER
BEFORE_RESOLVER
@ -266,11 +254,6 @@ input BooleanOperationFilterInput {
neq: Boolean
}
input CastVoteInput {
entryId: Long!
upvote: Boolean!
}
input CategoryFilterInput {
and: [CategoryFilterInput!]
icon: StringOperationFilterInput
@ -329,7 +312,6 @@ input EntryFilterInput {
dependantReleases: ListFilterInputTypeOfReleaseFilterInput
description: StringOperationFilterInput
downloads: LongOperationFilterInput
downvoteCount: IntOperationFilterInput
entryType: EntryTypeOperationFilterInput
icon: ImageFilterInput
iconId: UuidOperationFilterInput
@ -343,11 +325,10 @@ input EntryFilterInput {
name: StringOperationFilterInput
or: [EntryFilterInput!]
pluginInfo: PluginInfoFilterInput
popularityScore: FloatOperationFilterInput
releases: ListFilterInputTypeOfReleaseFilterInput
score: IntOperationFilterInput
summary: StringOperationFilterInput
tags: ListFilterInputTypeOfTagFilterInput
upvoteCount: IntOperationFilterInput
}
input EntrySortInput {
@ -356,7 +337,6 @@ input EntrySortInput {
createdAt: SortEnumType
description: SortEnumType
downloads: SortEnumType
downvoteCount: SortEnumType
entryType: SortEnumType
icon: ImageSortInput
iconId: SortEnumType
@ -367,9 +347,8 @@ input EntrySortInput {
latestReleaseId: SortEnumType
name: SortEnumType
pluginInfo: PluginInfoSortInput
score: SortEnumType
popularityScore: SortEnumType
summary: SortEnumType
upvoteCount: SortEnumType
}
input EntryTypeOperationFilterInput {
@ -379,6 +358,21 @@ input EntryTypeOperationFilterInput {
nin: [EntryType!]
}
input FloatOperationFilterInput {
eq: Float
gt: Float
gte: Float
in: [Float]
lt: Float
lte: Float
neq: Float
ngt: Float
ngte: Float
nin: [Float]
nlt: Float
nlte: Float
}
input ImageFilterInput {
and: [ImageFilterInput!]
description: StringOperationFilterInput
@ -635,23 +629,3 @@ input UuidOperationFilterInput {
nlt: UUID
nlte: UUID
}
input VoteFilterInput {
and: [VoteFilterInput!]
entry: EntryFilterInput
entryId: LongOperationFilterInput
id: LongOperationFilterInput
or: [VoteFilterInput!]
upvote: BooleanOperationFilterInput
userId: UuidOperationFilterInput
votedAt: DateTimeOperationFilterInput
}
input VoteSortInput {
entry: EntrySortInput
entryId: SortEnumType
id: SortEnumType
upvote: SortEnumType
userId: SortEnumType
votedAt: SortEnumType
}

View File

@ -240,6 +240,7 @@
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpKeepExistingMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpPlaceEmbeddedOnSameLineMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpUseContinuousIndentInsideBracesMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002EMemberReordering_002EMigrations_002ECSharpFileLayoutPatternRemoveIsAttributeUpgrade/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EAlwaysTreatStructAsNotReorderableMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateBlankLinesAroundFieldToBlankLinesAroundProperty/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=activatable/@EntryIndexedValue">True</s:Boolean>

View File

@ -4,43 +4,43 @@
<CentralPackageTransitivePinningEnabled>false</CentralPackageTransitivePinningEnabled>
</PropertyGroup>
<ItemGroup>
<PackageVersion Include="AsyncImageLoader.Avalonia" Version="3.2.1" />
<PackageVersion Include="Avalonia" Version="11.0.11" />
<PackageVersion Include="Avalonia.AvaloniaEdit" Version="11.0.6" />
<PackageVersion Include="Avalonia.Controls.ItemsRepeater" Version="11.0.11" />
<PackageVersion Include="Avalonia.Controls.PanAndZoom" Version="11.0.0.3" />
<PackageVersion Include="Avalonia.Desktop" Version="11.0.11" />
<PackageVersion Include="AsyncImageLoader.Avalonia" Version="3.3.0" />
<PackageVersion Include="Avalonia" Version="11.1.3" />
<PackageVersion Include="Avalonia.AvaloniaEdit" Version="11.1.0" />
<PackageVersion Include="Avalonia.Controls.ItemsRepeater" Version="11.1.3" />
<PackageVersion Include="Avalonia.Controls.PanAndZoom" Version="11.1.0.1" />
<PackageVersion Include="Avalonia.Desktop" Version="11.1.3" />
<PackageVersion Include="Avalonia.Diagnostics" Version="11.0.9" />
<PackageVersion Include="Avalonia.ReactiveUI" Version="11.0.11" />
<PackageVersion Include="Avalonia.ReactiveUI" Version="11.1.3" />
<PackageVersion Include="Avalonia.Skia.Lottie" Version="11.0.0" />
<PackageVersion Include="Avalonia.Win32" Version="11.0.11" />
<PackageVersion Include="Avalonia.Win32" Version="11.1.3" />
<PackageVersion Include="Microsoft.Win32.SystemEvents" Version="8.0.0" />
<PackageVersion Include="Avalonia.Xaml.Behaviors" Version="11.0.10.9" />
<PackageVersion Include="AvaloniaEdit.TextMate" Version="11.0.6" />
<PackageVersion Include="Avalonia.Xaml.Behaviors" Version="11.1.0.4" />
<PackageVersion Include="AvaloniaEdit.TextMate" Version="11.1.0" />
<PackageVersion Include="DryIoc.Microsoft.DependencyInjection" Version="6.2.0" />
<PackageVersion Include="DryIoc.dll" Version="5.4.3" />
<PackageVersion Include="DynamicData" Version="8.4.1" />
<PackageVersion Include="EmbedIO" Version="3.5.2" />
<PackageVersion Include="FluentAvalonia.ProgressRing" Version="1.69.2" />
<PackageVersion Include="FluentAvaloniaUI" Version="2.0.5" />
<PackageVersion Include="FluentAvaloniaUI" Version="2.1.0" />
<PackageVersion Include="HidSharp" Version="2.1.0" />
<PackageVersion Include="Humanizer.Core" Version="2.14.1" />
<PackageVersion Include="IdentityModel" Version="7.0.0" />
<PackageVersion Include="JetBrains.Annotations" Version="2023.3.0" />
<PackageVersion Include="LiteDB" Version="5.0.17" />
<PackageVersion Include="JetBrains.Annotations" Version="2024.2.0" />
<PackageVersion Include="LiteDB" Version="5.0.21" />
<PackageVersion Include="Markdown.Avalonia.Tight" Version="11.0.2" />
<PackageVersion Include="Material.Icons.Avalonia" Version="2.1.10" />
<PackageVersion Include="McMaster.NETCore.Plugins" Version="1.4.0" />
<PackageVersion Include="Microsoft.EntityFrameworkCore" Version="8.0.2" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Sqlite" Version="8.0.6" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.6">
<PackageVersion Include="Microsoft.EntityFrameworkCore.Sqlite" Version="8.0.8" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.8">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageVersion>
<PackageVersion Include="Microsoft.Extensions.Http" Version="8.0.0" />
<PackageVersion Include="Microsoft.Toolkit.Uwp.Notifications" Version="7.1.3" />
<PackageVersion Include="Microsoft.Win32" Version="2.0.1" />
<PackageVersion Include="Microsoft.Windows.Compatibility" Version="8.0.6" />
<PackageVersion Include="Microsoft.Windows.Compatibility" Version="8.0.8" />
<PackageVersion Include="NoStringEvaluating" Version="2.5.2" />
<PackageVersion Include="Octopus.Octodiff" Version="2.0.546" />
<PackageVersion Include="PropertyChanged.SourceGenerator" Version="1.1.0" />
@ -50,16 +50,16 @@
<PackageVersion Include="RawInput.Sharp" Version="0.1.3" />
<PackageVersion Include="ReactiveUI" Version="20.1.1" />
<PackageVersion Include="ReactiveUI.Validation" Version="4.0.9" />
<PackageVersion Include="Serilog" Version="4.0.0" />
<PackageVersion Include="Serilog" Version="4.0.1" />
<PackageVersion Include="Serilog.Sinks.Console" Version="6.0.0" />
<PackageVersion Include="Serilog.Sinks.Debug" Version="3.0.0" />
<PackageVersion Include="Serilog.Sinks.File" Version="6.0.0" />
<PackageVersion Include="SkiaSharp" Version="2.88.8" />
<PackageVersion Include="SkiaSharp.Vulkan.SharpVk" Version="2.88.8" />
<PackageVersion Include="Splat.DryIoc" Version="15.1.1" />
<PackageVersion Include="StrawberryShake.Server" Version="13.9.6" />
<PackageVersion Include="System.IdentityModel.Tokens.Jwt" Version="7.6.2" />
<PackageVersion Include="Splat.DryIoc" Version="15.2.22" />
<PackageVersion Include="StrawberryShake.Server" Version="13.9.12" />
<PackageVersion Include="System.IdentityModel.Tokens.Jwt" Version="8.0.2" />
<PackageVersion Include="System.Text.Json" Version="8.0.4" />
<PackageVersion Include="TextMateSharp.Grammars" Version="1.0.57" />
<PackageVersion Include="TextMateSharp.Grammars" Version="1.0.63" />
</ItemGroup>
</Project>