mirror of
https://github.com/BlossomiShymae/Needlework.Net.git
synced 2025-12-06 18:20:47 +01:00
Compare commits
5 Commits
38e1ea2301
...
0.9.0.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2e4637f533 | ||
|
|
7aaa79956c | ||
|
|
e9d4615ecf | ||
|
|
fb63adc1b7 | ||
|
|
b41be19cd9 |
1
Needlework.Net/Assets/libraries.json
Normal file
1
Needlework.Net/Assets/libraries.json
Normal file
@@ -0,0 +1 @@
|
|||||||
|
[{"Repo":"GrrrLCU","Description":"A simple wrapper for the LCU. Grrr. x3","Language":"C#","Link":"https://github.com/BlossomiShymae/GrrrLCU"},{"Repo":"Kunc.RiotGames","Description":null,"Language":"C#","Link":"https://github.com/AoshiW/Kunc.RiotGames"},{"Repo":"rito","Description":"Rito is a simple, crossplatform (Windows and Linux) C++20 library interfacing with Riot services (i.e. Riot REST API and League of Legends client).","Language":"cpp","Link":"https://github.com/bartekprtc/rito"},{"Repo":"R4J","Description":"A Java library containing the API for every Riot game","Language":"Java","Link":"https://github.com/stelar7/R4J"},{"Repo":"hasagi-core","Description":"LCU library with auto-generated types for request parameters and responses","Language":"JavaScript","Link":"https://github.com/dysolix/hasagi-core"},{"Repo":"lcu-driver","Description":"Python3 helper for the League of Legends LCU API.","Language":"Python","Link":"https://github.com/sousa-andre/lcu-driver"},{"Repo":"willump","Description":"Python3 helper for the League of Legends LCU API.","Language":"Python","Link":"https://github.com/elliejs/Willump"},{"Repo":"Irelia","Description":"LoL LCU Wrapper for Rust, built on top of hyper!","Language":"Rust","Link":"https://github.com/AlsoSylv/Irelia"},{"Repo":"Shaco","Description":"League of Legends LCU wrapper for rust","Language":"Rust","Link":"https://github.com/Leastrio/Shaco"},{"Repo":"hasagi-core","Description":"LCU library with auto-generated types for request parameters and responses","Language":"TypeScript","Link":"https://github.com/dysolix/hasagi-core"},{"Repo":"hexgate","Description":"LCU API wrapper for League of Legends","Language":"TypeScript","Link":"https://github.com/cuppachino/hexgate"}]
|
||||||
9
Needlework.Net/Models/Library.cs
Normal file
9
Needlework.Net/Models/Library.cs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
namespace Needlework.Net.Models;
|
||||||
|
|
||||||
|
public class Library
|
||||||
|
{
|
||||||
|
public required string Repo { get; init; }
|
||||||
|
public string? Description { get; init; }
|
||||||
|
public required string Language { get; init; }
|
||||||
|
public required string Link { get; init; }
|
||||||
|
}
|
||||||
@@ -11,7 +11,7 @@
|
|||||||
<AvaloniaXamlIlDebuggerLaunch>False</AvaloniaXamlIlDebuggerLaunch>
|
<AvaloniaXamlIlDebuggerLaunch>False</AvaloniaXamlIlDebuggerLaunch>
|
||||||
<ApplicationIcon>app.ico</ApplicationIcon>
|
<ApplicationIcon>app.ico</ApplicationIcon>
|
||||||
<AssemblyName>NeedleworkDotNet</AssemblyName>
|
<AssemblyName>NeedleworkDotNet</AssemblyName>
|
||||||
<AssemblyVersion>0.8.0.0</AssemblyVersion>
|
<AssemblyVersion>0.9.0.0</AssemblyVersion>
|
||||||
<FileVersion>$(AssemblyVersion)</FileVersion>
|
<FileVersion>$(AssemblyVersion)</FileVersion>
|
||||||
<AvaloniaXamlVerboseExceptions>False</AvaloniaXamlVerboseExceptions>
|
<AvaloniaXamlVerboseExceptions>False</AvaloniaXamlVerboseExceptions>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|||||||
@@ -18,8 +18,8 @@ public partial class EndpointsViewModel : ObservableObject
|
|||||||
|
|
||||||
public EndpointsViewModel(IAvaloniaList<string> plugins, Action<ObservableObject> onClicked)
|
public EndpointsViewModel(IAvaloniaList<string> plugins, Action<ObservableObject> onClicked)
|
||||||
{
|
{
|
||||||
Plugins = plugins;
|
Plugins = new AvaloniaList<string>(plugins);
|
||||||
Query = plugins;
|
Query = new AvaloniaList<string>(plugins);
|
||||||
OnClicked = onClicked;
|
OnClicked = onClicked;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,17 @@
|
|||||||
using CommunityToolkit.Mvvm.Input;
|
using Avalonia.Platform;
|
||||||
|
using CommunityToolkit.Mvvm.Input;
|
||||||
|
using Needlework.Net.Models;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
using System.Text.Json;
|
||||||
|
|
||||||
namespace Needlework.Net.ViewModels.Pages;
|
namespace Needlework.Net.ViewModels.Pages;
|
||||||
|
|
||||||
public partial class HomeViewModel : PageBase
|
public partial class HomeViewModel : PageBase
|
||||||
{
|
{
|
||||||
|
public List<Library> Libraries { get; } = JsonSerializer.Deserialize<List<Library>>(AssetLoader.Open(new Uri($"avares://NeedleworkDotNet/Assets/libraries.json")))!;
|
||||||
|
|
||||||
public HomeViewModel() : base("Home", "home", int.MinValue) { }
|
public HomeViewModel() : base("Home", "home", int.MinValue) { }
|
||||||
|
|
||||||
[RelayCommand]
|
[RelayCommand]
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ public class EventViewModel : ObservableObject
|
|||||||
public EventViewModel(EventData eventData)
|
public EventViewModel(EventData eventData)
|
||||||
{
|
{
|
||||||
Time = $"{DateTime.Now:HH:mm:ss.fff}";
|
Time = $"{DateTime.Now:HH:mm:ss.fff}";
|
||||||
Type = eventData?.EventType.ToUpper() ?? string.Empty;
|
Type = eventData?.EventType?.ToUpper() ?? string.Empty;
|
||||||
Uri = eventData?.Uri ?? string.Empty;
|
Uri = eventData?.Uri ?? string.Empty;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using BlossomiShymae.GrrrLCU;
|
using Avalonia.Collections;
|
||||||
|
using BlossomiShymae.GrrrLCU;
|
||||||
using CommunityToolkit.Mvvm.ComponentModel;
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
using CommunityToolkit.Mvvm.Input;
|
using CommunityToolkit.Mvvm.Input;
|
||||||
using CommunityToolkit.Mvvm.Messaging;
|
using CommunityToolkit.Mvvm.Messaging;
|
||||||
@@ -8,8 +9,11 @@ using System.Collections.Generic;
|
|||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Net.Http;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using Websocket.Client;
|
using Websocket.Client;
|
||||||
|
|
||||||
namespace Needlework.Net.ViewModels.Pages.Websocket;
|
namespace Needlework.Net.ViewModels.Pages.Websocket;
|
||||||
@@ -25,37 +29,76 @@ public partial class WebsocketViewModel : PageBase
|
|||||||
[ObservableProperty] private bool _isTail = false;
|
[ObservableProperty] private bool _isTail = false;
|
||||||
[ObservableProperty] private EventViewModel? _selectedEventLog = null;
|
[ObservableProperty] private EventViewModel? _selectedEventLog = null;
|
||||||
|
|
||||||
|
[ObservableProperty] private IAvaloniaList<string> _eventTypes = new AvaloniaList<string>();
|
||||||
|
[ObservableProperty] private string _eventType = "OnJsonApiEvent";
|
||||||
|
|
||||||
private Dictionary<string, EventMessage> _events = [];
|
private Dictionary<string, EventMessage> _events = [];
|
||||||
|
|
||||||
public WebsocketClient? Client { get; set; }
|
public WebsocketClient? Client { get; set; }
|
||||||
|
|
||||||
|
public List<IDisposable> ClientDisposables = [];
|
||||||
|
|
||||||
|
private readonly object _tokenLock = new();
|
||||||
|
public CancellationTokenSource TokenSource { get; set; } = new();
|
||||||
|
|
||||||
|
public HttpClient HttpClient { get; }
|
||||||
|
|
||||||
public IReadOnlyList<EventViewModel> FilteredEventLog => string.IsNullOrWhiteSpace(Search) ? EventLog : [.. EventLog.Where(x => x.Key.Contains(Search, StringComparison.InvariantCultureIgnoreCase))];
|
public IReadOnlyList<EventViewModel> FilteredEventLog => string.IsNullOrWhiteSpace(Search) ? EventLog : [.. EventLog.Where(x => x.Key.Contains(Search, StringComparison.InvariantCultureIgnoreCase))];
|
||||||
|
|
||||||
public WebsocketViewModel() : base("Event Viewer", "plug", -100)
|
public WebsocketViewModel(HttpClient httpClient) : base("Event Viewer", "plug", -100)
|
||||||
{
|
{
|
||||||
|
HttpClient = httpClient;
|
||||||
EventLog.CollectionChanged += (s, e) => OnPropertyChanged(nameof(FilteredEventLog));
|
EventLog.CollectionChanged += (s, e) => OnPropertyChanged(nameof(FilteredEventLog));
|
||||||
var thread = new Thread(InitializeWebsocket) { IsBackground = true };
|
Task.Run(async () =>
|
||||||
thread.Start();
|
{
|
||||||
|
await InitializeEventTypes();
|
||||||
|
InitializeWebsocket();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task InitializeEventTypes()
|
||||||
|
{
|
||||||
|
var file = await HttpClient.GetStringAsync("https://raw.githubusercontent.com/dysolix/hasagi-types/refs/heads/main/lcu-events.d.ts");
|
||||||
|
var matches = EventTypesRegex().Matches(file);
|
||||||
|
Avalonia.Threading.Dispatcher.UIThread.Invoke(() => EventTypes.AddRange(matches.Select(m => m.Groups[1].Value)));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void InitializeWebsocket()
|
private void InitializeWebsocket()
|
||||||
{
|
{
|
||||||
while (true)
|
lock (_tokenLock)
|
||||||
{
|
{
|
||||||
try
|
if (Client != null)
|
||||||
{
|
{
|
||||||
var client = Connector.CreateLcuWebsocketClient();
|
foreach (var disposable in ClientDisposables)
|
||||||
client.EventReceived.Subscribe(OnMessage);
|
disposable.Dispose();
|
||||||
client.DisconnectionHappened.Subscribe(OnDisconnection);
|
ClientDisposables.Clear();
|
||||||
client.ReconnectionHappened.Subscribe(OnReconnection);
|
Client.Dispose();
|
||||||
|
|
||||||
client.Start();
|
|
||||||
client.Send(new EventMessage(EventRequestType.Subscribe, EventKinds.OnJsonApiEvent));
|
|
||||||
Client = client;
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
catch (Exception) { }
|
TokenSource.Cancel();
|
||||||
Thread.Sleep(TimeSpan.FromSeconds(5));
|
var tokenSource = new CancellationTokenSource();
|
||||||
|
var thread = new Thread(() =>
|
||||||
|
{
|
||||||
|
while (!tokenSource.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var client = Connector.CreateLcuWebsocketClient();
|
||||||
|
ClientDisposables.Add(client.EventReceived.Subscribe(OnMessage));
|
||||||
|
ClientDisposables.Add(client.DisconnectionHappened.Subscribe(OnDisconnection));
|
||||||
|
ClientDisposables.Add(client.ReconnectionHappened.Subscribe(OnReconnection));
|
||||||
|
|
||||||
|
client.Start();
|
||||||
|
client.Send(new EventMessage(EventRequestType.Subscribe, new EventKind() { Prefix = EventType }));
|
||||||
|
Client = client;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
catch (Exception) { }
|
||||||
|
Thread.Sleep(TimeSpan.FromSeconds(5));
|
||||||
|
}
|
||||||
|
})
|
||||||
|
{ IsBackground = true };
|
||||||
|
thread.Start();
|
||||||
|
TokenSource = tokenSource;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,10 +127,13 @@ public partial class WebsocketViewModel : PageBase
|
|||||||
|
|
||||||
private void OnDisconnection(DisconnectionInfo info)
|
private void OnDisconnection(DisconnectionInfo info)
|
||||||
{
|
{
|
||||||
Trace.WriteLine($"-- Disconnection --\nType:{info.Type}\nSubProocol:{info.SubProtocol}\nCloseStatus:{info.CloseStatus}\nCloseStatusDescription:{info.CloseStatusDescription}\nExceptionMessage:{info?.Exception?.Message}\n:InnerException:{info?.Exception?.InnerException}");
|
Trace.WriteLine($"-- Disconnection --\nType:{info.Type}\nSubProtocol:{info.SubProtocol}\nCloseStatus:{info.CloseStatus}\nCloseStatusDescription:{info.CloseStatusDescription}\nExceptionMessage:{info?.Exception?.Message}\n:InnerException:{info?.Exception?.InnerException}");
|
||||||
Client?.Dispose();
|
InitializeWebsocket();
|
||||||
var thread = new Thread(InitializeWebsocket) { IsBackground = true };
|
}
|
||||||
thread.Start();
|
|
||||||
|
partial void OnEventTypeChanged(string value)
|
||||||
|
{
|
||||||
|
InitializeWebsocket();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnMessage(EventMessage message)
|
private void OnMessage(EventMessage message)
|
||||||
@@ -122,4 +168,7 @@ public partial class WebsocketViewModel : PageBase
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[GeneratedRegex("\"(.*?)\":")]
|
||||||
|
public static partial Regex EventTypesRegex();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -76,6 +76,7 @@
|
|||||||
<Grid>
|
<Grid>
|
||||||
<TransitioningContentControl Content="{Binding CurrentPage}"/>
|
<TransitioningContentControl Content="{Binding CurrentPage}"/>
|
||||||
<Button Content="{Binding Version}"
|
<Button Content="{Binding Version}"
|
||||||
|
Background="RoyalBlue"
|
||||||
HorizontalAlignment="Right"
|
HorizontalAlignment="Right"
|
||||||
VerticalAlignment="Bottom"
|
VerticalAlignment="Bottom"
|
||||||
Margin="16"/>
|
Margin="16"/>
|
||||||
|
|||||||
@@ -5,59 +5,116 @@
|
|||||||
xmlns:vm="using:Needlework.Net.ViewModels.Pages"
|
xmlns:vm="using:Needlework.Net.ViewModels.Pages"
|
||||||
xmlns:controls="using:Needlework.Net.Controls"
|
xmlns:controls="using:Needlework.Net.Controls"
|
||||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||||
|
Name="HomeControl"
|
||||||
x:Class="Needlework.Net.Views.Pages.HomeView"
|
x:Class="Needlework.Net.Views.Pages.HomeView"
|
||||||
x:DataType="vm:HomeViewModel">
|
x:DataType="vm:HomeViewModel">
|
||||||
|
<UserControl.Styles>
|
||||||
|
<Style Selector="Button">
|
||||||
|
<Setter Property="Command" Value="{Binding OpenUrlCommand}"/>
|
||||||
|
</Style>
|
||||||
|
<Style Selector="DataGrid">
|
||||||
|
<Setter Property="HorizontalGridLinesBrush" Value="{DynamicResource ControlElevationBorderBrush}"/>
|
||||||
|
</Style>
|
||||||
|
<Style Selector="DataGridColumnHeader TextBlock">
|
||||||
|
<Setter Property="Foreground" Value="{DynamicResource TextFillColorPrimaryBrush}"/>
|
||||||
|
</Style>
|
||||||
|
<Style Selector="DataGridRow DataGridCell">
|
||||||
|
<Setter Property="FontSize" Value="12"></Setter>
|
||||||
|
</Style>
|
||||||
|
<Style Selector="DataGridRow">
|
||||||
|
<Setter Property="Margin" Value="0 0 0 4"></Setter>
|
||||||
|
</Style>
|
||||||
|
</UserControl.Styles>
|
||||||
<!-- TOP LEVEL -->
|
<!-- TOP LEVEL -->
|
||||||
<ScrollViewer>
|
<Grid ColumnDefinitions="*,400"
|
||||||
<WrapPanel Margin="8"
|
RowDefinitions="*">
|
||||||
Orientation="Horizontal">
|
<!-- MAIN AREA -->
|
||||||
<!-- WELCOME -->
|
<ScrollViewer Grid.Column="0"
|
||||||
<StackPanel>
|
Grid.Row="0">
|
||||||
<Border Margin="12">
|
<WrapPanel Margin="8"
|
||||||
<StackPanel>
|
Orientation="Horizontal">
|
||||||
<TextBlock Theme="{StaticResource TitleTextBlockStyle}">
|
<!-- WELCOME -->
|
||||||
Welcome to Needlework.Net
|
<StackPanel>
|
||||||
</TextBlock>
|
<Border Margin="12">
|
||||||
<TextBlock>Get started with LCU development by clicking on the endpoints tab in the left panel.</TextBlock>
|
<StackPanel>
|
||||||
</StackPanel>
|
<TextBlock Theme="{StaticResource TitleTextBlockStyle}">
|
||||||
</Border>
|
Welcome to Needlework.Net
|
||||||
<controls:Card Margin="12">
|
</TextBlock>
|
||||||
<TextBlock TextWrapping="Wrap">THE PROGRAM IS PROVIDED “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGMENT, OR OF FITNESS FOR A PARTICULAR PURPOSE. LICENSOR DOES NOT WARRANT THAT THE FUNCTIONS CONTAINED IN THE PROGRAM WILL MEET YOUR REQUIREMENTS OR THAT OPERATION WILL BE UNINTERRUPTED OR ERROR FREE. LICENSOR MAKES NO WARRANTIES RESPECTING ANY HARM THAT MAY BE CAUSED BY MALICIOUS USE OF THIS SOFTWARE. LICENSOR FURTHER EXPRESSLY DISCLAIMS ANY WARRANTY OR REPRESENTATION TO AUTHORIZED USERS OR TO ANY THIRD PARTY.</TextBlock>
|
<TextBlock>Get started with LCU development by clicking on the endpoints tab in the left panel.</TextBlock>
|
||||||
</controls:Card>
|
|
||||||
</StackPanel>
|
|
||||||
<!-- FOOTER -->
|
|
||||||
<StackPanel>
|
|
||||||
<controls:Card Margin="12" Width="300">
|
|
||||||
<StackPanel>
|
|
||||||
<TextBlock
|
|
||||||
Theme="{StaticResource SubtitleTextBlockStyle}"
|
|
||||||
Margin="0 0 0 8">Resources</TextBlock>
|
|
||||||
<StackPanel Orientation="Horizontal">
|
|
||||||
<StackPanel.Styles>
|
|
||||||
<Style Selector="Button">
|
|
||||||
<Setter Property="Command" Value="{Binding OpenUrlCommand}"/>
|
|
||||||
</Style>
|
|
||||||
</StackPanel.Styles>
|
|
||||||
<Button CommandParameter="https://hextechdocs.dev/tag/lcu/" Margin="0 0 8 0">
|
|
||||||
Hextech Docs
|
|
||||||
</Button>
|
|
||||||
<Button CommandParameter="https://hextechdocs.dev/getting-started-with-the-lcu-api/">
|
|
||||||
Getting Started
|
|
||||||
</Button>
|
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</StackPanel>
|
</Border>
|
||||||
</controls:Card>
|
<controls:Card Margin="12">
|
||||||
|
<TextBlock TextWrapping="Wrap">THE PROGRAM IS PROVIDED “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGMENT, OR OF FITNESS FOR A PARTICULAR PURPOSE. LICENSOR DOES NOT WARRANT THAT THE FUNCTIONS CONTAINED IN THE PROGRAM WILL MEET YOUR REQUIREMENTS OR THAT OPERATION WILL BE UNINTERRUPTED OR ERROR FREE. LICENSOR MAKES NO WARRANTIES RESPECTING ANY HARM THAT MAY BE CAUSED BY MALICIOUS USE OF THIS SOFTWARE. LICENSOR FURTHER EXPRESSLY DISCLAIMS ANY WARRANTY OR REPRESENTATION TO AUTHORIZED USERS OR TO ANY THIRD PARTY.</TextBlock>
|
||||||
|
</controls:Card>
|
||||||
|
</StackPanel>
|
||||||
|
<!-- FOOTER -->
|
||||||
|
<StackPanel>
|
||||||
|
<controls:Card Margin="12" Width="300">
|
||||||
|
<StackPanel>
|
||||||
|
<TextBlock
|
||||||
|
Theme="{StaticResource SubtitleTextBlockStyle}"
|
||||||
|
Margin="0 0 0 8">Resources</TextBlock>
|
||||||
|
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
|
||||||
|
<Button CommandParameter="https://hextechdocs.dev/tag/lcu/" Margin="0 0 8 0">
|
||||||
|
Hextech Docs
|
||||||
|
</Button>
|
||||||
|
<Button CommandParameter="https://hextechdocs.dev/getting-started-with-the-lcu-api/">
|
||||||
|
Getting Started
|
||||||
|
</Button>
|
||||||
|
</StackPanel>
|
||||||
|
</StackPanel>
|
||||||
|
</controls:Card>
|
||||||
|
<controls:Card Margin="12" Width="300">
|
||||||
|
<StackPanel>
|
||||||
|
<TextBlock>© 2024 - Blossomi Shymae</TextBlock>
|
||||||
|
<TextBlock>MIT License</TextBlock>
|
||||||
|
</StackPanel>
|
||||||
|
</controls:Card>
|
||||||
|
</StackPanel>
|
||||||
|
<!-- LEGAL -->
|
||||||
<controls:Card Margin="12" Width="300">
|
<controls:Card Margin="12" Width="300">
|
||||||
<StackPanel>
|
<TextBlock TextWrapping="Wrap">Needlework.Net isn't endorsed by Riot Games and doesn't reflect the views or opinions of Riot Games or anyone officially involved in producing or managing Riot Games properties. Riot Games, and all associated properties are trademarks or registered trademarks of Riot Games, Inc.</TextBlock>
|
||||||
<TextBlock>© 2024 - Blossomi Shymae</TextBlock>
|
|
||||||
<TextBlock>MIT License</TextBlock>
|
|
||||||
</StackPanel>
|
|
||||||
</controls:Card>
|
</controls:Card>
|
||||||
</StackPanel>
|
</WrapPanel>
|
||||||
<!-- LEGAL -->
|
</ScrollViewer>
|
||||||
<controls:Card Margin="12" Width="300">
|
<!-- LIBRARIES -->
|
||||||
<TextBlock TextWrapping="Wrap">Needlework.Net isn't endorsed by Riot Games and doesn't reflect the views or opinions of Riot Games or anyone officially involved in producing or managing Riot Games properties. Riot Games, and all associated properties are trademarks or registered trademarks of Riot Games, Inc.</TextBlock>
|
<Grid Margin="20"
|
||||||
</controls:Card>
|
Grid.Column="1"
|
||||||
</WrapPanel>
|
Grid.Row="0"
|
||||||
</ScrollViewer>
|
ColumnDefinitions="*"
|
||||||
|
RowDefinitions="auto,*">
|
||||||
|
<TextBlock Theme="{StaticResource SubtitleTextBlockStyle}"
|
||||||
|
Grid.Column="0"
|
||||||
|
Grid.Row="0">Libraries</TextBlock>
|
||||||
|
<ScrollViewer Grid.Column="0"
|
||||||
|
Grid.Row="1"
|
||||||
|
HorizontalScrollBarVisibility="Disabled">
|
||||||
|
<ItemsRepeater ItemsSource="{Binding Libraries}">
|
||||||
|
<ItemsRepeater.ItemTemplate>
|
||||||
|
<DataTemplate>
|
||||||
|
<StackPanel Margin="0 12 0 0">
|
||||||
|
<TextBlock>
|
||||||
|
<Run Text="{Binding Language}"
|
||||||
|
FontWeight="Bold"/>
|
||||||
|
<Bold> - </Bold>
|
||||||
|
<Run Text="{Binding Repo}"
|
||||||
|
FontWeight="Bold"/>
|
||||||
|
</TextBlock>
|
||||||
|
<TextBlock Text="{Binding Description}"
|
||||||
|
IsVisible="{Binding Description, Converter={StaticResource NullBoolConverter}}"
|
||||||
|
TextAlignment="Left"
|
||||||
|
TextWrapping="WrapWithOverflow"
|
||||||
|
Width="350"/>
|
||||||
|
<Button Command="{Binding #HomeControl.((vm:HomeViewModel)DataContext).OpenUrlCommand}"
|
||||||
|
CommandParameter="{Binding Link}"
|
||||||
|
Margin="0 4 0 0">
|
||||||
|
<TextBlock Text="{Binding Link}"/>
|
||||||
|
</Button>
|
||||||
|
</StackPanel>
|
||||||
|
</DataTemplate>
|
||||||
|
</ItemsRepeater.ItemTemplate>
|
||||||
|
</ItemsRepeater>
|
||||||
|
</ScrollViewer>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
</UserControl>
|
</UserControl>
|
||||||
|
|||||||
@@ -10,12 +10,22 @@
|
|||||||
<Grid RowDefinitions="*,auto,*" Margin="16">
|
<Grid RowDefinitions="*,auto,*" Margin="16">
|
||||||
<Border Grid.Row="0"
|
<Border Grid.Row="0"
|
||||||
Padding="0 0 0 8">
|
Padding="0 0 0 8">
|
||||||
<Grid RowDefinitions="auto,*" ColumnDefinitions="*">
|
<Grid RowDefinitions="auto,auto,*" ColumnDefinitions="*">
|
||||||
|
<Grid Grid.Row="0"
|
||||||
|
Grid.Column="0"
|
||||||
|
RowDefinitions="*">
|
||||||
|
<ComboBox ItemsSource="{Binding EventTypes}"
|
||||||
|
SelectedItem="{Binding EventType}"
|
||||||
|
Grid.Row="0"
|
||||||
|
HorizontalAlignment="Stretch"
|
||||||
|
HorizontalContentAlignment="Left"/>
|
||||||
|
</Grid>
|
||||||
<Grid
|
<Grid
|
||||||
Grid.Row="0"
|
Grid.Row="1"
|
||||||
Grid.Column="0"
|
Grid.Column="0"
|
||||||
RowDefinitions="*"
|
RowDefinitions="*"
|
||||||
ColumnDefinitions="auto,*,auto,auto">
|
ColumnDefinitions="auto,*,auto,auto"
|
||||||
|
Margin="0 8 0 0">
|
||||||
<Button Margin="0 0 8 0"
|
<Button Margin="0 0 8 0"
|
||||||
Grid.Row="0"
|
Grid.Row="0"
|
||||||
Grid.Column="0"
|
Grid.Column="0"
|
||||||
@@ -37,7 +47,7 @@
|
|||||||
Content="Tail"
|
Content="Tail"
|
||||||
IsChecked="{Binding IsTail}"/>
|
IsChecked="{Binding IsTail}"/>
|
||||||
</Grid>
|
</Grid>
|
||||||
<ListBox Grid.Row="1"
|
<ListBox Grid.Row="2"
|
||||||
Grid.Column="0"
|
Grid.Column="0"
|
||||||
Name="EventViewer"
|
Name="EventViewer"
|
||||||
Margin="0 8 0 0"
|
Margin="0 8 0 0"
|
||||||
|
|||||||
Reference in New Issue
Block a user