first commit
This commit is contained in:
@@ -0,0 +1,65 @@
|
||||
#region License
|
||||
|
||||
// Copyright (C) 2020 Reetus
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#endregion
|
||||
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace ClassicAssist.Browser.Controls
|
||||
{
|
||||
public class ClearableComboBox : ComboBox
|
||||
{
|
||||
public static readonly DependencyProperty ClearCommandProperty =
|
||||
DependencyProperty.Register( "ClearCommand", typeof( ICommand ), typeof( ClearableComboBox ) );
|
||||
|
||||
public static readonly DependencyProperty ClearCommandParameterProperty =
|
||||
DependencyProperty.Register( "ClearCommandParameter", typeof( object ), typeof( ClearableComboBox ),
|
||||
new UIPropertyMetadata( null ) );
|
||||
|
||||
public ICommand ClearCommand
|
||||
{
|
||||
get => (ICommand) GetValue( ClearCommandProperty );
|
||||
set => SetValue( ClearCommandProperty, value );
|
||||
}
|
||||
|
||||
public object ClearCommandParameter
|
||||
{
|
||||
get => GetValue( ClearCommandParameterProperty );
|
||||
set => SetValue( ClearCommandParameterProperty, value );
|
||||
}
|
||||
|
||||
public override void OnApplyTemplate()
|
||||
{
|
||||
base.OnApplyTemplate();
|
||||
|
||||
Button button = (Button) GetTemplateChild( "ClearButton" );
|
||||
|
||||
if ( button != null )
|
||||
{
|
||||
button.Click += ClearButtonOnClick;
|
||||
}
|
||||
}
|
||||
|
||||
private void ClearButtonOnClick( object sender, RoutedEventArgs e )
|
||||
{
|
||||
SelectedItem = null;
|
||||
ClearCommand?.Execute( ClearCommandParameter );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,151 @@
|
||||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:controls="clr-namespace:ClassicAssist.Browser.Controls">
|
||||
<SolidColorBrush x:Key="ThemeForegroundBrush" Color="#CCCCCC" />
|
||||
<DrawingImage x:Key="ClearIcon">
|
||||
<DrawingImage.Drawing>
|
||||
<DrawingGroup ClipGeometry="M0,0 V512.001 H512.001 V0 H0 Z">
|
||||
<DrawingGroup.Transform>
|
||||
<TranslateTransform X="0.000250011682510376" Y="0" />
|
||||
</DrawingGroup.Transform>
|
||||
<DrawingGroup Opacity="1">
|
||||
<DrawingGroup Opacity="1">
|
||||
<GeometryDrawing Brush="{DynamicResource ThemeForegroundBrush}"
|
||||
Geometry="F1 M512.001,512.001z M0,0z M284.286,256.002L506.143,34.144C513.954,26.333 513.954,13.669 506.143,5.859 498.332,-1.951 485.668,-1.952 477.858,5.859L256,227.717 34.143,5.859C26.332,-1.952 13.668,-1.952 5.858,5.859 -1.952,13.67 -1.953,26.334 5.858,34.144L227.715,256.001 5.858,477.859C-1.953,485.67 -1.953,498.334 5.858,506.144 9.763,510.049 14.882,512.001 20.001,512.001 25.12,512.001 30.238,510.049 34.144,506.144L256,284.287 477.857,506.144C481.762,510.049 486.881,512.001 492,512.001 497.119,512.001 502.237,510.049 506.143,506.144 513.954,498.333 513.954,485.669 506.143,477.859L284.286,256.002z" />
|
||||
</DrawingGroup>
|
||||
</DrawingGroup>
|
||||
</DrawingGroup>
|
||||
</DrawingImage.Drawing>
|
||||
</DrawingImage>
|
||||
<Style TargetType="{x:Type controls:ClearableComboBox}">
|
||||
<Setter Property="OverridesDefaultStyle" Value="True" />
|
||||
<Setter Property="Background" Value="{DynamicResource TextBoxBackgroundBrush}" />
|
||||
<Setter Property="Foreground" Value="{DynamicResource TextBoxForegroundBrush}" />
|
||||
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto" />
|
||||
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto" />
|
||||
<Setter Property="ScrollViewer.CanContentScroll" Value="True" />
|
||||
<Setter Property="TextElement.Foreground" Value="{DynamicResource TextBoxForegroundBrush}" />
|
||||
<Setter Property="FocusVisualStyle" Value="{x:Null}" />
|
||||
<Setter Property="Validation.ErrorTemplate" Value="{DynamicResource ValidationErrorOverlayTemplate}" />
|
||||
<Setter Property="Padding" Value="3,0" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="{x:Type controls:ClearableComboBox}">
|
||||
<Grid>
|
||||
<TextBox x:Name="PART_EditableTextBox"
|
||||
IsReadOnly="{TemplateBinding IsReadOnly}"
|
||||
Focusable="True"
|
||||
Style="{DynamicResource TextBoxStyle}"
|
||||
Visibility="Hidden" />
|
||||
<Border x:Name="NonEditableBorder"
|
||||
Background="{DynamicResource ComboBoxNonEditableBackgroundBrush}"
|
||||
BorderThickness="1"
|
||||
BorderBrush="{DynamicResource ComboBoxNonEditableBorderBrush}">
|
||||
<ContentPresenter IsHitTestVisible="False"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Center"
|
||||
Content="{TemplateBinding ComboBox.SelectionBoxItem}"
|
||||
ContentTemplate="{TemplateBinding ComboBox.SelectionBoxItemTemplate}"
|
||||
ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}"
|
||||
Margin="{TemplateBinding Padding}" DockPanel.Dock="Left" />
|
||||
</Border>
|
||||
<Button x:Name="ClearButton" Padding="0" Background="Transparent"
|
||||
BorderBrush="Transparent" BorderThickness="0" Width="8" Height="8" Margin="0,0,20,0"
|
||||
HorizontalAlignment="Right">
|
||||
<Image Source="{DynamicResource ClearIcon}" Height="8" />
|
||||
</Button>
|
||||
<ToggleButton x:Name="ToggleButton"
|
||||
ClickMode="Press"
|
||||
HorizontalAlignment="Right"
|
||||
Background="{DynamicResource ComboBoxButtonBackgroundBrush}"
|
||||
BorderBrush="{DynamicResource ComboBoxButtonBorderBrush}"
|
||||
BorderThickness="0"
|
||||
Foreground="{DynamicResource ComboBoxButtonForegroundBrush}"
|
||||
IsChecked="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=IsDropDownOpen, Mode=TwoWay}">
|
||||
<ToggleButton.Template>
|
||||
<ControlTemplate TargetType="{x:Type ToggleButton}">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="20" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Border Grid.Column="1"
|
||||
x:Name="ButtonBorder"
|
||||
Margin="0"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
Background="{TemplateBinding Background}" />
|
||||
<Path x:Name="Arrow"
|
||||
Grid.Column="1"
|
||||
Data="M0,0 L0,2 L4,6 L8,2 L8,0 L4,4 z"
|
||||
Fill="{TemplateBinding Foreground}"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center" />
|
||||
</Grid>
|
||||
<ControlTemplate.Triggers>
|
||||
<Trigger Property="IsMouseOver" Value="True">
|
||||
<Setter TargetName="ButtonBorder" Property="Background"
|
||||
Value="{DynamicResource ComboBoxButtonHoverBackgroundBrush}" />
|
||||
</Trigger>
|
||||
<Trigger Property="IsPressed" Value="True">
|
||||
<Setter TargetName="ButtonBorder" Property="Background"
|
||||
Value="{DynamicResource ComboBoxButtonPressBackgroundBrush}" />
|
||||
</Trigger>
|
||||
<Trigger Property="IsChecked" Value="True">
|
||||
<Setter TargetName="ButtonBorder" Property="Background"
|
||||
Value="{DynamicResource ComboBoxButtonCheckedBackgroundBrush}" />
|
||||
</Trigger>
|
||||
<Trigger Property="IsEnabled" Value="False">
|
||||
<Setter TargetName="ButtonBorder" Property="Background"
|
||||
Value="{DynamicResource ComboBoxButtonDisabledBackgroundBrush}" />
|
||||
<Setter TargetName="ButtonBorder" Property="BorderBrush"
|
||||
Value="{DynamicResource ComboBoxButtonDisabledBorderBrush}" />
|
||||
<Setter TargetName="Arrow" Property="Fill"
|
||||
Value="{DynamicResource ComboBoxButtonDisabledForegroundBrush}" />
|
||||
</Trigger>
|
||||
</ControlTemplate.Triggers>
|
||||
</ControlTemplate>
|
||||
</ToggleButton.Template>
|
||||
</ToggleButton>
|
||||
<Popup Placement="Bottom"
|
||||
Focusable="False"
|
||||
AllowsTransparency="True"
|
||||
IsOpen="{TemplateBinding ComboBox.IsDropDownOpen}"
|
||||
PopupAnimation="Slide">
|
||||
<Grid MinWidth="{TemplateBinding ActualWidth}"
|
||||
MaxHeight="{TemplateBinding MaxDropDownHeight}">
|
||||
<Border BorderThickness="1"
|
||||
Background="{DynamicResource ComboBoxListBackgroundBrush}"
|
||||
BorderBrush="{DynamicResource ComboBoxListBorderBrush}"
|
||||
Margin="0,1,0,0">
|
||||
<ScrollViewer SnapsToDevicePixels="True">
|
||||
<ItemsPresenter KeyboardNavigation.DirectionalNavigation="Contained" />
|
||||
</ScrollViewer>
|
||||
</Border>
|
||||
</Grid>
|
||||
</Popup>
|
||||
</Grid>
|
||||
<ControlTemplate.Triggers>
|
||||
<Trigger Property="IsMouseOver" Value="True">
|
||||
<Setter TargetName="NonEditableBorder" Property="Background"
|
||||
Value="{DynamicResource ComboBoxNonEditableHoverBackgroundBrush}" />
|
||||
</Trigger>
|
||||
<Trigger Property="IsEnabled" Value="False">
|
||||
<Setter TargetName="NonEditableBorder" Property="Background"
|
||||
Value="{DynamicResource ComboBoxNonEditableDisabledBackgroundBrush}" />
|
||||
<Setter TargetName="NonEditableBorder" Property="BorderBrush"
|
||||
Value="{DynamicResource ComboBoxNonEditableDisabledBorderBrush}" />
|
||||
</Trigger>
|
||||
<Trigger Property="IsEditable" Value="True">
|
||||
<Setter Property="IsTabStop" Value="False" />
|
||||
<Setter TargetName="PART_EditableTextBox" Property="Visibility" Value="Visible" />
|
||||
<Setter TargetName="NonEditableBorder" Property="Visibility" Value="Hidden" />
|
||||
<Setter TargetName="ToggleButton" Property="BorderThickness" Value="1,0,0,0" />
|
||||
<Setter TargetName="ToggleButton" Property="Focusable" Value="False" />
|
||||
</Trigger>
|
||||
</ControlTemplate.Triggers>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
</ResourceDictionary>
|
||||
@@ -0,0 +1,58 @@
|
||||
#region License
|
||||
|
||||
// Copyright (C) 2020 Reetus
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace ClassicAssist.Browser.Data
|
||||
{
|
||||
public class CategoriesConverter : JsonConverter
|
||||
{
|
||||
public override void WriteJson( JsonWriter writer, object value, JsonSerializer serializer )
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override object ReadJson( JsonReader reader, Type objectType, object existingValue,
|
||||
JsonSerializer serializer )
|
||||
{
|
||||
switch ( reader.TokenType )
|
||||
{
|
||||
case JsonToken.StartArray:
|
||||
{
|
||||
JToken token = JToken.Load( reader );
|
||||
return token.ToObject<string[]>();
|
||||
}
|
||||
case JsonToken.String:
|
||||
{
|
||||
JToken token = JToken.Load( reader );
|
||||
return new[] { token.ToObject<string>() };
|
||||
}
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public override bool CanConvert( Type objectType )
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,318 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using ClassicAssist.Shared;
|
||||
using ClassicAssist.Browser.Models;
|
||||
using LiteDB;
|
||||
using Newtonsoft.Json;
|
||||
using Octokit;
|
||||
using Repository = ClassicAssist.Browser.Models.Repository;
|
||||
|
||||
namespace ClassicAssist.Browser.Data
|
||||
{
|
||||
public class Database
|
||||
{
|
||||
private const string DATABASE_FILE = "macros.db";
|
||||
|
||||
private const string MANIFEST_URL =
|
||||
"https://raw.githubusercontent.com/Reetus/ClassicAssist-Macros/master/Macros/metadata.json";
|
||||
|
||||
private const string MACRO_RAW_BASEURL =
|
||||
"https://raw.githubusercontent.com/Reetus/ClassicAssist-Macros/master/Macros/";
|
||||
|
||||
private const string MACRO_BASEURL = "https://github.com/Reetus/ClassicAssist-Macros/tree/master/Macros/";
|
||||
|
||||
private const string REPOSITORY_OWNER = "Reetus";
|
||||
private const string REPOSITORY_NAME = "ClassicAssist-Macros";
|
||||
|
||||
private static Database _instance;
|
||||
private static readonly object _instanceLock = new object();
|
||||
private readonly GitHubClient _github;
|
||||
private readonly HttpClient _httpClient;
|
||||
private ILiteCollection<Macro> _macros;
|
||||
private ILiteCollection<Manifest> _manifest;
|
||||
private ILiteCollection<Repository> _repository;
|
||||
|
||||
private Database()
|
||||
{
|
||||
_httpClient = new HttpClient();
|
||||
string databasePath = Path.Combine( Engine.StartupPath ?? Environment.CurrentDirectory, DATABASE_FILE );
|
||||
LiteDatabase database = new LiteDatabase( $"Filename={databasePath};Connection=Shared" );
|
||||
_github = new GitHubClient( new ProductHeaderValue( "ClassicAssist" ) );
|
||||
|
||||
InitCollections( database );
|
||||
}
|
||||
|
||||
private void InitCollections( ILiteDatabase database )
|
||||
{
|
||||
_repository = database.GetCollection<Repository>( "repository" );
|
||||
_repository.EnsureIndex( x => x.Id );
|
||||
_manifest = database.GetCollection<Manifest>( "manifest" );
|
||||
_manifest.EnsureIndex( x => x.Id );
|
||||
_macros = database.GetCollection<Macro>( "macros" );
|
||||
_macros.EnsureIndex( x => x.Id );
|
||||
}
|
||||
|
||||
public string GetCommitHash()
|
||||
{
|
||||
Repository latest = _repository.Find( r => true ).OrderByDescending( r => r.DateTime ).FirstOrDefault() ??
|
||||
new Repository();
|
||||
|
||||
return latest.CommitHash;
|
||||
}
|
||||
|
||||
public async Task<string> GetGithubHash()
|
||||
{
|
||||
Reference reference = await _github.Git.Reference.Get( REPOSITORY_OWNER, REPOSITORY_NAME, "heads/master" );
|
||||
|
||||
string hash = reference.Object.Sha;
|
||||
|
||||
Repository latest = _repository.Find( r => true ).OrderByDescending( r => r.DateTime ).FirstOrDefault() ??
|
||||
new Repository();
|
||||
|
||||
latest.CommitHash = hash;
|
||||
latest.DateTime = DateTime.Now;
|
||||
_repository.Upsert( latest );
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
public async Task<Manifest> GetManifest()
|
||||
{
|
||||
Manifest latest = _manifest.Find( r => true ).OrderByDescending( r => r.DateTime ).FirstOrDefault();
|
||||
|
||||
if ( latest != null && !( DateTime.Now - latest.DateTime >= TimeSpan.FromMinutes( 15 ) ) )
|
||||
{
|
||||
return latest;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if ( latest != null && GetCommitHash() == await GetGithubHash() )
|
||||
{
|
||||
return latest;
|
||||
}
|
||||
}
|
||||
catch ( RateLimitExceededException )
|
||||
{
|
||||
// Github throttle error
|
||||
}
|
||||
|
||||
latest = await FetchManifest();
|
||||
_manifest.Upsert( latest );
|
||||
|
||||
return latest;
|
||||
}
|
||||
|
||||
public async Task<string[]> GetMacros( IEnumerable<Filter> filter = null )
|
||||
{
|
||||
Manifest manifest = await GetManifest();
|
||||
|
||||
if ( filter == null )
|
||||
{
|
||||
return manifest.Files.Select( f => f.Name ).OrderBy( f => f ).ToArray();
|
||||
}
|
||||
|
||||
string shardFilter = filter.FirstOrDefault( t => t.FilterType == FilterType.Shard )?.Value;
|
||||
string eraFilter = filter.FirstOrDefault( t => t.FilterType == FilterType.Era )?.Value;
|
||||
string authorFilter = filter.FirstOrDefault( t => t.FilterType == FilterType.Author )?.Value;
|
||||
|
||||
Predicate<string[]> categoryPredicate =
|
||||
CategoryToPredicate( filter.FirstOrDefault( t => t.FilterType == FilterType.Category ) );
|
||||
|
||||
IEnumerable<string> macros = manifest.Files.Where( m =>
|
||||
( string.IsNullOrEmpty( shardFilter ) || m.Shard != null && m.Shard.Equals( shardFilter ) ) &&
|
||||
( string.IsNullOrEmpty( eraFilter ) || m.Era == null || m.Era.Equals( eraFilter ) ) &&
|
||||
( string.IsNullOrEmpty( authorFilter ) || m.Author == null || m.Author.Equals( authorFilter ) ) &&
|
||||
categoryPredicate( m.Categories ) ).Select( m => m.Name );
|
||||
|
||||
return macros.ToArray();
|
||||
}
|
||||
|
||||
private Predicate<string[]> CategoryToPredicate( Filter filter )
|
||||
{
|
||||
if ( filter.Category == null )
|
||||
{
|
||||
return f => true;
|
||||
}
|
||||
|
||||
return m =>
|
||||
{
|
||||
if ( m.Length < filter.Category.Values.Length )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for ( int i = 0; i < filter.Category.Values.Length; i++ )
|
||||
{
|
||||
string macroCategory = m[i];
|
||||
string filterCategory = filter.Category.Values[i];
|
||||
|
||||
if ( !macroCategory.Equals( filterCategory ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
}
|
||||
|
||||
public async Task<string[]> GetShards()
|
||||
{
|
||||
Manifest manifest = await GetManifest();
|
||||
|
||||
return manifest.Files.Where( f => f.Shard != null ).Select( f => f.Shard ).OrderBy( f => f ).Distinct()
|
||||
.ToArray();
|
||||
}
|
||||
|
||||
private async Task<Manifest> FetchManifest()
|
||||
{
|
||||
HttpResponseMessage response = await _httpClient.GetAsync( MANIFEST_URL );
|
||||
|
||||
string json = await response.Content.ReadAsStringAsync();
|
||||
|
||||
Metadata[] obj = JsonConvert.DeserializeObject<Metadata[]>( json );
|
||||
|
||||
if ( obj == null )
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
Manifest manifest = new Manifest { Files = obj };
|
||||
|
||||
return manifest;
|
||||
}
|
||||
|
||||
public static Database GetInstance()
|
||||
{
|
||||
// ReSharper disable once InvertIf
|
||||
if ( _instance == null )
|
||||
{
|
||||
lock ( _instanceLock )
|
||||
{
|
||||
if ( _instance == null )
|
||||
{
|
||||
_instance = new Database();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return _instance;
|
||||
}
|
||||
|
||||
public async Task<string[]> GetEras()
|
||||
{
|
||||
Manifest manifest = await GetManifest();
|
||||
|
||||
return manifest.Files.Where( f => f.Era != null ).Select( f => f.Era ).OrderBy( f => f ).Distinct()
|
||||
.ToArray();
|
||||
}
|
||||
|
||||
public async Task<string[]> GetAuthors()
|
||||
{
|
||||
Manifest manifest = await GetManifest();
|
||||
|
||||
return manifest.Files.Where( f => f.Author != null ).Select( f => f.Author ).OrderBy( f => f ).Distinct()
|
||||
.ToArray();
|
||||
}
|
||||
|
||||
public async Task<Category[]> GetCategories()
|
||||
{
|
||||
Manifest manifest = await GetManifest();
|
||||
|
||||
List<Category> results = new List<Category>();
|
||||
|
||||
IEnumerable<string[]> categories = manifest.Files.Select( f => f.Categories ).OrderBy( f => f[0] )
|
||||
.ThenBy( f => f.Length ).Distinct();
|
||||
|
||||
foreach ( string[] category in categories )
|
||||
{
|
||||
if ( category.Length == 0 )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( results.All( e => e.Name != category[0] ) )
|
||||
{
|
||||
results.Add( new Category { Name = category[0], Values = new[] { category[0] } } );
|
||||
}
|
||||
|
||||
if ( category.Length == 1 )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
string res = $"--{category[1]}";
|
||||
|
||||
if ( category.Length > 2 )
|
||||
{
|
||||
for ( int i = 2; i < category.Length; i++ )
|
||||
{
|
||||
res += $" ˃ {category[i]}";
|
||||
}
|
||||
}
|
||||
|
||||
if ( results.All( e => e.Name != res ) )
|
||||
{
|
||||
results.Add( new Category { Name = res, Values = category } );
|
||||
}
|
||||
}
|
||||
|
||||
return results.ToArray();
|
||||
}
|
||||
|
||||
public async Task<string> GetMacroByName( string value )
|
||||
{
|
||||
Manifest manifest = await GetManifest();
|
||||
|
||||
Metadata macro = manifest.Files.FirstOrDefault( f => f.Name == value );
|
||||
|
||||
if ( macro == null )
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
Macro cached = _macros.Find( m => m.Name == macro.Name && m.SHA1 == macro.SHA1 ).FirstOrDefault();
|
||||
|
||||
if ( cached != null )
|
||||
{
|
||||
return cached.Text;
|
||||
}
|
||||
|
||||
string url = string.Concat( MACRO_RAW_BASEURL, macro.FileName.Replace( '\\', '/' ) );
|
||||
|
||||
string result = await _httpClient.GetStringAsync( url );
|
||||
|
||||
if ( string.IsNullOrEmpty( result ) )
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
Macro inserted = new Macro { Name = macro.Name, SHA1 = macro.SHA1, Text = result };
|
||||
_macros.Insert( inserted );
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public async void OpenGithubMacroURL( string value )
|
||||
{
|
||||
Manifest manifest = await GetManifest();
|
||||
|
||||
Metadata macro = manifest.Files.FirstOrDefault( f => f.Name == value );
|
||||
|
||||
if ( macro == null )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
string url = string.Concat( MACRO_BASEURL, macro.FileName.Replace( '\\', '/' ) );
|
||||
|
||||
Process.Start( url );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
#region License
|
||||
|
||||
// Copyright (C) 2020 Reetus
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#endregion
|
||||
|
||||
using ClassicAssist.Browser.Models;
|
||||
|
||||
namespace ClassicAssist.Browser.Data
|
||||
{
|
||||
public class Filter
|
||||
{
|
||||
public Category Category { get; set; }
|
||||
public FilterType FilterType { get; set; }
|
||||
public string Value { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
#region License
|
||||
|
||||
// Copyright (C) 2020 Reetus
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#endregion
|
||||
|
||||
namespace ClassicAssist.Browser.Data
|
||||
{
|
||||
public enum FilterType
|
||||
{
|
||||
Shard,
|
||||
Era,
|
||||
Author,
|
||||
Category
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,146 @@
|
||||
<UserControl x:Class="ClassicAssist.Browser.MacroBrowserControl"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
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:resources="clr-namespace:ClassicAssist.Shared.Resources;assembly=ClassicAssist.Shared"
|
||||
xmlns:avalonedit="http://icsharpcode.net/sharpdevelop/avalonedit"
|
||||
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
|
||||
xmlns:misc="clr-namespace:ClassicAssist.UI.Misc"
|
||||
xmlns:controls="clr-namespace:ClassicAssist.Browser.Controls"
|
||||
xmlns:data="clr-namespace:ClassicAssist.Browser.Data"
|
||||
xmlns:browser="clr-namespace:ClassicAssist.Browser"
|
||||
xmlns:controls1="clr-namespace:ClassicAssist.UI.Controls"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="550" d:DesignWidth="900">
|
||||
<UserControl.DataContext>
|
||||
<browser:MacroBrowserViewModel />
|
||||
</UserControl.DataContext>
|
||||
<UserControl.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceDictionary Source="../Resources/DarkTheme.xaml" />
|
||||
<ResourceDictionary Source="../Resources/Icons.xaml" />
|
||||
<ResourceDictionary
|
||||
Source="../UI/Views/Debug/DebugToolBarStyle.xaml" />
|
||||
<ResourceDictionary Source="Controls/ClearableComboBox.xaml" />
|
||||
<ResourceDictionary Source="../Resources/LeftRightIconToggleButton.xaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
|
||||
</ResourceDictionary>
|
||||
</UserControl.Resources>
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="5" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid Grid.Row="0">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
<controls1:StretchyWrapPanel Orientation="Horizontal" Grid.Row="0" Margin="10,0,10,10">
|
||||
<controls1:StretchyWrapPanel.Resources>
|
||||
<Style TargetType="{x:Type TextBlock}" BasedOn="{StaticResource {x:Type TextBlock}}">
|
||||
<Setter Property="Margin" Value="10,0,10,0" />
|
||||
<Setter Property="VerticalAlignment" Value="Center" />
|
||||
<Setter Property="HorizontalAlignment" Value="Right" />
|
||||
</Style>
|
||||
<Style TargetType="{x:Type controls:ClearableComboBox}"
|
||||
BasedOn="{StaticResource {x:Type controls:ClearableComboBox}}">
|
||||
<Setter Property="MinWidth" Value="80" />
|
||||
</Style>
|
||||
</controls1:StretchyWrapPanel.Resources>
|
||||
<TextBlock Text="{x:Static resources:Strings.Shard_}" Margin="0,0,10,0" />
|
||||
<controls:ClearableComboBox ItemsSource="{Binding Shards}" ClearCommand="{Binding ClearCommand}"
|
||||
ClearCommandParameter="{x:Static data:FilterType.Shard}"
|
||||
SelectedItem="{Binding ShardFilter}" />
|
||||
<TextBlock Text="{x:Static resources:Strings.Era}" />
|
||||
<controls:ClearableComboBox ItemsSource="{Binding Eras}" ClearCommand="{Binding ClearCommand}"
|
||||
ClearCommandParameter="{x:Static data:FilterType.Era}"
|
||||
SelectedItem="{Binding EraFilter}" />
|
||||
<TextBlock Text="{x:Static resources:Strings.Author}" />
|
||||
<controls:ClearableComboBox ItemsSource="{Binding Authors}" ClearCommand="{Binding ClearCommand}"
|
||||
ClearCommandParameter="{x:Static data:FilterType.Author}"
|
||||
SelectedItem="{Binding AuthorFilter}" />
|
||||
<TextBlock Text="{x:Static resources:Strings.Category}" />
|
||||
<controls:ClearableComboBox ItemsSource="{Binding Categories}" ClearCommand="{Binding ClearCommand}"
|
||||
ClearCommandParameter="{x:Static data:FilterType.Category}"
|
||||
SelectedItem="{Binding CategoryFilter}" />
|
||||
</controls1:StretchyWrapPanel>
|
||||
<Grid Row="1" Margin="10,0,10,0">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition>
|
||||
<ColumnDefinition.Style>
|
||||
<Style TargetType="{x:Type ColumnDefinition}">
|
||||
<Setter Property="Width" Value="200" />
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding IsChecked, ElementName=ToggleButton}" Value="True">
|
||||
<Setter Property="Width" Value="0" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</ColumnDefinition.Style>
|
||||
</ColumnDefinition>
|
||||
<ColumnDefinition Width="5" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid Grid.Column="0">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<ListBox x:Name="listBox" ItemsSource="{Binding Macros}" Grid.Column="0" Grid.Row="0"
|
||||
SelectedItem="{Binding SelectedItem}">
|
||||
<ListBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock Text="{Binding}" ToolTip="{Binding}" />
|
||||
</DataTemplate>
|
||||
</ListBox.ItemTemplate>
|
||||
</ListBox>
|
||||
<TextBlock Grid.Row="1" TextWrapping="Wrap">
|
||||
<Hyperlink NavigateUri="https://github.com/Reetus/ClassicAssist-Macros/blob/master/README.md"
|
||||
RequestNavigate="Hyperlink_RequestNavigate">
|
||||
<Run Text="{x:Static resources:Strings.Learn_how_to_contribute_your_own_macros___}" />
|
||||
</Hyperlink>
|
||||
</TextBlock>
|
||||
</Grid>
|
||||
<GridSplitter Grid.Column="1" Width="5" HorizontalAlignment="Stretch" />
|
||||
<Grid Grid.Column="2">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<avalonedit:TextEditor ShowLineNumbers="True" x:Name="CodeTextEditor" Grid.Row="0"
|
||||
HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto"
|
||||
FontFamily="Consolas" Margin="10,0,0,0" IsReadOnly="True">
|
||||
<i:Interaction.Behaviors>
|
||||
<misc:AvalonEditBehaviour
|
||||
TextBinding="{Binding SelectedMacro}" />
|
||||
</i:Interaction.Behaviors>
|
||||
</avalonedit:TextEditor>
|
||||
<WrapPanel Grid.Row="1" Orientation="Horizontal" Margin="10,10,0,0">
|
||||
<WrapPanel.Resources>
|
||||
<Style TargetType="{x:Type Button}" BasedOn="{StaticResource {x:Type Button}}">
|
||||
<Setter Property="Margin" Value="0,0,10,0" />
|
||||
<Setter Property="Padding" Value="10,5" />
|
||||
<Setter Property="FontSize" Value="11" />
|
||||
</Style>
|
||||
</WrapPanel.Resources>
|
||||
<ToggleButton x:Name="ToggleButton" Height="15" Margin="0"
|
||||
Style="{DynamicResource LeftRightIconToggleButton}" VerticalAlignment="Center" />
|
||||
<Button Content="{x:Static resources:Strings.Copy_to_clipboard}"
|
||||
Command="{Binding CopyToClipboardCommand}" CommandParameter="{Binding SelectedMacro}" />
|
||||
<Button Content="{x:Static resources:Strings.Create_Macro}"
|
||||
Command="{Binding CreateMacroCommand}" CommandParameter="{Binding SelectedItem}" />
|
||||
<Button Content="{x:Static resources:Strings.Open_in_Github}"
|
||||
Command="{Binding OpenGithubCommand}"
|
||||
CommandParameter="{Binding SelectedItem, ElementName=listBox}" />
|
||||
</WrapPanel>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<ProgressBar Grid.Row="1" IsIndeterminate="True"
|
||||
Visibility="{Binding Loading, Converter={StaticResource BooleanToVisibilityConverter}}" />
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,31 @@
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Navigation;
|
||||
using System.Xml;
|
||||
using ICSharpCode.AvalonEdit.Highlighting;
|
||||
using ICSharpCode.AvalonEdit.Highlighting.Xshd;
|
||||
|
||||
namespace ClassicAssist.Browser
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for MainWindow.xaml
|
||||
/// </summary>
|
||||
public partial class MacroBrowserControl : UserControl
|
||||
{
|
||||
public MacroBrowserControl()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
CodeTextEditor.SyntaxHighlighting = HighlightingLoader.Load(
|
||||
new XmlTextReader( Path.Combine( Path.GetDirectoryName( Assembly.GetExecutingAssembly().Location ),
|
||||
"Python.Dark.xshd" ) ), HighlightingManager.Instance );
|
||||
}
|
||||
|
||||
private void Hyperlink_RequestNavigate( object sender, RequestNavigateEventArgs e )
|
||||
{
|
||||
Process.Start( e.Uri.ToString() );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,351 @@
|
||||
#region License
|
||||
|
||||
// Copyright (C) 2020 Reetus
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Threading;
|
||||
using ClassicAssist.Browser.Data;
|
||||
using ClassicAssist.Browser.Models;
|
||||
using ClassicAssist.Data.Macros;
|
||||
using ClassicAssist.Shared.Resources;
|
||||
using ClassicAssist.UI.ViewModels;
|
||||
using Microsoft.Scripting.Utils;
|
||||
|
||||
namespace ClassicAssist.Browser
|
||||
{
|
||||
public class MacroBrowserViewModel : BaseViewModel
|
||||
{
|
||||
private readonly Dictionary<string, Func<Task<string[]>>>
|
||||
_data = new Dictionary<string, Func<Task<string[]>>>();
|
||||
|
||||
private readonly Database _database = Database.GetInstance();
|
||||
private string _authorFilter;
|
||||
private ObservableCollection<string> _authors = new ObservableCollection<string>();
|
||||
|
||||
private ObservableCollection<Category> _categories = new ObservableCollection<Category>();
|
||||
private Category _categoryFilter;
|
||||
|
||||
private ICommand _clearCommand;
|
||||
private ICommand _copyToClipboardCommand;
|
||||
private ICommand _createMacroCommand;
|
||||
private string _eraFilter;
|
||||
private ObservableCollection<string> _eras = new ObservableCollection<string>();
|
||||
|
||||
private bool _loading = true;
|
||||
private ObservableCollection<string> _macros = new ObservableCollection<string>();
|
||||
private ICommand _openGithubCommand;
|
||||
private string _selectedItem;
|
||||
private string _selectedMacro;
|
||||
private string _shardFilter;
|
||||
private ObservableCollection<string> _shards = new ObservableCollection<string>();
|
||||
private Dispatcher _test;
|
||||
|
||||
public MacroBrowserViewModel()
|
||||
{
|
||||
_data.Add( nameof( Macros ), async () => await _database.GetMacros() );
|
||||
_data.Add( nameof( Shards ), async () => await _database.GetShards() );
|
||||
_data.Add( nameof( Eras ), async () => await _database.GetEras() );
|
||||
_data.Add( nameof( Authors ), async () => await _database.GetAuthors() );
|
||||
|
||||
_test = Dispatcher.CurrentDispatcher;
|
||||
|
||||
Task.Run( async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
await RefreshData();
|
||||
}
|
||||
catch ( Exception e )
|
||||
{
|
||||
MessageBox.Show( $"{Strings.Failed_to_download_manifest___}\n\n{e.Message}", Strings.Error,
|
||||
MessageBoxButton.OK, MessageBoxImage.Error );
|
||||
}
|
||||
finally
|
||||
{
|
||||
Loading = false;
|
||||
}
|
||||
} );
|
||||
}
|
||||
|
||||
public string AuthorFilter
|
||||
{
|
||||
get => _authorFilter;
|
||||
set
|
||||
{
|
||||
SetProperty( ref _authorFilter, value );
|
||||
ApplyFilter();
|
||||
}
|
||||
}
|
||||
|
||||
public ObservableCollection<string> Authors
|
||||
{
|
||||
get => _authors;
|
||||
set => SetProperty( ref _authors, value );
|
||||
}
|
||||
|
||||
public ObservableCollection<Category> Categories
|
||||
{
|
||||
get => _categories;
|
||||
set => SetProperty( ref _categories, value );
|
||||
}
|
||||
|
||||
public Category CategoryFilter
|
||||
{
|
||||
get => _categoryFilter;
|
||||
set
|
||||
{
|
||||
SetProperty( ref _categoryFilter, value );
|
||||
ApplyFilter();
|
||||
}
|
||||
}
|
||||
|
||||
public ICommand ClearCommand => _clearCommand ?? ( _clearCommand = new RelayCommand( ClearFilter, o => true ) );
|
||||
|
||||
public ICommand CopyToClipboardCommand =>
|
||||
_copyToClipboardCommand ??
|
||||
( _copyToClipboardCommand = new RelayCommand( CopyToClipboard, o => SelectedItem != null ) );
|
||||
|
||||
public ICommand CreateMacroCommand =>
|
||||
_createMacroCommand ??
|
||||
( _createMacroCommand = new RelayCommandAsync( CreateMacro, o => SelectedItem != null ) );
|
||||
|
||||
public string EraFilter
|
||||
{
|
||||
get => _eraFilter;
|
||||
set
|
||||
{
|
||||
SetProperty( ref _eraFilter, value );
|
||||
ApplyFilter();
|
||||
}
|
||||
}
|
||||
|
||||
public ObservableCollection<string> Eras
|
||||
{
|
||||
get => _eras;
|
||||
set => SetProperty( ref _eras, value );
|
||||
}
|
||||
|
||||
public bool Loading
|
||||
{
|
||||
get => _loading;
|
||||
set => SetProperty( ref _loading, value );
|
||||
}
|
||||
|
||||
public ObservableCollection<string> Macros
|
||||
{
|
||||
get => _macros;
|
||||
set => SetProperty( ref _macros, value );
|
||||
}
|
||||
|
||||
public ICommand OpenGithubCommand =>
|
||||
_openGithubCommand ?? ( _openGithubCommand = new RelayCommand( OpenGithub, o => SelectedItem != null ) );
|
||||
|
||||
public string SelectedItem
|
||||
{
|
||||
get => _selectedItem;
|
||||
set
|
||||
{
|
||||
SetProperty( ref _selectedItem, value );
|
||||
GetMacro( value ).ConfigureAwait( false );
|
||||
}
|
||||
}
|
||||
|
||||
public string SelectedMacro
|
||||
{
|
||||
get => _selectedMacro;
|
||||
set => SetProperty( ref _selectedMacro, value );
|
||||
}
|
||||
|
||||
public string ShardFilter
|
||||
{
|
||||
get => _shardFilter;
|
||||
set
|
||||
{
|
||||
SetProperty( ref _shardFilter, value );
|
||||
ApplyFilter();
|
||||
}
|
||||
}
|
||||
|
||||
public ObservableCollection<string> Shards
|
||||
{
|
||||
get => _shards;
|
||||
set => SetProperty( ref _shards, value );
|
||||
}
|
||||
|
||||
private async Task CreateMacro( object obj )
|
||||
{
|
||||
if ( !( obj is string macro ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
MessageBoxResult result = MessageBox.Show( Strings.Macro_Warning, Strings.Warning, MessageBoxButton.YesNo,
|
||||
MessageBoxImage.Warning );
|
||||
|
||||
if ( result != MessageBoxResult.Yes )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
MacroManager.GetInstance().NewMacro?.Invoke( macro, await _database.GetMacroByName( macro ) );
|
||||
}
|
||||
|
||||
private static void CopyToClipboard( object obj )
|
||||
{
|
||||
if ( !( obj is string macro ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
Clipboard.SetText( macro );
|
||||
}
|
||||
catch ( Exception )
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
|
||||
private void ClearFilter( object obj )
|
||||
{
|
||||
if ( !( obj is FilterType filterType ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
switch ( filterType )
|
||||
{
|
||||
case FilterType.Shard:
|
||||
ShardFilter = null;
|
||||
break;
|
||||
case FilterType.Era:
|
||||
EraFilter = null;
|
||||
break;
|
||||
case FilterType.Author:
|
||||
AuthorFilter = null;
|
||||
break;
|
||||
case FilterType.Category:
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
|
||||
ApplyFilter();
|
||||
}
|
||||
|
||||
private void ApplyFilter()
|
||||
{
|
||||
List<Filter> filters = new List<Filter>
|
||||
{
|
||||
new Filter { FilterType = FilterType.Shard, Value = ShardFilter },
|
||||
new Filter { FilterType = FilterType.Era, Value = EraFilter },
|
||||
new Filter { FilterType = FilterType.Author, Value = AuthorFilter },
|
||||
new Filter { FilterType = FilterType.Category, Category = CategoryFilter }
|
||||
};
|
||||
|
||||
_database.GetMacros( filters ).ContinueWith( t =>
|
||||
{
|
||||
_dispatcher.Invoke( () =>
|
||||
{
|
||||
Macros.Clear();
|
||||
Macros.AddRange( t.Result );
|
||||
} );
|
||||
} );
|
||||
}
|
||||
|
||||
private async Task GetMacro( string value )
|
||||
{
|
||||
try
|
||||
{
|
||||
Loading = true;
|
||||
string macro = await _database.GetMacroByName( value );
|
||||
|
||||
SelectedMacro = macro;
|
||||
}
|
||||
catch ( Exception e )
|
||||
{
|
||||
MessageBox.Show( $"{Strings.Failed_to_download_macro___}\n\n{e.Message}", Strings.Error,
|
||||
MessageBoxButton.OK, MessageBoxImage.Error );
|
||||
}
|
||||
finally
|
||||
{
|
||||
Loading = false;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task RefreshData()
|
||||
{
|
||||
try
|
||||
{
|
||||
foreach ( KeyValuePair<string, Func<Task<string[]>>> kvp in _data )
|
||||
{
|
||||
PropertyInfo property =
|
||||
GetType().GetProperty( kvp.Key, BindingFlags.Instance | BindingFlags.Public );
|
||||
|
||||
if ( property == null )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
string[] data = await kvp.Value.Invoke();
|
||||
|
||||
if ( data == null )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
ObservableCollection<string> obj = (ObservableCollection<string>) property.GetValue( this );
|
||||
|
||||
if ( obj == null )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
_test.Invoke( () =>
|
||||
{
|
||||
obj.Clear();
|
||||
obj.AddRange( data );
|
||||
} );
|
||||
}
|
||||
|
||||
await _dispatcher.InvokeAsync( async () => Categories.AddRange( await _database.GetCategories() ) );
|
||||
}
|
||||
catch ( Exception e )
|
||||
{
|
||||
MessageBox.Show( e.Message, Strings.Error );
|
||||
}
|
||||
}
|
||||
|
||||
private void OpenGithub( object obj )
|
||||
{
|
||||
if ( !( obj is string macro ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_database.OpenGithubMacroURL( macro );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
#region License
|
||||
|
||||
// Copyright (C) 2020 Reetus
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#endregion
|
||||
|
||||
namespace ClassicAssist.Browser.Models
|
||||
{
|
||||
public class Category
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public string[] Values { get; set; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Name;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
#region License
|
||||
|
||||
// Copyright (C) 2020 Reetus
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#endregion
|
||||
|
||||
using LiteDB;
|
||||
|
||||
namespace ClassicAssist.Browser.Models
|
||||
{
|
||||
public class Macro
|
||||
{
|
||||
[BsonId]
|
||||
public int Id { get; set; }
|
||||
|
||||
public string Name { get; set; }
|
||||
public string SHA1 { get; set; }
|
||||
public string Text { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
#region License
|
||||
|
||||
// Copyright (C) 2020 Reetus
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using LiteDB;
|
||||
|
||||
namespace ClassicAssist.Browser.Models
|
||||
{
|
||||
public class Manifest
|
||||
{
|
||||
public DateTime DateTime { get; set; } = DateTime.Now;
|
||||
public Metadata[] Files { get; set; }
|
||||
|
||||
[BsonId]
|
||||
public int Id { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
#region License
|
||||
|
||||
// Copyright (C) 2020 Reetus
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using ClassicAssist.Browser.Data;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace ClassicAssist.Browser.Models
|
||||
{
|
||||
public class Metadata
|
||||
{
|
||||
public string Author { get; set; }
|
||||
|
||||
[JsonConverter( typeof( CategoriesConverter ) )]
|
||||
public string[] Categories { get; set; }
|
||||
|
||||
public string Description { get; set; }
|
||||
public string Era { get; set; }
|
||||
public string FileName { get; set; }
|
||||
public DateTime ModifiedDate { get; set; }
|
||||
public string Name { get; set; }
|
||||
public string SHA1 { get; set; }
|
||||
public string Shard { get; set; }
|
||||
public int Size { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
#region License
|
||||
|
||||
// Copyright (C) 2020 Reetus
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using LiteDB;
|
||||
|
||||
namespace ClassicAssist.Browser.Models
|
||||
{
|
||||
public class Repository
|
||||
{
|
||||
public string CommitHash { get; set; }
|
||||
public DateTime DateTime { get; set; } = DateTime.Now;
|
||||
|
||||
[BsonId]
|
||||
public int Id { get; set; }
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user