Skip to content

Commit fb4a9a3

Browse files
committed
Remove code-behind
1 parent ad7890b commit fb4a9a3

File tree

10 files changed

+217
-175
lines changed

10 files changed

+217
-175
lines changed

Flow.Launcher.Plugin.OneNote/Icons/IconProvider.cs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
using System.Windows;
77
using System.Windows.Media;
88
using System.Windows.Media.Imaging;
9-
using Flow.Launcher.Plugin.OneNote.UI;
109
using Color = System.Drawing.Color;
1110

1211
namespace Flow.Launcher.Plugin.OneNote.Icons
@@ -32,9 +31,8 @@ public class IconProvider : BaseModel, IDisposable
3231
private readonly ConcurrentDictionary<string,ImageSource> iconCache = new();
3332
private readonly string imagesDirectory;
3433

35-
public DirectoryInfo GeneratedImagesDirectoryInfo { get; private set; }
34+
public DirectoryInfo GeneratedImagesDirectoryInfo { get; }
3635
public int CachedIconCount => iconCache.Keys.Count(k => char.IsDigit(k.Split('.')[1][1]));
37-
public string CachedIconsFileSize => GetCachedIconsMemorySize();
3836

3937
private readonly PluginInitContext context;
4038

@@ -105,7 +103,6 @@ public Result.IconDelegate GetIcon(IconGeneratorInfo info)
105103
var imageSource = iconCache.GetOrAdd($"{info.Prefix}.{info.Color.Value.ToArgb()}.png", ImageSourceFactory,
106104
info.Color.Value);
107105
OnPropertyChanged(nameof(CachedIconCount));
108-
OnPropertyChanged(nameof(CachedIconsFileSize));
109106
return imageSource;
110107
}
111108

@@ -180,11 +177,10 @@ public void ClearCachedIcons()
180177

181178
}
182179
OnPropertyChanged(nameof(CachedIconCount));
183-
OnPropertyChanged(nameof(CachedIconsFileSize));
184180
}
185181

186182

