Syro now saves/loads session state to solution directory

This commit is contained in:
Rikki Tooley 2015-04-03 17:34:28 +01:00
parent cd157882eb
commit 4e6446b744
4 changed files with 241 additions and 137 deletions

View File

@ -108,6 +108,7 @@
<Compile Include="Resources\NullToInvisibleConverter.cs" /> <Compile Include="Resources\NullToInvisibleConverter.cs" />
<Compile Include="Tools\ProgressReport.cs" /> <Compile Include="Tools\ProgressReport.cs" />
<Compile Include="Tools\Reflektor.cs" /> <Compile Include="Tools\Reflektor.cs" />
<Compile Include="ViewModels\MainState.cs" />
<Compile Include="ViewModels\MainViewModel.cs" /> <Compile Include="ViewModels\MainViewModel.cs" />
<Compile Include="ViewModels\ViewModelBase.cs" /> <Compile Include="ViewModels\ViewModelBase.cs" />
<Compile Include="ViewModels\ViewModelLocator.cs" /> <Compile Include="ViewModels\ViewModelLocator.cs" />

View File

@ -5,8 +5,6 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:controls="http://metro.mahapps.com/winfx/xaml/controls" xmlns:controls="http://metro.mahapps.com/winfx/xaml/controls"
xmlns:viewModels="clr-namespace:IF.Lastfm.Syro.ViewModels" xmlns:viewModels="clr-namespace:IF.Lastfm.Syro.ViewModels"
xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
xmlns:objectModel="clr-namespace:System.Collections.ObjectModel;assembly=System"
mc:Ignorable="d" mc:Ignorable="d"
d:DataContext="{d:DesignInstance viewModels:MainViewModel}" d:DesignWidth="400" d:DesignHeight="308"> d:DataContext="{d:DesignInstance viewModels:MainViewModel}" d:DesignWidth="400" d:DesignHeight="308">
@ -30,17 +28,17 @@
<ComboBox Grid.Column="0" <ComboBox Grid.Column="0"
ItemsSource="{Binding BaseCommandTypes}" ItemsSource="{Binding BaseCommandTypes}"
SelectedItem="{Binding SelectedBaseCommandType, Mode=TwoWay}" SelectedItem="{Binding State.SelectedBaseCommandType, Mode=TwoWay}"
IsTextSearchEnabled="False" /> IsTextSearchEnabled="False" />
<ComboBox Grid.Column="1" <ComboBox Grid.Column="1"
ItemsSource="{Binding LastResponseTypes}" ItemsSource="{Binding LastResponseTypes}"
SelectedItem="{Binding SelectedResponseType, Mode=TwoWay}" SelectedItem="{Binding State.SelectedResponseType, Mode=TwoWay}"
IsTextSearchEnabled="False" /> IsTextSearchEnabled="False" />
<ComboBox Grid.Column="2" <ComboBox Grid.Column="2"
ItemsSource="{Binding LastObjectTypes}" ItemsSource="{Binding LastObjectTypes}"
SelectedItem="{Binding SelectedLastObjectType, Mode=TwoWay}" SelectedItem="{Binding State.SelectedLastObjectType, Mode=TwoWay}"
IsTextSearchEnabled="False" /> IsTextSearchEnabled="False" />
</Grid> </Grid>
<Grid Row="1" <Grid Row="1"
@ -61,7 +59,7 @@
Style="{StaticResource SyroNormalFontStyle}" Style="{StaticResource SyroNormalFontStyle}"
Margin="0,0,10,0"/> Margin="0,0,10,0"/>
<TextBox Grid.Column="1" <TextBox Grid.Column="1"
Text="{Binding CommandMethodName, Mode=TwoWay}"/> Text="{Binding State.CommandMethodName, Mode=TwoWay}"/>
</Grid> </Grid>
<Grid Grid.Column="1"> <Grid Grid.Column="1">
@ -74,7 +72,7 @@
Style="{StaticResource SyroNormalFontStyle}" Style="{StaticResource SyroNormalFontStyle}"
Margin="10,0"/> Margin="10,0"/>
<TextBox Grid.Column="1" <TextBox Grid.Column="1"
Text="{Binding CommandPageNumber, Mode=TwoWay}"/> Text="{Binding State.CommandPageNumber, Mode=TwoWay}"/>
</Grid> </Grid>
<Grid Grid.Column="2"> <Grid Grid.Column="2">
@ -87,7 +85,7 @@
Style="{StaticResource SyroNormalFontStyle}" Style="{StaticResource SyroNormalFontStyle}"
Margin="10,0"/> Margin="10,0"/>
<TextBox Grid.Column="1" <TextBox Grid.Column="1"
Text="{Binding CommandItemCount, Mode=TwoWay}"/> Text="{Binding State.CommandItemCount, Mode=TwoWay}"/>
</Grid> </Grid>
</Grid> </Grid>
@ -179,20 +177,26 @@
</StackPanel> </StackPanel>
</Border> </Border>
</TabItem> </TabItem>
<TabItem Header="Sign in"> <TabItem Header="Config">
<Border Padding="28,10"> <Border Padding="28,10">
<StackPanel> <StackPanel>
<TextBlock Style="{StaticResource SyroNormalFontStyle}" <TextBlock Style="{StaticResource SyroNormalFontStyle}"
Text="Username" Text="Username"
Margin="0,0,0,10" /> Margin="0,0,0,10" />
<TextBox Text="{Binding LastUsername, Mode=TwoWay}" <TextBox Text="{Binding State.LastUsername, Mode=TwoWay}"
Margin="0,0,0,15" /> Margin="0,0,0,15" />
<TextBlock Style="{StaticResource SyroNormalFontStyle}" <TextBlock Style="{StaticResource SyroNormalFontStyle}"
Text="Password" Text="Password"
Margin="0,0,0,10" /> Margin="0,0,0,10" />
<TextBox Text="{Binding LastPassword, Mode=TwoWay}" <TextBox Text="{Binding State.LastPassword, Mode=TwoWay}"
Margin="0,0,0,15" /> Margin="0,0,0,25" />
<Button Command="{Binding DeleteConfigCommand}"
HorizontalAlignment="Left"
Margin="0,0,10,10">
<TextBlock Style="{StaticResource SyroNormalFontStyle}" Margin="10,5">Reset config</TextBlock>
</Button>
<TextBlock>Config is automatically saved to (SolutionDir)/syro.json on exit.</TextBlock>
</StackPanel> </StackPanel>
</Border> </Border>
</TabItem> </TabItem>

