Reworked ConfigManager

This commit is contained in:
ruri
2019-12-21 18:35:00 +01:00
parent dbded96af1
commit 16e10f7c3d
12 changed files with 448 additions and 294 deletions
+17 -7
View File
@@ -20,28 +20,38 @@ namespace OpenBullet.Models
public int Id { get; set; }
private string apiUrl = "";
public string ApiUrl { get { return apiUrl; } set { apiUrl = value; OnPropertyChanged(); } }
public string ApiUrl { get => apiUrl; set { apiUrl = value; OnPropertyChanged(); } }
private AuthMode auth = AuthMode.ApiKey;
public AuthMode Auth { get { return auth; } set { auth = value; OnPropertyChanged(); OnPropertyChanged("ApiKeyVisible"); OnPropertyChanged("UserPassVisible"); } }
public AuthMode Auth
{
get => auth;
set
{
auth = value;
OnPropertyChanged();
OnPropertyChanged(nameof(ApiKeyVisible));
OnPropertyChanged(nameof(UserPassVisible));
}
}
private string apiKey = "";
public string ApiKey { get { return apiKey; } set { apiKey = value; OnPropertyChanged(); } }
public string ApiKey { get => apiKey; set { apiKey = value; OnPropertyChanged(); } }
private string username = "";
public string Username { get { return username; } set { username = value; OnPropertyChanged(); } }
public string Username { get => username; set { username = value; OnPropertyChanged(); } }
private string password = "";
public string Password { get { return password; } set { password = value; OnPropertyChanged(); } }
public string Password { get => password; set { password = value; OnPropertyChanged(); } }
[JsonIgnore]
public bool AuthInitialized { get; set; } = false;
[JsonIgnore]
public Visibility ApiKeyVisible { get { return Auth == AuthMode.ApiKey ? Visibility.Visible : Visibility.Collapsed; } }
public Visibility ApiKeyVisible { get => Auth == AuthMode.ApiKey ? Visibility.Visible : Visibility.Collapsed; }
[JsonIgnore]
public Visibility UserPassVisible { get { return Auth == AuthMode.UserPass ? Visibility.Visible : Visibility.Collapsed; } }
public Visibility UserPassVisible { get => Auth == AuthMode.UserPass ? Visibility.Visible : Visibility.Collapsed; }
public Source(int id)
{
+99 -15
View File
@@ -10,8 +10,10 @@ using RuriLib.ViewModels;
namespace OpenBullet.Repositories
{
public class ConfigRepository : IRepository<ConfigViewModel, string>
// The ID is a tuple containing the category and the filename without extension (they are enough to uniquely identify a config in the repo)
public class ConfigRepository : IRepository<ConfigViewModel, (string, string)>
{
public static string defaultCategory = "Default";
public string BaseFolder { get; set; }
public ConfigRepository(string baseFolder)
@@ -21,44 +23,98 @@ namespace OpenBullet.Repositories
public void Add(ConfigViewModel entity)
{
if (!File.Exists(entity.Path))
var path = GetPath(entity);
// Create the category folder if it doesn't exist
if (entity.Category != defaultCategory && !Directory.Exists(entity.Category))
{
IOManager.SaveConfig(entity.Config, entity.Path);
Directory.CreateDirectory(Path.Combine(BaseFolder, entity.Category));
}
if (!File.Exists(path))
{
IOManager.SaveConfig(entity.Config, path);
}
else
{
throw new IOException("A file with the same name already exists");
throw new IOException("A config with the same name and category already exists");
}
}
public IEnumerable<ConfigViewModel> Get()
{
throw new NotImplementedException();
List<ConfigViewModel> configs = new List<ConfigViewModel>();
// Load the configs in the root folder
foreach (var file in Directory.EnumerateFiles(Globals.configFolder).Where(file => file.EndsWith(".loli")))
{
try
{
configs.Add(new ConfigViewModel(
Path.GetFileNameWithoutExtension(file),
defaultCategory,
IOManager.LoadConfig(file)));
}
catch { }
}
// Load the configs in the subfolders
foreach (var categoryFolder in Directory.EnumerateDirectories(Globals.configFolder))
{
foreach (var file in Directory.EnumerateFiles(categoryFolder).Where(file => file.EndsWith(".loli")))
{
try
{
configs.Add(new ConfigViewModel(
Path.GetFileNameWithoutExtension(file),
Path.GetFileName(categoryFolder),
IOManager.LoadConfig(file)));
}
catch { }
}
}
return configs;
}
public ConfigViewModel Get(string id)
public ConfigViewModel Get((string, string) id)
{
throw new NotImplementedException();
var category = id.Item1;
var fileName = id.Item2;
var path = GetPath(category, fileName);
return new ConfigViewModel(fileName, category, IOManager.LoadConfig(path));
}
public void Remove(ConfigViewModel entity)
{
if (File.Exists(entity.Path))
var path = GetPath(entity);
if (File.Exists(path))
{
File.Delete(entity.Path);
File.Delete(path);
}
else
{
throw new IOException("File not found");
}
}
public void RemoveAll()
{
throw new NotImplementedException();
Directory.Delete(BaseFolder, true);
Directory.CreateDirectory(BaseFolder);
}
public void Update(ConfigViewModel entity)
{
if (File.Exists(entity.Path))
var path = GetPath(entity);
if (File.Exists(path))
{
IOManager.SaveConfig(entity.Config, entity.Path);
IOManager.SaveConfig(entity.Config, path);
}
else
{
@@ -68,17 +124,45 @@ namespace OpenBullet.Repositories
public void Add(IEnumerable<ConfigViewModel> entities)
{
throw new NotImplementedException();
foreach (var entity in entities)
{
Add(entity);
}
}
public void Remove(IEnumerable<ConfigViewModel> entities)
{
throw new NotImplementedException();
foreach (var entity in entities)
{
Remove(entity);
}
}
public void Update(IEnumerable<ConfigViewModel> entities)
{
throw new NotImplementedException();
foreach (var entity in entities)
{
Update(entity);
}
}
private string GetPath(ConfigViewModel config)
{
return GetPath(config.Category, config.FileName);
}
private string GetPath(string category, string fileName)
{
var file = $"{fileName}.loli";
if (category != defaultCategory)
{
return Path.Combine(BaseFolder, category, file);
}
else
{
return Path.Combine(BaseFolder, file);
}
}
}
}
+144 -95
View File
@@ -1,7 +1,9 @@
using Extreme.Net;
using OpenBullet.Models;
using OpenBullet.Repositories;
using RuriLib;
using RuriLib.Functions.Formats;
using RuriLib.Interfaces;
using RuriLib.ViewModels;
using System;
using System.Collections.Generic;
@@ -13,117 +15,123 @@ using System.Linq;
using System.Net;
using System.Text;
using System.Windows;
using System.Windows.Data;
namespace OpenBullet.ViewModels
{
public class ConfigManagerViewModel : ViewModelBase
public class ConfigManagerViewModel : ViewModelBase, IConfigManager
{
private List<ConfigViewModel> cachedConfigs = new List<ConfigViewModel>();
private ConfigRepository _diskRepo;
private ObservableCollection<ConfigViewModel> configsList;
public ObservableCollection<ConfigViewModel> ConfigsList {
get {
return
SearchString == "" ?
configsList :
new ObservableCollection<ConfigViewModel>(configsList.Where(c => c.Name.ToLower().Contains(SearchString.ToLower())));
}
set { configsList = value; OnPropertyChanged("ConfigsList"); OnPropertyChanged("Total"); } }
public int Total { get { return ConfigsList.Count; } }
public string SavedConfig { get; set; }
public Config moreInfoConfig;
public Config MoreInfoConfig { get { return moreInfoConfig; } set { moreInfoConfig = value; OnPropertyChanged("MoreInfoConfig"); } }
public string CurrentConfigName
private ObservableCollection<ConfigViewModel> configsCollection;
public ObservableCollection<ConfigViewModel> ConfigsCollection
{
get
{
if (Globals.mainWindow.ConfigsPage.CurrentConfig != null)
{
return Globals.mainWindow.ConfigsPage.CurrentConfig.Name;
}
else
{
return "None";
}
get => configsCollection;
private set
{
configsCollection = value;
OnPropertyChanged(); // We need to raise this when we create a new collection or it will not show up!
}
}
public IEnumerable<ConfigViewModel> Configs => ConfigsCollection;
public int Total => ConfigsCollection.Count;
public int SavedHash { get; set; } = 0;
private Config hoveredConfig;
public Config HoveredConfig { get => hoveredConfig; set { hoveredConfig = value; OnPropertyChanged(); } }
private ConfigViewModel currentConfig;
public ConfigViewModel CurrentConfig
{
get => currentConfig;
set
{
currentConfig = value;
OnPropertyChanged(nameof(CurrentConfigName));
}
}
private string searchString = "";
public string SearchString { get { return searchString; } set { searchString = value; OnPropertyChanged("SearchString"); OnPropertyChanged("ConfigsList"); OnPropertyChanged("Total"); } }
public string CurrentConfigName => CurrentConfig == null ? "None" : CurrentConfig.Name;
public ConfigManagerViewModel()
{
configsList = new ObservableCollection<ConfigViewModel>();
RefreshList(true);
_diskRepo = new ConfigRepository(Globals.configFolder);
Rescan();
}
public bool NameTaken(string name)
#region Filters
private string searchString = "";
public string SearchString
{
return ConfigsList.Any(x => x.Name == name);
}
public void RefreshCurrent()
{
OnPropertyChanged("CurrentConfigName");
}
public void RefreshList(bool pullSources)
{
// Scan the directory and the sources for configs
if (pullSources)
{
ConfigsList = new ObservableCollection<ConfigViewModel>(
GetConfigsFromSources()
.Concat(GetConfigsFromDisk(true))
);
get => searchString;
set
{
searchString = value;
OnPropertyChanged();
CollectionViewSource.GetDefaultView(ConfigsCollection).Refresh();
OnPropertyChanged(nameof(Total));
}
else
{
ConfigsList = new ObservableCollection<ConfigViewModel>(
cachedConfigs
.Concat(GetConfigsFromDisk(true))
);
}
OnPropertyChanged("Total");
}
public List<ConfigViewModel> GetConfigsFromDisk(bool sort = false)
public void HookFilters()
{
List<ConfigViewModel> models = new List<ConfigViewModel>();
CollectionView view = (CollectionView)CollectionViewSource.GetDefaultView(ConfigsCollection);
view.Filter = ConfigsFilter;
}
// Load the configs in the root folder
foreach(var file in Directory.EnumerateFiles(Globals.configFolder).Where(file => file.EndsWith(".loli")))
{
try { models.Add(new ConfigViewModel(file, "Default", IOManager.LoadConfig(file))); }
catch { Globals.logger.LogError(Components.ConfigManager, "Could not load file: " + file); }
}
private bool ConfigsFilter(object item)
{
return (item as ConfigViewModel).Name.ToLower().Contains(searchString.ToLower());
}
#endregion
// Load the configs in the subfolders
foreach(var categoryFolder in Directory.EnumerateDirectories(Globals.configFolder))
#region Get from disk
public List<ConfigViewModel> GetConfigsFromDisk(bool sort = false, bool reverse = false)
{
var configs = _diskRepo.Get().ToList();
if (sort)
{
foreach(var file in Directory.EnumerateFiles(categoryFolder).Where(file => file.EndsWith(".loli")))
configs.Sort((m1, m2) => m1.Config.Settings.LastModified.CompareTo(m2.Config.Settings.LastModified));
if (reverse)
{
try { models.Add(new ConfigViewModel(file, Path.GetFileName(categoryFolder), IOManager.LoadConfig(file))); }
catch { Globals.logger.LogError(Components.ConfigManager, "Could not load file: " + file); }
configs.Reverse();
}
}
return configs;
}
#endregion
#region Get from sources
public IEnumerable<ConfigViewModel> GetConfigsFromSources()
{
var configs = new List<ConfigViewModel>();
foreach (var source in Globals.obSettings.Sources.Sources)
{
try
{
configs.AddRange(PullSource(source));
}
catch (Exception ex)
{
Globals.logger.LogError(Components.ConfigManager, $"Error with API {source.ApiUrl}\r\nReason: {ex.Message}", true);
}
}
if (sort) { models.Sort((m1, m2) => m1.Config.Settings.LastModified.CompareTo(m2.Config.Settings.LastModified)); }
return models;
return configs;
}
public List<ConfigViewModel> GetConfigsFromSources()
public IEnumerable<ConfigViewModel> PullSource(Source source)
{
var list = new List<ConfigViewModel>();
cachedConfigs = new List<ConfigViewModel>();
foreach(var source in Globals.obSettings.Sources.Sources)
using (var wc = new WebClient())
{
WebClient wc = new WebClient();
var configs = new List<ConfigViewModel>();
switch (source.Auth)
{
case Source.AuthMode.ApiKey:
@@ -140,21 +148,12 @@ namespace OpenBullet.ViewModels
}
byte[] file = new byte[] { };
try
{
file = wc.DownloadData(source.ApiUrl);
}
catch (Exception ex)
{
MessageBox.Show($"Could not contact API {source.ApiUrl}\r\nReason: {ex.Message}");
continue;
}
file = wc.DownloadData(source.ApiUrl);
var status = wc.ResponseHeaders["Result"];
if (status != null && status == "Error")
{
MessageBox.Show($"Error from API {source.ApiUrl}\r\nThe server says: {Encoding.ASCII.GetString(file)}");
continue;
throw new Exception($"The server says: {Encoding.ASCII.GetString(file)}");
}
try
@@ -171,17 +170,67 @@ namespace OpenBullet.ViewModels
{
var text = tr.ReadToEnd();
var cfg = IOManager.DeserializeConfig(text);
list.Add(new ConfigViewModel("", category, cfg, true));
cachedConfigs.Add(new ConfigViewModel("", category, cfg, true));
configs.Add(new ConfigViewModel("", category, cfg, true));
}
}
}
}
}
catch { }
return configs;
}
}
#endregion
#region CRUD Operations
// Create
public void Add(ConfigViewModel config)
{
_diskRepo.Add(config);
ConfigsCollection.Add(config);
}
// Read
public void Rescan()
{
ConfigsCollection = new ObservableCollection<ConfigViewModel>(
GetConfigsFromDisk(true, true)
.Concat(GetConfigsFromSources()));
HookFilters();
OnPropertyChanged(nameof(Total));
}
// Update
public void Update(ConfigViewModel config)
{
_diskRepo.Update(config);
}
public void SaveCurrent()
{
Update(CurrentConfig);
}
// Delete
public void Remove(ConfigViewModel config)
{
_diskRepo.Remove(config);
ConfigsCollection.Remove(config);
}
public void Remove(IEnumerable<ConfigViewModel> configs)
{
var toRemove = configs.ToArray();
foreach (var config in toRemove)
{
ConfigsCollection.Remove(config);
}
return list;
_diskRepo.Remove(toRemove);
}
#endregion
}
}
@@ -1,4 +1,5 @@
using OpenBullet.Views.Main.Configs;
using OpenBullet.Repositories;
using OpenBullet.Views.Main.Configs;
using RuriLib;
using RuriLib.Functions.Files;
using System.Linq;
@@ -22,8 +23,8 @@ namespace OpenBullet
authorTextbox.Text = Globals.obSettings.General.DefaultAuthor;
nameTextbox.Focus();
categoryCombobox.Items.Add("Default");
foreach(var category in Globals.mainWindow.ConfigsPage.ConfigManagerPage.vm.ConfigsList.Select(c => c.Category).Distinct())
categoryCombobox.Items.Add(ConfigRepository.defaultCategory);
foreach(var category in Globals.mainWindow.ConfigsPage.ConfigManagerPage.vm.ConfigsCollection.Select(c => c.Category).Distinct())
categoryCombobox.Items.Add(category);
categoryCombobox.SelectedIndex = 0;
@@ -38,7 +39,7 @@ namespace OpenBullet
else if (nameTextbox.Text != Files.MakeValidFileName(nameTextbox.Text)) { MessageBox.Show("The name contains invalid characters"); return; }
// Check if category is ok
if (categoryCombobox.Text.Trim() == "") categoryCombobox.Text = "Default";
if (string.IsNullOrWhiteSpace(categoryCombobox.Text)) categoryCombobox.Text = ConfigRepository.defaultCategory;
else if (categoryCombobox.Text != Files.MakeValidFileName(categoryCombobox.Text)) { MessageBox.Show("The category contains invalid characters"); return; }
((ConfigManager)Caller).CreateConfig(nameTextbox.Text, categoryCombobox.Text, authorTextbox.Text);
@@ -31,7 +31,7 @@
</Grid>
<!-- Proxies List View -->
<ListView x:Name="configsListView" Grid.Row="1" Foreground="{DynamicResource ForegroundMain}" Background="Transparent" ItemsSource="{Binding Path=ConfigsList}" SelectionMode="Extended" BorderThickness="1" VirtualizingPanel.IsVirtualizing="True">
<ListView x:Name="configsListView" Grid.Row="1" Foreground="{DynamicResource ForegroundMain}" Background="Transparent" ItemsSource="{Binding Path=ConfigsCollection}" SelectionMode="Extended" BorderThickness="1" VirtualizingPanel.IsVirtualizing="True">
<!-- Show Headers by overriding the default style -->
<ListView.Style>
@@ -59,22 +59,20 @@ namespace OpenBullet
configsListView.Items.SortDescriptions.Add(new SortDescription(sortBy, newDir));
}
private void ListViewItem_MouseDoubleClick(object sender, System.Windows.Input.MouseButtonEventArgs e)
private void ListViewItem_MouseDoubleClick(object sender, MouseButtonEventArgs e)
{
selectButton_Click(this, null);
}
private void ListViewItem_KeyDown(object sender, System.Windows.Input.KeyEventArgs e)
private void ListViewItem_KeyDown(object sender, KeyEventArgs e)
{
if (e.Key == System.Windows.Input.Key.Enter)
if (e.Key == Key.Enter)
selectButton_Click(this, null);
}
private void searchButton_Click(object sender, RoutedEventArgs e)
{
vm.SearchString = filterTextbox.Text;
if (vm.SearchString == "")
vm.RefreshList(false);
}
private void filterTextbox_KeyDown(object sender, KeyEventArgs e)
@@ -94,7 +94,7 @@
</Grid>
<!-- Proxies List View -->
<ListView x:Name="configsListView" Grid.Row="2" Foreground="{DynamicResource ForegroundMain}" Background="Transparent" ItemsSource="{Binding Path=ConfigsList}" SelectionMode="Extended" BorderThickness="1" VirtualizingPanel.IsVirtualizing="True" SelectionChanged="configsListView_SelectionChanged">
<ListView x:Name="configsListView" Grid.Row="2" Foreground="{DynamicResource ForegroundMain}" Background="Transparent" ItemsSource="{Binding Path=ConfigsCollection}" SelectionMode="Extended" BorderThickness="1" VirtualizingPanel.IsVirtualizing="True" SelectionChanged="configsListView_SelectionChanged">
<!-- Show Headers by overriding the default style -->
<ListView.Style>
@@ -256,37 +256,37 @@
<StackPanel Grid.Column="0" Grid.Row="0" Orientation="Horizontal">
<Label Content="Allowed Wordlists:"/>
<Label Content="{Binding MoreInfoConfig.AllowedWordlists}"/>
<Label Content="{Binding HoveredConfig.AllowedWordlists}"/>
</StackPanel>
<StackPanel Grid.Column="0" Grid.Row="1" Orientation="Horizontal">
<Label Content="Blocks Amount:"/>
<Label Content="{Binding MoreInfoConfig.BlocksAmount}"/>
<Label Content="{Binding HoveredConfig.BlocksAmount}"/>
</StackPanel>
<StackPanel Grid.Column="0" Grid.Row="2" Grid.ColumnSpan="3" Orientation="Horizontal">
<Label Content="Additional Info:"/>
<Label Content="{Binding MoreInfoConfig.Settings.AdditionalInfo}"/>
<Label Content="{Binding HoveredConfig.Settings.AdditionalInfo}"/>
</StackPanel>
<StackPanel Grid.Column="1" Grid.Row="0" Orientation="Horizontal">
<Label Content="Last Modified:"/>
<Label Content="{Binding MoreInfoConfig.LastModifiedString}"/>
<Label Content="{Binding HoveredConfig.LastModifiedString}"/>
</StackPanel>
<StackPanel Grid.Column="1" Grid.Row="1" Orientation="Horizontal">
<Label Content="Suggested Bots:"/>
<Label Content="{Binding MoreInfoConfig.Settings.SuggestedBots}"/>
<Label Content="{Binding HoveredConfig.Settings.SuggestedBots}"/>
</StackPanel>
<StackPanel Grid.Column="2" Grid.Row="0" Orientation="Horizontal">
<Label Content="Built with version:"/>
<Label Content="{Binding MoreInfoConfig.Settings.Version}"/>
<Label Content="{Binding HoveredConfig.Settings.Version}"/>
</StackPanel>
<StackPanel Grid.Column="2" Grid.Row="1" Orientation="Horizontal">
<Label Content="Author:" Foreground="{DynamicResource ForegroundRetry}"/>
<Label Content="{Binding MoreInfoConfig.Settings.Author}" Foreground="{DynamicResource ForegroundRetry}"/>
<Label Content="{Binding HoveredConfig.Settings.Author}" Foreground="{DynamicResource ForegroundRetry}"/>
</StackPanel>
</Grid>
</Grid>
@@ -2,8 +2,10 @@
using RuriLib;
using RuriLib.ViewModels;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
@@ -20,7 +22,8 @@ namespace OpenBullet.Views.Main.Configs
public ConfigManagerViewModel vm = new ConfigManagerViewModel();
private GridViewColumnHeader listViewSortCol = null;
private SortAdorner listViewSortAdorner = null;
public ConfigViewModel Current { get { return Globals.mainWindow.ConfigsPage.CurrentConfig; } set { Globals.mainWindow.ConfigsPage.CurrentConfig = value; vm.RefreshCurrent(); } }
private IEnumerable<ConfigViewModel> Selected => configsListView.SelectedItems.Cast<ConfigViewModel>();
public void OnSaveConfig(object sender, EventArgs e)
{
@@ -33,22 +36,44 @@ namespace OpenBullet.Views.Main.Configs
DataContext = vm;
}
#region State
// Checks if the config's hash is the same as the saved one
public bool CheckSaved()
{
var stacker = Globals.mainWindow.ConfigsPage.StackerPage;
if (Current == null || Globals.obSettings.General.DisableNotSavedWarning || stacker == null) return true;
// If we don't have a config selected or we suppressed the warning or we don't have a Stacker open
if (vm.CurrentConfig == null || Globals.obSettings.General.DisableNotSavedWarning || stacker == null)
{
return true;
}
// Blocks to LS conversion because we are going to hash the LS
stacker.SetScript();
var cvm = stacker.vm.Config;
if (string.IsNullOrEmpty(vm.SavedConfig) || cvm == null) return true;
return vm.SavedConfig == IOManager.SerializeConfig(cvm.Config);
// If we don't have a config loaded in Stacker
if (cvm == null)
{
return true;
}
return vm.SavedHash == cvm.Config.Script.GetHashCode();
}
// Saves a hash of the LS of the config in Stacker
public void SaveState()
{
var cvm = Globals.mainWindow.ConfigsPage.StackerPage.vm.Config;
if (cvm != null) vm.SavedConfig = IOManager.SerializeConfig(cvm.Config);
if (cvm != null)
{
vm.SavedHash = cvm.Config.Script.GetHashCode();
}
}
#endregion
#region Buttons
private void loadConfigButton_Click(object sender, RoutedEventArgs e)
{
if (!CheckSaved())
@@ -59,61 +84,73 @@ namespace OpenBullet.Views.Main.Configs
return;
}
// Create new instance of stacker
Current = (ConfigViewModel)configsListView.SelectedItem; // Set Current Config
if (Current != null)
{
if (Current.Remote)
{
Globals.logger.LogError(Components.ConfigManager, "The config was pulled from a remote source and cannot be edited!", true);
Current = null;
return;
}
Globals.logger.LogInfo(Components.ConfigManager, "Loading config: " + Current.Name);
Globals.mainWindow.ConfigsPage.menuOptionStacker.IsEnabled = true;
Globals.mainWindow.ConfigsPage.menuOptionOtherOptions.IsEnabled = true;
var newStacker = new Stacker(Current);
if (Globals.mainWindow.ConfigsPage.StackerPage != null)
{
newStacker.vm.TestData = Globals.mainWindow.ConfigsPage.StackerPage.vm.TestData;
newStacker.vm.TestProxy = Globals.mainWindow.ConfigsPage.StackerPage.vm.TestProxy;
newStacker.vm.ProxyType = Globals.mainWindow.ConfigsPage.StackerPage.vm.ProxyType;
}
Globals.mainWindow.ConfigsPage.StackerPage = newStacker; // Create a Stacker instance
Globals.logger.LogInfo(Components.ConfigManager, "Created and assigned a new Stacker instance");
Globals.mainWindow.ConfigsPage.OtherOptionsPage = new ConfigOtherOptions(); // Create an Other Options instance
Globals.logger.LogInfo(Components.ConfigManager, "Created and assigned a new Other Options instance");
Globals.mainWindow.ConfigsPage.menuOptionStacker_MouseDown(this, null); // Switch to Stacker
// Save the last state of the config
Globals.mainWindow.ConfigsPage.StackerPage.SetScript();
SaveState();
}
else
{
Globals.logger.LogError(Components.ConfigManager, "No config selected for loading", true);
}
// Load the config
LoadConfig(configsListView.SelectedItem as ConfigViewModel);
}
private void saveConfigButton_Click(object sender, RoutedEventArgs e)
{
if (Current == null)
{
Globals.logger.LogError(Components.ConfigManager, "No config selected for saving!");
return;
}
SaveConfig();
}
private void deleteConfigsButton_Click(object sender, RoutedEventArgs e)
{
Globals.logger.LogWarning(Components.ConfigManager, "Deletion initiated, prompting warning");
if (MessageBox.Show("This will delete the physical files from your disk! Are you sure you want to continue?", "WARNING", MessageBoxButton.YesNo, MessageBoxImage.Warning) == MessageBoxResult.Yes)
{
vm.Remove(Selected);
Globals.logger.LogInfo(Components.ConfigManager, "Deletion completed");
}
else
{
Globals.logger.LogInfo(Components.ConfigManager, "Deletion cancelled");
}
}
private void rescanConfigsButton_Click(object sender, RoutedEventArgs e)
{
vm.Rescan();
}
private void newConfigButton_Click(object sender, RoutedEventArgs e)
{
if (!CheckSaved())
{
Globals.logger.LogWarning(Components.Stacker, "Config not saved, prompting quit confirmation");
if (MessageBox.Show("The Config in Stacker wasn't saved.\r\nAre you sure you want to create a new config?",
"Confirmation", MessageBoxButton.YesNo, MessageBoxImage.Warning) == MessageBoxResult.No)
return;
}
(new MainDialog(new DialogNewConfig(this), "New Config")).ShowDialog();
}
private void searchButton_Click(object sender, RoutedEventArgs e)
{
vm.SearchString = filterTextbox.Text;
}
private void filterTextbox_KeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Enter)
searchButton_Click(this, null);
}
private void openConfigFolderButton_Click(object sender, RoutedEventArgs e)
{
try
{
System.Diagnostics.Process.Start(System.IO.Path.Combine(Directory.GetCurrentDirectory(), Globals.configFolder));
}
catch { Globals.logger.LogError(Components.ConfigManager, "No config folder found!", true); }
}
#endregion
#region Saving, Loading and Creating
public void SaveConfig()
{
if (Globals.mainWindow.ConfigsPage.CurrentConfig == null ||
if (vm.CurrentConfig == null ||
Globals.mainWindow.ConfigsPage.StackerPage == null ||
Globals.mainWindow.ConfigsPage.OtherOptionsPage == null)
{
@@ -121,7 +158,7 @@ namespace OpenBullet.Views.Main.Configs
return;
}
if (Current.Remote)
if (vm.CurrentConfig.Remote)
{
Globals.logger.LogError(Components.ConfigManager, "The config was pulled from a remote source and cannot be saved!", true);
return;
@@ -138,89 +175,85 @@ namespace OpenBullet.Views.Main.Configs
if (stacker.View == StackerView.Blocks)
stacker.LS.FromBlocks(stacker.GetList());
Current.Config.Script = stacker.LS.Script;
vm.CurrentConfig.Config.Script = stacker.LS.Script;
Globals.logger.LogInfo(Components.ConfigManager, $"Saving config {vm.CurrentConfigName}");
Current.Config.Settings.LastModified = DateTime.Now;
Current.Config.Settings.Version = Globals.obVersion;
vm.CurrentConfig.Config.Settings.LastModified = DateTime.Now;
vm.CurrentConfig.Config.Settings.Version = Globals.obVersion;
Globals.logger.LogInfo(Components.ConfigManager, "Converted the unbinded observables and set the Last Modified date");
// Save to file
if (!IOManager.SaveConfig(Current.Config, Current.Path)) {
Globals.logger.LogError(Components.ConfigManager, "Failed to save the config to file.", true);
// Save to file
try
{
vm.SaveCurrent();
// Save the last state of the config
SaveState();
}
catch (Exception ex)
{
Globals.logger.LogError(Components.ConfigManager, $"Failed to save the config. Reason: {ex.Message}", true);
}
}
public void LoadConfig(ConfigViewModel config)
{
if (config == null)
{
Globals.logger.LogError(Components.ConfigManager, "The config to load cannot be null");
}
// Set the config as current
vm.CurrentConfig = config;
if (vm.CurrentConfig.Remote)
{
Globals.logger.LogError(Components.ConfigManager, "The config was pulled from a remote source and cannot be edited!", true);
vm.CurrentConfig = null;
return;
};
}
Globals.logger.LogInfo(Components.ConfigManager, "Loading config: " + vm.CurrentConfig.Name);
Globals.mainWindow.ConfigsPage.menuOptionStacker.IsEnabled = true;
Globals.mainWindow.ConfigsPage.menuOptionOtherOptions.IsEnabled = true;
var newStacker = new Stacker(vm.CurrentConfig);
// Preserve the old stacker test data and proxy
if (Globals.mainWindow.ConfigsPage.StackerPage != null)
{
newStacker.vm.TestData = Globals.mainWindow.ConfigsPage.StackerPage.vm.TestData;
newStacker.vm.TestProxy = Globals.mainWindow.ConfigsPage.StackerPage.vm.TestProxy;
newStacker.vm.ProxyType = Globals.mainWindow.ConfigsPage.StackerPage.vm.ProxyType;
}
Globals.mainWindow.ConfigsPage.StackerPage = newStacker; // Create a Stacker instance
Globals.logger.LogInfo(Components.ConfigManager, "Created and assigned a new Stacker instance");
Globals.mainWindow.ConfigsPage.OtherOptionsPage = new ConfigOtherOptions(); // Create an Other Options instance
Globals.logger.LogInfo(Components.ConfigManager, "Created and assigned a new Other Options instance");
Globals.mainWindow.ConfigsPage.menuOptionStacker_MouseDown(this, null); // Switch to Stacker
// Save the last state of the config
Globals.mainWindow.ConfigsPage.StackerPage.SetScript();
SaveState();
Globals.logger.LogInfo(Components.ConfigManager, "Refreshing the list");
vm.RefreshList(false);
}
private void deleteConfigsButton_Click(object sender, RoutedEventArgs e)
{
Globals.logger.LogWarning(Components.ConfigManager, "Deletion initiated, prompting warning");
if (MessageBox.Show("This will delete the physical files from your disk! Are you sure you want to continue?", "WARNING", MessageBoxButton.YesNo, MessageBoxImage.Warning) == MessageBoxResult.Yes)
{
foreach(ConfigViewModel config in configsListView.SelectedItems)
{
try
{
File.Delete(config.Path);
}
catch { Globals.logger.LogError(Components.ConfigManager, "Could not delete file: " + config.Path); }
}
Globals.logger.LogInfo(Components.ConfigManager, $"Deleted {configsListView.SelectedItems.Count} configs");
vm.RefreshList(false);
}
else
{
Globals.logger.LogInfo(Components.ConfigManager, "Deletion cancelled");
}
}
private void rescanConfigsButton_Click(object sender, RoutedEventArgs e)
{
vm.RefreshList(true);
}
private void newConfigButton_Click(object sender, RoutedEventArgs e)
{
if (!CheckSaved())
{
Globals.logger.LogWarning(Components.Stacker, "Config not saved, prompting quit confirmation");
if (MessageBox.Show("The Config in Stacker wasn't saved.\nAre you sure you want to create a new config?",
"Confirmation", MessageBoxButton.YesNo, MessageBoxImage.Warning) == MessageBoxResult.No)
return;
}
(new MainDialog(new DialogNewConfig(this), "New Config")).ShowDialog();
}
public void CreateConfig(string name, string category, string author)
{
// Build the filename
var path = Globals.configFolder + "\\" + (category == "Default" ? "" : (category + "\\")) + name + ".loli";
// Create the Category folder if it doesn't exist
if(category != "Default")
{
var categoryFolder = System.IO.Path.Combine(Directory.GetCurrentDirectory(), Globals.configFolder, category);
if (!Directory.Exists(categoryFolder))
Directory.CreateDirectory(categoryFolder);
}
// Build the base config structure
var settings = new ConfigSettings();
settings.Name = name;
settings.Author = author;
Globals.logger.LogInfo(Components.ConfigManager, "Setting up the new Config object, with path '" + path + "'");
Current = new ConfigViewModel(path, category, new Config(settings, ""));
var newConfig = new ConfigViewModel(name, category, new Config(settings, string.Empty));
var newStacker = new Stacker(Current);
// Add it to the collection and persistent storage
vm.Add(newConfig);
vm.CurrentConfig = newConfig;
var newStacker = new Stacker(vm.CurrentConfig);
if (Globals.mainWindow.ConfigsPage.StackerPage != null) // Maintain the previous stacker settings
{
newStacker.vm.TestData = Globals.mainWindow.ConfigsPage.StackerPage.vm.TestData;
@@ -232,20 +265,13 @@ namespace OpenBullet.Views.Main.Configs
Globals.mainWindow.ConfigsPage.OtherOptionsPage = new ConfigOtherOptions(); // Create an Other Options instance
Globals.logger.LogInfo(Components.ConfigManager, "Created and assigned a new Other Options instance");
Globals.mainWindow.ConfigsPage.menuOptionStacker_MouseDown(this, null); // Switch to Stacker
// Save to disk
saveConfigButton_Click(this, null);
vm.RefreshList(false);
// Create new instance of stacker
Globals.mainWindow.ConfigsPage.StackerPage = new Stacker(Current);
Globals.mainWindow.ConfigsPage.menuOptionStacker_MouseDown(this, null); // Switch to Stacker
}
#endregion
#region ListView
private void configsListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
try { vm.MoreInfoConfig = ((ConfigViewModel)configsListView.SelectedItem).Config; } catch { }
try { vm.HoveredConfig = ((ConfigViewModel)configsListView.SelectedItem).Config; } catch { }
}
private void listViewColumnHeader_Click(object sender, RoutedEventArgs e)
@@ -268,31 +294,10 @@ namespace OpenBullet.Views.Main.Configs
configsListView.Items.SortDescriptions.Add(new SortDescription(sortBy, newDir));
}
private void searchButton_Click(object sender, RoutedEventArgs e)
{
vm.SearchString = filterTextbox.Text;
if(vm.SearchString == "")
vm.RefreshList(false);
}
private void filterTextbox_KeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Enter)
searchButton_Click(this, null);
}
private void openConfigFolderButton_Click(object sender, RoutedEventArgs e)
{
try
{
System.Diagnostics.Process.Start(System.IO.Path.Combine(Directory.GetCurrentDirectory(), Globals.configFolder));
}
catch { Globals.logger.LogError(Components.ConfigManager, "No config folder found!", true); }
}
private void ListViewItem_MouseDoubleClick(object sender, MouseButtonEventArgs e)
{
loadConfigButton_Click(this, new RoutedEventArgs());
}
#endregion
}
}
+2 -1
View File
@@ -13,7 +13,8 @@ namespace OpenBullet.Views.Main
public ConfigManager ConfigManagerPage;
public Stacker StackerPage;
public ConfigOtherOptions OtherOptionsPage;
public ConfigViewModel CurrentConfig { get; set; }
public ConfigViewModel CurrentConfig => ConfigManagerPage.vm.CurrentConfig;
public ConfigsSection()
{
+1 -1
View File
@@ -288,7 +288,7 @@ namespace OpenBullet.Views.Main
// Try to select the config referring to the first selected hit
try
{
var cfg = Globals.mainWindow.ConfigsPage.ConfigManagerPage.vm.ConfigsList.First(c => c.Name == first.ConfigName).Config;
var cfg = Globals.mainWindow.ConfigsPage.ConfigManagerPage.vm.ConfigsCollection.First(c => c.Name == first.ConfigName).Config;
runner.vm.SetConfig(cfg, false);
runner.vm.BotsAmount = Math.Min(cfg.Settings.SuggestedBots, hitsListView.SelectedItems.Count);
}
+6
View File
@@ -34,6 +34,12 @@ namespace RuriLib.Interfaces
/// <param name="config">The config to remove</param>
void Remove(ConfigViewModel config);
/// <summary>
/// Removes multiple configs.
/// </summary>
/// <param name="configs">The configs to remove</param>
void Remove(IEnumerable<ConfigViewModel> configs);
/// <summary>
/// Updates a config.
/// </summary>
+6 -6
View File
@@ -14,9 +14,9 @@ namespace RuriLib.ViewModels
/// <summary>The Category of the config.</summary>
public string Category { get { return category; } set { category = value; OnPropertyChanged(); } }
private string path = "";
/// <summary>The path of the config file on disk.</summary>
public string Path { get { return path; } set { path = value; OnPropertyChanged(); } }
private string fileName = "";
/// <summary>The name of the file containing the config, without the extension.</summary>
public string FileName { get { return fileName; } set { fileName = value; OnPropertyChanged(); } }
/// <summary>Whether the config was pulled from a remote source.</summary>
public bool Remote { get; set; } = false;
@@ -27,13 +27,13 @@ namespace RuriLib.ViewModels
/// <summary>
/// Constructs an instance of the ConfigViewModel class.
/// </summary>
/// <param name="path">The path of the config file on disk</param>
/// <param name="fileName">The name of the file containing the config, without the extension</param>
/// <param name="category">The category of the config</param>
/// <param name="config">The actual Config object</param>
/// <param name="remote">Whether the Config was pulled from a remote source</param>
public ConfigViewModel(string path, string category, Config config, bool remote = false)
public ConfigViewModel(string fileName, string category, Config config, bool remote = false)
{
Path = path;
FileName = fileName;
Category = category;
Config = config;
Remote = remote;