187-
private string GetCachedIconsMemorySize()
183+
public string GetCachedIconsMemorySize()
188184
{
189185
var i = GeneratedImagesDirectoryInfo.EnumerateFiles()
190186
.Select(file => file.Length)

Flow.Launcher.Plugin.OneNote/Main.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
using System.Threading.Tasks;
55
using System.Windows.Controls;
66
using Flow.Launcher.Plugin.OneNote.Icons;
7-
using Flow.Launcher.Plugin.OneNote.UI.ViewModels;
87
using Flow.Launcher.Plugin.OneNote.UI.Views;
98
using Odotocodot.OneNote.Linq;
109
namespace Flow.Launcher.Plugin.OneNote
@@ -67,7 +66,7 @@ public List<Result> LoadContextMenus(Result selectedResult)
6766

6867
public Control CreateSettingPanel()
6968
{
70-
return new SettingsView(new SettingsViewModel(context, settings, iconProvider));
69+
return new SettingsView(context, settings, iconProvider);
7170
}
7271

7372
public void Dispose()
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
#nullable enable
2+
using System;
3+
using System.Windows.Input;
4+
5+
namespace Flow.Launcher.Plugin.OneNote.UI
6+
{
7+
public sealed class RelayCommand : ICommand
8+
{
9+
private readonly Action<object?> execute;
10+
private readonly Predicate<object?>? canExecute;
11+
12+
public event EventHandler? CanExecuteChanged
13+
{
14+
add => CommandManager.RequerySuggested += value;
15+
remove => CommandManager.RequerySuggested -= value;
16+
}
17+
18+
public RelayCommand(Action<object?> execute, Predicate<object?>? canExecute = null)
19+
{
20+
this.execute = execute;
21+
this.canExecute = canExecute;
22+
}
23+
24+
public bool CanExecute(object? parameter)
25+
{
26+
return canExecute?.Invoke(parameter) != false;
27+
}
28+
29+
public void Execute(object? parameter)
30+
{
31+
execute(parameter);
32+
}
33+
}
34+
}

Flow.Launcher.Plugin.OneNote/UI/ViewModels/ChangeKeywordViewModel.cs

Lines changed: 38 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,71 @@
1-
using System.Linq;
1+
using System;
2+
using System.Linq;
3+
using System.Windows.Input;
24

35
namespace Flow.Launcher.Plugin.OneNote.UI.ViewModels
46
{
57
public class ChangeKeywordViewModel : Model
68
{
79
private readonly PluginInitContext context;
810
private readonly KeywordViewModel[] keywords;
9-
private string newKeyword;
11+
private readonly Action closeAction;
1012

11-
public ChangeKeywordViewModel(SettingsViewModel settingsViewModel)
13+
private string errorMessage;
14+
15+
public ChangeKeywordViewModel(SettingsViewModel settingsViewModel, PluginInitContext context, Action close)
1216
{
13-
context = settingsViewModel.context;
17+
this.context = context;
18+
closeAction = close;
1419
keywords = settingsViewModel.Keywords;
1520
SelectedKeyword = settingsViewModel.SelectedKeyword;
21+
ChangeKeywordCommand = new RelayCommand(
22+
keyword => ChangeKeyword((string)keyword),
23+
keyword => CanChangeKeyword((string)keyword));
24+
CloseCommand = new RelayCommand( _=> closeAction?.Invoke());
25+
}
26+
public KeywordViewModel SelectedKeyword { get; }
27+
28+
public ICommand CloseCommand { get; }
29+
30+
public ICommand ChangeKeywordCommand { get; }
31+
32+
public string ErrorMessage
33+
{
34+
get => errorMessage;
35+
private set => SetProperty(ref errorMessage, value);
1636
}
17-
public KeywordViewModel SelectedKeyword { get; init; }
18-
public string NewKeyword { get => newKeyword; set => SetProperty(ref newKeyword, value); }
1937

20-
public bool ChangeKeyword(out string errorMessage)
38+
private bool CanChangeKeyword(string newKeyword)
2139
{
22-
errorMessage = null;
23-
var oldKeyword = SelectedKeyword.Keyword;
24-
if (string.IsNullOrWhiteSpace(NewKeyword))
40+
if (string.IsNullOrWhiteSpace(newKeyword))
2541
{
26-
errorMessage = "The new keyword cannot be empty.";
42+
//ErrorMessage = "The new keyword cannot be empty.";
2743
return false;
2844
}
2945

30-
var newKeyword = NewKeyword.Trim();
31-
if (oldKeyword == newKeyword)
46+
newKeyword = newKeyword.Trim();
47+
if (SelectedKeyword.Keyword == newKeyword)
3248
{
33-
errorMessage = "The new keyword is the same as the old keyword.";
49+
ErrorMessage = "The new keyword is the same as the old keyword.";
3450
return false;
3551
}
3652

3753
var alreadySetKeyword = keywords.FirstOrDefault(k => k.Keyword == newKeyword);
3854
if (alreadySetKeyword != null)
3955
{
40-
errorMessage = $"The new keyword matches an already set one:\n"
41-
+ $"\"{alreadySetKeyword.Name}\" => \"{alreadySetKeyword.Keyword}\"";
56+
ErrorMessage = $"The new keyword is already set for {alreadySetKeyword.Name}.";
4257
return false;
4358
}
4459

45-
SelectedKeyword.Keyword = newKeyword;
46-
context.API.SaveSettingJsonStorage<Settings>();
60+
ErrorMessage = null;
4761
return true;
62+
}
4863

64+
private void ChangeKeyword(string newKeyword)
65+
{
66+
SelectedKeyword.Keyword = newKeyword.Trim();
67+
context.API.SaveSettingJsonStorage<Settings>();
68+
closeAction?.Invoke();
4969
}
5070
}
5171

Flow.Launcher.Plugin.OneNote/UI/ViewModels/KeywordViewModel.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,17 @@ namespace Flow.Launcher.Plugin.OneNote.UI.ViewModels
66
{
77
public partial class KeywordViewModel : BaseModel
88
{
9-
public object Instance { get; init; }
10-
public PropertyInfo PropertyInfo { get; init; }
11-
public string Name { get; init; }
9+
private object Instance { get; init; }
10+
private PropertyInfo PropertyInfo { get; init; }
11+
public string Name { get; private init; }
1212

1313
public string Keyword
1414
{
1515
get => (string)PropertyInfo.GetValue(Instance);
1616
set
1717
{
1818
PropertyInfo.SetValue(Instance, value, null);
19-
OnPropertyChanged(nameof(Keyword));
19+
OnPropertyChanged();
2020
}
2121
}
2222

Lines changed: 59 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,74 @@
1-

2-
using System;
3-
using System.Collections.Generic;
4-
using System.Linq;
1+
using System.Threading.Tasks;
2+
using System.Windows.Input;
53
using Flow.Launcher.Plugin.OneNote.Icons;
4+
using Modern = ModernWpf.Controls;
65

76
namespace Flow.Launcher.Plugin.OneNote.UI.ViewModels
87
{
98
public class SettingsViewModel : Model
109
{
11-
public readonly PluginInitContext context;
10+
private readonly IconProvider iconProvider;
11+
private KeywordViewModel selectedKeyword;
12+
1213
public SettingsViewModel(PluginInitContext context, Settings settings, IconProvider iconProvider)
1314
{
1415
Settings = settings;
15-
this.context = context;
1616
Keywords = KeywordViewModel.GetKeywordViewModels(settings.Keywords);
17-
IconProvider = iconProvider;
18-
IconProvider.PropertyChanged += (sender, args) => OnPropertyChanged(nameof(CanClearCachedIcons));
17+
this.iconProvider = iconProvider;
18+
19+
EditCommand = new RelayCommand(
20+
_ => new Views.ChangeKeywordWindow(this, context).ShowDialog(), //Avert your eyes! This is not MVVM!
21+
_ => SelectedKeyword != null);
22+
23+
OpenGeneratedIconsFolderCommand = new RelayCommand(
24+
_ => context.API.OpenDirectory(iconProvider.GeneratedImagesDirectoryInfo.FullName));
25+
26+
ClearCachedIconsCommand = new RelayCommand(
27+
async _ => await ClearCachedIcons(),
28+
_ => iconProvider.CachedIconCount > 0);
29+
30+
iconProvider.PropertyChanged += (_, args) =>
31+
{
32+
if (args.PropertyName == nameof(iconProvider.CachedIconCount))
33+
{
34+
OnPropertyChanged(nameof(CachedIconsFileSize));
35+
CommandManager.InvalidateRequerySuggested();
36+
}
37+
};
38+
SelectedKeyword = Keywords[0];
39+
}
40+
public ICommand EditCommand { get; }
41+
public ICommand OpenGeneratedIconsFolderCommand { get; }
42+
public ICommand ClearCachedIconsCommand { get; }
43+
public Settings Settings { get; }
44+
public KeywordViewModel[] Keywords { get; }
45+
public string CachedIconsFileSize => iconProvider.GetCachedIconsMemorySize();
46+
47+
public KeywordViewModel SelectedKeyword
48+
{
49+
get => selectedKeyword;
50+
set => SetProperty(ref selectedKeyword, value);
1951
}
2052

21-
public Settings Settings { get; init; }
22-
public KeywordViewModel[] Keywords { get; init; }
23-
//TODO refactor this expose the properties instead of the class
24-
public IconProvider IconProvider { get; init; }
25-
public KeywordViewModel SelectedKeyword { get; set; }
53+
//quick and dirty non MVVM stuffs
54+
private async Task ClearCachedIcons()
55+
{
56+
var dialog = new Modern.ContentDialog()
57+
{
58+
Title = "Clear Cached Icons",
59+
Content = $"Delete cached notebook and sections icons.\n" +
60+
$"This will delete {iconProvider.CachedIconCount} icon{(iconProvider.CachedIconCount != 1 ? "s" : string.Empty)}.",
61+
PrimaryButtonText = "Yes",
62+
CloseButtonText = "Cancel",
63+
DefaultButton = Modern.ContentDialogButton.Close,
64+
};
65+
66+
var result = await dialog.ShowAsync();
2667

27-
#pragma warning disable CA1822 // Mark members as static
28-
public IEnumerable<int> DefaultRecentCountOptions => Enumerable.Range(1, 16);
29-
public IEnumerable<IconTheme> PluginThemes => Enum.GetValues<IconTheme>();
30-
#pragma warning restore CA1822 // Mark members as static
31-
public void OpenGeneratedIconsFolder() => context.API.OpenDirectory(IconProvider.GeneratedImagesDirectoryInfo.FullName);
32-
public void ClearCachedIcons() => IconProvider.ClearCachedIcons();
33-
public bool CanClearCachedIcons => IconProvider.CachedIconCount > 0;
68+
if (result == Modern.ContentDialogResult.Primary)
69+
{
70+
iconProvider.ClearCachedIcons();
71+
}
72+
}
3473
}
3574
}

Flow.Launcher.Plugin.OneNote/UI/Views/ChangeKeywordWindow.xaml

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,8 @@
6060
</Grid.ColumnDefinitions>
6161
<Button
6262
Grid.Column="4"
63-
Click="CloseWindow"
63+
Command="{Binding CloseCommand}"
64+
IsCancel="True"
6465
Style="{StaticResource TitleBarCloseButtonStyle}">
6566
<Path
6667
Width="46"
@@ -131,8 +132,15 @@
131132
Width="105"
132133
Margin="10,10,15,10"
133134
HorizontalAlignment="Left"
135+
VerticalAlignment="Center" />
136+
<TextBlock
137+
Width="170"
138+
Margin="10,5,10,5"
134139
VerticalAlignment="Center"
135-
Text="{Binding NewKeyword}" />
140+
d:Text="This is an error message&#x0a;This is an error message"
141+
Text="{Binding ErrorMessage}"
142+
TextAlignment="Justify"
143+
TextWrapping="Wrap" />
136144
</StackPanel>
137145
</StackPanel>
138146
</StackPanel>
@@ -142,19 +150,24 @@
142150
Background="{DynamicResource PopupButtonAreaBGColor}"
143151
BorderBrush="{DynamicResource PopupButtonAreaBorderColor}"
144152
BorderThickness="0,1,0,0">
145-
<StackPanel HorizontalAlignment="Center" Orientation="Horizontal">
153+
<StackPanel
154+
Grid.Row="1"
155+
HorizontalAlignment="Center"
156+
Orientation="Horizontal">
146157
<Button
147158
Width="145"
148159
Height="30"
149160
Margin="10,0,5,0"
150-
Click="CloseWindow"
151-
Content="{DynamicResource cancel}" />
161+
Command="{Binding CloseCommand}"
162+
Content="{DynamicResource cancel}"
163+
IsCancel="True" />
152164
<Button
153165
x:Name="btnDone"
154166
Width="145"
155167
Height="30"
156168
Margin="5,0,10,0"
157-
Click="Button_ChangeKeyword"
169+
Command="{Binding ChangeKeywordCommand}"
170+
CommandParameter="{Binding ElementName=TextBox_NewKeyword, Path=Text}"
158171
Style="{StaticResource AccentButtonStyle}">
159172
<TextBlock x:Name="lblAdd" Text="{DynamicResource done}" />
160173
</Button>

Flow.Launcher.Plugin.OneNote/UI/Views/ChangeKeywordWindow.xaml.cs

Lines changed: 2 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -5,34 +5,15 @@ namespace Flow.Launcher.Plugin.OneNote.UI.Views
55
{
66
public partial class ChangeKeywordWindow
77
{
8-
private readonly ChangeKeywordViewModel viewModel;
9-
10-
public ChangeKeywordWindow(SettingsViewModel settingsViewModel)
8+
public ChangeKeywordWindow(SettingsViewModel viewModel, PluginInitContext context)
119
{
1210
InitializeComponent();
13-
DataContext = viewModel = new ChangeKeywordViewModel(settingsViewModel);
11+
DataContext = new ChangeKeywordViewModel(viewModel, context, Close);
1412
}
1513

1614
private void WindowLoaded(object sender, RoutedEventArgs e)
1715
{
1816
TextBox_NewKeyword.Focus();
1917
}
20-
21-
private void CloseWindow(object sender, RoutedEventArgs e)
22-
{
23-
Close();
24-
}
25-
26-
private void Button_ChangeKeyword(object sender, RoutedEventArgs e)
27-
{
28-
if(viewModel.ChangeKeyword(out string errorMessage))
29-
{
30-
Close();
31-
}
32-
else
33-
{
34-
MessageBox.Show(this, errorMessage,"Invalid Keyword", MessageBoxButton.OK, MessageBoxImage.Error);
35-
}
36-
}
3718
}
3819
}

0 commit comments

Comments
 (0)