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

Initial workshop commit

This commit is contained in:
Robert 2023-06-11 18:52:17 +02:00
parent 70b6035b0d
commit bde4e861c2
18 changed files with 441 additions and 133 deletions

View File

@ -12,6 +12,7 @@
<ProjectReference Include="..\Artemis.UI.Shared\Artemis.UI.Shared.csproj" />
<ProjectReference Include="..\Artemis.VisualScripting\Artemis.VisualScripting.csproj" />
<ProjectReference Include="..\Artemis.WebClient.Updating\Artemis.WebClient.Updating.csproj" />
<ProjectReference Include="..\Artemis.WebClient.Workshop\Artemis.WebClient.Workshop.csproj" />
</ItemGroup>
<ItemGroup>

View File

@ -12,6 +12,7 @@ using Artemis.UI.Shared.DryIoc;
using Artemis.UI.Shared.Services;
using Artemis.VisualScripting.DryIoc;
using Artemis.WebClient.Updating.DryIoc;
using Artemis.WebClient.Workshop.DryIoc;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.ApplicationLifetimes;
@ -45,6 +46,7 @@ public static class ArtemisBootstrapper
_container.RegisterUI();
_container.RegisterSharedUI();
_container.RegisterUpdatingClient();
_container.RegisterWorkshopClient();
_container.RegisterNoStringEvaluating();
configureServices?.Invoke(_container);

View File

@ -10,62 +10,26 @@
xmlns:controls="clr-namespace:Artemis.UI.Shared.Controls;assembly=Artemis.UI.Shared"
xmlns:gradientPicker="clr-namespace:Artemis.UI.Shared.Controls.GradientPicker;assembly=Artemis.UI.Shared"
xmlns:materialIconPicker="clr-namespace:Artemis.UI.Shared.MaterialIconPicker;assembly=Artemis.UI.Shared"
xmlns:workshop1="clr-namespace:Artemis.WebClient.Workshop;assembly=Artemis.WebClient.Workshop"
mc:Ignorable="d" d:DesignWidth="800"
x:Class="Artemis.UI.Screens.Workshop.WorkshopView"
x:DataType="workshop:WorkshopViewModel">
<Border Classes="router-container">
<ScrollViewer>
<StackPanel Margin="12" Spacing="5">
<Border Classes="card">
<StackPanel Spacing="5">
<TextBlock Classes="h4">Notification tests</TextBlock>
<Button Command="{CompiledBinding ShowNotification}" CommandParameter="{x:Static builders:NotificationSeverity.Informational}">
Notification test (default)
</Button>
<Button Command="{CompiledBinding ShowNotification}" CommandParameter="{x:Static builders:NotificationSeverity.Warning}">
Notification test (warning)
</Button>
<Button Command="{CompiledBinding ShowNotification}" CommandParameter="{x:Static builders:NotificationSeverity.Error}">
Notification test (error)
</Button>
<Button Command="{CompiledBinding ShowNotification}" CommandParameter="{x:Static builders:NotificationSeverity.Success}">
Notification test (success)
</Button>
<shared:HotkeyBox Watermark="Some hotkey" Width="250" HorizontalAlignment="Left" />
<controls1:NumberBox
attachedProperties:NumberBoxAssist.PrefixText="$"
attachedProperties:NumberBoxAssist.SuffixText="%">
</controls1:NumberBox>
<TextBox
attachedProperties:TextBoxAssist.PrefixText="$"
attachedProperties:TextBoxAssist.SuffixText="%">
</TextBox>
<TextBlock Classes="h4" Text="{CompiledBinding TestValue}"/>
<controls1:NumberBox Value="{CompiledBinding TestValue}"/>
<controls:DraggableNumberBox Value="{CompiledBinding TestValue}"/>
<controls:DraggableNumberBox Value="{CompiledBinding TestValue}" Classes="condensed"/>
<StackPanel Orientation="Horizontal" Spacing="5">
<Border Classes="card" Cursor="{CompiledBinding Cursor}">
<TextBlock Text="{CompiledBinding SelectedCursor}"></TextBlock>
</Border>
<shared:EnumComboBox Value="{CompiledBinding SelectedCursor}"></shared:EnumComboBox>
</StackPanel>
<Button Command="{CompiledBinding CreateRandomGradient}">
Create random gradient
</Button>
<gradientPicker:GradientPickerButton ColorGradient="{CompiledBinding ColorGradient}" IsCompact="True" />
<materialIconPicker:MaterialIconPickerButton Name="IconPicker" Value="Abc"/>
<TextBlock Text="{CompiledBinding #IconPicker.Value}"></TextBlock>
</StackPanel>
</Border>
</StackPanel>
</ScrollViewer>
<Grid ColumnDefinitions="300,*" Margin="0 10">
<Border Classes="card-condensed" Grid.Column="0" Margin="0 0 10 0">
<ListBox ItemsSource="{CompiledBinding Test}">
<ListBox.ItemTemplate>
<DataTemplate x:DataType="workshop1:IGetEntries_Entries_Nodes">
<Panel>
<StackPanel Margin="4">
<TextBlock Text="{CompiledBinding Name}" VerticalAlignment="Center" />
<TextBlock Text="{CompiledBinding Author}" VerticalAlignment="Center" Classes="subtitle" FontSize="13" />
</StackPanel>
</Panel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Border>
</Grid>
</Border>
</UserControl>