View File

@ -0,0 +1,123 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using IF.Lastfm.Syro.Helpers;
namespace IF.Lastfm.Syro.ViewModels
{
internal class MainState : ViewModelBase
{
private Type _selectedLastObjectType;
private Type _selectedResponseType;
private Type _selectedCommandType;
private string _lastPassword;
private string _lastUsername;
private string _commandMethodName;
private string _commandPageNumber;
private string _commandItemCount;
private Dictionary<string, string> _commandParameters;
public string CommandMethodName
{
get { return _commandMethodName; }
set
{
if (value == _commandMethodName) return;
_commandMethodName = value;
OnPropertyChanged();
}
}
public string CommandPageNumber
{
get { return _commandPageNumber; }
set
{
if (value == _commandPageNumber) return;
_commandPageNumber = value;
OnPropertyChanged();
}
}
public string CommandItemCount
{
get { return _commandItemCount; }
set
{
if (value == _commandItemCount) return;
_commandItemCount = value;
OnPropertyChanged();
}
}
public Type SelectedResponseType
{
get { return _selectedResponseType; }
set
{
if (value == _selectedResponseType) return;
_selectedResponseType = value;
OnPropertyChanged();
}
}
public Type SelectedLastObjectType
{
get { return _selectedLastObjectType; }
set
{
if (value == _selectedLastObjectType) return;
_selectedLastObjectType = value;
OnPropertyChanged();
}
}
public Type SelectedBaseCommandType
{
get { return _selectedCommandType; }
set
{
if (value == _selectedCommandType) return;
_selectedCommandType = value;
OnPropertyChanged();
}
}
public string LastUsername
{
get { return _lastUsername; }
set
{
if (value == _lastUsername) return;
_lastUsername = value;
OnPropertyChanged();
}
}
public string LastPassword
{
get { return _lastPassword; }
set
{
if (value == _lastPassword) return;
_lastPassword = value;
OnPropertyChanged();
}
}
public Dictionary<string, string> CommandParameters
{
get { return _commandParameters; }
set
{
if (Equals(value, _commandParameters)) return;
_commandParameters = value;
OnPropertyChanged();
}
}
}
}

View File

@ -13,7 +13,9 @@
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input; using System.Windows.Input;
using Newtonsoft.Json.Linq;
namespace IF.Lastfm.Syro.ViewModels namespace IF.Lastfm.Syro.ViewModels
{ {
@ -24,25 +26,21 @@ internal class MainViewModel : ViewModelBase
private List<string> _remainingCommands; private List<string> _remainingCommands;
private int _apiProgress; private int _apiProgress;
private string _reportPath; private string _reportPath;
private Type _selectedCommandType;
private ObservableCollection<Pair<string, string>> _commandParameters;
private Type _selectedLastObjectType;
private bool _executingCommand;
private Type _selectedResponseType;
private ILastAuth _lastAuth; private ILastAuth _lastAuth;
private bool _executingCommand;
private string _commandResult; private string _commandResult;
private string _commandMethodName; private const string SYRO_CONFIG_FILENAME = "syro.json";
private string _commandPageNumber;
private string _commandItemCount;
private string _lastPassword;
private string _lastUsername;
private const string ReportFilename = "PROGRESS.md"; private const string ReportFilename = "PROGRESS.md";
private MainState _state;
private string _configPath;
private ObservableCollection<Pair<string, string>> _commandParameters;
#region Binding properties #region Binding properties
public ICommand GenerateProgressReportCommand { get; private set; } public ICommand GenerateProgressReportCommand { get; private set; }
public ICommand OpenReportCommand { get; private set; } public ICommand OpenReportCommand { get; private set; }
public ICommand ExecuteSelectedCommandCommand { get; private set; } public ICommand ExecuteSelectedCommandCommand { get; private set; }
public ICommand DeleteConfigCommand { get; private set; }
public string CommandResult public string CommandResult
{ {
@ -99,42 +97,30 @@ public List<string> RemainingCommands
} }
} }
public IEnumerable<Type> BaseCommandTypes { get; private set; } public MainState State
public Type SelectedBaseCommandType
{ {
get { return _selectedCommandType; } get { return _state; }
set set
{ {
if (value == _selectedCommandType) return; if (Equals(value, _state)) return;
_state = value;
_selectedCommandType = value;
OnPropertyChanged(); OnPropertyChanged();
} }
} }
public IEnumerable<Type> BaseCommandTypes { get; private set; }
public IEnumerable<Type> LastObjectTypes { get; private set; } public IEnumerable<Type> LastObjectTypes { get; private set; }
public Type SelectedLastObjectType
{
get { return _selectedLastObjectType; }
set
{
if (value == _selectedLastObjectType) return;
_selectedLastObjectType = value;
OnPropertyChanged();
}
}
public IEnumerable<Type> LastResponseTypes { get; private set; } public IEnumerable<Type> LastResponseTypes { get; private set; }
public Type SelectedResponseType public bool ExecutingCommand
{ {
get { return _selectedResponseType; } get { return _executingCommand; }
set set
{ {
if (value == _selectedResponseType) return; if (value.Equals(_executingCommand)) return;
_selectedResponseType = value; _executingCommand = value;
OnPropertyChanged(); OnPropertyChanged();
} }
} }
@ -150,72 +136,6 @@ public ObservableCollection<Pair<string, string>> CommandParameters
} }
} }
public bool ExecutingCommand
{
get { return _executingCommand; }
set
{
if (value.Equals(_executingCommand)) return;
_executingCommand = value;
OnPropertyChanged();
}
}
public string CommandMethodName
{
get { return _commandMethodName; }
set
{
if (value == _commandMethodName) return;
_commandMethodName = value;
OnPropertyChanged();
}
}
public string CommandPageNumber
{
get { return _commandPageNumber; }
set
{
if (value == _commandPageNumber) return;
_commandPageNumber = value;
OnPropertyChanged();
}
}
public string CommandItemCount
{
get { return _commandItemCount; }
set
{
if (value == _commandItemCount) return;
_commandItemCount = value;
OnPropertyChanged();
}
}
public string LastUsername
{
get { return _lastUsername; }
set
{
if (value == _lastUsername) return;
_lastUsername = value;
OnPropertyChanged();
}
}
public string LastPassword
{
get { return _lastPassword; }
set
{
if (value == _lastPassword) return;
_lastPassword = value;
OnPropertyChanged();
}
}
#endregion #endregion
public MainViewModel(ILastAuth lastAuth) public MainViewModel(ILastAuth lastAuth)
@ -225,34 +145,90 @@ public MainViewModel(ILastAuth lastAuth)
GenerateProgressReportCommand = new AsyncDelegateCommand(GenerateProgressReport); GenerateProgressReportCommand = new AsyncDelegateCommand(GenerateProgressReport);
OpenReportCommand = new DelegateCommand(OpenProgressReport); OpenReportCommand = new DelegateCommand(OpenProgressReport);
ExecuteSelectedCommandCommand = new AsyncDelegateCommand(ExecuteSelectedCommand); ExecuteSelectedCommandCommand = new AsyncDelegateCommand(ExecuteSelectedCommand);
DeleteConfigCommand = new DelegateCommand(() =>
{
if (_configPath != null && File.Exists(_configPath))
{
File.Delete(_configPath);
}
InitialiseState();
});
var currentDir = AppDomain.CurrentDomain.BaseDirectory; var currentDir = AppDomain.CurrentDomain.BaseDirectory;
SolutionDir = Path.GetFullPath(currentDir + "../../../../"); // assuming this is running in debug dir SolutionDir = Path.GetFullPath(currentDir + "../../../../"); // assuming this is running in debug dir
_configPath = Path.GetFullPath(SolutionDir + SYRO_CONFIG_FILENAME);
BaseCommandTypes = new List<Type> BaseCommandTypes = new List<Type>
{ {
typeof(DummyGetAsyncCommand<>), typeof(DummyGetAsyncCommand<>),
typeof(DummyPostAsyncCommand<>) typeof(DummyPostAsyncCommand<>)
}; };
LastObjectTypes = Reflektor.FindClassesCastableTo(typeof (ILastfmObject)); LastObjectTypes = Reflektor.FindClassesCastableTo(typeof(ILastfmObject));
LastResponseTypes = Reflektor.FindClassesCastableTo(typeof (LastResponse)); LastResponseTypes = Reflektor.FindClassesCastableTo(typeof(LastResponse));
SelectedBaseCommandType = BaseCommandTypes.FirstOrDefault(); InitialiseState();
SelectedLastObjectType = LastObjectTypes.FirstOrDefault();
SelectedResponseType = LastResponseTypes.FirstOrDefault();
CommandParameters = new ObservableCollection<Pair<string, string>>(new List<Pair<string, string>> Application.Current.Exit += OnAppExit;
}
private void InitialiseState()
{
var state = LoadState();
var pairs = state.CommandParameters != null
? state.CommandParameters.Select(kv => new Pair<string, string>(kv.Key, kv.Value))
: Enumerable.Repeat(new Pair<string, string>(), 5);
State = state;
CommandParameters = new ObservableCollection<Pair<string, string>>(pairs);
}
private void OnAppExit(object sender, ExitEventArgs e)
{
var json = JsonConvert.SerializeObject(_state);
var lines = new[]
{ {
new Pair<string, string>(), json
new Pair<string, string>(), };
new Pair<string, string>(),
new Pair<string, string>(),
new Pair<string, string>()
});
CommandMethodName = "album.getInfo"; File.WriteAllLines(_configPath, lines);
CommandPageNumber = "0"; }
CommandItemCount = "20";
public MainState LoadState()
{
MainState state = null;
if (File.Exists(_configPath))
{
try
{
var json = File.ReadAllText(_configPath);
state = JsonConvert.DeserializeObject<MainState>(json);
}
catch
{
state = null;
}
}
if (state == null)
{
state = new MainState
{
SelectedBaseCommandType = BaseCommandTypes.FirstOrDefault(),
SelectedLastObjectType = LastObjectTypes.FirstOrDefault(),
SelectedResponseType = LastResponseTypes.FirstOrDefault(),
CommandParameters = new Dictionary<string, string>{
{"album", "The Fall of Math"},
{"artist", "65daysofstatic"}
},
CommandMethodName = "album.getInfo",
CommandPageNumber = "0",
CommandItemCount = "20",
};
}
return state;
} }
private async Task ExecuteSelectedCommand() private async Task ExecuteSelectedCommand()
@ -267,13 +243,13 @@ private async Task ExecuteSelectedCommand()
try try
{ {
// build up the command<response<lastobject>> // build up the command<response<lastobject>>
var responseType = SelectedResponseType.MakeGenericType(SelectedLastObjectType); var responseType = _state.SelectedResponseType.MakeGenericType(_state.SelectedLastObjectType);
var genericType = SelectedBaseCommandType.MakeGenericType(responseType); var genericType = _state.SelectedBaseCommandType.MakeGenericType(responseType);
if ((_lastAuth.UserSession == null || _lastAuth.UserSession.Username != LastUsername) if ((_lastAuth.UserSession == null || _lastAuth.UserSession.Username != _state.LastUsername)
&& SelectedBaseCommandType == typeof (DummyPostAsyncCommand<>)) && _state.SelectedBaseCommandType == typeof(DummyPostAsyncCommand<>))
{ {
await _lastAuth.GetSessionTokenAsync(LastUsername, LastPassword); await _lastAuth.GetSessionTokenAsync(_state.LastUsername, _state.LastPassword);
} }
var instance = Activator.CreateInstance(genericType, _lastAuth); var instance = Activator.CreateInstance(genericType, _lastAuth);
@ -283,15 +259,16 @@ private async Task ExecuteSelectedCommand()
.ToDictionary(pair => pair.Key, pair => pair.Value); .ToDictionary(pair => pair.Key, pair => pair.Value);
var methodProperty = genericType.GetProperty("Method", BindingFlags.Public | BindingFlags.Instance); var methodProperty = genericType.GetProperty("Method", BindingFlags.Public | BindingFlags.Instance);
methodProperty.SetValue(instance, CommandMethodName); methodProperty.SetValue(instance, _state.CommandMethodName);
if (SelectedResponseType == typeof(PageResponse<>)) if (_state.SelectedResponseType == typeof(PageResponse<>)
|| _state.CommandMethodName.EndsWith("s")) // yolo
{ {
var pageProperty = genericType.GetProperty("Page", BindingFlags.Public | BindingFlags.Instance); var pageProperty = genericType.GetProperty("Page", BindingFlags.Public | BindingFlags.Instance);
pageProperty.SetValue(instance, int.Parse(CommandPageNumber)); pageProperty.SetValue(instance, int.Parse(_state.CommandPageNumber));
var countProperty = genericType.GetProperty("Count", BindingFlags.Public | BindingFlags.Instance); var countProperty = genericType.GetProperty("Count", BindingFlags.Public | BindingFlags.Instance);
countProperty.SetValue(instance, int.Parse(CommandItemCount)); countProperty.SetValue(instance, int.Parse(_state.CommandItemCount));
} }
var parametersProperty = genericType.GetProperty("Parameters", var parametersProperty = genericType.GetProperty("Parameters",
@ -309,8 +286,7 @@ private async Task ExecuteSelectedCommand()
var formattedJson = jo.ToString(Formatting.Indented); var formattedJson = jo.ToString(Formatting.Indented);
// writeout to file // writeout to file
var filename = string.Format("syro-{0}-{1}.json", jo.Properties().First().Name, var filename = string.Format("syro-{0}-{1}.json", _state.CommandMethodName.Replace(".", "-"), DateTime.Now.ToString("yyMMdd-HHmmss"));
DateTime.Now.ToString("yyMMdd-HHmmss"));
var tempDirPath = Path.GetFullPath(SolutionDir + "tmp/"); var tempDirPath = Path.GetFullPath(SolutionDir + "tmp/");
if (!Directory.Exists(tempDirPath)) if (!Directory.Exists(tempDirPath))