View File

@ -1,70 +1,52 @@
using System.Reactive;
using System;
using System.Collections.ObjectModel;
using System.Reactive;
using System.Reactive.Linq;
using System.Threading.Tasks;
using Artemis.Core;
using Artemis.UI.Shared.Services;
using Artemis.UI.Shared.Services.Builders;
using Artemis.WebClient.Workshop;
using Avalonia.Input;
using ReactiveUI;
using SkiaSharp;
using StrawberryShake;
namespace Artemis.UI.Screens.Workshop;
public class WorkshopViewModel : MainScreenViewModel
{
private readonly ObservableAsPropertyHelper<Cursor> _cursor;
private readonly INotificationService _notificationService;
private readonly IWorkshopClient _workshopClient;
private ColorGradient _colorGradient = new()
public WorkshopViewModel(IScreen hostScreen, IWorkshopClient workshopClient) : base(hostScreen, "workshop")
{
new ColorGradientStop(new SKColor(0xFFFF6D00), 0f),
new ColorGradientStop(new SKColor(0xFFFE6806), 0.2f),
new ColorGradientStop(new SKColor(0xFFEF1788), 0.4f),
new ColorGradientStop(new SKColor(0xFFEF1788), 0.6f),
new ColorGradientStop(new SKColor(0xFF00FCCC), 0.8f),
new ColorGradientStop(new SKColor(0xFF00FCCC), 1f)
};
private StandardCursorType _selectedCursor;
private double _testValue;
public WorkshopViewModel(IScreen hostScreen, INotificationService notificationService) : base(hostScreen, "workshop")
{
_notificationService = notificationService;
_cursor = this.WhenAnyValue(vm => vm.SelectedCursor).Select(c => new Cursor(c)).ToProperty(this, vm => vm.Cursor);
_workshopClient = workshopClient;
DisplayName = "Workshop";
ShowNotification = ReactiveCommand.Create<NotificationSeverity>(ExecuteShowNotification);
Task.Run(() => GetEntries());
}
public ReactiveCommand<NotificationSeverity, Unit> ShowNotification { get; set; }
public ObservableCollection<IGetEntries_Entries_Nodes> Test { get; set; } = new();
public StandardCursorType SelectedCursor
private async Task GetEntries()
{
get => _selectedCursor;
set => RaiseAndSetIfChanged(ref _selectedCursor, value);
}
public Cursor Cursor => _cursor.Value;
public ColorGradient ColorGradient
{
get => _colorGradient;
set => RaiseAndSetIfChanged(ref _colorGradient, value);
}
public double TestValue
{
get => _testValue;
set => RaiseAndSetIfChanged(ref _testValue, value);
}
public void CreateRandomGradient()
{
ColorGradient = ColorGradient.GetRandom(6);
}
private void ExecuteShowNotification(NotificationSeverity severity)
{
_notificationService.CreateNotification().WithTitle("Test title").WithMessage("Test message").WithSeverity(severity).Show();
try
{
IOperationResult<IGetEntriesResult> entries = await _workshopClient.GetEntries.ExecuteAsync();
if (entries.Data?.Entries?.Nodes == null)
return;
foreach (IGetEntries_Entries_Nodes getEntriesEntriesNodes in entries.Data.Entries.Nodes)
{
Console.WriteLine(getEntriesEntriesNodes);
Test.Add(getEntriesEntriesNodes);
}
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
}
}

View File

@ -1,15 +0,0 @@
{
"name": "Untitled GraphQL Schema",
"schemaPath": "schema.graphql",
"extensions": {
"endpoints": {
"Default GraphQL Endpoint": {
"url": "https://updating.artemis-rgb.com/graphql",
"headers": {
"user-agent": "JS GraphQL"
},
"introspect": true
}
}
}
}

View File

@ -13,4 +13,8 @@
<PackageReference Include="Microsoft.Extensions.Http" Version="7.0.0" />
<PackageReference Include="StrawberryShake.Server" Version="13.0.5" />
</ItemGroup>
<ItemGroup>
<None Remove=".graphqlconfig" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,8 @@
schema: schema.graphql
extensions:
endpoints:
Default GraphQL Endpoint:
url: https://updating.artemis-rgb.com/graphql
headers:
user-agent: JS GraphQL
introspect: true

View File

@ -1,13 +0,0 @@
scalar _KeyFieldSet
directive @key(fields: _KeyFieldSet!) on SCHEMA | OBJECT
directive @serializationType(name: String!) on SCALAR
directive @runtimeType(name: String!) on SCALAR
directive @enumValue(value: String!) on ENUM_VALUE
directive @rename(name: String!) on INPUT_FIELD_DEFINITION | INPUT_OBJECT | ENUM | ENUM_VALUE
extend schema @key(fields: "id")

View File

@ -1,4 +1,4 @@
# This file was generated based on ".graphqlconfig". Do not edit manually.
# This file was generated. Do not edit manually.
schema {
query: Query
@ -107,10 +107,11 @@ type Release {
type ReleaseStatistic {
count: Int!
date: Date!
lastReportedUsage: DateTime!
linuxCount: Int!
osxCount: Int!
releaseId: UUID!
release: Release
windowsCount: Int!
}
@ -144,6 +145,9 @@ enum SortEnumType {
DESC
}
"The `Date` scalar represents an ISO-8601 compliant date type."
scalar Date
"The `DateTime` scalar represents an ISO-8601 compliant date time type."
scalar DateTime
@ -176,6 +180,21 @@ input BooleanOperationFilterInput {
neq: Boolean
}
input DateOperationFilterInput {
eq: Date
gt: Date
gte: Date
in: [Date]
lt: Date
lte: Date
neq: Date
ngt: Date
ngte: Date
nin: [Date]
nlt: Date
nlte: Date
}
input DateTimeOperationFilterInput {
eq: DateTime
gt: DateTime
@ -265,20 +284,22 @@ input ReleaseSortInput {
input ReleaseStatisticFilterInput {
and: [ReleaseStatisticFilterInput!]
count: IntOperationFilterInput
date: DateOperationFilterInput
lastReportedUsage: DateTimeOperationFilterInput
linuxCount: IntOperationFilterInput
or: [ReleaseStatisticFilterInput!]
osxCount: IntOperationFilterInput
releaseId: UuidOperationFilterInput
release: ReleaseFilterInput
windowsCount: IntOperationFilterInput
}
input ReleaseStatisticSortInput {
count: SortEnumType
date: SortEnumType
lastReportedUsage: SortEnumType
linuxCount: SortEnumType
osxCount: SortEnumType
releaseId: SortEnumType
release: ReleaseSortInput
windowsCount: SortEnumType
}

View File

@ -0,0 +1,12 @@
{
"version": 1,
"isRoot": true,
"tools": {
"strawberryshake.tools": {
"version": "13.0.0-rc.4",
"commands": [
"dotnet-graphql"
]
}
}
}

View File

@ -0,0 +1,22 @@
{
"schema": "schema.graphql",
"documents": "**/*.graphql",
"extensions": {
"strawberryShake": {
"name": "WorkshopClient",
"namespace": "Artemis.WebClient.Workshop",
"url": "https://localhost:7281/graphql/",
"emitGeneratedCode": false,
"records": {
"inputs": false,
"entities": false
},
"transportProfiles": [
{
"default": "Http",
"subscription": "WebSocket"
}
]
}
}
}

View File

@ -0,0 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="DryIoc.dll" Version="5.4.0" />
<PackageReference Include="DryIoc.Microsoft.DependencyInjection" Version="6.2.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="7.0.0" />
<PackageReference Include="Microsoft.Extensions.Http" Version="7.0.0" />
<PackageReference Include="StrawberryShake.Server" Version="13.0.5" />
</ItemGroup>
<ItemGroup>
<None Remove=".graphqlconfig" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,26 @@
using DryIoc;
using DryIoc.Microsoft.DependencyInjection;
using Microsoft.Extensions.DependencyInjection;
namespace Artemis.WebClient.Workshop.DryIoc;
/// <summary>
/// Provides an extension method to register services onto a DryIoc <see cref="IContainer"/>.
/// </summary>
public static class ContainerExtensions
{
/// <summary>
/// Registers the updating client into the container.
/// </summary>
/// <param name="container">The builder building the current container</param>
public static void RegisterWorkshopClient(this IContainer container)
{
ServiceCollection serviceCollection = new();
serviceCollection
.AddHttpClient()
.AddWorkshopClient()
.ConfigureHttpClient(client => client.BaseAddress = new Uri("https://localhost:7281/graphql"));
container.WithDependencyInjectionAdapter(serviceCollection);
}
}

View File

@ -0,0 +1,9 @@
query GetEntries {
entries {
nodes {
author
name
entryType
}
}
}

View File

@ -0,0 +1,7 @@
query GetEntryById($id: UUID!) {
entry(id: $id) {
author
name
entryType
}
}

View File

@ -0,0 +1,8 @@
schema: schema.graphql
extensions:
endpoints:
Default GraphQL Endpoint:
url: https://localhost:7281/graphql
headers:
user-agent: JS GraphQL
introspect: true

View File

@ -0,0 +1,244 @@
# This file was generated. Do not edit manually.
schema {
query: Query
mutation: Mutation
}
"A connection to a list of items."
type EntriesConnection {
"A list of edges."
edges: [EntriesEdge!]
"A flattened list of the nodes."
nodes: [Entry!]
"Information to aid in pagination."
pageInfo: PageInfo!
"Identifies the total count of items in the connection."
totalCount: Int!
}
"An edge in a connection."
type EntriesEdge {
"A cursor for use in pagination."
cursor: String!
"The item at the end of the edge."
node: Entry!
}
type Entry {
author: UUID!
description: String!
entryType: EntryType!
icon: Image
id: UUID!
images: [Image!]!
name: String!
releases: [Release!]!
tags: [String!]!
}
type Image {
id: UUID!
mimeType: String!
}
type Mutation {
addEntry(input: EntryInput!): Entry
}
"Information about pagination in a connection."
type PageInfo {
"When paginating forwards, the cursor to continue."
endCursor: String
"Indicates whether more edges exist following the set defined by the clients arguments."
hasNextPage: Boolean!
"Indicates whether more edges exist prior the set defined by the clients arguments."
hasPreviousPage: Boolean!
"When paginating backwards, the cursor to continue."
startCursor: String
}
type Query {
entries(
"Returns the elements in the list that come after the specified cursor."
after: String,
"Returns the elements in the list that come before the specified cursor."
before: String,
"Returns the first _n_ elements from the list."
first: Int,
"Returns the last _n_ elements from the list."
last: Int,
order: [EntrySortInput!],
where: EntryFilterInput
): EntriesConnection
entry(id: UUID!): Entry
}
type Release {
createdAt: DateTime!
downloadSize: Long!
downloads: Long!
id: UUID!
md5Hash: String
version: String!
}
enum EntryType {
LAYOUT
PLUGIN
PROFILE
}
enum SortEnumType {
ASC
DESC
}
"The `DateTime` scalar represents an ISO-8601 compliant date time type."
scalar DateTime
"The `Long` scalar type represents non-fractional signed whole 64-bit numeric values. Long can represent values between -(2^63) and 2^63 - 1."
scalar Long
scalar UUID
input DateTimeOperationFilterInput {
eq: DateTime
gt: DateTime
gte: DateTime
in: [DateTime]
lt: DateTime
lte: DateTime
neq: DateTime
ngt: DateTime
ngte: DateTime
nin: [DateTime]
nlt: DateTime
nlte: DateTime
}
input EntryFilterInput {
and: [EntryFilterInput!]
author: UuidOperationFilterInput
description: StringOperationFilterInput
entryType: EntryTypeOperationFilterInput
icon: ImageFilterInput
id: UuidOperationFilterInput
images: ListFilterInputTypeOfImageFilterInput
name: StringOperationFilterInput
or: [EntryFilterInput!]
releases: ListFilterInputTypeOfReleaseFilterInput
tags: ListStringOperationFilterInput
}
input EntryInput {
description: String!
entryType: EntryType!
name: String!
tags: [String!]!
}
input EntrySortInput {
author: SortEnumType
description: SortEnumType
entryType: SortEnumType
icon: ImageSortInput
id: SortEnumType
name: SortEnumType
}
input EntryTypeOperationFilterInput {
eq: EntryType
in: [EntryType!]
neq: EntryType
nin: [EntryType!]
}
input ImageFilterInput {
and: [ImageFilterInput!]
id: UuidOperationFilterInput
mimeType: StringOperationFilterInput
or: [ImageFilterInput!]
}
input ImageSortInput {
id: SortEnumType
mimeType: SortEnumType
}
input ListFilterInputTypeOfImageFilterInput {
all: ImageFilterInput
any: Boolean
none: ImageFilterInput
some: ImageFilterInput
}
input ListFilterInputTypeOfReleaseFilterInput {
all: ReleaseFilterInput
any: Boolean
none: ReleaseFilterInput
some: ReleaseFilterInput
}
input ListStringOperationFilterInput {
all: StringOperationFilterInput
any: Boolean
none: StringOperationFilterInput
some: StringOperationFilterInput
}
input LongOperationFilterInput {
eq: Long
gt: Long
gte: Long
in: [Long]
lt: Long
lte: Long
neq: Long
ngt: Long
ngte: Long
nin: [Long]
nlt: Long
nlte: Long
}
input ReleaseFilterInput {
and: [ReleaseFilterInput!]
createdAt: DateTimeOperationFilterInput
downloadSize: LongOperationFilterInput
downloads: LongOperationFilterInput
id: UuidOperationFilterInput
md5Hash: StringOperationFilterInput
or: [ReleaseFilterInput!]
version: StringOperationFilterInput
}
input StringOperationFilterInput {
and: [StringOperationFilterInput!]
contains: String
endsWith: String
eq: String
in: [String]
ncontains: String
nendsWith: String
neq: String
nin: [String]
nstartsWith: String
or: [StringOperationFilterInput!]
startsWith: String
}
input UuidOperationFilterInput {
eq: UUID
gt: UUID
gte: UUID
in: [UUID]
lt: UUID
lte: UUID
neq: UUID
ngt: UUID
ngte: UUID
nin: [UUID]
nlt: UUID
nlte: UUID
}

View File

@ -21,6 +21,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Artemis.VisualScripting", "
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Artemis.WebClient.Updating", "Artemis.WebClient.Updating\Artemis.WebClient.Updating.csproj", "{7C8C6F50-0CC8-45B3-B608-A7218C005E4B}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Artemis.WebClient.Workshop", "Artemis.WebClient.Workshop\Artemis.WebClient.Workshop.csproj", "{2B982C2E-3CBC-4DAB-9167-CCCA4C78E92B}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
@ -63,6 +65,10 @@ Global
{7C8C6F50-0CC8-45B3-B608-A7218C005E4B}.Debug|x64.Build.0 = Debug|Any CPU
{7C8C6F50-0CC8-45B3-B608-A7218C005E4B}.Release|x64.ActiveCfg = Release|Any CPU
{7C8C6F50-0CC8-45B3-B608-A7218C005E4B}.Release|x64.Build.0 = Release|Any CPU
{2B982C2E-3CBC-4DAB-9167-CCCA4C78E92B}.Debug|x64.ActiveCfg = Debug|Any CPU
{2B982C2E-3CBC-4DAB-9167-CCCA4C78E92B}.Debug|x64.Build.0 = Debug|Any CPU
{2B982C2E-3CBC-4DAB-9167-CCCA4C78E92B}.Release|x64.ActiveCfg = Release|Any CPU
{2B982C2E-3CBC-4DAB-9167-CCCA4C78E92B}.Release|x64.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE